commit bd0065c6356d57de89cd0a023a7f84c121389ea1 Author: kitsunecafe Date: Wed Nov 6 17:17:16 2024 -0600 ewrarf :3 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d570088 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ + diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..53bfdb5 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,22 @@ +{ + "name": "graphecs", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "graphecs", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "bitecs": "^0.3.40" + } + }, + "node_modules/bitecs": { + "version": "0.3.40", + "resolved": "https://registry.npmjs.org/bitecs/-/bitecs-0.3.40.tgz", + "integrity": "sha512-wAylY4pNfX8IeIH5phtwt1lUNtHKrkoSNrArI7Ris2Y4nEQWFIVvXdgAuqprEg9bq8Wolmlj0gVfeG6MFmtI2Q==", + "license": "MPL-2.0" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..5de5863 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "graphecs", + "version": "1.0.0", + "main": "src/index.js", + "type": "module", + "scripts": { + "start": "node src/index.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "", + "dependencies": { + "bitecs": "^0.3.40" + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..595ae73 --- /dev/null +++ b/src/index.js @@ -0,0 +1,43 @@ +import { query } from './query.js' +import { + createWorld, + Types, + defineComponent, + defineQuery, + addEntity, + addComponent, + pipe, +} from 'bitecs' + +const Edge = { from: Types.eid, to: Types.eid } +const Fox = defineComponent() +const Knows = defineComponent(Edge) +const Bot = defineComponent() + +const components = { + Fox, + Bot, + Knows +} + +const world = createWorld() +world.components = components + +const rown = addEntity(world) +addComponent(world, Fox, rown) + +const cynn = addEntity(world) +addComponent(world, Bot, cynn) + +const edge = addEntity(world) +addComponent(world, Knows, edge) +Knows.from[edge] = rown +Knows.to[edge] = cynn + +//const q = query(world, '(:Fox)') +//q(world).forEach(eid => console.log(eid, 'has Fox!')) + +const q2 = query(world, '(rawran:Fox)-[:Knows]->(cynnnnnnnn:Bot)') +q2(world).forEach(eid => console.log(eid)) + + diff --git a/src/query.js b/src/query.js new file mode 100644 index 0000000..0c6eb9d --- /dev/null +++ b/src/query.js @@ -0,0 +1,49 @@ +import { defineQuery, hasComponent } from 'bitecs' +/// danm this rules !!! +const re = /\((?\w+)?:(?\w+)\)(-\[(?\w+)?:(?\w+)\]->\((?\w+)?:(?\w+)\))*/ + +const node = (name, label) => ({ name, label }) + +const parse = s => { + const result = s.match(re) + const groups = result.groups + + return { + from: node(groups.fromName || 'a', groups.fromLabel), + to: node(groups.toName || 'b', groups.toLabel), + edge: node(groups.edgeName, groups.edgeLabel) + } +} + +export const query = (world, s) => { + const meta = parse(s) + const from = world.components[meta.from.label] + const to = world.components[meta.to.label] + const edge = world.components[meta.edge.label] + + const fromQuery = defineQuery([from]) + const toQuery = defineQuery([to]) + const edgeQuery = defineQuery([edge]) + + return (world) => { + const result = [] + + const fq = fromQuery(world) + const tq = toQuery(world) + const eq = edgeQuery(world) + + for(const feid of fq) { + const targets = [] + + for(const eeid of eq) { + if(edge.from[eeid] === feid && hasComponent(world, to, edge.to[eeid])) { + targets.push(edge.to[eeid]) + } + } + + result.push({ [feid]: targets }) + } + + return result + } +} diff --git a/src/result.js b/src/result.js new file mode 100644 index 0000000..fa9cf61 --- /dev/null +++ b/src/result.js @@ -0,0 +1,40 @@ +export class Result { + constructor(value, error) { + this.value = value + this.error = error + } + + static Ok(value) { + return new Result(value, null) + } + + static Err(error) { + return new Result(null, error) + } + + isOk() { + return this.error === null + } + + isErr() { + return !this.isOk() + } + + map(fn) { + if (this.isOk()) { + return Result.Ok(fn(this.value)) + } else { + return this + } + } + + flatMap(fn) { + if (this.isOk()) { + return fn(this.value) + } else { + return this + } + } +} + +