File size: 10,198 Bytes
4e5bc49 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 |
#!/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)
|