private void AnalyzeReplayData(int index) { _entities.Clear(); var game = _replay.Games.ElementAtOrDefault(index); if(game == null) return; var gameEntity = game.Data[0] as GameEntity; if(gameEntity == null) throw new Exception("No Game Entity"); _gameEntity = gameEntity; _entities.Add(gameEntity.Id, new Entity(gameEntity.Id, tags: gameEntity.Tags) {Name = "GameEntity"}); var p1 = game.Data[1] as PlayerEntity; if(p1 == null) throw new Exception("No Player1 Entity"); _p1Entity = p1; _entities.Add(p1.Id, new Entity(p1.Id, p1.Tags, p1.PlayerId) {Name = p1.Name}); var p2 = game.Data[2] as PlayerEntity; if(p2 == null) throw new Exception("No Player2 Entity"); _p2Entity = p2; _entities.Add(p2.Id, new Entity(p2.Id, p2.Tags, p2.PlayerId) {Name = p2.Name}); foreach(var data in game.Data.Skip(3)) AnalyzeGameData(data, Actions, 0); var localPlayer = Actions.FirstOrDefault( action => (action.GameState.Player1.Hand.All(x => !string.IsNullOrEmpty(x.CardId)) && action.GameState.Player2.Hand.All(x => string.IsNullOrEmpty(x.CardId))) || (action.GameState.Player1.Hand.All(x => string.IsNullOrEmpty(x.CardId)) && action.GameState.Player2.Hand.All(x => !string.IsNullOrEmpty(x.CardId)))); if(localPlayer == null) throw new Exception("Could not determine local player"); var p1IsLocal = localPlayer.GameState.Player1.Hand.All(x => !string.IsNullOrEmpty(x.CardId)) && localPlayer.GameState.Player2.Hand.All(x => string.IsNullOrEmpty(x.CardId)); Action gs; int count = 0; while ((gs = GetActionAtIndex(count++)) != null) { gs.GameState.LocalPlayer = p1IsLocal ? gs.GameState.Player1 : gs.GameState.Player2; gs.GameState.Opponent = p1IsLocal ? gs.GameState.Player2 : gs.GameState.Player1; } }
public static void Handle(string timestamp, string data, ParserState state) { var trimmed = data.Trim(); var indentLevel = data.Length - trimmed.Length; data = trimmed; if(state.Node != null && indentLevel <= state.Node.IndentLevel) state.Node = state.Node.Parent ?? state.Node; if(data == "CREATE_GAME") { state.CurrentGame = new Game {Data = new List<GameData>()}; state.Replay.Games.Add(state.CurrentGame); state.Node = new Node(typeof(Game), state.CurrentGame, 0, null); return; } var match = Regexes.ActionCreategameRegex.Match(data); if(match.Success) { var id = match.Groups[1].Value; Debug.Assert(id == "1"); var gEntity = new GameEntity {Id = int.Parse(id), Tags = new List<Tag>()}; state.CurrentGame.Data.Add(gEntity); state.Node = new Node(typeof(GameEntity), gEntity, indentLevel, state.Node); return; } match = Regexes.ActionCreategamePlayerRegex.Match(data); if(match.Success) { var id = match.Groups[1].Value; var playerId = match.Groups[2].Value; var accountHi = match.Groups[3].Value; var accountLo = match.Groups[4].Value; var pEntity = new PlayerEntity { Id = int.Parse(id), AccountHi = accountHi, AccountLo = accountLo, PlayerId = int.Parse(playerId), Tags = new List<Tag>() }; state.CurrentGame.Data.Add(pEntity); state.Node = new Node(typeof(PlayerEntity), pEntity, indentLevel, state.Node); return; } match = Regexes.ActionStartRegex.Match(data); if(match.Success) { var rawEntity = match.Groups[1].Value; var rawType = match.Groups[2].Value; var index = match.Groups[3].Value; var rawTarget = match.Groups[4].Value; var entity = Helper.ParseEntity(rawEntity, state); var target = Helper.ParseEntity(rawTarget, state); var type = Helper.ParseEnum<POWER_SUBTYPE>(rawType); var action = new Action { Data = new List<GameData>(), Entity = entity, Index = int.Parse(index), Target = target, //TimeStamp = timestamp, Type = type }; if(state.Node.Type == typeof(Game)) ((Game)state.Node.Object).Data.Add(action); else if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(action); else throw new Exception("Invalid node " + state.Node.Type); state.Node = new Node(typeof(Action), action, indentLevel, state.Node); return; } match = Regexes.ActionMetadataRegex.Match(data); if(match.Success) { var rawMeta = match.Groups[1].Value; var rawData = match.Groups[2].Value; var info = match.Groups[3].Value; var parsedData = Helper.ParseEntity(rawData, state); var meta = Helper.ParseEnum<METADATA_TYPE>(rawMeta); var metaData = new MetaData {Data = parsedData, Info = int.Parse(info), Meta = meta, MetaInfo = new List<Info>()}; if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(metaData); else throw new Exception("Invalid node " + state.Node.Type); state.Node = new Node(typeof(MetaData), metaData, indentLevel, state.Node); return; } match = Regexes.ActionMetaDataInfoRegex.Match(data); if(match.Success) { var index = match.Groups[1].Value; var rawEntity = match.Groups[2].Value; var entity = Helper.ParseEntity(rawEntity, state); var metaInfo = new Info {Id = entity, Index = int.Parse(index)}; if(state.Node.Type == typeof(MetaData)) ((MetaData)state.Node.Object).MetaInfo.Add(metaInfo); else throw new Exception("Invalid node " + state.Node.Type); } match = Regexes.ActionShowEntityRegex.Match(data); if(match.Success) { var rawEntity = match.Groups[1].Value; var cardId = match.Groups[2].Value; var entity = Helper.ParseEntity(rawEntity, state); var showEntity = new ShowEntity {CardId = cardId, Entity = entity, Tags = new List<Tag>()}; if(state.Node.Type == typeof(Game)) ((Game)state.Node.Object).Data.Add(showEntity); else if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(showEntity); else throw new Exception("Invalid node " + state.Node.Type); state.Node = new Node(typeof(ShowEntity), showEntity, indentLevel, state.Node); return; } match = Regexes.ActionHideEntityRegex.Match(data); if(match.Success) { var rawEntity = match.Groups[1].Value; var tagName = match.Groups[2].Value; var value = match.Groups[3].Value; var entity = Helper.ParseEntity(rawEntity, state); var tag = Helper.ParseTag(tagName, value); var hideEntity = new HideEntity {Entity = entity, TagName = tag.Name, TagValue = tag.Value}; if(state.Node.Type == typeof(Game)) ((Game)state.Node.Object).Data.Add(hideEntity); else if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(hideEntity); else throw new Exception("Invalid node: " + state.Node.Type); return; } match = Regexes.ActionFullentityRegex1.Match(data); if(!match.Success) match = Regexes.ActionFullentityRegex2.Match(data); if(match.Success) { var rawEntity = match.Groups[1].Value; var cardId = match.Groups[2].Value; var entity = Helper.ParseEntity(rawEntity, state); var showEntity = new FullEntity {CardId = cardId, Id = entity, Tags = new List<Tag>()}; if(state.Node.Type == typeof(Game)) ((Game)state.Node.Object).Data.Add(showEntity); else if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(showEntity); else throw new Exception("Invalid node " + state.Node.Type); state.Node = new Node(typeof(FullEntity), showEntity, indentLevel, state.Node); return; } match = Regexes.ActionTagChangeRegex.Match(data); if(match.Success) { var rawEntity = match.Groups[1].Value; var tagName = match.Groups[2].Value; var value = match.Groups[3].Value; var tag = Helper.ParseTag(tagName, value); if(tag.Name == (int)GAME_TAG.CURRENT_PLAYER) UpdateCurrentPlayer(state, rawEntity, tag); var entity = Helper.ParseEntity(rawEntity, state); if(tag.Name == (int)GAME_TAG.ENTITY_ID) entity = UpdatePlayerEntity(state, rawEntity, tag, entity); var tagChange = new TagChange {Entity = entity, Name = tag.Name, Value = tag.Value}; if(state.Node.Type == typeof(Game)) ((Game)state.Node.Object).Data.Add(tagChange); else if(state.Node.Type == typeof(Action)) ((Action)state.Node.Object).Data.Add(tagChange); else throw new Exception("Invalid node " + state.Node.Type); return; } match = Regexes.ActionTagRegex.Match(data); if(match.Success) { var tagName = match.Groups[1].Value; var value = match.Groups[2].Value; var tag = Helper.ParseTag(tagName, value); if(tag.Name == (int)GAME_TAG.CURRENT_PLAYER) state.FirstPlayerId = ((PlayerEntity)state.Node.Object).Id; if(state.Node.Type == typeof(GameEntity)) ((GameEntity)state.Node.Object).Tags.Add(tag); else if(state.Node.Type == typeof(PlayerEntity)) ((PlayerEntity)state.Node.Object).Tags.Add(tag); else if(state.Node.Type == typeof(FullEntity)) ((FullEntity)state.Node.Object).Tags.Add(tag); else if(state.Node.Type == typeof(ShowEntity)) ((ShowEntity)state.Node.Object).Tags.Add(tag); else throw new Exception("Invalid node " + state.Node.Type + " -- " + data); } }