Sport / app.py
Bandey's picture
Rename dreamteam.py to app.py
c08b46c verified
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 20 02:58:47 2019
@author: ManishChalana
"""
import numpy as np
import collections
import pandas as pd
class Team:
def __init__(self, players, teams):
self.players = players
self.team1 = teams[0]
self.team2 = teams[1]
numPlayers = collections.Counter([player['team'] for player in self.players])
assert list(numPlayers.values())==[11,11], "Invalid combination! Number of players in " + self.team1 + ": " + str(numPlayers[self.team1]) + "," + self.team2 + ": " + str(numPlayers[self.team2])
class Dream11(Team):
def __init__(self, players, teams):
super().__init__(players, teams)
self.teamParams = {'min':4, 'max':7}
self.maxPoints = 100
self.combinations = [[1,3,2,5], [1,3,3,4], [1,4,1,5], [1,4,2,4], [1,4,3,3], [1,5,1,4], [1,5,2,3]]
# self.combinationsProb = [0.14]*6 + [0.16]
# self.combinationsProb = [0.1,0.2,0.05,0.2,0.3,0.05,0.1]
self.playerNames = [p['name'] for p in players]
self.playerPointMap = {p['name']:p['points'] for p in self.players}
self.playerTeamMap = {p['name']:p['team'] for p in self.players}
self.playerTypeMap = {p['name']:p['type'] for p in self.players}
self.playerTypeCount = collections.Counter(self.playerTypeMap.values())
@staticmethod
def getSoftmaxProbabilities(points, toneDownMultiplier=1):
if len(points) == 0:
return []
points = [toneDownMultiplier*point for point in points]
denom = np.sum([np.exp(point) for point in points])
softMax = [np.exp(point)/denom for point in points]
return softMax
def sample(self, players, req):
numStars = np.sum([p['star'] for p in players])
availableStars = [p['name'] for p in players if p['star']==1]
availableStarsPoints = [p['points'] for p in players if p['star']==1]
availableStarsSoftMax = Dream11.getSoftmaxProbabilities(availableStarsPoints)
availableNonStars = [p['name'] for p in players if not(p['star']==1)]
availableNonStarsPoints = [p['points'] for p in players if not(p['star']==1)]
availableNonStarsSoftMax = Dream11.getSoftmaxProbabilities(availableNonStarsPoints)
if numStars >= req:
return ([] if len(availableStars)==0 else list(np.random.choice(availableStars, size = req, p=availableStarsSoftMax, replace=False)))
else:
return availableStars + list(np.random.choice(availableNonStars, size = req - numStars, p=availableNonStarsSoftMax, replace=False))
def calculateTeamVector(self, team):
teamVector = [player['points'] if (player['name'] in team) else 0 for player in self.players]
return teamVector
def checkUniqueTeamCriteria(self, sampledTeam, selectedTeams):
return (np.sum([set(team)==set(sampledTeam) for team in selectedTeams]) == 0)
def checkMinPlayersTeamCriteria(self, teamDemography):
return (teamDemography[self.team1]>=self.teamParams['min']) and (teamDemography[self.team2]>=self.teamParams['min'])
def checkMaxPlayersTeamCriteria(self, teamDemography):
return (teamDemography[self.team1]<=self.teamParams['max']) and (teamDemography[self.team2]<=self.teamParams['max'])
def checkMaxTeamPointsCriteria(self, sampledTeam):
totalPoints = np.sum([self.playerPointMap[player] for player in sampledTeam])
return (totalPoints <= self.maxPoints)
def checkSimilarityIndexCriteria(self, sampledTeam, selectedTeams, selected, thresh=24):
similarityIndexCriteria = False
similarityIndices = []
if selected>0:
similarityIndices = [np.sqrt(np.sum(np.square(np.array(self.calculateTeamVector(sampledTeam)) - np.array(self.calculateTeamVector(team))))) for team in selectedTeams]
if np.min(similarityIndices) > thresh:
similarityIndexCriteria = True
else:
similarityIndexCriteria = True
return similarityIndices, similarityIndexCriteria
def chooseCaptain(self, sampledTeam, captain):
[c, vc] = ['', '']
if captain:
sampledTeamSoftmax = [self.playerPointMap[name] for name in sampledTeam]
[c, vc] = np.random.choice(sampledTeam, size=2, replace=False, p=Dream11.getSoftmaxProbabilities(sampledTeamSoftmax, toneDownMultiplier=0.75))
return [c, vc]
def updateSelectedTeams(self, sampledTeam, selectedTeams, selected, captain):
#Finding the numbers of wks, bats, ar and bowls in the sampled team
teamDemography = collections.Counter([self.playerTeamMap[player] for player in sampledTeam])
# Finding the total number of points spent in selecting the sampled team and ensuring that it is less than maximum available points
pointsCriteria = self.checkMaxTeamPointsCriteria(sampledTeam)
# Ensuring that sampled team is not same as one of the previously selected teams
uniqueTeamCriteria = self.checkUniqueTeamCriteria(sampledTeam, selectedTeams)
# Making sure that minimum required players are selected in sampled team from each of the two parent teams
minPlayersCriteria = self.checkMinPlayersTeamCriteria(teamDemography)
# Making sure that maximum required players are selected in sampled team from each of the two parent teams
maxPlayersCriteria = self.checkMaxPlayersTeamCriteria(teamDemography)
# Calculating the similarity index of the sampled team with the already selected teams to ensure dissimilarity
similarityIndices, similarityIndexCriteria = self.checkSimilarityIndexCriteria(sampledTeam, selectedTeams, selected)
# Choosing a captain and vice captain
[c, vc] = self.chooseCaptain(sampledTeam, captain)
if pointsCriteria and uniqueTeamCriteria and minPlayersCriteria and maxPlayersCriteria and similarityIndexCriteria:
# When all criterias are fulfilled by the team, append the sampled team to list of already selected teams
selectedTeams.append(sampledTeam)
selected = selected + 1
self.printTeamDetails(sampledTeam, selected, c, vc, similarityIndices)
# Finding the attributes of the selected team
return selectedTeams, selected
def printTeamDetails(self, sampledTeam, index, c, vc, similarityIndices):
selectedPlayersNames = [name.upper() for name in sampledTeam]
selectedPlayersPoints = [[p for p in self.players if p['name']==name][0]['points'] for name in sampledTeam]
selectedPlayersTeams = [[p for p in self.players if p['name']==name][0]['team'].upper() for name in sampledTeam]
selectedPlayersTypes = [[p for p in self.players if p['name']==name][0]['type'] for name in sampledTeam]
selectedPlayersCVC = ['c' if name==c else 'vc' if name==vc else ' ' for name in sampledTeam ]
selectedPlayersTypesCounter = collections.Counter(selectedPlayersTypes)
selectedPlayersTeamsCounter = collections.Counter(selectedPlayersTeams)
# Defining a dataframe containing the details of sampled team
teamDf = pd.DataFrame({'Player': selectedPlayersNames, 'C/VC': selectedPlayersCVC, 'Points':selectedPlayersPoints, 'Team':selectedPlayersTeams, 'Type':selectedPlayersTypes}, index=range(1,12))[['Player', 'C/VC', 'Team', 'Type', 'Points']]
teamDf = pd.concat([teamDf[teamDf['Type']==playType].sort_values(['Points'], ascending=False) for playType in ['wk', 'bat', 'ar', 'bowl']])
teamDf.index = range(1,12)
# Printing the team on console
print("------------ Team", index, "------------\n")
print(teamDf)
print("\nTotal points invested:", np.sum(teamDf['Points']))
print("Wicket-keepers:", selectedPlayersTypesCounter['wk'], ", Batsman:", selectedPlayersTypesCounter['bat'], ", All-rounders:", selectedPlayersTypesCounter['ar'], " Bowlers:", selectedPlayersTypesCounter['bowl'])
print(self.team1.upper(), ":", selectedPlayersTeamsCounter[self.team1.upper()], self.team2.upper(), ":", selectedPlayersTeamsCounter[self.team2.upper()])
print("Similarity indices:", similarityIndices)
print('\n')
def generateTeams(self, numTeams, captain=False):
selectedTeams = []
selected = 0
while selected < numTeams:
# Choose a random combination of number of wicket-keepers, batsman, all-rounders and bowlers
while True:
[numWks, numBats, numArs, numBowls] = self.combinations[np.random.choice(len(self.combinations), size=1)[0]]
if (numWks <= self.playerTypeCount['wk']) and (numBats <=self.playerTypeCount['bat']) and (numArs <=self.playerTypeCount['ar']) and (numBowls<=self.playerTypeCount['bowl']):
break
# Choose Keepers
wks = self.sample([p for p in self.players if p['type']=='wk'], numWks)
# Choose batsman
bats = self.sample([p for p in self.players if p['type']=='bat'], numBats)
# Choose all-rounders
ars = self.sample([p for p in self.players if p['type']=='ar'], numArs)
# Choose bowlers
bowls = self.sample([p for p in self.players if p['type']=='bowl'], numBowls)
# Chosen team
sampledTeam = wks + bats + ars + bowls
# Update selected teams list based on whether the sampled team fulfills all eligibility criteria
selectedTeams, selected = self.updateSelectedTeams(sampledTeam, selectedTeams, selected, captain)