namespace AIStudio.Tools.PowerPoint; /// /// Counts the slides an answer has started while it still streams in, without reading it as JSON. /// /// /// A slide starts with the key of its layout, or with the key of the template slide it is taken /// from. JSON escapes the quotation marks within a text, so no text of a slide looks like such a /// key. The answer grows by thousands of characters, and the count runs with every rendering, so /// each count starts where the last one ended. One counter belongs to one answer. /// public sealed class StreamedSlideCounter { private static readonly string[] SLIDE_KEYS = ["\"layout\"", "\"template_slide\""]; private int countedLength; private int countedSlides; /// /// Counts the slides which the answer has started so far. /// /// The answer as far as it has streamed in, which only grows. /// How many slides the answer has started. public int Count(string answerSoFar) { // An answer which got shorter was replaced; it is counted anew: if (answerSoFar.Length < this.countedLength) { this.countedLength = 0; this.countedSlides = 0; } foreach (var key in SLIDE_KEYS) { // // A key which the last count saw only in part ends after the end of what it counted, // so the count goes back by less than one key: // var index = Math.Max(0, this.countedLength - key.Length + 1); while ((index = answerSoFar.IndexOf(key, index, StringComparison.Ordinal)) >= 0) { this.countedSlides++; index += key.Length; } } this.countedLength = answerSoFar.Length; return this.countedSlides; } }