From 611cde2e29f7b804b7c519086b85822db7028762 Mon Sep 17 00:00:00 2001 From: Rudis Muiznieks Date: Sun, 10 Aug 2014 15:25:20 -0500 Subject: [PATCH] fixed some enumeration and state resolution problems (I think) --- Ficdown.Parser.Tests/IntegrationTests.cs | 2 +- Ficdown.Parser/Model/Parser/ResolvedPage.cs | 3 ++ Ficdown.Parser/Model/Player/PageState.cs | 1 - Ficdown.Parser/Model/Player/State.cs | 1 + Ficdown.Parser/Parser/StateResolver.cs | 47 ++++++++++++++------- Ficdown.Parser/Player/GameTraverser.cs | 18 ++++++++ Ficdown.Parser/Player/StateManager.cs | 26 ++++++++++-- Ficdown.Parser/Render/HtmlRenderer.cs | 9 +++- Ficdown.Parser/Render/IRenderer.cs | 3 +- 9 files changed, 84 insertions(+), 26 deletions(-) diff --git a/Ficdown.Parser.Tests/IntegrationTests.cs b/Ficdown.Parser.Tests/IntegrationTests.cs index 1451c0b..083aac1 100644 --- a/Ficdown.Parser.Tests/IntegrationTests.cs +++ b/Ficdown.Parser.Tests/IntegrationTests.cs @@ -22,7 +22,7 @@ File.Delete(file); } var rend = new HtmlRenderer(); - rend.Render(story, path); + rend.Render(story, path, true); } } } diff --git a/Ficdown.Parser/Model/Parser/ResolvedPage.cs b/Ficdown.Parser/Model/Parser/ResolvedPage.cs index de190a9..147ecea 100644 --- a/Ficdown.Parser/Model/Parser/ResolvedPage.cs +++ b/Ficdown.Parser/Model/Parser/ResolvedPage.cs @@ -1,8 +1,11 @@ namespace Ficdown.Parser.Model.Parser { + using System.Collections.Generic; + public class ResolvedPage { public string Name { get; set; } public string Content { get; set; } + public IEnumerable ActiveToggles { get; set; } } } diff --git a/Ficdown.Parser/Model/Player/PageState.cs b/Ficdown.Parser/Model/Player/PageState.cs index b71290f..7e54915 100644 --- a/Ficdown.Parser/Model/Player/PageState.cs +++ b/Ficdown.Parser/Model/Player/PageState.cs @@ -14,7 +14,6 @@ public IDictionary StateMatrix { get; set; } - public string Resolved { get; set; } public IDictionary Links { get; set; } private string _uniqueHash; diff --git a/Ficdown.Parser/Model/Player/State.cs b/Ficdown.Parser/Model/Player/State.cs index 8ae1f4c..c291a8e 100644 --- a/Ficdown.Parser/Model/Player/State.cs +++ b/Ficdown.Parser/Model/Player/State.cs @@ -7,5 +7,6 @@ public BitArray PlayerState { get; set; } public BitArray ScenesSeen { get; set; } public BitArray ActionsToShow { get; set; } + public BitArray ActionFirstToggles { get; set; } } } diff --git a/Ficdown.Parser/Parser/StateResolver.cs b/Ficdown.Parser/Parser/StateResolver.cs index d7e21ff..502a0cc 100644 --- a/Ficdown.Parser/Parser/StateResolver.cs +++ b/Ficdown.Parser/Parser/StateResolver.cs @@ -30,7 +30,8 @@ new ResolvedPage { Name = GetPageNameForHash(page.CompressedHash), - Content = ResolveDescription(page) + Content = ResolveDescription(page), + ActiveToggles = GetStateDictionary(page).Where(t => t.Value).Select(t => t.Key) }).ToList(); } @@ -54,30 +55,44 @@ var resolved = new StringBuilder(); resolved.AppendFormat("## {0}\n\n", page.Scene.Name); + var firstToggleCounter = 0; for (var i = 0; i < page.State.ActionsToShow.Count; i++) { if (page.State.ActionsToShow[i]) { - resolved.AppendFormat("{0}\n\n", _story.Actions.Single(a => a.Value.Id == i + 1).Value.Description); + var actionTuple = _story.Actions.Single(a => a.Value.Id == i + 1); + var actionAnchors = Utilities.ParseAnchors(actionTuple.Value.Description); + var anchorDict = GetStateDictionary(page); + if (actionAnchors.Any(a => a.Href.Conditions.ContainsKey(actionTuple.Key))) + { + if (page.State.ActionFirstToggles[firstToggleCounter++]) + { + anchorDict[actionTuple.Key] = false; + } + } + resolved.AppendFormat("{0}\n\n", actionAnchors.Aggregate(actionTuple.Value.Description, + (current, anchor) => + current.Replace(anchor.Original, + ResolveAnchor(anchor, anchorDict, + page.Links.ContainsKey(anchor.Original) ? page.Links[anchor.Original] : null)))); } } - var text = resolved.Append(page.Scene.Description).ToString(); - - var anchors = Utilities.ParseAnchors(text); - - text = RegexLib.EmptyListItem.Replace(anchors.Aggregate(text, - (current, anchor) => - current.Replace(anchor.Original, - ResolveAnchor(anchor, GetStateDictionary(page), - page.Links.ContainsKey(anchor.Original) ? page.Links[anchor.Original] : null))), - string.Empty); - + var anchors = Utilities.ParseAnchors(page.Scene.Description); + var stateDict = GetStateDictionary(page); + var text = + RegexLib.EmptyListItem.Replace( + anchors.Aggregate(page.Scene.Description, + (current, anchor) => + current.Replace(anchor.Original, + ResolveAnchor(anchor, stateDict, + page.Links.ContainsKey(anchor.Original) ? page.Links[anchor.Original] : null))), + string.Empty); var seen = page.State.ScenesSeen[page.Scene.Id - 1]; - text = !seen + resolved.Append(!seen ? RegexLib.BlockQuoteToken.Replace(text, string.Empty) - : RegexLib.BlockQuotes.Replace(text, string.Empty); - return text; + : RegexLib.BlockQuotes.Replace(text, string.Empty)); + return resolved.ToString(); } private IDictionary GetStateDictionary(PageState page) diff --git a/Ficdown.Parser/Player/GameTraverser.cs b/Ficdown.Parser/Player/GameTraverser.cs index 557dc0d..ee9e672 100644 --- a/Ficdown.Parser/Player/GameTraverser.cs +++ b/Ficdown.Parser/Player/GameTraverser.cs @@ -49,6 +49,24 @@ } } + // make sure every page gets affected data on every page that it links to + foreach (var pageTuple in _processed) + { + foreach (var linkTuple in pageTuple.Value.Links) + { + for (var i = 0; i < _processed[linkTuple.Value].AffectedState.PlayerState.Count; i++) + { + pageTuple.Value.AffectedState.PlayerState[i] |= + _processed[linkTuple.Value].AffectedState.PlayerState[i]; + } + for (var i = 0; i < _processed[linkTuple.Value].AffectedState.ScenesSeen.Count; i++) + { + pageTuple.Value.AffectedState.ScenesSeen[i] |= + _processed[linkTuple.Value].AffectedState.ScenesSeen[i]; + } + } + } + // compress redundancies foreach (var row in _processed) { diff --git a/Ficdown.Parser/Player/StateManager.cs b/Ficdown.Parser/Player/StateManager.cs index dbf1a3a..ea5f52d 100644 --- a/Ficdown.Parser/Player/StateManager.cs +++ b/Ficdown.Parser/Player/StateManager.cs @@ -51,13 +51,15 @@ { PlayerState = new BitArray(_stateMatrix.Keys.Count), ScenesSeen = new BitArray(_sceneCount), - ActionsToShow = new BitArray(_actionCount) + ActionsToShow = new BitArray(_actionCount), + ActionFirstToggles = null }, AffectedState = new State { PlayerState = new BitArray(_stateMatrix.Keys.Count), ScenesSeen = new BitArray(_sceneCount), - ActionsToShow = new BitArray(_actionCount) + ActionsToShow = new BitArray(_actionCount), + ActionFirstToggles = null }, Scene = _story.Scenes[_story.FirstScene].Single(s => s.Conditions == null), StateMatrix = _stateMatrix @@ -71,17 +73,26 @@ var newState = ClonePage(current); newState.State.ScenesSeen[current.Scene.Id - 1] = true; + List actionFirstToggles = null; if (anchor.Href.Toggles != null) { foreach (var toggle in anchor.Href.Toggles) { if (_story.Actions.ContainsKey(toggle)) { + if(actionFirstToggles == null) actionFirstToggles = new List(); newState.State.ActionsToShow[_story.Actions[toggle].Id - 1] = true; + if ( + Utilities.ParseAnchors(_story.Actions[toggle].Description) + .Any(a => a.Href.Conditions.ContainsKey(toggle))) + actionFirstToggles.Add(!current.State.PlayerState[_stateMatrix[toggle]]); } newState.State.PlayerState[_stateMatrix[toggle]] = true; } } + newState.State.ActionFirstToggles = actionFirstToggles != null + ? new BitArray(actionFirstToggles.ToArray()) + : null; newState.Scene = GetScene(target, newState.State.PlayerState); return newState; } @@ -98,10 +109,16 @@ public static string GetUniqueHash(State state, string sceneKey) { - var combined = new bool[state.PlayerState.Count + state.ScenesSeen.Count + state.ActionsToShow.Count]; + var combined = + new bool[ + state.PlayerState.Count + state.ScenesSeen.Count + state.ActionsToShow.Count + + (state.ActionFirstToggles != null ? state.ActionFirstToggles.Count : 0)]; state.PlayerState.CopyTo(combined, 0); state.ScenesSeen.CopyTo(combined, state.PlayerState.Count); state.ActionsToShow.CopyTo(combined, state.PlayerState.Count + state.ScenesSeen.Count); + if (state.ActionFirstToggles != null) + state.ActionFirstToggles.CopyTo(combined, + state.PlayerState.Count + state.ScenesSeen.Count + state.ActionsToShow.Count); var ba = new BitArray(combined); var byteSize = (int)Math.Ceiling(combined.Length / 8.0); var encoded = new byte[byteSize]; @@ -115,7 +132,8 @@ { PlayerState = page.State.PlayerState.And(page.AffectedState.PlayerState), ScenesSeen = page.State.ScenesSeen.And(page.AffectedState.ScenesSeen), - ActionsToShow = page.State.ActionsToShow + ActionsToShow = page.State.ActionsToShow, + ActionFirstToggles = page.State.ActionFirstToggles }; return GetUniqueHash(compressed, page.Scene.Key); } diff --git a/Ficdown.Parser/Render/HtmlRenderer.cs b/Ficdown.Parser/Render/HtmlRenderer.cs index c9e4712..b316566 100644 --- a/Ficdown.Parser/Render/HtmlRenderer.cs +++ b/Ficdown.Parser/Render/HtmlRenderer.cs @@ -2,9 +2,9 @@ { using System.Collections.Generic; using System.IO; + using System.Linq; using MarkdownSharp; using Model.Parser; - using Model.Story; using Parser; internal class HtmlRenderer : IRenderer @@ -16,7 +16,7 @@ _md = new Markdown(); } - public void Render(IEnumerable pages, string outPath) + public void Render(IEnumerable pages, string outPath, bool debug = false) { foreach (var page in pages) { @@ -26,6 +26,11 @@ var newAnchor = string.Format("[{0}]({1}.html)", anchor.Text, anchor.Href.Target); content = content.Replace(anchor.Original, newAnchor); } + if (debug) + { + content += string.Format("\n\n### State Debug\n\n{0}", + string.Join("\n", page.ActiveToggles.Select(t => string.Format("- {0}", t)).ToArray())); + } File.WriteAllText(Path.Combine(outPath, string.Format("{0}.html", page.Name)), _md.Transform(content)); } } diff --git a/Ficdown.Parser/Render/IRenderer.cs b/Ficdown.Parser/Render/IRenderer.cs index 4a1c9db..0bfe5da 100644 --- a/Ficdown.Parser/Render/IRenderer.cs +++ b/Ficdown.Parser/Render/IRenderer.cs @@ -2,10 +2,9 @@ { using System.Collections.Generic; using Model.Parser; - using Model.Story; internal interface IRenderer { - void Render(IEnumerable pages, string outPath); + void Render(IEnumerable pages, string outPath, bool debug); } }