using System;
using System.Collections.Generic;
using Vellum;
namespace Ariadne.Vellum.UnitTests
{
///
/// The context the trigger wait scripts run in, with the triggers they wait on and a log they write to.
///
public class Hallway
{
public Trigger Door = new Trigger();
public Trigger Alarm = new Trigger();
public List Log = new List();
}
public class HallwayConverter : SaveConverter
{
public override SaveNode Write(Hallway value, SaveSession session)
{
SaveNode returnMe = SaveNode.NewTable();
returnMe.Entries["door"] = session.ToNode(value.Door);
returnMe.Entries["alarm"] = session.ToNode(value.Alarm);
returnMe.Entries["log"] = session.ToNode(value.Log);
return returnMe;
}
public override Hallway Read(SaveNode node, SaveSession session)
{
var returnMe = new Hallway();
session.Publish(node, returnMe);
returnMe.Door = session.FromNode(node.RequireEntry("door"));
returnMe.Alarm = session.FromNode(node.RequireEntry("alarm"));
returnMe.Log = session.FromNode>(node.RequireEntry("log"));
return returnMe;
}
public override bool TryListChildren(SaveNode node, ChildList children)
{
SaveNode door;
SaveNode alarm;
SaveNode log;
if (!node.TryGetEntry("door", out door) || !node.TryGetEntry("alarm", out alarm)
|| !node.TryGetEntry("log", out log))
{
return false;
}
children.Add(door, typeof(Trigger));
children.Add(alarm, typeof(Trigger));
children.Add(log, typeof(List));
return true;
}
}
///
/// A hallway and what runs in it, which are saved and loaded together.
///
public class Scene
{
public Hallway Hallway;
public ContentType Content;
}
public class SceneConverter : SaveConverter>
{
public override SaveNode Write(Scene value, SaveSession session)
{
SaveNode returnMe = SaveNode.NewTable();
returnMe.Entries["hallway"] = session.ToNode(value.Hallway);
returnMe.Entries["content"] = session.ToNode(value.Content);
return returnMe;
}
public override Scene Read(SaveNode node, SaveSession session)
{
var returnMe = new Scene();
session.Publish(node, returnMe);
returnMe.Hallway = session.FromNode(node.RequireEntry("hallway"));
returnMe.Content = session.FromNode(node.RequireEntry("content"));
return returnMe;
}
public override bool TryListChildren(SaveNode node, ChildList children)
{
SaveNode hallway;
SaveNode content;
if (!node.TryGetEntry("hallway", out hallway) || !node.TryGetEntry("content", out content))
{
return false;
}
children.Add(hallway, typeof(Hallway));
children.Add(content, typeof(ContentType));
return true;
}
}
///
/// A hallway and what runs in it, whose converter doesn't say what it holds, so a load can't plan ahead.
///
public class UnplannedScene
{
public Hallway Hallway;
public ContentType Content;
}
public class UnplannedSceneConverter : SaveConverter>
{
public override SaveNode Write(UnplannedScene value, SaveSession session)
{
SaveNode returnMe = SaveNode.NewTable();
returnMe.Entries["hallway"] = session.ToNode(value.Hallway);
returnMe.Entries["content"] = session.ToNode(value.Content);
return returnMe;
}
public override UnplannedScene Read(SaveNode node, SaveSession session)
{
var returnMe = new UnplannedScene();
session.Publish(node, returnMe);
returnMe.Hallway = session.FromNode(node.RequireEntry("hallway"));
returnMe.Content = session.FromNode(node.RequireEntry("content"));
return returnMe;
}
}
///
/// Waits for the door, then logs.
///
public partial class HallDoorScript : Arc
{
protected override void Run(Hallway hallway)
{
hallway.Log.Add("start");
door:
Wait(hallway.Door);
hallway.Log.Add("door");
}
}
///
/// Waits for either trigger with a time limit, and logs which one came.
///
public partial class HallTimedScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(Hallway hallway)
{
hallway.Log.Add("start");
either:
Trigger fired = WaitAny(timeout: Limit, hallway.Door, hallway.Alarm);
hallway.Log.Add(fired == null ? "timed out" : fired == hallway.Alarm ? "alarm" : "door");
}
}
///
/// Waits for the alarm with a time limit, then for the door.
///
public partial class HallTimedThenDoorScript : Arc
{
public TimeSpan Limit = TimeSpan.FromSeconds(2);
protected override void Run(Hallway hallway)
{
alarm:
Wait(hallway.Alarm, timeout: Limit);
hallway.Log.Add("alarm window over");
door:
Wait(hallway.Door);
hallway.Log.Add("door");
}
}
///
/// Waits for the door, then logs its name.
///
public partial class HallNamedScript : Arc
{
public string Name;
protected override void Run(Hallway hallway)
{
door:
Wait(hallway.Door);
hallway.Log.Add(Name);
}
}
///
/// Waits for either trigger, and logs which one it was.
///
public partial class HallEitherScript : Arc
{
protected override void Run(Hallway hallway)
{
either:
Trigger fired = WaitAny(hallway.Door, hallway.Alarm);
hallway.Log.Add(fired == hallway.Alarm ? "alarm" : "door");
}
}
///
/// Waits for both triggers, and logs which one came last.
///
public partial class HallBothScript : Arc
{
protected override void Run(Hallway hallway)
{
both:
Trigger last = WaitAll(hallway.Door, hallway.Alarm);
hallway.Log.Add(last == hallway.Alarm ? "alarm last" : "door last");
}
}
///
/// Waits for the door twice, with a local counting the trips.
///
public partial class HallTwiceScript : Arc
{
protected override void Run(Hallway hallway)
{
int count = 0;
while (count < 2)
{
spin:
Wait(hallway.Door);
++count;
hallway.Log.Add("door " + count);
}
}
}
///
/// Offers a passage for other arcs to run, which waits for the door.
///
public partial class HallLookoutScript : Arc
{
public void Watch(Hallway hallway)
{
watch:
Wait(hallway.Door);
hallway.Log.Add("seen");
}
protected override void Run(Hallway hallway)
{
}
}
///
/// Runs the passage of another arc that waits for the door.
///
public partial class HallRelayScript : Arc
{
public HallLookoutScript Lookout;
protected override void Run(Hallway hallway)
{
relay:
Lookout.Watch(hallway);
hallway.Log.Add("relayed");
}
}
///
/// Waits in a generic passage, which keeps its locals in a frame of its own.
///
public partial class HallGenericScript : Arc
{
private Trigger Choose(Hallway hallway, ItemType marker)
{
inner:
return WaitAny(hallway.Door, hallway.Alarm);
}
protected override void Run(Hallway hallway)
{
outer:
Trigger picked = Choose(hallway, 5);
hallway.Log.Add(picked == hallway.Alarm ? "alarm" : "door");
}
}
}