diff --git a/src/SCClassicalPlanning.Documentation/Pages/lab/GoalSpaceExplorer.razor b/src/SCClassicalPlanning.Documentation/Pages/lab/GoalSpaceExplorer.razor
index 6dc91a8..f738f0f 100644
--- a/src/SCClassicalPlanning.Documentation/Pages/lab/GoalSpaceExplorer.razor
+++ b/src/SCClassicalPlanning.Documentation/Pages/lab/GoalSpaceExplorer.razor
@@ -1,69 +1,195 @@
@page "/lab/goal-space-explorer"
-@using SCClassicalPlanning
-@using SCClassicalPlanning.ExampleDomains.AsCode;
+@using SCClassicalPlanning;
+@using SCClassicalPlanning.ExampleDomains.AsPDDL;
@using SCClassicalPlanning.Planning.StateAndGoalSpace;
+@using SCClassicalPlanning.ProblemCreation;
+@using System.ComponentModel.DataAnnotations;
-
Goal Space Explorer - Blocks World
-
-
- Yes, this is ugly and raw.
- The author is more of a back-end guy, for now.
- Will likely improve on it gradually whenever the mood takes me.
- Who knows, might even add some pretty graph visualisation stuff at some point.
- Anyway, below is a list of all edges on the currently explored path from the end goal of the problem.
- Explore an edge (adding it to the end of the current path) by clicking on the action to regress.
- NB: so far, our treatment of goal spaces is not lifted - which can result in combinatorial explosion. And we don't yet prune unsatisifiable goals via invariants knowledge.
- So goal space exploration isn't actually massively useful..
- It's interesting though, so there.
- { PathToCurrentNode.Clear(); })" @onclick:preventDefault="true" @onclick:stopPropagation="true">[Reset]
-
-
-
- -
- End Goal: @Problem.Goal
-
+
+ if (parseError != null)
+ {
+
+
Query Failed
+
+ Sorry, this demo isn't perfect.
+ In particular, the input validation is a little lacklustre.
+ It'll hopefully improve gradually over time.
+ In case it helps, here's the details of the exception that was thrown:
+
+
@(parseError.ToString())
+
+ }
+ else if (problem != null)
+ {
+
+ @{
+ RenderListItem(null, new GoalSpaceNode(problem, problem.Goal), path.First?.Value);
+ }
+
+ @for (var n = path.First; n != null; n = n.Next)
+ {
+ RenderListItem(n, n.Value.To, n.Next?.Value);
+ }
+
+ }
+}
@code {
- private readonly LinkedList PathToCurrentNode = new();
+ private static Dictionary> Presets = new()
+ {
+ ["[Empty]"] = () => new(
+ domainPddl: string.Empty,
+ problemPddl: string.Empty),
+
+ ["Blocks World"] = () => new(
+ domainPddl: BlocksWorld.DomainPDDL,
+ problemPddl: BlocksWorld.ExampleProblemPDDL),
+
+ ["Air Cargo"] = () => new(
+ domainPddl: AirCargo.DomainPDDL,
+ problemPddl: AirCargo.ExampleProblemPDDL),
+ };
- [Parameter]
- public Problem Problem { get; set; } = BlocksWorld.ExampleProblem;
+ private FormData formData = Presets["Blocks World"].Invoke();
- public GoalSpaceNode RootNode => new(Problem, Problem.Goal);
+ private Exception? parseError = null; // TODO: should be done via form validation instead.. tidy me!
+ private Problem? problem = null;
+ private LinkedList path = new();
+
+ private void HandleFormSubmission(EditContext editContext)
+ {
+ try
+ {
+ problem = null;
+ parseError = null;
+ path.Clear();
+ problem = PddlParser.ParseProblem(formData.ProblemPDDL, formData.DomainPDDL);
+ }
+ catch (Exception e)
+ {
+ parseError = e;
+ }
+ }
- public void ExploreEdge(GoalSpaceEdge priorEdge, GoalSpaceEdge edge)
+ private void ExploreEdge(LinkedListNode? lastPathNode, GoalSpaceEdge edge)
{
- var currentLLNode = PathToCurrentNode.Find(priorEdge);
- if (currentLLNode != null)
+ if (lastPathNode != null)
{
- while (currentLLNode.Next != null)
+ // huh, weird - i thought .net linked lists could just be chopped.
+ // turns out we have to remove nodes one at a time.
+ while (lastPathNode.Next != null)
{
- PathToCurrentNode.Remove(currentLLNode.Next);
+ path.Remove(lastPathNode.Next);
}
}
+ else
+ {
+ path.Clear();
+ }
+
+ path.AddLast(edge);
+ }
+
+ private class FormData
+ {
+ public FormData(string domainPddl, string problemPddl)
+ {
+ this.DomainPDDL = domainPddl;
+ this.ProblemPDDL = problemPddl;
+ }
+
+ public string DomainPDDL { get; set; }
- PathToCurrentNode.AddLast(edge);
+ public string ProblemPDDL { get; set; }
}
}