private IEnumerable <MonsterBehavior> GetMonsterBehaviorsFromLines(IReadOnlyList <string> behaviorLines, MonsterBehaviorType behaviorType) { var monsterBehaviors = new List <MonsterBehavior>(); List <int> behaviorLinesIndexes; if (behaviorType == MonsterBehaviorType.Legendary) { behaviorLinesIndexes = Enumerable.Range(0, behaviorLines.Count) .Where(i => behaviorLines[i].StartsWith("> **") || behaviorLines[i].StartsWith(">**")) .ToList(); } else { behaviorLinesIndexes = Enumerable.Range(0, behaviorLines.Count) .Where(i => behaviorLines[i].StartsWith("> ***") || behaviorLines[i].StartsWith(">***")) .ToList(); } for (var i = 0; i < behaviorLinesIndexes.Count; i++) { List <string> singleBehaviorLines; if (i + 1 < behaviorLinesIndexes.Count) { singleBehaviorLines = behaviorLines.Skip(behaviorLinesIndexes[i]) .Take(behaviorLinesIndexes[i + 1] - behaviorLinesIndexes[i]).ToList(); } else { singleBehaviorLines = behaviorLines.Skip(behaviorLinesIndexes[i]).ToList(); } if (behaviorType == MonsterBehaviorType.Legendary) { var baseLine = singleBehaviorLines.First(b => b.StartsWith("> **") || b.StartsWith(">**")); var baseLineSplit = baseLine.Split(new[] { "**", "**" }, StringSplitOptions.None); var parenIndex = baseLineSplit[1].IndexOf('('); var name = baseLineSplit[1].Trim().Replace(".", string.Empty); string restrictions = null; if (parenIndex != -1) { name = baseLineSplit[1].Remove(parenIndex).Trim(); var restrictionsSplit = baseLine.Split('(', ')'); if (restrictionsSplit.ElementAtOrDefault(1) != null) { restrictions = restrictionsSplit[1].Trim(); } } var descriptionFinal = string .Join(" ", new List <string>(singleBehaviorLines.Skip(1)) { baseLine.Split("**")[2].Trim() }) .RemoveMarkdownCharacters(); var monsterBehavior = new MonsterBehavior { MonsterBehaviorTypeEnum = behaviorType, Name = name.RemoveMarkdownCharacters(), Description = descriptionFinal, DescriptionWithLinks = descriptionFinal, Restrictions = restrictions }; monsterBehaviors.Add(monsterBehavior); } else { var baseLine = singleBehaviorLines.First(b => b.StartsWith("> **") || b.StartsWith(">**")); var description = singleBehaviorLines.Skip(1).ToList(); description.Insert(0, baseLine.Split("***")[2].Trim()); var baseLineSplit = baseLine.Split(new[] { "***", "***" }, StringSplitOptions.None); var parenIndex = baseLineSplit[1].IndexOf('('); var name = baseLineSplit[1].Trim().Replace(".", string.Empty); string restrictions = null; if (parenIndex != -1) { name = baseLineSplit[1].Remove(parenIndex).Trim(); var restrictionsSplit = baseLine.Split('(', ')'); if (restrictionsSplit.ElementAtOrDefault(1) != null) { restrictions = restrictionsSplit[1].Trim(); } } var descriptionFinal = string .Join(" ", new List <string>(singleBehaviorLines.Skip(1)) { baseLine.Split("**")[2].Trim() }) .RemoveMarkdownCharacters(); var descriptionWithLinks = descriptionFinal; var castingLevels = new List <string> { Localization.AtWill, Localization.FirstLevel, Localization.SecondLevel, Localization.ThirdLevel, Localization.FourthLevel, Localization.FifthLevel, Localization.SixthLevel, Localization.SeventhLevel, Localization.EighthLevel, Localization.NinthLevel }; castingLevels.AddRange(castingLevels.Select(c => c.Replace(' ', '-')).ToList()); if (name.Contains("casting", StringComparison.InvariantCultureIgnoreCase)) { var lines = new List <string>(singleBehaviorLines); for (var j = 0; j < lines.Count; j++) { var c = castingLevels.FirstOrDefault(c => Regex.IsMatch(lines[j], @"^>\s*.*:", RegexOptions.IgnoreCase)); if (c != null) { var powerLineSplit = lines[j].Split(':'); var powers = powerLineSplit[1].RemoveMarkdownCharacters().Split(',') .Select(s => s.Trim()); var powersUpdated = new List <string>(); foreach (var power in powers) { powersUpdated.Add($"[{power}](#{Uri.EscapeUriString(power)})"); } lines[j] = $"{powerLineSplit[0]}: *{string.Join(", ", powersUpdated)}*"; } } descriptionWithLinks = string .Join("\r\n", lines) .RemoveMarkdownCharacters(); } var monsterBehavior = new MonsterBehavior { MonsterBehaviorTypeEnum = behaviorType, Name = name.RemoveMarkdownCharacters(), Description = descriptionFinal, DescriptionWithLinks = descriptionWithLinks, Restrictions = restrictions }; if (Regex.IsMatch(baseLine.Split("***")[2].Trim(), @"\*.+\*")) { if (behaviorType == MonsterBehaviorType.Action) { if (baseLine.Split("***")[2].Trim().Contains($"*{Localization.melee}", StringComparison.InvariantCultureIgnoreCase)) { monsterBehavior.AttackTypeEnum = AttackType.MeleeWeapon; } else if (baseLine.Split("***")[2].Trim().Contains($"*{Localization.ranged}", StringComparison.InvariantCultureIgnoreCase)) { monsterBehavior.AttackTypeEnum = AttackType.RangedWeapon; } else { monsterBehavior.AttackTypeEnum = AttackType.None; } var attackSplit = baseLine.Split("***")[2].Trim().Split(',').Select(s => s.Trim()).ToList(); var hitSplit = Regex.Split(baseLine.Split("***")[2].Trim(), Localization.MonsterHitSplitPattern); var hitCommaSplit = hitSplit.SafeAccess(0)?.Split(',')?.ToList() ?? new List <string>(); var hitSpaceSplit = hitSplit.SafeAccess(1)?.Split(' ')?.ToList() ?? new List <string>(); var didParseAttBonus = int.TryParse(Regex.Match(attackSplit[0], @"-?\d+").Value, out var parsedAttBonus); monsterBehavior.AttackBonus = didParseAttBonus ? parsedAttBonus : 0; monsterBehavior.Range = attackSplit.ToArray().SafeAccess(1)?.Trim() ?? ""; monsterBehavior.NumberOfTargets = hitCommaSplit.ToArray().SafeAccess(2)?.Trim(); if (Regex.IsMatch(hitSplit.SafeAccess(1)?.Trim() ?? string.Empty, @"^\d+.*\(.*\)")) { monsterBehavior.Damage = Regex.Match(hitSplit.SafeAccess(1) ?? string.Empty, @"-?\d+").Value.Trim(); monsterBehavior.DamageRoll = hitSplit.SafeAccess(1)?.Split('(', ')').ElementAtOrDefault(1)?.Trim(); if (hitSpaceSplit.FindIndex(f => f.Contains(Localization.damage, StringComparison.InvariantCultureIgnoreCase)) != -1) { if (Enum.TryParse(hitSpaceSplit[hitSpaceSplit.FindIndex(f => f.Contains(Localization.damage, StringComparison.InvariantCultureIgnoreCase)) - 1], true, out DamageType damageType) && Enum.IsDefined(typeof(DamageType), damageType)) { monsterBehavior.DamageTypeEnum = damageType; } else { monsterBehavior.DamageTypeEnum = DamageType.Unknown; } } } } } monsterBehaviors.Add(monsterBehavior); } } return(monsterBehaviors); }
private IEnumerable <MonsterBehavior> GetMonsterBehaviorsFromLines(IReadOnlyList <string> behaviorLines, MonsterBehaviorType behaviorType) { var monsterBehaviors = new List <MonsterBehavior>(); List <int> behaviorLinesIndexes; if (behaviorType == MonsterBehaviorType.Legendary) { behaviorLinesIndexes = Enumerable.Range(0, behaviorLines.Count) .Where(i => behaviorLines[i].StartsWith("> **") || behaviorLines[i].StartsWith(">**")) .ToList(); } else { behaviorLinesIndexes = Enumerable.Range(0, behaviorLines.Count) .Where(i => behaviorLines[i].StartsWith("> ***") || behaviorLines[i].StartsWith(">***")) .ToList(); } for (var i = 0; i < behaviorLinesIndexes.Count; i++) { List <string> singleBehaviorLines; if (i + 1 < behaviorLinesIndexes.Count) { singleBehaviorLines = behaviorLines.Skip(behaviorLinesIndexes[i]) .Take(behaviorLinesIndexes[i + 1] - behaviorLinesIndexes[i]).ToList(); } else { singleBehaviorLines = behaviorLines.Skip(behaviorLinesIndexes[i]).ToList(); } if (behaviorType == MonsterBehaviorType.Legendary) { var baseLine = singleBehaviorLines.First(b => b.StartsWith("> **") || b.StartsWith(">**")); var baseLineSplit = baseLine.Split(new[] { "**", "**" }, StringSplitOptions.None); var parenIndex = baseLineSplit[1].IndexOf('('); var name = baseLineSplit[1].Trim().Replace(".", string.Empty); string restrictions = null; if (parenIndex != -1) { name = baseLineSplit[1].Remove(parenIndex).Trim(); var restrictionsSplit = baseLine.Split('(', ')'); if (restrictionsSplit.ElementAtOrDefault(1) != null) { restrictions = restrictionsSplit[1].Trim(); } } var monsterBehavior = new MonsterBehavior { MonsterBehaviorTypeEnum = behaviorType, Name = name.RemoveMarkdownCharacters(), Description = string .Join(" ", new List <string>(singleBehaviorLines.Skip(1)) { baseLine.Split("**")[2].Trim() }) .RemoveMarkdownCharacters(), Restrictions = restrictions }; monsterBehaviors.Add(monsterBehavior); } else { var baseLine = singleBehaviorLines.First(b => b.StartsWith("> **") || b.StartsWith(">**")); var description = singleBehaviorLines.Skip(1).ToList(); description.Insert(0, baseLine.Split("***")[2].Trim()); var baseLineSplit = baseLine.Split(new[] { "***", "***" }, StringSplitOptions.None); var parenIndex = baseLineSplit[1].IndexOf('('); var name = baseLineSplit[1].Trim().Replace(".", string.Empty); string restrictions = null; if (parenIndex != -1) { name = baseLineSplit[1].Remove(parenIndex).Trim(); var restrictionsSplit = baseLine.Split('(', ')'); if (restrictionsSplit.ElementAtOrDefault(1) != null) { restrictions = restrictionsSplit[1].Trim(); } } var monsterBehavior = new MonsterBehavior { MonsterBehaviorTypeEnum = behaviorType, Name = name, Description = string.Join(" ", description).RemoveMarkdownCharacters(), Restrictions = restrictions }; if (Regex.IsMatch(baseLine.Split("***")[2].Trim(), @"\*.+\*")) { if (behaviorType == MonsterBehaviorType.Action) { if (baseLine.Split("***")[2].Trim().Contains($"*{Localization.melee}", StringComparison.InvariantCultureIgnoreCase)) { monsterBehavior.AttackTypeEnum = AttackType.MeleeWeapon; } else if (baseLine.Split("***")[2].Trim().Contains($"*{Localization.ranged}", StringComparison.InvariantCultureIgnoreCase)) { monsterBehavior.AttackTypeEnum = AttackType.RangedWeapon; } else { monsterBehavior.AttackTypeEnum = AttackType.None; } var attackSplit = baseLine.Split("***")[2].Trim().Split(',').Select(s => s.Trim()).ToList(); var hitSplit = Regex.Split(baseLine.Split("***")[2].Trim(), Localization.MonsterHitSplitPattern); var hitCommaSplit = hitSplit.SafeAccess(0)?.Split(',')?.ToList() ?? new List <string>(); var hitSpaceSplit = hitSplit.SafeAccess(1)?.Split(' ')?.ToList() ?? new List <string>(); var didParseAttBonus = int.TryParse(Regex.Match(attackSplit[0], @"-?\d+").Value, out var parsedAttBonus); monsterBehavior.AttackBonus = didParseAttBonus ? parsedAttBonus : 0; monsterBehavior.Range = attackSplit.ToArray().SafeAccess(1)?.Trim() ?? ""; monsterBehavior.NumberOfTargets = hitCommaSplit.ToArray().SafeAccess(2)?.Trim(); if (Regex.IsMatch(hitSplit.SafeAccess(1)?.Trim() ?? string.Empty, @"^\d+.*\(.*\)")) { monsterBehavior.Damage = Regex.Match(hitSplit.SafeAccess(1) ?? string.Empty, @"-?\d+").Value.Trim(); monsterBehavior.DamageRoll = hitSplit.SafeAccess(1)?.Split('(', ')').ElementAtOrDefault(1)?.Trim(); if (hitSpaceSplit.FindIndex(f => f.Contains(Localization.damage, StringComparison.InvariantCultureIgnoreCase)) != -1) { if (Enum.TryParse(hitSpaceSplit[hitSpaceSplit.FindIndex(f => f.Contains(Localization.damage, StringComparison.InvariantCultureIgnoreCase)) - 1], true, out DamageType damageType) && Enum.IsDefined(typeof(DamageType), damageType)) { monsterBehavior.DamageTypeEnum = damageType; } else { monsterBehavior.DamageTypeEnum = DamageType.Unknown; } } } } } monsterBehaviors.Add(monsterBehavior); } } return(monsterBehaviors); }