|
|
|
|
|
""" |
|
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.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): |
|
|
|
teamDemography = collections.Counter([self.playerTeamMap[player] for player in sampledTeam]) |
|
|
|
|
|
pointsCriteria = self.checkMaxTeamPointsCriteria(sampledTeam) |
|
|
|
|
|
uniqueTeamCriteria = self.checkUniqueTeamCriteria(sampledTeam, selectedTeams) |
|
|
|
|
|
minPlayersCriteria = self.checkMinPlayersTeamCriteria(teamDemography) |
|
|
|
|
|
maxPlayersCriteria = self.checkMaxPlayersTeamCriteria(teamDemography) |
|
|
|
|
|
similarityIndices, similarityIndexCriteria = self.checkSimilarityIndexCriteria(sampledTeam, selectedTeams, selected) |
|
|
|
|
|
[c, vc] = self.chooseCaptain(sampledTeam, captain) |
|
|
|
if pointsCriteria and uniqueTeamCriteria and minPlayersCriteria and maxPlayersCriteria and similarityIndexCriteria: |
|
|
|
|
|
selectedTeams.append(sampledTeam) |
|
selected = selected + 1 |
|
|
|
self.printTeamDetails(sampledTeam, selected, c, vc, similarityIndices) |
|
|
|
|
|
|
|
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) |
|
|
|
|
|
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) |
|
|
|
|
|
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: |
|
|
|
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 |
|
|
|
|
|
wks = self.sample([p for p in self.players if p['type']=='wk'], numWks) |
|
|
|
|
|
bats = self.sample([p for p in self.players if p['type']=='bat'], numBats) |
|
|
|
|
|
ars = self.sample([p for p in self.players if p['type']=='ar'], numArs) |
|
|
|
|
|
bowls = self.sample([p for p in self.players if p['type']=='bowl'], numBowls) |
|
|
|
|
|
sampledTeam = wks + bats + ars + bowls |
|
|
|
|
|
selectedTeams, selected = self.updateSelectedTeams(sampledTeam, selectedTeams, selected, captain) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|