namespace Ficdown.Parser.Engine { using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using Model.Parser; using Model.Story; using Action = Model.Story.Action; public class BlockHandler : IBlockHandler { public IEnumerable ExtractBlocks(IEnumerable lines) { var blocks = new List(); Block currentBlock = null; foreach (var line in lines) { var match = Regex.Match(line, @"^(?#{1,3})\s+(?[^#].*)$"); if (match.Success) { if (currentBlock != null) blocks.Add(currentBlock); currentBlock = new Block() { Type = (BlockType) match.Groups["level"].Length, Name = match.Groups["name"].Value, Lines = new List() }; } else { if (currentBlock != null) currentBlock.Lines.Add(line); } } if (currentBlock != null) blocks.Add(currentBlock); return blocks; } public Story ParseBlocks(IEnumerable blocks) { // get the story var storyBlock = blocks.Single(b => b.Type == BlockType.Story); var storyName = RegexLib.Anchors.Match(storyBlock.Name); if (!storyName.Success) throw new FormatException("Story name must be a link to the first scene."); var story = new Story { Name = storyName.Groups["text"].Value, Description = string.Join("\n", storyBlock.Lines).Trim(), Scenes = new Dictionary>(), States = new Dictionary>() }; var scenes = blocks.Where(b => b.Type == BlockType.Scene).Select(b => BlockToScene(b)); foreach (var scene in scenes) { var key = Utilities.NormalizeString(scene.Name); if (!story.Scenes.ContainsKey(key)) story.Scenes.Add(key, new List()); story.Scenes[key].Add(scene); } return story; } private Scene BlockToScene(Block block) { var scene = new Scene { Description = string.Join("\n", block.Lines).Trim() }; var sceneName = RegexLib.Anchors.Match(block.Name); if (sceneName.Success) { scene.Name = sceneName.Groups["text"].Value; } else { scene.Name = block.Name; } return scene; } } }