def __init__(self, match_id: int): ''' Calls the API and creates a match representation from result. Args: match_id: Dota match ID ''' if not isinstance(match_id, int): raise TypeError('`match_id` must have type int.') else: self.id = match_id response = api.get_match_details(match_id=match_id) # TODO: check supported modes, rewrote this if response['game_mode'] != 2 and response['game_mode'] != 16: raise NotImplementedError( 'Sorry, Match currently' + ' does not support {}'.format(response['game_mode_name']) + ' game mode.') self.radiant = Heroes() self.dire = Heroes() self.radiant_win = response['radiant_win'] # select picks and add heroes to appropriate teams for pick in filter(lambda x: x['is_pick'], response['picks_bans']): if pick['team'] == 0: self.radiant.add(Hero(pick['hero_id'])) else: self.dire.add(Hero(pick['hero_id']))
def get_recommendations(pick, against=[], ban=[]): ''' Chooses 5 best heroes to add to the `pick`. Args: pick (list): heroes to which next one should be recommended against (list) (optional, default=[]): list of heroes against which `pick` heroes are going to play ban (list) (optional, default=[]): banned heroes. Returns: (list): heroes that will fit the best for the next pick for `pick`. ''' # create Heroes objects for arguments pick_heroes = Heroes.from_names(pick) ban_heroes = Heroes.from_names(ban) against_heroes = Heroes.from_names(against) recommendations = list() while (len(recommendations) < 5): a = _get_recommendation(pick_heroes, against_heroes, ban_heroes) recommendations.append(a) # add hero to ban to get the next best hero ban_heroes.add(a) recommendations_names = [hero.in_game_name for hero in recommendations] return recommendations_names
def test_description(self): names = ['Sniper', 'Lina', 'Dazzle'] heroes = Heroes.from_names(names) description = heroes.get_description(['role']) self.assertEqual((9, ), description.shape)
def test_init_with_ids(self): ''' I'm not sure how to test classes like this. So, what tests are doing is basically: call method with some arguments, check if something goes wrong. ''' # this is fine Heroes.from_ids([1, 14, 112]) # call with invalid id self.assertRaises(ValueError, Heroes.from_ids, [0, 228]) # call with non-integer id self.assertRaises(TypeError, Heroes.from_ids, ['1', 54]) # call with specific patch, fine too Heroes.from_ids([15, 25, 89], patch='706f')
def test_init_with_names(self): ''' I'm not sure how to test classes like this. So, what tests are doing is basically: call method with some arguments, check if something goes wrong. ''' # this is fine Heroes.from_names(['Gyrocopter', 'Bounty Hunter', 'Viper']) # call with invalid id self.assertRaises(ValueError, Heroes.from_names, ['Best hero', 'Anti-Mage']) # call with non-string id self.assertRaises(TypeError, Heroes.from_ids, ['Shadow Fiend', 54]) # call with specific patch, fine too Heroes.from_names(['Axe', 'Underlord', 'Bane'], patch='706f')
def test_iter(self): ''' One more time: I'm not sure what to do there, but user should be able to iterate over heroes. ''' heroes = Heroes.from_ids([1, 15, 65]) for hero in heroes: pass
def test_get_ids(self): names = ['Sniper', 'Lina', 'Dazzle'] heroes = Heroes.from_names(names) ids = heroes.get_ids() for name in names: self.assertEqual(ids[name], Hero.from_name(name).id) bin_ids = heroes.get_ids(binarised=True) # len of binarised ids should be equal to amount of heroes self.assertEqual((len(self.all_heroes), ), bin_ids.shape) # amount of 1s should be equal to amount of heroes in the object self.assertEqual(len(list(filter(lambda x: x == 1, bin_ids))), len(heroes))
hero1, hero2 = sorted([next_hero_id, picked_hero]) total_connection += winrate.loc[hero1][hero2] for enemy in against: total_connection -= lose_rate.loc[next_hero_id][enemy] if total_connection > best_connection: best_hero = next_hero_id best_connection = total_connection return best_hero.item() # In[25]: pick = Heroes() pick.add(Hero.from_name('')) ban = Heroes() ban.add(Hero.from_name('Shadow Fiend')) ban.add(Hero.from_name('Invoker')) against = Heroes() against.add(Hero.from_name('Slardar')) against.add(Hero.from_name('Witch Doctor')) while len(pick) < 5: next_hero = get_next_hero(list(pick.get_ids()), ban=list(ban.get_ids()), against=list(against.get_ids())) pick.add(Hero(next_hero))
class Match(object): ''' Representation of the single match. Attributes: id (int) : id of the match radiant (Heroes): Heroes in radiant team dire (Heroes): Heroes in dire team ''' def __init__(self, match_id: int): ''' Calls the API and creates a match representation from result. Args: match_id: Dota match ID ''' if not isinstance(match_id, int): raise TypeError('`match_id` must have type int.') else: self.id = match_id response = api.get_match_details(match_id=match_id) # TODO: check supported modes, rewrote this if response['game_mode'] != 2 and response['game_mode'] != 16: raise NotImplementedError( 'Sorry, Match currently' + ' does not support {}'.format(response['game_mode_name']) + ' game mode.') self.radiant = Heroes() self.dire = Heroes() self.radiant_win = response['radiant_win'] # select picks and add heroes to appropriate teams for pick in filter(lambda x: x['is_pick'], response['picks_bans']): if pick['team'] == 0: self.radiant.add(Hero(pick['hero_id'])) else: self.dire.add(Hero(pick['hero_id'])) def get_description(self, include): ''' Returns description of certain match. Description consist of 3 parts: radiant description, dire description and result. Complete length of description vector is 2n + 1, where n is a length of side description (depends on choosen parameters). Args: include (list): the same with Hero.get_description(). Returns: pd.Series ''' # get descriptions of sides radiant_description = self.radiant.get_description(include) dire_description = self.dire.get_description(include) len_desc = radiant_description.shape[0] # create array for MultiIndex object index_arrays = [['radiant'] * len_desc + ['dire'] * len_desc, list(radiant_description.index) * 2] # convert array to list of tuples index_tuples = list(zip(*index_arrays)) # add result comlumn index_tuples.append(('result', 'radiant_win')) index = pd.MultiIndex.from_tuples(index_tuples, names=['side', 'variables']) # unite all the columns variables = [*radiant_description, *dire_description, self.radiant_win] description = pd.Series(variables, index=index) return description
def setUp(self): self.all_heroes = Heroes.all()