mahler
Version:
A automated task composer and HTN based planner for building autonomous system agents
142 lines • 3.79 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.plan = plan;
exports.branch = branch;
exports.fork = fork;
exports.sequence = sequence;
const dag_1 = require("../dag");
const Label = {
of(id) {
return dag_1.Node.value({ id });
},
};
// Create a linked list from a list of strings
// returns the head and tail of the list
function fromList(elems) {
const [first, ...labels] = elems;
const root = Label.of(first);
let tail = root;
for (const label of labels) {
const node = Label.of(label);
tail.next = node;
tail = node;
}
return [root, tail];
}
function fromFork(branches) {
branches = branches.filter((b) => b.length > 0);
// If all branches are empty, return
if (branches.length === 0) {
return [null, null];
}
// If there is only a branch, call the branch method
if (branches.length === 1) {
return fromBranch(branches[0]);
}
// For multiple branches, create a fork and
// a join for the ends
const root = dag_1.Node.fork();
const tail = dag_1.Node.join();
for (const b of branches) {
const [r, t] = fromBranch(b);
// We already checked that the branch is not empty
// but typescript cannot infer that so we wrap this in
// an if
if (r != null && t != null) {
t.next = tail;
root.next.push(r);
}
}
return [root, tail];
}
function fromBranch(elems) {
let root = null;
let tail = null;
while (elems.length > 0) {
let r = null;
let t = null;
// Find the next fork
const forkIndex = elems.findIndex((e) => Array.isArray(e));
const length = forkIndex > 0 ? forkIndex : elems.length;
if (forkIndex === 0) {
// If the fork is the first element of the branch, create a fork
const branches = elems.shift();
[r, t] = fromFork(branches);
}
else if (length > 0) {
// Otherwise create a sequence with the first N elements of the branch
[r, t] = fromList(elems.splice(0, length));
}
if (root == null) {
root = r;
tail = t;
}
else if (tail != null) {
tail.next = r;
tail = t;
}
}
return [root, tail];
}
/**
* Start building a plan
*/
function plan() {
let root = null;
let tail = null;
function setEnds(r, t) {
if (root == null) {
root = r;
tail = t;
}
else if (tail != null) {
tail.next = r;
tail = t;
}
}
const builder = {
action(description) {
return builder.actions(description);
},
actions(...descriptions) {
const [r, t] = fromList(descriptions);
setEnds(r, t);
return builder;
},
fork(...branches) {
const [r, t] = fromFork(branches);
setEnds(r, t);
return builder;
},
root() {
return root;
},
end() {
return (0, dag_1.toString)(root, (l) => l.id);
},
};
return builder;
}
/**
* Utility method to create a branch from an array
* of values
*
* Each value may be a string or the result of `fork()`
*/
function branch(...values) {
return values.filter((v) => !Array.isArray(v) || v.length > 0);
}
/**
* Create a new fork from a list of branches
*
* Branches are returned by the `branch` method
*/
function fork(...branches) {
return branches.filter((b) => b.length > 0);
}
function sequence(...actions) {
return plan()
.actions(...actions)
.end();
}
//# sourceMappingURL=builder.js.map