/// <summary> /// Return the demo name /// </summary> /// <param name="matchInfo"></param> /// <param name="roundStats"></param> /// <returns></returns> private static string GetDemoName(CDataGCCStrike15_v2_MatchInfo matchInfo, CMsgGCCStrike15_v2_MatchmakingServerRoundStats roundStats) { return("match730_" + string.Format("{0,21:D21}", roundStats.reservationid) + "_" + string.Format("{0,10:D10}", matchInfo.watchablematchinfo.tv_port) + "_" + matchInfo.watchablematchinfo.server_ip); }
public async Task <Dictionary <string, string> > GetDemoListUrl() { Dictionary <string, string> demoUrlList = new Dictionary <string, string>(); string filePath = AppSettings.GetMatchListDataFilePath(); if (File.Exists(filePath)) { using (FileStream file = File.OpenRead(filePath)) { try { CMsgGCCStrike15_v2_MatchList matchList = Serializer.Deserialize <CMsgGCCStrike15_v2_MatchList>(file); foreach (CDataGCCStrike15_v2_MatchInfo matchInfo in matchList.matches) { // old definition if (matchInfo.roundstats_legacy != null) { CMsgGCCStrike15_v2_MatchmakingServerRoundStats roundStats = matchInfo.roundstats_legacy; await ProcessRoundStats(matchInfo, roundStats, demoUrlList); } else { // new definition List <CMsgGCCStrike15_v2_MatchmakingServerRoundStats> roundStatsList = matchInfo.roundstatsall; foreach (CMsgGCCStrike15_v2_MatchmakingServerRoundStats roundStats in roundStatsList) { await ProcessRoundStats(matchInfo, roundStats, demoUrlList); } } } } catch (Exception e) { Logger.Instance.Log(e); } } } return(demoUrlList); }
public static void CreateMatchInfo(MatchInfo match, out CDataGCCStrike15_v2_MatchInfo matchInfo, out ExtraMatchStats extraStats, System.Threading.CancellationToken cancelToken) { matchInfo = null; extraStats = null; if (match.availableOffline) { CDataGCCStrike15_v2_MatchInfo tempMatchInfo = new CDataGCCStrike15_v2_MatchInfo(); ExtraMatchStats tempExtraStats = new ExtraMatchStats(); #region File Name Data ulong reservationId = 0; bool reservationIdSpecified = false; string[] fileNameSplits = match.fileName.Split('_'); if (match.fileName.IndexOf("match730_") == 0 && fileNameSplits.Length == 4) { try { reservationId = Convert.ToUInt64(fileNameSplits[1]); reservationIdSpecified = true; WatchableMatchInfo watchablematchinfo = new WatchableMatchInfo(); watchablematchinfo.tv_port = Convert.ToUInt32(fileNameSplits[2]); watchablematchinfo.server_ip = Convert.ToUInt32(fileNameSplits[3]); tempMatchInfo.watchablematchinfo = watchablematchinfo; } catch (Exception) { } } #endregion using (FileStream fileStream = File.Open(match.GetMatchFilePath(), FileMode.Open, FileAccess.Read)) using (DemoInfo.DemoParser dp = new DemoInfo.DemoParser(fileStream)) { #region Data Analysis #region Match Info Variables int matchStartTick = 0; CMsgGCCStrike15_v2_MatchmakingServerRoundStats currentRoundStats = null; Dictionary <uint, int> totalAssists = new Dictionary <uint, int>(); Dictionary <uint, int> totalDeaths = new Dictionary <uint, int>(); Dictionary <uint, int> totalEnemyHeadshots = new Dictionary <uint, int>(); Dictionary <uint, int> totalEnemyKills = new Dictionary <uint, int>(); Dictionary <uint, int> totalKills = new Dictionary <uint, int>(); Dictionary <uint, int> totalMvps = new Dictionary <uint, int>(); Dictionary <uint, int> totalScores = new Dictionary <uint, int>(); List <List <DemoInfo.Player> > playerTeams = new List <List <DemoInfo.Player> >(); //List<uint> accountIds = new List<uint>(); int[] totalTeamScore = new int[2]; #endregion Action <uint> AddPlayerToCurrentRound = (accountId) => { currentRoundStats.reservation.account_ids.Add(accountId); currentRoundStats.assists.Add(0); currentRoundStats.deaths.Add(0); currentRoundStats.enemy_headshots.Add(0); currentRoundStats.enemy_kills.Add(0); currentRoundStats.kills.Add(0); currentRoundStats.mvps.Add(0); currentRoundStats.scores.Add(0); }; Func <uint, int> GetPlayerIndex = (accountId) => { int playerIndex = currentRoundStats.reservation.account_ids.IndexOf(accountId); if (playerIndex < 0) { AddPlayerToCurrentRound(accountId); playerIndex = currentRoundStats.reservation.account_ids.Count - 1; } return(playerIndex); }; EventHandler <DemoInfo.MatchStartedEventArgs> matchStartedHandler = (obj, msea) => { matchStartTick = dp.CurrentTick; foreach (var player in dp.PlayerInformations) { if (player != null && player.SteamID > 0) { uint accountId = new SteamKit2.SteamID((ulong)player.SteamID).AccountID; #region Extra Stats Data tempExtraStats.accountIds.Add(accountId); tempExtraStats.playerNames.Add(player.Name); #endregion var teamToAddTo = playerTeams.Find((team) => team.Exists((teamPlayer) => teamPlayer.Team == player.Team)); if (teamToAddTo == null) { teamToAddTo = new List <DemoInfo.Player>(); playerTeams.Add(teamToAddTo); } teamToAddTo.Add(player); } } }; EventHandler <DemoInfo.RoundStartedEventArgs> roundStartedHandler = (obj, rsea) => { #region Match Info Data currentRoundStats = new CMsgGCCStrike15_v2_MatchmakingServerRoundStats(); tempMatchInfo.roundstatsall.Add(currentRoundStats); currentRoundStats.team_scores.AddRange(totalTeamScore); CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve reservation = new CMsgGCCStrike15_v2_MatchmakingGC2ServerReserve(); currentRoundStats.reservation = reservation; foreach (var player in dp.PlayerInformations) { if (player != null && player.SteamID > 0) { AddPlayerToCurrentRound(new SteamKit2.SteamID((ulong)player.SteamID).AccountID); } } #endregion #region Extra Stats Data tempExtraStats.roundStartTicks.Add(dp.CurrentTick); #endregion }; EventHandler <DemoInfo.PlayerKilledEventArgs> playerKilledHandler = (obj, pkea) => { if (currentRoundStats != null) { if (pkea.Victim?.SteamID > 0) { uint victimAccountId = new SteamKit2.SteamID((ulong)pkea.Victim.SteamID).AccountID; int victimIndex = GetPlayerIndex(victimAccountId); UnityEngine.Debug.Assert(victimIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + victimIndex + " accountId: " + victimAccountId + " name " + pkea.Victim.Name); if (victimIndex > -1) { if (!totalDeaths.ContainsKey(victimAccountId)) { totalDeaths[victimAccountId] = 0; } currentRoundStats.deaths[victimIndex] = ++totalDeaths[victimAccountId]; } } if (pkea.Killer?.SteamID > 0) { uint killerAccountId = new SteamKit2.SteamID((ulong)pkea.Killer.SteamID).AccountID; int killerIndex = GetPlayerIndex(killerAccountId); UnityEngine.Debug.Assert(killerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + killerIndex + " accountId: " + killerAccountId + " name " + pkea.Killer.Name); if (killerIndex > -1) { if (!totalKills.ContainsKey(killerAccountId)) { totalKills[killerAccountId] = 0; } currentRoundStats.kills[killerIndex] = ++totalKills[killerAccountId]; bool enemyKill = pkea.Victim.TeamID != pkea.Killer.TeamID; if (!totalEnemyKills.ContainsKey(killerAccountId)) { totalEnemyKills[killerAccountId] = 0; } currentRoundStats.enemy_kills[killerIndex] += enemyKill ? ++totalEnemyKills[killerAccountId] : 0; if (!totalEnemyHeadshots.ContainsKey(killerAccountId)) { totalEnemyHeadshots[killerAccountId] = 0; } currentRoundStats.enemy_headshots[killerIndex] += enemyKill && pkea.Headshot ? ++totalEnemyHeadshots[killerAccountId] : 0; } } if (pkea.Assister?.SteamID > 0) { uint assisterAccountId = new SteamKit2.SteamID((ulong)pkea.Assister.SteamID).AccountID; int assisterIndex = GetPlayerIndex(assisterAccountId); UnityEngine.Debug.Assert(assisterIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + assisterIndex + " accountId: " + assisterAccountId + " name " + pkea.Assister.Name); if (assisterIndex > -1) { if (!totalAssists.ContainsKey(assisterAccountId)) { totalAssists[assisterAccountId] = 0; } currentRoundStats.assists[assisterIndex] = ++totalAssists[assisterAccountId]; } } } }; EventHandler <DemoInfo.RoundMVPEventArgs> roundMVPHandler = (obj, rmea) => { if (rmea.Player?.SteamID > 0) { uint playerAccountId = new SteamKit2.SteamID((ulong)rmea.Player.SteamID).AccountID; if (!totalMvps.ContainsKey(playerAccountId)) { totalMvps[playerAccountId] = 0; } int playerIndex = GetPlayerIndex(playerAccountId); UnityEngine.Debug.Assert(playerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + playerIndex + " accountId: " + playerAccountId + " name " + rmea.Player.Name); if (playerIndex > -1 && playerIndex < currentRoundStats.mvps.Count) { currentRoundStats.mvps[playerIndex] = ++totalMvps[playerAccountId]; } } }; EventHandler <DemoInfo.RoundEndedEventArgs> roundEndedHandler = (obj, reea) => { #region Match Info Data Debug.Assert(currentRoundStats != null, "How can you end a round without starting it!? @tick " + dp.CurrentTick); if (currentRoundStats != null) { if (reea.Winner != DemoInfo.Team.Spectate) { int teamIndex = playerTeams.FindIndex((team) => team[0].Team == reea.Winner); if (teamIndex > -1 && teamIndex < totalTeamScore.Length) { currentRoundStats.team_scores[teamIndex] = ++totalTeamScore[teamIndex]; } } currentRoundStats.match_duration = (int)((dp.CurrentTick - matchStartTick) * dp.TickTime); foreach (var player in dp.PlayerInformations) { if (player != null && player.SteamID > 0) { uint playerAccountId = new SteamKit2.SteamID((ulong)player.SteamID).AccountID; int playerIndex = GetPlayerIndex(playerAccountId); Debug.Assert(playerIndex > -1, "How do we not have this player yet?? @tick " + dp.CurrentTick + " index: " + playerIndex + " accountId: " + playerAccountId + " name " + player.Name); currentRoundStats.scores[playerIndex] = player.AdditionaInformations.Score; } } } #endregion #region Extra Stats Data tempExtraStats.roundEndTicks.Add(dp.CurrentTick); tempExtraStats.roundWinner.Add((int)reea.Winner); #endregion }; #endregion dp.MatchStarted += matchStartedHandler; dp.RoundStart += roundStartedHandler; dp.PlayerKilled += playerKilledHandler; dp.RoundMVP += roundMVPHandler; dp.RoundEnd += roundEndedHandler; dp.ParseHeader(); while (dp.ParseNextTick() && !cancelToken.IsCancellationRequested) { match.infoProgress = dp.CurrentTick / (float)dp.Header.PlaybackFrames; } dp.MatchStarted -= matchStartedHandler; dp.RoundStart -= roundStartedHandler; dp.PlayerKilled -= playerKilledHandler; dp.RoundMVP -= roundMVPHandler; dp.RoundEnd -= roundEndedHandler; #region Last round stats if (reservationIdSpecified) { currentRoundStats.reservationid = reservationId; } currentRoundStats.reservation.game_type = (uint)(GameType)Enum.Parse(typeof(GameType), dp.Map); if (totalTeamScore[0] != totalTeamScore[1]) { var winningTeam = (DemoInfo.Team)currentRoundStats.round_result; currentRoundStats.match_result = (winningTeam == DemoInfo.Team.Terrorist ? 1 : 2); //1 is CT, 2 is T. I do the switching because of team switching at half } else { currentRoundStats.match_result = 0; } #endregion } if (cancelToken.IsCancellationRequested) { tempMatchInfo = null; tempExtraStats = null; } matchInfo = tempMatchInfo; extraStats = tempExtraStats; } }
/// <summary> /// Check if the round stats contains useful information and in this case do the work /// 1. Check if the demo archive is still available /// 2. Create the .info file /// 3. Add the demo to the download list /// </summary> /// <param name="matchInfo"></param> /// <param name="roundStats"></param> /// <param name="demoUrlList"></param> /// <returns></returns> private async Task ProcessRoundStats(CDataGCCStrike15_v2_MatchInfo matchInfo, CMsgGCCStrike15_v2_MatchmakingServerRoundStats roundStats, Dictionary <string, string> demoUrlList) { string demoName = GetDemoName(matchInfo, roundStats); if (roundStats.reservationid != 0 && roundStats.map != null) { if (await IsDownloadRequired(demoName, roundStats.map)) { if (SerializeMatch(matchInfo, demoName)) { demoUrlList.Add(demoName, roundStats.map); } } } }
private static void ProcessRoundStats(CDataGCCStrike15_v2_MatchInfo matchInfo, CMsgGCCStrike15_v2_MatchmakingServerRoundStats roundStats, Dictionary <string, string> demoUrlList) { var demoName = GetDemoName(matchInfo, roundStats); if (roundStats.reservationid != 0 && roundStats.map != null) { demoUrlList.Add(demoName, roundStats.map); } }