mirror of
https://github.com/morten-olsen/bob.git
synced 2026-02-08 01:46:29 +01:00
feat: improved plugin structure
This commit is contained in:
@@ -25,5 +25,8 @@
|
|||||||
"build": "tsc --build configs/tsconfig.libs.json"
|
"build": "tsc --build configs/tsconfig.libs.json"
|
||||||
},
|
},
|
||||||
"types": "./dist/cjs/types/index.d.ts",
|
"types": "./dist/cjs/types/index.d.ts",
|
||||||
"version": "0.1.8"
|
"version": "0.1.8",
|
||||||
|
"dependencies": {
|
||||||
|
"@sinclair/typebox": "^0.31.14"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,59 +1,73 @@
|
|||||||
import { Attributes, GraphNode } from '../types/node';
|
import { GraphNode } from '../types/node';
|
||||||
import { Planable } from '../types/planable';
|
import { Planable } from '../types/planable';
|
||||||
import { PluginAttributes, Plugins } from '../types/plugin';
|
import { PluginAttributes, PluginContext, Plugins } from '../types/plugin';
|
||||||
import { expandNode } from './expand-node';
|
import { expandNode } from './expand-node';
|
||||||
|
|
||||||
type CalulationOptions<TPlugins extends Plugins> = {
|
type CalulationOptions<TPlugins extends Plugins> = {
|
||||||
location: string;
|
|
||||||
time: number;
|
|
||||||
planables: Planable<PluginAttributes<TPlugins>>[];
|
|
||||||
plugins: TPlugins;
|
plugins: TPlugins;
|
||||||
|
};
|
||||||
|
|
||||||
|
type CalulationResult<TPlugins extends Plugins> = {
|
||||||
|
root: GraphNode<PluginAttributes<TPlugins>, PluginContext<TPlugins>>;
|
||||||
|
nodes: GraphNode<PluginAttributes<TPlugins>, PluginContext<TPlugins>>[];
|
||||||
|
completed: GraphNode<PluginAttributes<TPlugins>, PluginContext<TPlugins>>[];
|
||||||
|
planables: Planable<PluginAttributes<TPlugins>>[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type RunOptions<TPlugins extends Plugins> = {
|
||||||
|
start: number;
|
||||||
|
context: PluginContext<TPlugins>;
|
||||||
|
planables: Planable<PluginAttributes<TPlugins>>[];
|
||||||
heuristic?: (result: any) => boolean;
|
heuristic?: (result: any) => boolean;
|
||||||
onUpdated?: (result: any) => void;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
type CalulationResult<TAttributes extends Attributes> = {
|
class Bob<TPlugins extends Plugins> {
|
||||||
root: GraphNode<TAttributes>;
|
#options: CalulationOptions<TPlugins>;
|
||||||
nodes: GraphNode<TAttributes>[];
|
#id: number = 0;
|
||||||
completed: GraphNode<TAttributes>[];
|
|
||||||
planables: Planable<TAttributes>[];
|
constructor(options: CalulationOptions<TPlugins>) {
|
||||||
|
this.#options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
#getNextId = (): string => {
|
||||||
|
return (this.#id++).toString();
|
||||||
};
|
};
|
||||||
|
|
||||||
const idGen = () => {
|
public run = async ({
|
||||||
let id = 0;
|
|
||||||
return () => {
|
|
||||||
id += 1;
|
|
||||||
return id.toString();
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const calulation = async <TPlugins extends Plugins>({
|
|
||||||
location,
|
|
||||||
time,
|
|
||||||
planables,
|
planables,
|
||||||
plugins,
|
start,
|
||||||
|
context,
|
||||||
heuristic,
|
heuristic,
|
||||||
onUpdated,
|
}: RunOptions<TPlugins>): Promise<CalulationResult<TPlugins>> => {
|
||||||
}: CalulationOptions<TPlugins>): Promise<
|
const { plugins } = this.#options;
|
||||||
CalulationResult<PluginAttributes<TPlugins>>
|
|
||||||
> => {
|
|
||||||
const generateId = idGen();
|
|
||||||
let exploreId = 1;
|
let exploreId = 1;
|
||||||
const root: GraphNode<PluginAttributes<TPlugins>> = {
|
const root: GraphNode<
|
||||||
id: generateId(),
|
PluginAttributes<TPlugins>,
|
||||||
|
PluginContext<TPlugins>
|
||||||
|
> = {
|
||||||
|
id: this.#getNextId(),
|
||||||
|
context,
|
||||||
type: 'root',
|
type: 'root',
|
||||||
score: 0,
|
score: 0,
|
||||||
parent: null,
|
parent: null,
|
||||||
duration: 0,
|
duration: 0,
|
||||||
time,
|
time: start,
|
||||||
location,
|
|
||||||
exploreId: 0,
|
exploreId: 0,
|
||||||
remaining: planables,
|
remaining: planables,
|
||||||
};
|
};
|
||||||
|
|
||||||
const nodes: GraphNode<PluginAttributes<TPlugins>>[] = [root];
|
const nodes: GraphNode<
|
||||||
const leafNodes: GraphNode<PluginAttributes<TPlugins>>[] = [root];
|
PluginAttributes<TPlugins>,
|
||||||
const completed: GraphNode<PluginAttributes<TPlugins>>[] = [];
|
PluginContext<TPlugins>
|
||||||
|
>[] = [root];
|
||||||
|
const leafNodes: GraphNode<
|
||||||
|
PluginAttributes<TPlugins>,
|
||||||
|
PluginContext<TPlugins>
|
||||||
|
>[] = [root];
|
||||||
|
const completed: GraphNode<
|
||||||
|
PluginAttributes<TPlugins>,
|
||||||
|
PluginContext<TPlugins>
|
||||||
|
>[] = [];
|
||||||
|
|
||||||
const popHighestScore = () => {
|
const popHighestScore = () => {
|
||||||
const highestScore = Math.max(...leafNodes.map((n) => n.score));
|
const highestScore = Math.max(...leafNodes.map((n) => n.score));
|
||||||
@@ -68,20 +82,22 @@ const calulation = async <TPlugins extends Plugins>({
|
|||||||
while (leafNodes.length > 0) {
|
while (leafNodes.length > 0) {
|
||||||
const node = popHighestScore();
|
const node = popHighestScore();
|
||||||
node.exploreId = exploreId++;
|
node.exploreId = exploreId++;
|
||||||
const expanded = await expandNode({ node, generateId, plugins });
|
const expanded = await expandNode({
|
||||||
|
node,
|
||||||
|
generateId: this.#getNextId,
|
||||||
|
plugins,
|
||||||
|
});
|
||||||
nodes.push(...expanded);
|
nodes.push(...expanded);
|
||||||
completed.push(...expanded.filter((n) => n.remaining.length === 0));
|
completed.push(...expanded.filter((n) => n.remaining.length === 0));
|
||||||
leafNodes.push(...expanded.filter((n) => n.remaining.length > 0));
|
leafNodes.push(...expanded.filter((n) => n.remaining.length > 0));
|
||||||
if (heuristic && heuristic({ root, nodes, completed, planables })) {
|
if (heuristic && heuristic({ root, nodes, completed, planables })) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (onUpdated) {
|
|
||||||
onUpdated({ root, nodes, completed, planables });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { root, nodes, completed, planables };
|
return { root, nodes, completed, planables };
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
export type { CalulationOptions, CalulationResult };
|
export type { CalulationOptions, CalulationResult };
|
||||||
export { calulation };
|
export { Bob };
|
||||||
|
|||||||
@@ -1,18 +1,26 @@
|
|||||||
import { Attributes, GraphNode } from '../types/node';
|
import { Attributes, GraphNode } from '../types/node';
|
||||||
import { Plugin } from '../types/plugin';
|
import { Plugins } from '../types/plugin';
|
||||||
import { hasImpossible } from './is-impossible';
|
import { hasImpossible } from './is-impossible';
|
||||||
|
|
||||||
type ExpandOptions<TAttributes extends Attributes> = {
|
type ExpandOptions<
|
||||||
node: GraphNode<TAttributes>;
|
TAttributes extends Attributes,
|
||||||
|
TContext extends Attributes,
|
||||||
|
> = {
|
||||||
|
node: GraphNode<TAttributes, TContext>;
|
||||||
generateId: () => string;
|
generateId: () => string;
|
||||||
plugins: Plugin[];
|
plugins: Plugins;
|
||||||
};
|
};
|
||||||
|
|
||||||
const expandNode = async <TAttributes extends Attributes>({
|
const expandNode = async <
|
||||||
|
TAttributes extends Attributes,
|
||||||
|
TContext extends Attributes,
|
||||||
|
>({
|
||||||
node,
|
node,
|
||||||
generateId,
|
generateId,
|
||||||
plugins,
|
plugins,
|
||||||
}: ExpandOptions<TAttributes>): Promise<GraphNode<TAttributes>[]> => {
|
}: ExpandOptions<TAttributes, TContext>): Promise<
|
||||||
|
GraphNode<TAttributes, TContext>[]
|
||||||
|
> => {
|
||||||
const isImpossible = hasImpossible({ node });
|
const isImpossible = hasImpossible({ node });
|
||||||
|
|
||||||
if (isImpossible) {
|
if (isImpossible) {
|
||||||
@@ -21,7 +29,7 @@ const expandNode = async <TAttributes extends Attributes>({
|
|||||||
}
|
}
|
||||||
|
|
||||||
const metaNodes = await Promise.all(
|
const metaNodes = await Promise.all(
|
||||||
plugins.map(async (plugin) => {
|
Object.values(plugins).map(async (plugin) => {
|
||||||
if (!plugin.getMetaNodes) {
|
if (!plugin.getMetaNodes) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
@@ -39,7 +47,7 @@ const expandNode = async <TAttributes extends Attributes>({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const planables = node.remaining.filter((planable) => {
|
const planables = node.remaining.filter((planable) => {
|
||||||
const hasNonPlanable = plugins.some(
|
const hasNonPlanable = Object.values(plugins).some(
|
||||||
(plugin) => plugin.isPlanable && !plugin.isPlanable(node, planable),
|
(plugin) => plugin.isPlanable && !plugin.isPlanable(node, planable),
|
||||||
);
|
);
|
||||||
return !hasNonPlanable;
|
return !hasNonPlanable;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
export type { GraphNode } from './types/node';
|
export type { GraphNode } from './types/node';
|
||||||
export type { Planable } from './types/planable';
|
export type { Planable } from './types/planable';
|
||||||
export { expandNode } from './algorithm/expand-node';
|
export { expandNode } from './algorithm/expand-node';
|
||||||
export { calulation, type CalulationResult } from './algorithm/calulation';
|
export { Bob, type CalulationResult } from './algorithm/calulation';
|
||||||
export { plugins } from './plugins/index';
|
export { plugins } from './plugins/index';
|
||||||
|
|||||||
20
packages/algorithm/src/plugins/create.ts
Normal file
20
packages/algorithm/src/plugins/create.ts
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import type { TSchema, Static } from '@sinclair/typebox';
|
||||||
|
import type { Plugin } from '../types/plugin';
|
||||||
|
|
||||||
|
const createPlugin = <
|
||||||
|
TAttribuesSchema extends TSchema,
|
||||||
|
TContextSchema extends TSchema,
|
||||||
|
>(
|
||||||
|
attributes: TAttribuesSchema,
|
||||||
|
context: TContextSchema,
|
||||||
|
plugin: Omit<
|
||||||
|
Plugin<Static<TAttribuesSchema>, Static<TContextSchema>>,
|
||||||
|
'attributes' | 'context'
|
||||||
|
>,
|
||||||
|
): Plugin<Static<TAttribuesSchema>, Static<TContextSchema>> => ({
|
||||||
|
...plugin,
|
||||||
|
attributes,
|
||||||
|
context,
|
||||||
|
});
|
||||||
|
|
||||||
|
export { createPlugin };
|
||||||
@@ -1,9 +1,8 @@
|
|||||||
import { Attributes } from '../types/node';
|
|
||||||
import { Plugin } from '../types/plugin';
|
import { Plugin } from '../types/plugin';
|
||||||
import { transport } from './transport';
|
import { transport } from './transport';
|
||||||
|
|
||||||
const plugins = {
|
const plugins = {
|
||||||
transport,
|
transport,
|
||||||
} satisfies Record<string, (...args: any[]) => Plugin<Attributes>>;
|
} satisfies Record<string, (...args: any[]) => Plugin>;
|
||||||
|
|
||||||
export { plugins };
|
export { plugins };
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { GraphNode } from '../types/node';
|
import { Type } from '@sinclair/typebox';
|
||||||
import { Plugin } from '../types/plugin';
|
import { createPlugin } from './create';
|
||||||
|
|
||||||
type GetTravelTime = (from: string, to: string) => Promise<number>;
|
type GetTravelTime = (from: string, to: string) => Promise<number>;
|
||||||
|
|
||||||
@@ -7,13 +7,15 @@ type TransportOptions = {
|
|||||||
getTravelTime: GetTravelTime;
|
getTravelTime: GetTravelTime;
|
||||||
};
|
};
|
||||||
|
|
||||||
type TransportAttributes = {
|
const transport = ({ getTravelTime }: TransportOptions) =>
|
||||||
locations?: string[];
|
createPlugin(
|
||||||
};
|
Type.Object({
|
||||||
|
locations: Type.Optional(Type.Array(Type.String())),
|
||||||
const transport = ({
|
}),
|
||||||
getTravelTime,
|
Type.Object({
|
||||||
}: TransportOptions): Plugin<TransportAttributes> => ({
|
location: Type.String(),
|
||||||
|
}),
|
||||||
|
{
|
||||||
getMetaNodes: async (node) => {
|
getMetaNodes: async (node) => {
|
||||||
const locations =
|
const locations =
|
||||||
(node.type !== 'travel' &&
|
(node.type !== 'travel' &&
|
||||||
@@ -24,28 +26,33 @@ const transport = ({
|
|||||||
.flat(),
|
.flat(),
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
.filter((location) => location !== node.location)
|
.filter((location) => location !== node.context.location)
|
||||||
.filter(Boolean)
|
.filter(Boolean)
|
||||||
.map((l) => l!)) ||
|
.map((l) => l!)) ||
|
||||||
[];
|
[];
|
||||||
|
|
||||||
const travelNodes = await Promise.all(
|
const travelNodes = await Promise.all(
|
||||||
locations.map<Promise<GraphNode<TransportAttributes>>>(
|
locations.map(async (location) => {
|
||||||
async (location) => {
|
const travelTime = await getTravelTime(
|
||||||
const travelTime = await getTravelTime(node.location, location);
|
node.context.location,
|
||||||
|
location,
|
||||||
|
);
|
||||||
return {
|
return {
|
||||||
...node,
|
...node,
|
||||||
type: 'travel',
|
type: 'travel' as const,
|
||||||
|
context: {
|
||||||
|
...node.context,
|
||||||
|
location,
|
||||||
|
},
|
||||||
planable: undefined,
|
planable: undefined,
|
||||||
location,
|
location,
|
||||||
exploreId: 0,
|
exploreId: 0,
|
||||||
score: node.score - 20,
|
score: node.score - 10,
|
||||||
time: node.time + node.duration,
|
time: node.time + node.duration,
|
||||||
duration: travelTime,
|
duration: travelTime,
|
||||||
parent: node.id,
|
parent: node.id,
|
||||||
};
|
};
|
||||||
},
|
}),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return travelNodes;
|
return travelNodes;
|
||||||
@@ -53,12 +60,13 @@ const transport = ({
|
|||||||
isPlanable: (node, planable) => {
|
isPlanable: (node, planable) => {
|
||||||
if (
|
if (
|
||||||
planable.attributes?.locations &&
|
planable.attributes?.locations &&
|
||||||
!planable.attributes?.locations.includes(node.location)
|
!planable.attributes?.locations.includes(node.context.location)
|
||||||
) {
|
) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
export { transport };
|
export { transport };
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ import type { Planable } from './planable';
|
|||||||
|
|
||||||
type Attributes = any;
|
type Attributes = any;
|
||||||
|
|
||||||
type GraphNode<TAttributes extends Attributes = Attributes> = {
|
type GraphNode<
|
||||||
|
TAttributes extends Attributes = Attributes,
|
||||||
|
TContext extends Attributes = Attributes,
|
||||||
|
> = {
|
||||||
id: string;
|
id: string;
|
||||||
type: 'root' | 'planable' | 'travel';
|
type: 'root' | 'planable' | 'travel';
|
||||||
score: number;
|
score: number;
|
||||||
location: string;
|
context: TContext;
|
||||||
parent: string | null;
|
parent: string | null;
|
||||||
time: number;
|
time: number;
|
||||||
exploreId: number;
|
exploreId: number;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ type Planable<TAttributes extends Attributes = Attributes> = {
|
|||||||
};
|
};
|
||||||
attributes: TAttributes;
|
attributes: TAttributes;
|
||||||
required?: boolean;
|
required?: boolean;
|
||||||
locations?: string[];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export type { Planable };
|
export type { Planable };
|
||||||
|
|||||||
@@ -1,25 +1,31 @@
|
|||||||
import { Attributes, GraphNode } from './node';
|
import { GraphNode } from './node';
|
||||||
import { Planable } from './planable';
|
import { Planable } from './planable';
|
||||||
|
|
||||||
type Plugin<TAttributes extends Attributes = Attributes> = {
|
type Plugin<TAttributes = any, TContext = any> = {
|
||||||
|
context: any;
|
||||||
|
attributes: any;
|
||||||
getMetaNodes?: (
|
getMetaNodes?: (
|
||||||
node: GraphNode<TAttributes>,
|
node: GraphNode<TAttributes, TContext>,
|
||||||
) => Promise<GraphNode<TAttributes>[]>;
|
) => Promise<GraphNode<TAttributes, TContext>[]>;
|
||||||
isImpossible?: (node: GraphNode<TAttributes>) => Promise<boolean>;
|
isImpossible?: (node: GraphNode<TAttributes, TContext>) => Promise<boolean>;
|
||||||
isPlanable?: (
|
isPlanable?: (
|
||||||
node: GraphNode<TAttributes>,
|
node: GraphNode<TAttributes, TContext>,
|
||||||
planable: Planable<TAttributes>,
|
planable: Planable<TAttributes>,
|
||||||
) => boolean;
|
) => boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
type Plugins = Plugin[];
|
type Plugins = Record<string, Plugin>;
|
||||||
|
|
||||||
type PluginAttributes<TPlugins extends Plugins> = {
|
type PluginAttributes<TPlugins extends Plugins> = {
|
||||||
[K in keyof TPlugins]: TPlugins[K] extends Plugin<infer TAttributes>
|
[K in keyof TPlugins]: TPlugins[K] extends Plugin<infer TAttributes, any>
|
||||||
? TAttributes extends Attributes
|
|
||||||
? TAttributes
|
? TAttributes
|
||||||
: never
|
|
||||||
: never;
|
: never;
|
||||||
}[number];
|
}[keyof TPlugins];
|
||||||
|
|
||||||
export type { Plugin, Plugins, PluginAttributes };
|
type PluginContext<TPlugins extends Plugins> = {
|
||||||
|
[K in keyof TPlugins]: TPlugins[K] extends Plugin<any, infer TContext>
|
||||||
|
? TContext
|
||||||
|
: never;
|
||||||
|
}[keyof TPlugins];
|
||||||
|
|
||||||
|
export type { Plugin, Plugins, PluginAttributes, PluginContext };
|
||||||
|
|||||||
@@ -1,8 +1,12 @@
|
|||||||
{
|
{
|
||||||
"extends": "./tsconfig.base.json",
|
"extends": "./tsconfig.base.json",
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["ES2022", "DOM"],
|
"lib": [
|
||||||
|
"ES2022",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
"target": "ES2022",
|
"target": "ES2022",
|
||||||
"module": "ESNext"
|
"module": "ES2022",
|
||||||
|
"moduleResolution": "node"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<title>Vite + React + TS</title>
|
<title>Vite + React + TS</title>
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ const Block: React.FC<BlockProps> = ({
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
setError(error);
|
setError(error);
|
||||||
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
setRunning(false);
|
setRunning(false);
|
||||||
@@ -75,6 +76,7 @@ const Block: React.FC<BlockProps> = ({
|
|||||||
}
|
}
|
||||||
if (type === 'error') {
|
if (type === 'error') {
|
||||||
setError(payload);
|
setError(payload);
|
||||||
|
console.error(payload);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
worker.addEventListener('message', listener);
|
worker.addEventListener('message', listener);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { calulation, plugins } from '@bob-the-algorithm/core';
|
import { Bob, plugins } from '@bob-the-algorithm/core';
|
||||||
import { createWorker } from '../../features/runner/worker';
|
import { createWorker } from '../../features/runner/worker';
|
||||||
import { convertResult } from '../../utils/graph';
|
import { convertResult } from '../../utils/graph';
|
||||||
|
|
||||||
@@ -6,17 +6,21 @@ const MIN = 1000 * 60;
|
|||||||
const HOUR = 1000 * 60 * 60;
|
const HOUR = 1000 * 60 * 60;
|
||||||
|
|
||||||
const getTravelTime = async () => 30 * MIN;
|
const getTravelTime = async () => 30 * MIN;
|
||||||
|
const transport = plugins.transport({
|
||||||
|
getTravelTime,
|
||||||
|
});
|
||||||
|
|
||||||
const realistic = async () => {
|
const realistic = async () => {
|
||||||
const result = await calulation({
|
try {
|
||||||
|
const bob = new Bob({
|
||||||
|
plugins: { transport },
|
||||||
|
});
|
||||||
|
const result = await bob.run({
|
||||||
|
context: {
|
||||||
location: 'home',
|
location: 'home',
|
||||||
time: 0,
|
},
|
||||||
|
start: 0,
|
||||||
heuristic: ({ completed }) => completed.length >= 3,
|
heuristic: ({ completed }) => completed.length >= 3,
|
||||||
plugins: [
|
|
||||||
plugins.transport({
|
|
||||||
getTravelTime,
|
|
||||||
}),
|
|
||||||
],
|
|
||||||
planables: [
|
planables: [
|
||||||
{
|
{
|
||||||
id: `Brush teeth`,
|
id: `Brush teeth`,
|
||||||
@@ -141,6 +145,10 @@ const realistic = async () => {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
return convertResult(result);
|
return convertResult(result);
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
createWorker({
|
createWorker({
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import './script.ts';
|
||||||
const worker = new Worker(new URL('./script.ts', import.meta.url), {
|
const worker = new Worker(new URL('./script.ts', import.meta.url), {
|
||||||
type: 'module',
|
type: 'module',
|
||||||
});
|
});
|
||||||
|
|||||||
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@@ -31,6 +31,10 @@ importers:
|
|||||||
version: 20.5.9
|
version: 20.5.9
|
||||||
|
|
||||||
packages/algorithm:
|
packages/algorithm:
|
||||||
|
dependencies:
|
||||||
|
'@sinclair/typebox':
|
||||||
|
specifier: ^0.31.14
|
||||||
|
version: 0.31.14
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@bob-the-algorithm/config':
|
'@bob-the-algorithm/config':
|
||||||
specifier: workspace:^
|
specifier: workspace:^
|
||||||
@@ -1234,6 +1238,10 @@ packages:
|
|||||||
rollup: 3.28.1
|
rollup: 3.28.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@sinclair/typebox@0.31.14:
|
||||||
|
resolution: {integrity: sha512-2spk0ie6J/4r+nwb55OtBXUn5cZLF9S98fopIjuutBVoq8yLRNh+h8QvMkCjMu5gWBMnnZ/PUSXeHE3xGBPKLQ==}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@swc/core-darwin-arm64@1.3.82:
|
/@swc/core-darwin-arm64@1.3.82:
|
||||||
resolution: {integrity: sha512-JfsyDW34gVKD3uE0OUpUqYvAD3yseEaicnFP6pB292THtLJb0IKBBnK50vV/RzEJtc1bR3g1kNfxo2PeurZTrA==}
|
resolution: {integrity: sha512-JfsyDW34gVKD3uE0OUpUqYvAD3yseEaicnFP6pB292THtLJb0IKBBnK50vV/RzEJtc1bR3g1kNfxo2PeurZTrA==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
|||||||
Reference in New Issue
Block a user