import { addTag, } from '../../tags/addTag'; import { AwarenessRelation, } from '../relations/AwarenessRelation'; import { AwareTypes, } from '../relations/AwareTypes'; import { EpistemicTypes, } from './EpistemicTypes'; import { EpistemologyType, } from './EpistemologyType'; import { getStructuredTags, } from '../../tags/getStructuredTags'; import { getTag, } from '../../tags/getTag'; import { IAwarenessRelation, } from '../relations/IAwarenessRelation'; import { IEpistemology, } from './IEpistemology'; import { IEpistemologyConstructorArgs, } from './IEpistemologyConstructorArgs'; import { FindEpistemicArgs, IFindBaseArgs, FindAwarenessArgs, } from '../querying/FindModelArgs'; import { IModel, } from '../models/IModel'; import { isAwareType, } from '../typeGuards/isAwareType'; import { ISerializedEpistemology, } from './ISerializedEpistemology'; import { isEpistemicType, } from '../typeGuards/isEpistemicType'; import { ITag, } from '../../tags/ITag'; import { IThoughtRelation, } from '../relations/IThoughtRelation'; import { IWorld, } from '../world/IWorld'; import { ModelType, } from '../models/ModelType'; import { OnticTypes, } from '../ontology/OnticTypes'; import { removeTag, } from '../../tags/removeTag'; import { Tag, } from '../../tags/Tag'; import { assertValid, } from 'ts-assertions'; export class Epistemology< Type extends EpistemicTypes | ModelType.Thought, Knowledge extends ModelType, > implements IEpistemology { /* Thoughts may not be "aware" of anything. Other types need both ontic and * epistemic aspects in order to be aware. */ private readonly __awareness: Type extends EpistemicTypes & OnticTypes ? IAwarenessRelation : null; public get awareness() { return this.__awareness; } private readonly __modelType: Type; public get modelType() { return this.__modelType; } private __tags: readonly ITag[] = Object.freeze([]); public get tags() { return this.__tags; } private readonly __type: symbol = EpistemologyType; public get type() { return this.__type; } private readonly __thoughts: IThoughtRelation; public get thoughts() { return this.__thoughts; } private readonly __world: IWorld; public get world() { return this.__world; } constructor(world: IWorld, args: IEpistemologyConstructorArgs) { this.__world = assertValid(world); const { finalize, initialize, modelType, tags, } = assertValid>(args); this.__modelType = assertValid( modelType, 'The value of the modelType argument did not meet the isModelType ' + 'type guard.', isEpistemicType, ); if (isAwareType(this.modelType)) { // @ts-ignore this.__awareness = ( new AwarenessRelation( this.world, { modelType: this.modelType }, ) ); } if (tags) { this.__tags = getStructuredTags(assertValid( tags, 'The tags argument to the Epistemology constructor was not valid.', Array.isArray, )); } if (typeof finalize === 'function') { this.finalize = finalize; } if (typeof initialize === 'function') { this.initialize = initialize; this.initialize(this); } } public readonly addTag = (tag: Tag) => ( void (this.__tags = Object.freeze(addTag(tag))) ); public readonly clone = ( self: IEpistemology, ): IEpistemology => { const copy = Object.assign( Object.create(Object.getPrototypeOf(self)), self, ); copy.__awareness = self.awareness ? self.awareness.clone(self.awareness!) : null; copy.finalize = typeof self.finalize === 'function' ? self.finalize : null; copy.initialize = typeof self.initialize === 'function' ? self.initialize : null; /*copy.__thoughts = self.thoughts ? self.thoughts.clone(self.thoughts) : null;*/ copy.world = self.world; return copy; }; public readonly destroy = ( self: IEpistemology, ) => { if (typeof self.finalize === 'function') { self.finalize(self); } if (self.awareness) { self.awareness.destroy(self.awareness!); } //self.thoughts.destroy(self.thoughts); self.tags.forEach(self.removeTag); ((self: any) => { delete self.__awareness; delete self.awareness; delete self.finalize; delete self.initialize; delete self.__thoughts; delete self.thoughts; delete self.__tags; delete self.tags; })(self); }; public readonly find = ( args: string | (IFindBaseArgs & FindEpistemicArgs), ): IModel | null => this.findAllGenerator( typeof args === 'string' ? { name: args, } as IFindBaseArgs & FindEpistemicArgs : args, ).next().value || null; public readonly findAll = ( args: '*' | (IFindBaseArgs & FindEpistemicArgs), ): readonly IModel[] => { const ret = []; for (const model of this.findAllGenerator(args)) { ret.push(model); } return ret; }; readonly findAllGenerator = ((self: IEpistemology) => function* ( args: '*' | (IFindBaseArgs & FindEpistemicArgs), ): IterableIterator> { if (self.awareness && isAwareType(self.modelType)) { yield* self.awareness.findAllGenerator( args as IFindBaseArgs & FindAwarenessArgs, ); } yield* self.thoughts.findAllGenerator(args); })(this); public readonly getTag = (toSearch: Tag) => getTag(this.tags, toSearch); public readonly removeTag = (tag: Tag) => ( void (this.__tags = Object.freeze(removeTag(this.tags, tag))) ); public readonly serialize = ( self: IEpistemology, spaces: number = 0, ) => JSON.stringify(self.serializeToObject(self), null, spaces); public readonly serializeToObject = ( self: IEpistemology, ): ISerializedEpistemology => ({ awareness: self.awareness ? self.awareness.serializeToObject(self.awareness!) : null, modelType: self.modelType, tags: [ ...self.tags ], thoughts: self.thoughts.serializeToObject(self.thoughts), }); public readonly finalize?: ( self: IEpistemology, ) => void; public readonly initialize?: ( self: IEpistemology, ) => void; }