public async Task <IHttpActionResult> GetAbilityDraftMatch(long id)
        {
            AbilityDraftMatch abilityDraftMatch = await db.AbilityDraftMatches.Include(m => m.Players.Select(p => p.Abilities))
                                                  .Include(m => m.Players.Select(p => p.Hero.Roles)).SingleOrDefaultAsync(m => m.MatchId == id);

            if (abilityDraftMatch == null)
            {
                var gameFetcher = ServiceLocator.GetInstance().GetService <IGameFetcher>();
                try
                {
                    abilityDraftMatch = await gameFetcher.FetchGame(id.ToString());
                }
                catch (GameFetcherException e)
                {
                    return(InternalServerError(e));
                }

                //if we did not get a match from our game fetcher than as far as we know it doesn't exist and return notfound
                if (abilityDraftMatch == null)
                {
                    return(NotFound());
                }
                //add the fetched game to the database and update stats related to this match
                var matchDetailUpdater = new MatchDetailUpdater(ServiceLocator.GetInstance().GetService <IDataSource>(), ServiceLocator.GetInstance().GetService <IStatUpdater>());
                await matchDetailUpdater.UpdateDataSourceAndStats(abilityDraftMatch);
            }

            var dto = AbilityDraftMatchDataTransferObject.CreateAbilityDraftMatchDataTransferObject(abilityDraftMatch);

            return(Ok(dto));
        }
Exemplo n.º 2
0
        private async Task <HeroAbilityStat> CreateNewHeroAbilityStat(AbilityDraftMatch match, Player player, Ability ability)
        {
            //lookup existing hero and ability from datasource. These should be in there because we add the match to the datasource before updating stats.
            var existingHero = await dataSource.LookupHero(player.Hero.HeroId);

            var existingAbility = await dataSource.LookupAbility(ability.AbilityId);

            if (existingHero == null)
            {
                throw new StatUpdaterException("An existing hero with heroId " + player.Hero.HeroId + " could not be found.");
            }
            if (existingAbility == null)
            {
                throw new StatUpdaterException("An existing ability with abilityId " + ability.AbilityId + " could not be found.");
            }
            existingHero.EntityState    = ModelEntityState.Unchanged;
            existingAbility.EntityState = ModelEntityState.Unchanged;

            return(new HeroAbilityStat
            {
                HeroId = existingHero.HeroId,
                AbilityId = existingAbility.AbilityId,
                Matches = 1,
                Wins = PlayerWonMatch(match, player) ? 1 : 0,
                Hero = existingHero,
                Ability = existingAbility,
                EntityState = ModelEntityState.Added
            });
        }
Exemplo n.º 3
0
        public async Task UpdateStats(AbilityDraftMatch match)
        {
            foreach (Player player in match.Players)
            {
                foreach (Ability ability in player.Abilities)
                {
                    var existingHeroAbilityStat = await dataSource.LookupHeroAbilityStat(player.Hero.HeroId, ability.AbilityId);

                    if (existingHeroAbilityStat == null)
                    {
                        var newStat = await CreateNewHeroAbilityStat(match, player, ability);
                        await AddHeroAbilityStat(newStat);
                    }
                    else
                    {
                        existingHeroAbilityStat.Matches++;
                        existingHeroAbilityStat.Wins        = PlayerWonMatch(match, player) ? existingHeroAbilityStat.Wins + 1 : existingHeroAbilityStat.Wins;
                        existingHeroAbilityStat.EntityState = ModelEntityState.Modified;
                        await UpdateHeroAbilityStat(existingHeroAbilityStat);
                    }
                }
            }
        }
Exemplo n.º 4
0
        public async Task UpdateDataSourceAndStats(AbilityDraftMatch match)
        {
            match.EntityState = ModelEntityState.Added;
            var addedAbilities = new List <Ability>(); //some abilities such as talents can be learned by multiple heroes in the same match so we need to make sure

            //we dont add that ability multiple times from the same match.

            foreach (var player in match.Players)
            {
                player.EntityState = ModelEntityState.Added;
                var foundHero = await dataSource.LookupHero(player.Hero.HeroId);

                player.Hero.EntityState = foundHero == null ? ModelEntityState.Added : ModelEntityState.Unchanged;  //add it if not found else leave it unchanged.

                foreach (var ability in player.Abilities.ToList())
                {
                    //lookup ability in abilities added this match first, else lookup in datasource.
                    var foundAbility = addedAbilities.FirstOrDefault(a => a.AbilityId == ability.AbilityId);
                    if (foundAbility == null)
                    {
                        foundAbility = await dataSource.LookupAbility(ability.AbilityId);

                        if (foundAbility != null)
                        {
                            foundAbility.EntityState = ModelEntityState.Unchanged; //if we got the item from the database we don't want it to be readded.
                            addedAbilities.Add(foundAbility);                      //add it to local list so we don't have to lookup from datasource multiple times.
                        }
                    }

                    if (foundAbility != null)             //if ability exists in datasource or abilities added this game.
                    {
                        player.Abilities.Remove(ability); //remove the object that has the same abilityid and replace it with the one that is either already in the
                        //datasource or has been set up to be added to the datasource. This prevents 2 objects in the datasource with the same abilityId.
                        player.Abilities.Add(foundAbility);
                    }
                    else
                    {
                        ability.EntityState = ModelEntityState.Added;
                        addedAbilities.Add(ability);
                    }
                }
            }
            bool matchSuccessfullyAdded = true;

            try
            {
                await this.dataSource.AddEntity <AbilityDraftMatch>(match);
            }
            catch (DataSourceException)
            {
                //if there's an issue adding the match to the datastore then we don't update stats with this match.
                matchSuccessfullyAdded = false;

                throw;
            }
            if (matchSuccessfullyAdded) //don't update stats if the match wasn't added successfully otherwise in future when we add the match again we might count stats twice.
            {
                try
                {
                    await this.statUpdater.UpdateStats(match);
                }
                catch (StatUpdaterException)
                {
                    throw;
                }
            }
        }
