mirror of
https://github.com/morten-olsen/bob.git
synced 2026-02-08 01:46:29 +01:00
feat: add capabilities
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
|
||||
> bob-the-algorithm@ build /Users/alice/work/private/bob/packages/algorithm
|
||||
> @bob-the-algorithm/core@0.1.8 build /home/alice/Git/bob/packages/algorithm
|
||||
> tsc --build configs/tsconfig.libs.json
|
||||
|
||||
|
||||
@@ -21,6 +21,10 @@ type RunOptions<TPlugins extends Plugins> = {
|
||||
heuristic?: (result: any) => boolean;
|
||||
};
|
||||
|
||||
type PlanableWithPlugins<TPlugins extends Plugins> = Planable<
|
||||
PluginAttributes<TPlugins>
|
||||
>;
|
||||
|
||||
class Bob<TPlugins extends Plugins> {
|
||||
#options: CalulationOptions<TPlugins>;
|
||||
#id: number = 0;
|
||||
@@ -99,5 +103,5 @@ class Bob<TPlugins extends Plugins> {
|
||||
};
|
||||
}
|
||||
|
||||
export type { CalulationOptions, CalulationResult };
|
||||
export type { CalulationOptions, CalulationResult, PlanableWithPlugins };
|
||||
export { Bob };
|
||||
|
||||
@@ -70,7 +70,7 @@ const expandNode = async <
|
||||
node.time + node.duration,
|
||||
planable.start?.min || 0,
|
||||
);
|
||||
return {
|
||||
const nextNode = {
|
||||
...node,
|
||||
type: 'planable',
|
||||
exploreId: 0,
|
||||
@@ -83,6 +83,14 @@ const expandNode = async <
|
||||
completed: remaining.length === 0,
|
||||
parent: node.id,
|
||||
};
|
||||
return Object.values(plugins).reduce(
|
||||
// TODO: remove any
|
||||
(acc, plugin) =>
|
||||
(plugin.mutateNode
|
||||
? plugin.mutateNode(acc as any, planable)
|
||||
: acc) as any,
|
||||
nextNode,
|
||||
) as any;
|
||||
});
|
||||
|
||||
return [...planableNodes, ...metaNodes.flat()];
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
export type { GraphNode } from './types/node';
|
||||
export type { Planable } from './types/planable';
|
||||
export { expandNode } from './algorithm/expand-node';
|
||||
export { Bob, type CalulationResult } from './algorithm/calulation';
|
||||
export {
|
||||
Bob,
|
||||
type CalulationResult,
|
||||
type PlanableWithPlugins,
|
||||
} from './algorithm/calulation';
|
||||
export { plugins } from './plugins/index';
|
||||
|
||||
57
packages/algorithm/src/plugins/capabilities.ts
Normal file
57
packages/algorithm/src/plugins/capabilities.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
import { Type } from '@sinclair/typebox';
|
||||
import { createPlugin } from './create';
|
||||
|
||||
const capabilities = () =>
|
||||
createPlugin(
|
||||
Type.Object({
|
||||
capabilities: Type.Optional(
|
||||
Type.Object({
|
||||
provides: Type.Optional(Type.Array(Type.String())),
|
||||
consumes: Type.Optional(Type.Array(Type.String())),
|
||||
requires: Type.Optional(Type.Array(Type.String())),
|
||||
perhibits: Type.Optional(Type.Array(Type.String())),
|
||||
}),
|
||||
),
|
||||
}),
|
||||
Type.Object({
|
||||
capabilities: Type.Array(Type.String()),
|
||||
}),
|
||||
{
|
||||
isPlanable: (node, planable) => {
|
||||
const { requires = [], perhibits = [] } =
|
||||
planable.attributes?.capabilities || {};
|
||||
const capabilities = node.context.capabilities;
|
||||
|
||||
if (requires.length === 0 && perhibits.length === 0) {
|
||||
return true;
|
||||
}
|
||||
const satisfiesRequire = requires.every((c) =>
|
||||
capabilities.includes(c),
|
||||
);
|
||||
const satisfiesPerhibit = !perhibits.some((c) =>
|
||||
capabilities.includes(c),
|
||||
);
|
||||
return satisfiesRequire && satisfiesPerhibit;
|
||||
},
|
||||
mutateNode: (node, planable) => {
|
||||
const { provides = [], consumes = [] } =
|
||||
planable.attributes?.capabilities || {};
|
||||
const capabilities = node.context.capabilities || [];
|
||||
|
||||
const newCapabilities = [
|
||||
...capabilities.filter((c) => !consumes.includes(c)),
|
||||
...provides,
|
||||
];
|
||||
|
||||
return {
|
||||
...node,
|
||||
context: {
|
||||
...node.context,
|
||||
capabilities: newCapabilities,
|
||||
},
|
||||
};
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
export { capabilities };
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Plugin } from '../types/plugin';
|
||||
import { transport } from './transport';
|
||||
import { capabilities } from './capabilities';
|
||||
|
||||
const plugins = {
|
||||
transport,
|
||||
capabilities,
|
||||
} satisfies Record<string, (...args: any[]) => Plugin>;
|
||||
|
||||
export { plugins };
|
||||
|
||||
@@ -47,7 +47,7 @@ const transport = ({ getTravelTime }: TransportOptions) =>
|
||||
planable: undefined,
|
||||
location,
|
||||
exploreId: 0,
|
||||
score: node.score - 10,
|
||||
score: node.score - 5,
|
||||
time: node.time + node.duration,
|
||||
duration: travelTime,
|
||||
parent: node.id,
|
||||
|
||||
@@ -12,6 +12,10 @@ type Plugin<TAttributes = any, TContext = any> = {
|
||||
node: GraphNode<TAttributes, TContext>,
|
||||
planable: Planable<TAttributes>,
|
||||
) => boolean;
|
||||
mutateNode?: (
|
||||
node: GraphNode<TAttributes, TContext>,
|
||||
planable: Planable<TAttributes>,
|
||||
) => GraphNode<TAttributes, TContext>;
|
||||
};
|
||||
|
||||
type Plugins = Record<string, Plugin>;
|
||||
|
||||
Reference in New Issue
Block a user