public GameStats(LogData log) { id = log.id; Date = log.GameStartDate; Map = log.Map; Length = log.GameLength; if (log.Spectated) { Player = "(Spectator)"; } else if (log.PlayerName == "") { Player = "(Unknown)"; } else { Player = log.PlayerName; } Server = log.Server; BlueTeam = String.Join(", ", log.BlueTeam.Select((x) => x.Name).ToArray()); PurpleTeam = String.Join(", ", log.PurpleTeam.Select((x) => x.Name).ToArray()); if (log.Spectated) { Result = "(Spectated)"; } else { Result = log.ExitCode.ToString().ToLower(); Result = Result.Substring(0, 1).ToUpper() + Result.Substring(1); if (Result == "Unknown") { Result = "(" + Result + ")"; } else if (log.BotGame) { Result += " (vs AI)"; } } }
private bool CriteriaSatisfied(LogData game, List<List<Summoner>> criteria) { if (TeamSatisfies(game.PlayerName, game.BlueTeam, criteria[0]) && (criteria.Count == 1 || TeamSatisfies(game.PlayerName, game.PurpleTeam, criteria[1]))) { return true; } if (TeamSatisfies(game.PlayerName, game.PurpleTeam, criteria[0]) && (criteria.Count == 1 || TeamSatisfies(game.PlayerName, game.BlueTeam, criteria[1]))) { return true; } return false; }
public GameDetails(LogData game, Main form) { mainForm = form; InitializeComponent(); Game = game; headerLabel.Text = String.Format("{0}, {1}v{2}{3}", Game.Map, Game.BlueTeam.Count, Game.PurpleTeam.Count, Game.BotGame ? " (Co-op vs. AI)" : ""); switch (Game.ExitCode) { case LogData.ExitCodes.WIN: resultLabel.Text = "VICTORY"; resultLabel.BackColor = Color.LimeGreen; resultLabel.ForeColor = Color.White; break; case LogData.ExitCodes.LOSE: resultLabel.Text = "DEFEAT"; resultLabel.BackColor = Color.Tomato; resultLabel.ForeColor = Color.Black; break; case LogData.ExitCodes.CRASH: resultLabel.Text = "CRASH"; resultLabel.BackColor = Color.Red; resultLabel.ForeColor = Color.White; break; case LogData.ExitCodes.UNKNOWN: resultLabel.Text = "UNKNOWN"; resultDisclaimer.SetToolTip(resultLabel, "Game result was not logged in this client version."); resultLabel.BackColor = Color.Silver; resultLabel.ForeColor = Color.Black; break; case LogData.ExitCodes.LEAVE: resultLabel.Text = "LEAVE"; resultLabel.BackColor = Color.Yellow; resultLabel.ForeColor = Color.Black; break; } if (Game.Spectated) { resultLabel.Text = "SPECTATED"; resultLabel.BackColor = Color.SlateBlue; resultLabel.ForeColor = Color.White; deathsLabel.Text = "You spectated this game."; } else { string msg = ""; if (Game.Deaths.Count > 7) { msg = " (Feeder!)"; } else if (Game.Deaths.Count == 0) { msg = " (Nice!)"; } deathsLabel.Text = String.Format("You had {0} death{1} this game. {2}", Game.Deaths.Count, Game.Deaths.Count == 1 ? "" : "s", msg); if (Game.Deaths.Count > 0) { deathsLabel.LinkArea = new LinkArea("You had ".Length, Game.Deaths.Count.ToString().Length); } } dateLabel.Text = String.Format("Played on {0}{1} (version {2})", Game.GameStartDate.ToString(@"MMM d, yyyy h:mm tt"), Game.Server == "" ? "" : " on " + Game.Server, Game.GameVersion); lengthLabel.Text = String.Format("Game length: {0}:{1:d2}", Game.GameLength/60, Game.GameLength%60); foreach (var summoner in Game.BlueTeam) { AddSummoner(summoner, blueTeamFlow, true, summoner.Name == Game.PlayerName); } foreach (var summoner in Game.PurpleTeam) { AddSummoner(summoner, purpleTeamFlow, false, summoner.Name == Game.PlayerName); } // for Hexakill if (Game.BlueTeam.Count > 5 || Game.PurpleTeam.Count > 5) { this.Height += 22; } }
public LogData ParseLog(string filename) { try { var file = File.Open(filename, FileMode.Open); var bs = new BufferedStream(file); var stream = new StreamReader(bs); var summonerMap = new Dictionary<string, int>(); int netUID = -2; var mergedTeam = new List<Summoner>(); double startTime = -1, lastTimeStamp = -1; bool disconnect = false; DateTime startDate = new DateTime(); Match match; var ret = new LogData(); ret.LogFile = filename; string line; string gameMode = ""; HashSet<string> gameMutators = new HashSet<string>(); while ((line = stream.ReadLine()) != null) { string[] parts = line.Split(new char[] {'|'}, 5, StringSplitOptions.None); if (parts.Length == 1) { // Old format e.g. --- Log started at Sun Apr 29 23:34:01 2012 match = LOG_START_REGEX1.Match(line); if (match.Success) { var parsedDate = String.Format("{0} {1}, {2} {3}", match.Groups[2].Value, // month match.Groups[3].Value, // day match.Groups[5].Value, // year match.Groups[4].Value // time ); if (!DateTime.TryParse(parsedDate, out startDate)) { Logger.LogMessage(filename + ": Invalid date in " + match.Groups[0].Value); } } } // v6.6 and above remove the excessive "Xkb added" columns. if (parts.Length != 3 && parts.Length != 5) { continue; } double timeStamp = 0; if (!double.TryParse(parts[0].Trim(), NumberStyles.Number, new CultureInfo("en-US"), out timeStamp)) { // This line is corrupted. Ignore it continue; } lastTimeStamp = timeStamp; string text = parts.Last().Substring(1); if ((match = LOG_START_REGEX2.Match(text)).Success) { if (!DateTime.TryParse(match.Groups[1].Value, out startDate)) { Logger.LogMessage(filename + ": Invalid date " + match.Groups[1].Value); } } else if ((match = GAME_ID_REGEX.Match(text)).Success) { // Obtain game ID. ret.GameID = match.Groups[1].Value; if (match.Groups[3].Success) { ret.Server = match.Groups[3].Value; } } else if ((match = BUILD_REGEX.Match(text)).Success) { // game version ret.GameVersion = new Version(match.Groups[1].Value); } else if ((match = MAP_REGEX.Match(text)).Success) { // Obtain map ID int mapID = int.Parse(match.Groups[1].Value); if (!MapDictionary.TryGetValue(mapID, out ret.Map)) { ret.Map = "Unknown Map"; } } else if ((match = NET_UID_REGEX.Match(text)).Success) { // client's ID netUID = int.Parse(match.Groups[1].Value); } else if (text.Contains("Started ReplayDownloadManager")) { // indicates that this was a spectated game. ret.Spectated = true; } else if (text == "GAMESTATE_GAMELOOP Begin") { // this indicates the game actually loaded. startTime = timeStamp; Debug.Assert(!startDate.Equals(new DateTime()), "Game started with undefined start date"); ret.GameStartDate = startDate.AddSeconds(startTime); } else if ((match = KILLER_REGEX.Match(text)).Success && !ret.Spectated) { var killer = match.Groups[1].Value; if (summonerMap.ContainsKey(killer)) { ret.Deaths.Add(summonerMap[killer]); } else { // Most likely tower or minion. ret.Deaths.Add(-1); } } else if (text == "Disconnected") { disconnect = true; } else if (text == "End game message processing!") { // indicates game end. ret.GameLength = (int) (timeStamp - startTime + 0.5); disconnect = false; } else if (text == "Finished Play game" && ret.GameLength == 0) { // The end game message always comes first. If it didn't, that means we forcibly left the game. ret.GameLength = (int) (timeStamp - startTime + 0.5); ret.ExitCode = LogData.ExitCodes.LEAVE; } else if ((match = EXITCODE_REGEX.Match(text)).Success) { switch (match.Groups[1].Value) { case "WIN": ret.ExitCode = LogData.ExitCodes.WIN; break; case "LOSE": ret.ExitCode = LogData.ExitCodes.LOSE; break; case "ABANDON": ret.ExitCode = LogData.ExitCodes.LEAVE; break; } } else if ((match = GAME_MODE_REGEX.Match(text)).Success) { gameMode = match.Groups[1].Value.ToLower(); } else if ((match = GAME_MUTATOR_REGEX.Match(text)).Success) { gameMutators.Add(match.Groups[1].Value.ToLower()); } else if (text.Contains("TwistedAura.dds")) { ret.Map = "Twisted Treeline"; // 3v3 doesn't have a special game mode, but this texture gets loaded } else if (text.Contains(" SRUAP_")) { ret.Map = "Summoner's Rift (New)"; } else { if (ret.GameVersion >= CLIENT_ID_VERSION) { match = CHAMPION_REGEX1.Match(text); if (match.Success) { var summoner = new Summoner() { Champion = FixChampionName(match.Groups[1].Value), SkinID = int.Parse(match.Groups[2].Value), Name = match.Groups[5].Value }; var teamID = int.Parse(match.Groups[3].Value); var clientID = int.Parse(match.Groups[4].Value); if (clientID == -1) { ret.BotGame = true; summoner.IsBot = true; } List<Summoner> team = (teamID == 100 ? ret.BlueTeam : ret.PurpleTeam); if (!summonerMap.ContainsKey(summoner.Name)) { team.Add(summoner); summonerMap[summoner.Name] = summonerMap.Count; } if (!ret.Spectated && clientID == netUID) { ret.PlayerName = summoner.Name; } } } else { match = CHAMPION_REGEX2.Match(text); if (match.Success) { var summoner = new Summoner() { Champion = FixChampionName(match.Groups[1].Value), Name = match.Groups[4].Value }; if (match.Groups[3].Success) { summoner.SkinID = int.Parse(match.Groups[3].Value); } else { summoner.SkinID = -1; } // Guess the team.. might not be accurate for 1v5 bot games and such. if (!summonerMap.ContainsKey(summoner.Name)) { mergedTeam.Add(summoner); summonerMap[summoner.Name] = summonerMap.Count; } } } } } if (ret.Map == null) { if (gameMode == "classic") { ret.Map = "Summoner's Rift"; if (gameMutators.Contains("urf")) { ret.Map += " (URF)"; } } else if (gameMode == "aram") { ret.Map = "Howling Abyss"; } else if (gameMode == "odin") { ret.Map = "Crystal Scar"; } else if (gameMode == "ascension") { ret.Map = "Crystal Scar (Ascension)"; } } // Overrides existing Twisted Treeline detection. if (gameMutators.Contains("6v6")) { ret.Map = "Twisted Treeline (Hexakill)"; } if (startTime == -1) { return null; // Game crashed before loading. } if (ret.GameLength == 0) { // Game crashed in the middle somewhere. ret.GameLength = (int) (lastTimeStamp - startTime + 0.5); ret.ExitCode = LogData.ExitCodes.CRASH; } if (disconnect) { ret.ExitCode = LogData.ExitCodes.CRASH; } if (mergedTeam.Count > 0) { // Assume half the players are on both teams. Doesn't account for uneven teams, of course.. int l = (mergedTeam.Count + 1)/2; ret.BlueTeam = mergedTeam.Take(l).ToList(); ret.PurpleTeam = mergedTeam.Skip(l).ToList(); if (ret.BlueTeam.All((x) => x.Name.EndsWith(" Bot")) || ret.PurpleTeam.All((x) => x.Name.EndsWith(" Bot"))) { ret.BotGame = true; } } return ret; } catch (Exception ex) { Logger.LogException(ex); return null; } }
public void AddGame(LogData data) { Games++; TimePlayed += data.GameLength; if (Name == data.PlayerName) { GamesAs++; } if (!String.IsNullOrEmpty(data.Server)) { Server = data.Server; } int resultTeam = data.BlueTeam.FindIndex(x => x.Name == data.PlayerName) >= 0 ? 0 : 1; int myTeam = data.BlueTeam.FindIndex(x => x.Name == Name) >= 0 ? 0 : 1; if (!String.IsNullOrEmpty(data.PlayerName) && data.PlayerName != Name) { if (myTeam == resultTeam) { GamesWith++; } else { GamesAgainst++; } } var summoner = (myTeam == 0 ? data.BlueTeam : data.PurpleTeam).Find(x => x.Name == Name); if (!ChampStats.ContainsKey(summoner.Champion)) { ChampStats[summoner.Champion] = new ChampionStats() { Name = summoner.Champion }; } var cs = ChampStats[summoner.Champion]; cs.Games++; if (Name == data.PlayerName && !data.BotGame) { cs.DeathGames++; cs.Deaths += data.Deaths.Count; } if ((data.ExitCode == LogData.ExitCodes.WIN || data.ExitCode == LogData.ExitCodes.LOSE) && !data.Spectated && !data.BotGame) { Debug.Assert(data.PlayerName != ""); bool gameResult = data.ExitCode == LogData.ExitCodes.WIN; if (data.PlayerName == Name) { if (gameResult) { WinsAs++; } else { LossesAs++; } } else if (myTeam != resultTeam) { gameResult = !gameResult; } else { if (gameResult) { WinsWith++; } else { LossesWith++; } } if (gameResult) { KnownWins++; cs.Wins++; } else { KnownLosses++; cs.Losses++; } } }