public static string ReplaceInLineConditionals(string text, List <FlagValue> flags) { var conditionBoundsPattern = @"\{([^\~\{]*?)\:([^\{]*?)(\|([^\{]*?))?\}"; var orPattern = @"(^\s*|\s*$)"; var andPattern = @"\s*(&&|\band\b)\s*"; var notPattern = @"\s*(\!|\bnot\b)\s*(.+?)\s*$"; var count = 0; var matches = Regex.Matches(text, conditionBoundsPattern); foreach (Match match in matches) { count++; if (count > 1000) { throw new System.Exception("Error in conditional!"); } if (matches.Count > 0) { var conditions = new List <string> (); var notConditions = new List <string> (); // Search "and" conditions var conditionMatches = Regex.Split(match.Groups [1].Value, andPattern); for (var i = 0; i < conditionMatches.Length; i++) { // Is not an "and" condition if (conditionMatches [i] != "&&" && conditionMatches [i] != "and") { // Search "not" conditions var notPatternMatches = Regex.Match(conditionMatches [i], notPattern); // Is a "not condition" if (notPatternMatches.Success) { notConditions.Add(notPatternMatches.Groups [2].Value.Replace(orPattern, "")); } else { conditions.Add(conditionMatches [i].Replace(orPattern, "")); } } } var replacementValue = ""; if (StoryModel.DoesArrayMeetConditions(conditions, notConditions, flags)) { replacementValue = match.Groups [2].Value; } else if (!string.IsNullOrEmpty(match.Groups [4].Value)) { replacementValue = match.Groups [4].Value; } text = Regex.Replace(text, conditionBoundsPattern, replacementValue); } } return(text); }
/// <summary> /// Generates and returns a PlayChunk that begins with the given Stitch /// and continues through the first available block of options. /// </summary> public PlayChunk CreateChunkForStitch(Stitch stitch) { if (stitch == null) { return(null); } PlayChunk chunk = new PlayChunk(); // Reload all flags from the previous stitch AllFlagsCollected.Clear(); if (LastChunk != null) { AllFlagsCollected.AddRange(LastChunk.FlagsCollected); } var currentStitch = stitch; var compiledText = ""; // Loop through all linked stitches while (currentStitch != null) { visitedStitches.Add(currentStitch); if (currentStitch.PageNumber >= 1) { chunk.HasSectionHeading = true; } bool isStitchVisible = StoryModel.DoesArrayMeetConditions(currentStitch.IfConditions, currentStitch.NotIfConditions, AllFlagsCollected); // This stitch passes flag tests and should be included in this chunk if (isStitchVisible) { // Remove newlines in preparation for compiling run-on stitches into one paragraph compiledText += currentStitch.Text.Replace("\n", " ") + " "; // If no more processing is needed, apply text substitutions and store the paragraph bool isRunOn = Regex.IsMatch(currentStitch.Text, @"\[\.\.\.\]") || currentStitch.RunOn; if (!isRunOn || currentStitch.DivertStitch == null) { var styledText = ApplyRuleSubstitutions(compiledText, AllFlagsCollected); chunk.Paragraphs.Add(new Paragraph(styledText, currentStitch.Image, currentStitch.PageLabel)); compiledText = ""; } // Modify all flags with flag states from the current stitch if (currentStitch.Flags.Count > 0) { StoryModel.ProcessFlagSetting(currentStitch, AllFlagsCollected); } } // Add stitch to chunk chunk.Stitches.Add(new BlockContent <Stitch> (currentStitch, isStitchVisible)); currentStitch = currentStitch.DivertStitch; } WordCount = 0; foreach (var p in chunk.Paragraphs) { WordCount += WordCountOf(p.Text); } // Add options to chunk if (LastStitch.Options.Count > 0) { foreach (var option in LastStitch.Options) { var isVisible = StoryModel.DoesArrayMeetConditions(option.IfConditions, option.NotIfConditions, AllFlagsCollected); if (isVisible) { chunk.Options.Add(new BlockContent <Option> (option, isVisible)); } } } chunk.FlagsCollected.AddRange(AllFlagsCollected); allChunks.Add(chunk); return(chunk); }