Exemplo n.º 5
0
        public async Task <AbilityDraftMatch> ToLocalAbilityDraftMatch(AbiltiyDraftGameJSON json)
        {
            var match = new AbilityDraftMatch
            {
                MatchId          = json.match_id,
                StartTime        = json.start_time,
                DurationSeconds  = json.duration,
                ServerCluster    = json.cluster,
                PatchNumber      = json.patch,
                SkillLevel       = json.skill,
                GameMode         = json.game_mode,
                DireKillScore    = json.dire_score,
                RadiantKillScore = json.radiant_score,
                RadiantWin       = json.radiant_win,
                Players          = new HashSet <Dota2HeroStats.Models.Player>()
            };

            foreach (JSONModels.Player player in json.players)
            {
                var p = new Dota2HeroStats.Models.Player
                {
                    MatchId    = player.match_id,
                    PlayerSlot = player.player_slot,
                    AccountId  = player.account_id,
                    IsRadiant  = player.isRadiant,

                    Item_0     = player.item_0,
                    Item_1     = player.item_1,
                    Item_2     = player.item_2,
                    Item_3     = player.item_3,
                    Item_4     = player.item_4,
                    Item_5     = player.item_5,
                    Backpack_0 = player.backpack_0,
                    Backpack_1 = player.backpack_1,
                    Backpack_2 = player.backpack_2,

                    HeroLevel = player.level,
                    Kills     = player.kills,
                    Deaths    = player.deaths,
                    Assists   = player.assists,

                    LastHits = player.last_hits ?? 0,
                    Denies   = player.denies ?? 0,

                    GoldPerMin = player.gold_per_min ?? 0,
                    XpPerMin   = player.xp_per_min ?? 0,

                    HeroDamage  = player.hero_damage ?? 0,
                    HeroHealing = player.hero_healing ?? 0,
                    TowerDamage = player.tower_damage ?? 0,

                    Abilities = new HashSet <Dota2HeroStats.Models.Ability>()
                };

                //Lookup heroid in database to see if it already exists and if so retrieve it.
                var hero = await LookupHero(player.hero_id);

                if (hero != null)
                {
                    p.Hero = hero;
                }
                else
                {
                    p.Hero = new Hero
                    {
                        HeroId        = player.hero_id,
                        Name          = "unknown",
                        LocalizedName = "unknown",
                        PrimaryAttr   = "unknown",
                        AttackType    = "unknown",
                        Legs          = 0,
                        Roles         = new HashSet <Role>()
                    };
                }
                //Lookup and add each ability if it exists.
                if (player.ability_upgrades_arr != null)//some older matches dont have a record of these and will be null.
                {
                    var distinctAbilities = player.ability_upgrades_arr.Distinct();
                    foreach (int abilityId in distinctAbilities)
                    {
                        var ability = await LookupAbility(abilityId);

                        if (ability != null)
                        {
                            p.Abilities.Add(ability);
                        }
                        else
                        {
                            p.Abilities.Add(new Ability
                            {
                                AbilityId  = abilityId,
                                Name       = "unknown",
                                Img        = "unknown",
                                IsUltimate = false
                            });
                        }
                    }
                }
                match.Players.Add(p);
            }
            return(match);
        }
Exemplo n.º 6
0
 private static bool PlayerWonMatch(AbilityDraftMatch match, Player player)
 {
     return((match.RadiantWin && player.IsRadiant) || (!match.RadiantWin && !player.IsRadiant));
 }
Exemplo n.º 7
0
 public async Task UpdateStats(AbilityDraftMatch match)
 {
     await Task.WhenAll(StatUpdaters.Select(updater => updater.UpdateStats(match)).ToArray());
 }
Exemplo n.º 8
0
 public static AbilityDraftMatchDataTransferObject CreateAbilityDraftMatchDataTransferObject(AbilityDraftMatch match)
 {
     return(new AbilityDraftMatchDataTransferObject
     {
         MatchId = match.MatchId,
         StartTime = match.StartTime,
         DurationSeconds = match.DurationSeconds,
         ServerCluster = match.ServerCluster,
         PatchNumber = match.PatchNumber,
         SkillLevel = match.SkillLevel,
         GameMode = match.GameMode,
         DireKillScore = match.DireKillScore,
         RadiantKillScore = match.RadiantKillScore,
         RadiantWin = match.RadiantWin,
         Players = match.Players.Select(p => PlayerDataTransferObject.CreatePlayerDataTransferObject(p)).ToList()
     });
 }