resolving action links in gametraverser now; added basic html renderer
This commit is contained in:
parent
a0c9ce5d8c
commit
692d7a670a
|
@ -1,6 +1,9 @@
|
||||||
namespace Ficdown.Parser.Tests
|
namespace Ficdown.Parser.Tests
|
||||||
{
|
{
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Render;
|
||||||
using TestStories;
|
using TestStories;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -12,6 +15,14 @@
|
||||||
var parser = new FicdownParser();
|
var parser = new FicdownParser();
|
||||||
var storyText = Encoding.UTF8.GetString(Resources.TheRobotKing);
|
var storyText = Encoding.UTF8.GetString(Resources.TheRobotKing);
|
||||||
var story = parser.ParseStory(storyText);
|
var story = parser.ParseStory(storyText);
|
||||||
|
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "itest_output");
|
||||||
|
if (!Directory.Exists(path)) Directory.CreateDirectory(path);
|
||||||
|
foreach (var file in Directory.GetFiles(path))
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
var rend = new HtmlRenderer();
|
||||||
|
rend.Render(story, path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,8 +36,9 @@ namespace Ficdown.Parser
|
||||||
{
|
{
|
||||||
var lines = storyText.Split(new[] {"\n", "\r\n"}, StringSplitOptions.None);
|
var lines = storyText.Split(new[] {"\n", "\r\n"}, StringSplitOptions.None);
|
||||||
var blocks = BlockHandler.ExtractBlocks(lines);
|
var blocks = BlockHandler.ExtractBlocks(lines);
|
||||||
GameTraverser.Story = BlockHandler.ParseBlocks(blocks);
|
var story = BlockHandler.ParseBlocks(blocks);
|
||||||
return StateResolver.Resolve(GameTraverser.Enumerate());
|
GameTraverser.Story = story;
|
||||||
|
return StateResolver.Resolve(GameTraverser.Enumerate(), story);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,9 +43,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Model\Parser\ResolvedPage.cs" />
|
<Compile Include="Model\Parser\ResolvedPage.cs" />
|
||||||
<Compile Include="Model\Traverser\PageState.cs" />
|
<Compile Include="Model\Player\PageState.cs" />
|
||||||
<Compile Include="Model\Traverser\State.cs" />
|
<Compile Include="Model\Player\State.cs" />
|
||||||
<Compile Include="Model\Traverser\StateQueueItem.cs" />
|
<Compile Include="Model\Player\StateQueueItem.cs" />
|
||||||
<Compile Include="Parser\BlockHandler.cs" />
|
<Compile Include="Parser\BlockHandler.cs" />
|
||||||
<Compile Include="Parser\IBlockHandler.cs" />
|
<Compile Include="Parser\IBlockHandler.cs" />
|
||||||
<Compile Include="Parser\RegexLib.cs" />
|
<Compile Include="Parser\RegexLib.cs" />
|
||||||
|
@ -66,6 +66,8 @@
|
||||||
<Compile Include="Model\Story\Action.cs" />
|
<Compile Include="Model\Story\Action.cs" />
|
||||||
<Compile Include="Model\Story\Scene.cs" />
|
<Compile Include="Model\Story\Scene.cs" />
|
||||||
<Compile Include="Model\Story\Story.cs" />
|
<Compile Include="Model\Story\Story.cs" />
|
||||||
|
<Compile Include="Render\HtmlRenderer.cs" />
|
||||||
|
<Compile Include="Render\IRenderer.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace Ficdown.Parser.Model.Traverser
|
namespace Ficdown.Parser.Model.Player
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
|
@ -1,4 +1,4 @@
|
||||||
namespace Ficdown.Parser.Model.Traverser
|
namespace Ficdown.Parser.Model.Player
|
||||||
{
|
{
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
namespace Ficdown.Parser.Model.Traverser
|
namespace Ficdown.Parser.Model.Player
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
|
@ -2,10 +2,11 @@
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Model.Parser;
|
using Model.Parser;
|
||||||
using Model.Traverser;
|
using Model.Player;
|
||||||
|
using Model.Story;
|
||||||
|
|
||||||
internal interface IStateResolver
|
internal interface IStateResolver
|
||||||
{
|
{
|
||||||
IEnumerable<ResolvedPage> Resolve(IEnumerable<PageState> pages);
|
IEnumerable<ResolvedPage> Resolve(IEnumerable<PageState> pages, Story story);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,15 @@
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Model.Parser;
|
using Model.Parser;
|
||||||
using Model.Traverser;
|
using Model.Player;
|
||||||
|
using Model.Story;
|
||||||
|
|
||||||
internal class StateResolver : IStateResolver
|
internal class StateResolver : IStateResolver
|
||||||
{
|
{
|
||||||
private static readonly Random _random = new Random((int) DateTime.Now.Ticks);
|
private static readonly Random _random = new Random((int) DateTime.Now.Ticks);
|
||||||
private readonly IDictionary<string, string> _pageNames;
|
private readonly IDictionary<string, string> _pageNames;
|
||||||
private readonly HashSet<string> _usedNames;
|
private readonly HashSet<string> _usedNames;
|
||||||
|
private Story _story;
|
||||||
|
|
||||||
public StateResolver()
|
public StateResolver()
|
||||||
{
|
{
|
||||||
|
@ -19,8 +21,9 @@
|
||||||
_usedNames = new HashSet<string>();
|
_usedNames = new HashSet<string>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<ResolvedPage> Resolve(IEnumerable<PageState> pages)
|
public IEnumerable<ResolvedPage> Resolve(IEnumerable<PageState> pages, Story story)
|
||||||
{
|
{
|
||||||
|
_story = story;
|
||||||
return
|
return
|
||||||
pages.Select(
|
pages.Select(
|
||||||
page =>
|
page =>
|
||||||
|
@ -48,11 +51,22 @@
|
||||||
|
|
||||||
private string ResolveDescription(PageState page)
|
private string ResolveDescription(PageState page)
|
||||||
{
|
{
|
||||||
var resolved = page.Scene.Description;
|
var resolved = new StringBuilder();
|
||||||
|
resolved.AppendFormat("## {0}\n\n", page.Scene.Name);
|
||||||
|
|
||||||
var anchors = Utilities.ParseAnchors(resolved);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
resolved = RegexLib.EmptyListItem.Replace(anchors.Aggregate(resolved,
|
var text = resolved.Append(page.Scene.Description).ToString();
|
||||||
|
|
||||||
|
var anchors = Utilities.ParseAnchors(text);
|
||||||
|
|
||||||
|
text = RegexLib.EmptyListItem.Replace(anchors.Aggregate(text,
|
||||||
(current, anchor) =>
|
(current, anchor) =>
|
||||||
current.Replace(anchor.Original,
|
current.Replace(anchor.Original,
|
||||||
ResolveAnchor(anchor, GetStateDictionary(page),
|
ResolveAnchor(anchor, GetStateDictionary(page),
|
||||||
|
@ -60,10 +74,10 @@
|
||||||
string.Empty);
|
string.Empty);
|
||||||
|
|
||||||
var seen = page.State.ScenesSeen[page.Scene.Id - 1];
|
var seen = page.State.ScenesSeen[page.Scene.Id - 1];
|
||||||
resolved = !seen
|
text = !seen
|
||||||
? RegexLib.BlockQuoteToken.Replace(resolved, string.Empty)
|
? RegexLib.BlockQuoteToken.Replace(text, string.Empty)
|
||||||
: RegexLib.BlockQuotes.Replace(resolved, string.Empty);
|
: RegexLib.BlockQuotes.Replace(text, string.Empty);
|
||||||
return resolved;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IDictionary<string, bool> GetStateDictionary(PageState page)
|
private IDictionary<string, bool> GetStateDictionary(PageState page)
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Model.Player;
|
||||||
using Model.Story;
|
using Model.Story;
|
||||||
using Model.Traverser;
|
|
||||||
using Parser;
|
using Parser;
|
||||||
|
|
||||||
internal class GameTraverser : IGameTraverser
|
internal class GameTraverser : IGameTraverser
|
||||||
|
@ -12,6 +12,7 @@
|
||||||
private Queue<StateQueueItem> _processingQueue;
|
private Queue<StateQueueItem> _processingQueue;
|
||||||
private IDictionary<string, PageState> _processed;
|
private IDictionary<string, PageState> _processed;
|
||||||
private IDictionary<string, PageState> _compressed;
|
private IDictionary<string, PageState> _compressed;
|
||||||
|
private IDictionary<int, Action> _actionMatrix;
|
||||||
|
|
||||||
private Story _story;
|
private Story _story;
|
||||||
public Story Story
|
public Story Story
|
||||||
|
@ -20,6 +21,7 @@
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
_story = value;
|
_story = value;
|
||||||
|
_actionMatrix = _story.Actions.ToDictionary(a => a.Value.Id, a => a.Value);
|
||||||
_manager = new StateManager(_story);
|
_manager = new StateManager(_story);
|
||||||
_processingQueue = new Queue<StateQueueItem>();
|
_processingQueue = new Queue<StateQueueItem>();
|
||||||
_processed = new Dictionary<string, PageState>();
|
_processed = new Dictionary<string, PageState>();
|
||||||
|
@ -65,11 +67,23 @@
|
||||||
return _compressed.Values;
|
return _compressed.Values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Action> GetActionsForPage(PageState page)
|
||||||
|
{
|
||||||
|
var actions = new List<Action>();
|
||||||
|
for (var i = 0; i < page.State.ActionsToShow.Count; i++)
|
||||||
|
{
|
||||||
|
if (page.State.ActionsToShow[i]) actions.Add(_actionMatrix[i + 1]);
|
||||||
|
}
|
||||||
|
return actions;
|
||||||
|
}
|
||||||
|
|
||||||
private void ProcessState(StateQueueItem currentState)
|
private void ProcessState(StateQueueItem currentState)
|
||||||
{
|
{
|
||||||
var states = new HashSet<string>();
|
var states = new HashSet<string>();
|
||||||
|
|
||||||
var anchors = Utilities.ParseAnchors(currentState.Page.Scene.Description);
|
var anchors = Utilities.ParseAnchors(currentState.Page.Scene.Description).ToList();
|
||||||
|
foreach (var action in GetActionsForPage(currentState.Page))
|
||||||
|
anchors.AddRange(Utilities.ParseAnchors(action.Description));
|
||||||
var conditionals =
|
var conditionals =
|
||||||
anchors.SelectMany(
|
anchors.SelectMany(
|
||||||
a => a.Href.Conditions != null ? a.Href.Conditions.Select(c => c.Key) : new string[] {})
|
a => a.Href.Conditions != null ? a.Href.Conditions.Select(c => c.Key) : new string[] {})
|
||||||
|
@ -80,6 +94,9 @@
|
||||||
foreach (var affected in currentState.AffectedStates)
|
foreach (var affected in currentState.AffectedStates)
|
||||||
{
|
{
|
||||||
// signal to previous scenes that this scene's used conditionals are important
|
// signal to previous scenes that this scene's used conditionals are important
|
||||||
|
if(currentState.Page.Scene.Conditions != null)
|
||||||
|
foreach (var conditional in currentState.Page.Scene.Conditions)
|
||||||
|
_manager.ToggleStateOn(affected, conditional.Key);
|
||||||
foreach (var conditional in conditionals) _manager.ToggleStateOn(affected, conditional);
|
foreach (var conditional in conditionals) _manager.ToggleStateOn(affected, conditional);
|
||||||
|
|
||||||
// signal to previous scenes if this scene has first-seen text
|
// signal to previous scenes if this scene has first-seen text
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
namespace Ficdown.Parser.Player
|
namespace Ficdown.Parser.Player
|
||||||
{
|
{
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Model.Player;
|
||||||
using Model.Story;
|
using Model.Story;
|
||||||
using Model.Traverser;
|
|
||||||
|
|
||||||
internal interface IGameTraverser
|
internal interface IGameTraverser
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,8 +5,8 @@
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Model.Parser;
|
using Model.Parser;
|
||||||
|
using Model.Player;
|
||||||
using Model.Story;
|
using Model.Story;
|
||||||
using Model.Traverser;
|
|
||||||
using Parser;
|
using Parser;
|
||||||
|
|
||||||
internal class StateManager
|
internal class StateManager
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
namespace Ficdown.Parser.Render
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using MarkdownSharp;
|
||||||
|
using Model.Parser;
|
||||||
|
using Model.Story;
|
||||||
|
using Parser;
|
||||||
|
|
||||||
|
internal class HtmlRenderer : IRenderer
|
||||||
|
{
|
||||||
|
private readonly Markdown _md;
|
||||||
|
|
||||||
|
public HtmlRenderer()
|
||||||
|
{
|
||||||
|
_md = new Markdown();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Render(IEnumerable<ResolvedPage> pages, string outPath)
|
||||||
|
{
|
||||||
|
foreach (var page in pages)
|
||||||
|
{
|
||||||
|
var content = page.Content;
|
||||||
|
foreach (var anchor in Utilities.ParseAnchors(page.Content))
|
||||||
|
{
|
||||||
|
var newAnchor = string.Format("[{0}]({1}.html)", anchor.Text, anchor.Href.Target);
|
||||||
|
content = content.Replace(anchor.Original, newAnchor);
|
||||||
|
}
|
||||||
|
File.WriteAllText(Path.Combine(outPath, string.Format("{0}.html", page.Name)), _md.Transform(content));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ficdown.Parser.Render
|
||||||
|
{
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Model.Parser;
|
||||||
|
using Model.Story;
|
||||||
|
|
||||||
|
internal interface IRenderer
|
||||||
|
{
|
||||||
|
void Render(IEnumerable<ResolvedPage> pages, string outPath);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue