diff --git a/README.md b/README.md index 6eb1e636..4f887684 100644 --- a/README.md +++ b/README.md @@ -51,7 +51,10 @@ When in doubt simplify. * [Muxified Turing Machine](https://github.com/Phuire-Research/Stratimux/blob/main/The-Muxified-Turing-Machine.md) - The governing concept for this entire framework.:| ## Change Log ![Tests](https://github.com/Phuire-Research/Stratimux/actions/workflows/node.js.yml/badge -### Stratimux 0.2.0 Stealth Roll Out +### QoL +* Broke up complex files into distinguishable parts +* Hooked in deck functionality into method creators properly +### Stratimux 0.2.0-1 Stealth Roll Out * Introduces type safety throughout your muxiums via a new DECK Interface System * e: Entry Action * c: Comparators, uses semaphores to ensure a stringless comparison @@ -59,9 +62,6 @@ When in doubt simplify. * Override + Hard Override - Will wipe out current actions within the Muxiums Action Que System -### Beyond 0.2.0 -* Originally intended to release a conversion guide, but due to the degree of changes. The focus has shifted back towards Huirth and supplying an easy means of accessing tutorials and a proper conceptual library. -* With this release will be reverting back to incremental changes and improvements. Other typescript projects @@ -129,7 +129,7 @@ export const createMuXConcept = () => { ); }; ``` -### muuXqOfMux.quality.ts +### muXqOfMux.quality.ts This isolates all the parts necessary for your actions to have impact within this system. Types are a qualitative description of the overall quality. As even though they are not explicitly used within this system. They likewise better inform training data, and likewise act as unique identifiers if you are accessing the action creators directly versus the DECK System. Internally Stratimux uses semaphores as the method of quality routing within the Muxium. This is to reduce the time complexity of each look up. To further increase the speed of execution of your applications, utilize the supplied DECK Interfaces at each point of entry. diff --git a/package.json b/package.json index dfefa88f..dcba9db5 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "stratimux", "license": "GPL-3.0", - "version": "0.2.1", + "version": "0.2.2", "description": "Muxified Turing Machine", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/src/concepts/chain/chain.concept.ts b/src/concepts/chain/chain.concept.ts index 7d5faa6a..a131da75 100644 --- a/src/concepts/chain/chain.concept.ts +++ b/src/concepts/chain/chain.concept.ts @@ -6,7 +6,7 @@ And would be considered a precursor to ActionStrategy. $>*/ /*<#*/ import { Action, MuxiumDeck, PrincipleFunction } from '../../index'; -import { createConcept } from '../../model/concept'; +import { createConcept } from '../../model/concept/concept'; import { chainPrinciple } from './chain.principle'; import { chainEnd } from './qualities/chainEnd.quality'; import { chainPrepareChain } from './qualities/prepareChain.quality'; diff --git a/src/concepts/chain/chain.principle.ts b/src/concepts/chain/chain.principle.ts index 4cffa830..6ffae418 100644 --- a/src/concepts/chain/chain.principle.ts +++ b/src/concepts/chain/chain.principle.ts @@ -4,14 +4,11 @@ generate a principle that observes the chain's actionQue and dispatches those actions in order upon each state notification. $>*/ /*<#*/ -import { Subscriber } from 'rxjs'; -import { Concepts } from '../../model/concept'; -import { Action } from '../../model/action'; -import { PrincipleFunction, registerPrincipleSubscription } from '../../model/principle'; -import { ChainPrinciple, ChainQualities, ChainState, chainName } from './chain.concept'; -import { selectMuxifiedState } from '../../model/selector'; -import { MuxiumDeck, MuxiumState } from '../muxium/muxium.concept'; -import { MuxifiedSubject } from '../../model/stagePlanner'; +import { Concepts } from '../../model/concept/concept.type'; +import { registerPrincipleSubscription } from '../../model/principle'; +import { ChainPrinciple, ChainState, chainName } from './chain.concept'; +import { selectMuxifiedState } from '../../model/selector/selector'; +import { Action } from '../../model/action/action.type'; export const chainPrinciple: ChainPrinciple = ({ observer, diff --git a/src/concepts/chain/qualities/prepareChain.quality.ts b/src/concepts/chain/qualities/prepareChain.quality.ts index e2a14f93..16ca69b7 100644 --- a/src/concepts/chain/qualities/prepareChain.quality.ts +++ b/src/concepts/chain/qualities/prepareChain.quality.ts @@ -1,26 +1,25 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Chain Concept, -generate a quality will add actions into the Chain's actionQue state property. -$>*/ -/*<#*/ -import { Action, AnyAction } from '../../../model/action'; -import { createQualityCardWithPayload } from '../../../model/quality'; -import { selectPayload } from '../../../model/selector'; -import { ChainState } from '../chain.concept'; - -export type ChainPrepareChainPayload = { - actions: AnyAction[] -} - -export const chainPrepareChain = createQualityCardWithPayload({ - type: 'dispatch Actions from Action Que via Payload to be Chained', - reducer: (state, {payload}) => { - return { - actionQue: [ - ...state.actionQue, - ...payload.actions - ] - }; - } -}); +/*<$ +For the asynchronous graph programming framework Stratimux and Chain Concept, +generate a quality will add actions into the Chain's actionQue state property. +$>*/ +/*<#*/ +import { AnyAction } from '../../../model/action/action.type'; +import { createQualityCardWithPayload } from '../../../model/quality'; +import { ChainState } from '../chain.concept'; + +export type ChainPrepareChainPayload = { + actions: AnyAction[] +} + +export const chainPrepareChain = createQualityCardWithPayload({ + type: 'dispatch Actions from Action Que via Payload to be Chained', + reducer: (state, {payload}) => { + return { + actionQue: [ + ...state.actionQue, + ...payload.actions + ] + }; + } +}); /*#>*/ \ No newline at end of file diff --git a/src/concepts/counter/counter.concept.ts b/src/concepts/counter/counter.concept.ts index 3600c69c..d6f848b2 100644 --- a/src/concepts/counter/counter.concept.ts +++ b/src/concepts/counter/counter.concept.ts @@ -1,42 +1,43 @@ -/*<$ -For the asynchronous graph programming framework Stratimux generate a Counter Concept that will keep track of a count in its state. -$>*/ -/*<#*/ -import { counterAdd } from './qualities/add.quality'; -import { counterSubtract } from './qualities/subtract.quality'; -import { counterSetCount } from './qualities/setCount.quality'; -import { Concept, createConcept } from '../../model/concept'; -import { counterMultiply } from './qualities/multiply.quality'; -export { countingStrategy } from './strategies/counting.strategy'; - -export type CounterState = { - count: number -} - -export const counterName = 'counter'; - -const initialCounterState: CounterState = { - count: 0 -}; - -const counterQualities = { - counterAdd, - counterSubtract, - counterSetCount, - counterMultiply -}; - -export type CounterDeck = { - counter: Concept, -}; - -export type CounterQualities = typeof counterQualities; - -export const createCounterConcept = () => { - return createConcept( - counterName, - initialCounterState, - counterQualities - ); -}; +/*<$ +For the asynchronous graph programming framework Stratimux generate a Counter Concept that will keep track of a count in its state. +$>*/ +/*<#*/ +import { counterAdd } from './qualities/add.quality'; +import { counterSubtract } from './qualities/subtract.quality'; +import { counterSetCount } from './qualities/setCount.quality'; +import { createConcept } from '../../model/concept/concept'; +import { Concept } from '../../model/concept/concept.type'; +import { counterMultiply } from './qualities/multiply.quality'; +export { countingStrategy } from './strategies/counting.strategy'; + +export type CounterState = { + count: number +} + +export const counterName = 'counter'; + +const initialCounterState: CounterState = { + count: 0 +}; + +const counterQualities = { + counterAdd, + counterSubtract, + counterSetCount, + counterMultiply +}; + +export type CounterDeck = { + counter: Concept, +}; + +export type CounterQualities = typeof counterQualities; + +export const createCounterConcept = () => { + return createConcept( + counterName, + initialCounterState, + counterQualities + ); +}; /*#>*/ \ No newline at end of file diff --git a/src/concepts/counter/counter.selector.ts b/src/concepts/counter/counter.selector.ts index 3b978315..307cf505 100644 --- a/src/concepts/counter/counter.selector.ts +++ b/src/concepts/counter/counter.selector.ts @@ -1,9 +1,10 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Counter Concept, generate a KeyedSelector for the Counter's count state property. -$>*/ -/*<#*/ -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; -import { CounterState } from './counter.concept'; - -export const counterSelectCount: KeyedSelector = createConceptKeyedSelector('counter', 'count'); +/*<$ +For the asynchronous graph programming framework Stratimux and Counter Concept, generate a KeyedSelector for the Counter's count state property. +$>*/ +/*<#*/ +import { createConceptKeyedSelector } from '../../model/selector/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { CounterState } from './counter.concept'; + +export const counterSelectCount: KeyedSelector = createConceptKeyedSelector('counter', 'count'); /*#>*/ \ No newline at end of file diff --git a/src/concepts/counter/qualities/multiply.quality.ts b/src/concepts/counter/qualities/multiply.quality.ts index 83ef1cf4..a6dd7f9f 100644 --- a/src/concepts/counter/qualities/multiply.quality.ts +++ b/src/concepts/counter/qualities/multiply.quality.ts @@ -6,7 +6,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { CounterState } from '../counter.concept'; import { counterSelectCount } from '../counter.selector'; import { createQualityCardWithPayload } from '../../../model/quality'; -import { selectPayload } from '../../../model/selector'; +import { selectPayload } from '../../../model/selector/selector'; type CounterMultiplyPayload = { by: number; diff --git a/src/concepts/counter/qualities/setCount.quality.ts b/src/concepts/counter/qualities/setCount.quality.ts index 3ed24900..8d611d75 100644 --- a/src/concepts/counter/qualities/setCount.quality.ts +++ b/src/concepts/counter/qualities/setCount.quality.ts @@ -1,27 +1,27 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Counter Concept, -generate a quality that set the state property count to the new count provided -by the action's payload. -$>*/ -/*<#*/ -import { defaultMethodCreator } from '../../../model/quality'; -import { CounterState } from '../counter.concept'; -import { counterSelectCount } from '../counter.selector'; -import { selectPayload } from '../../../model/selector'; -import { createQualityCardWithPayload } from '../../../model/quality'; - -export type CounterSetCountPayload = { - newCount: number -} -export const counterSetCount = createQualityCardWithPayload({ - type: 'Counter set Count', - reducer: (state, {payload}) => { - const {newCount} = payload; - return { - count: newCount - }; - }, - methodCreator: defaultMethodCreator, - keyedSelectors: [counterSelectCount] -}); +/*<$ +For the asynchronous graph programming framework Stratimux and Counter Concept, +generate a quality that set the state property count to the new count provided +by the action's payload. +$>*/ +/*<#*/ +import { defaultMethodCreator } from '../../../model/quality'; +import { CounterState } from '../counter.concept'; +import { counterSelectCount } from '../counter.selector'; +import { selectPayload } from '../../../model/selector/selector'; +import { createQualityCardWithPayload } from '../../../model/quality'; + +export type CounterSetCountPayload = { + newCount: number +} +export const counterSetCount = createQualityCardWithPayload({ + type: 'Counter set Count', + reducer: (state, {payload}) => { + const {newCount} = payload; + return { + count: newCount + }; + }, + methodCreator: defaultMethodCreator, + keyedSelectors: [counterSelectCount] +}); /*#>*/ \ No newline at end of file diff --git a/src/concepts/counter/strategies/counting.strategy.ts b/src/concepts/counter/strategies/counting.strategy.ts index 59fdc2c5..21adf05b 100644 --- a/src/concepts/counter/strategies/counting.strategy.ts +++ b/src/concepts/counter/strategies/counting.strategy.ts @@ -1,77 +1,77 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Counter Concept, -generate an ActionStrategy that will perform a series of counter actions that will -ultimately just increment the count by one. -$>*/ -/*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; -import { CounterDeck, CounterQualities, CounterState } from '../counter.concept'; -import { Deck } from '../../../model/deck'; - -export const countingTopic = 'Counting Strategy'; -export function countingStrategy>(deck: Partial): ActionStrategy | undefined { - if (deck.counter) { - const { - counterSubtract, - counterAdd - } = deck.counter.e; - - const stepFive = createActionNode(counterSubtract(), { - successNotes: { - preposition: 'and finally', - denoter: 'One.', - }, - }); - const stepFour = createActionNode(counterAdd(), { - successNode: stepFive, - successNotes: { - preposition: '', - denoter: 'One;', - }, - }); - const stepThree = createActionNode(counterAdd(), { - successNode: stepFour, - successNotes: { - preposition: '', - denoter: 'One;', - }, - }); - const stepTwo = createActionNode(counterSubtract(), { - successNode: stepThree, - successNotes: { - preposition: '', - denoter: 'One;', - }, - }); - const stepOne = createActionNode(counterAdd(), { - successNode: stepTwo, - successNotes: { - preposition: '', - denoter: 'One;', - }, - }); - - const params: ActionStrategyParameters = { - topic: countingTopic, - initialNode: stepOne, - }; - - return createStrategy(params); - } else { - return undefined; - } -} - -export const additionalCountingStrategyTopic = 'Additional Counting Strategy'; -export function additionalCountingStrategy>(deck: Partial): ActionStrategy | undefined { - if (deck.counter) { - const strategy = countingStrategy(deck); - if (strategy) { - strategy.topic = additionalCountingStrategyTopic; - return strategy; - } - } - return undefined; -} +/*<$ +For the asynchronous graph programming framework Stratimux and Counter Concept, +generate an ActionStrategy that will perform a series of counter actions that will +ultimately just increment the count by one. +$>*/ +/*<#*/ +import { CounterDeck } from '../counter.concept'; +import { Deck } from '../../../model/deck'; +import { ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; + +export const countingTopic = 'Counting Strategy'; +export function countingStrategy>(deck: Partial): ActionStrategy | undefined { + if (deck.counter) { + const { + counterSubtract, + counterAdd + } = deck.counter.e; + + const stepFive = createActionNode(counterSubtract(), { + successNotes: { + preposition: 'and finally', + denoter: 'One.', + }, + }); + const stepFour = createActionNode(counterAdd(), { + successNode: stepFive, + successNotes: { + preposition: '', + denoter: 'One;', + }, + }); + const stepThree = createActionNode(counterAdd(), { + successNode: stepFour, + successNotes: { + preposition: '', + denoter: 'One;', + }, + }); + const stepTwo = createActionNode(counterSubtract(), { + successNode: stepThree, + successNotes: { + preposition: '', + denoter: 'One;', + }, + }); + const stepOne = createActionNode(counterAdd(), { + successNode: stepTwo, + successNotes: { + preposition: '', + denoter: 'One;', + }, + }); + + const params: ActionStrategyParameters = { + topic: countingTopic, + initialNode: stepOne, + }; + + return createStrategy(params); + } else { + return undefined; + } +} + +export const additionalCountingStrategyTopic = 'Additional Counting Strategy'; +export function additionalCountingStrategy>(deck: Partial): ActionStrategy | undefined { + if (deck.counter) { + const strategy = countingStrategy(deck); + if (strategy) { + strategy.topic = additionalCountingStrategyTopic; + return strategy; + } + } + return undefined; +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/experiment.concept.ts b/src/concepts/experiment/experiment.concept.ts index 56e41ef0..e2570e08 100644 --- a/src/concepts/experiment/experiment.concept.ts +++ b/src/concepts/experiment/experiment.concept.ts @@ -3,8 +3,9 @@ For the asynchronous graph programming framework Stratimux generate the Experime different configurations of Stratimux to be provably terminating. $>*/ /*<#*/ -import { Mode, createConcept } from '../../model/concept'; -import { Action } from '../../model/action'; +import { Mode } from '../../model/concept/concept.type'; +import { createConcept } from '../../model/concept/concept'; +import { Action } from '../../model/action/action.type'; import { PrincipleFunction } from '../../model/principle'; export type ExperimentState = { diff --git a/src/concepts/experiment/experiment.principle.ts b/src/concepts/experiment/experiment.principle.ts index 506e3bd3..bb230db7 100644 --- a/src/concepts/experiment/experiment.principle.ts +++ b/src/concepts/experiment/experiment.principle.ts @@ -5,10 +5,9 @@ in sequence upon each observation of state. $>*/ /*<#*/ import { PrincipleFunction } from '../../model/principle'; -import { StagePlanner, createStage, stageWaitForOpenThenIterate } from '../../model/stagePlanner'; -import { selectMuxifiedState } from '../../model/selector'; +import { selectMuxifiedState } from '../../model/selector/selector'; +import { StagePlanner } from '../../model/stagePlanner/stagePlanner.type'; import { ExperimentState, experimentName } from './experiment.concept'; -import { muxiumRegisterStagePlanner } from '../muxium/qualities/registerStagePlanner.quality'; export const experimentActionQuePrincipleCreator = () => { const experimentActionQuePrinciple: PrincipleFunction = ({ @@ -18,11 +17,11 @@ export const experimentActionQuePrincipleCreator = () => { conceptSemaphore }) => { let readyToGo = false; - const planExperiment: StagePlanner = plan('Experiment Principle Plan', ({d__}) => [ - stageWaitForOpenThenIterate(() => + const planExperiment: StagePlanner = plan('Experiment Principle Plan', ({d__, stage, stageO}) => [ + stageO(() => (d__.muxium.e.muxiumRegisterStagePlanner({conceptName: experimentName, stagePlanner: planExperiment})) ), - createStage(({concepts}) => { + stage(({concepts}) => { const experimentState = selectMuxifiedState(concepts, conceptSemaphore); if (experimentState && experimentState.actionQue.length > 0) { if (!readyToGo) { diff --git a/src/concepts/experiment/qualities/asyncIterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/asyncIterateIdThenReceiveInMethod.quality.ts index 3b667a4d..b89f7a5b 100644 --- a/src/concepts/experiment/qualities/asyncIterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/asyncIterateIdThenReceiveInMethod.quality.ts @@ -3,14 +3,11 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep Then its method will asynchronously unify the state's id value onto the strategy. $>*/ /*<#*/ -import { Concepts } from '../../../model/concept'; import { ExperimentState } from '../experiment.concept'; -import { MuxifiedSubject } from '../../../model/stagePlanner'; -import { createAsyncMethodWithState } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; -import { Subject } from 'rxjs'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCard } from '../../../model/quality'; +import { createAsyncMethodWithState } from '../../../model/method/methodAsync'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const experimentAsyncIterateIdThenReceiveInMethod = createQualityCard({ type: 'Experiment asynchronously iterate ID then receive in Method via State', diff --git a/src/concepts/experiment/qualities/checkInStrategy.quality.ts b/src/concepts/experiment/qualities/checkInStrategy.quality.ts index 43f386a9..a80b3234 100644 --- a/src/concepts/experiment/qualities/checkInStrategy.quality.ts +++ b/src/concepts/experiment/qualities/checkInStrategy.quality.ts @@ -3,10 +3,10 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep in the current strategy to the state's actionQue. $>*/ /*<#*/ -import { strategySuccess } from '../../../model/actionStrategy'; import { muxiumConcludeType } from '../../muxium/qualities/conclude.quality'; import { ExperimentState } from '../experiment.concept'; import { createQualityCard } from '../../../model/quality'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const experimentCheckInStrategy = createQualityCard({ type: 'Experiment check in Action', diff --git a/src/concepts/experiment/qualities/debounceAsyncIterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/debounceAsyncIterateIdThenReceiveInMethod.quality.ts index 5cd7a3bd..226deef7 100644 --- a/src/concepts/experiment/qualities/debounceAsyncIterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/debounceAsyncIterateIdThenReceiveInMethod.quality.ts @@ -3,15 +3,11 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep Then debounce the action via the qualities method that will then unify the state's id into the strategy's data. $>*/ /*<#*/ -import { Concepts } from '../../../model/concept'; import { ExperimentState } from '../experiment.concept'; -import { MuxifiedSubject } from '../../../model/stagePlanner'; -import { createAsyncMethodDebounceWithState } from '../../../model/method'; -import { selectPayload } from '../../../model/selector'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; -import { Subject } from 'rxjs'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCardWithPayload } from '../../../model/quality'; +import { createAsyncMethodDebounceWithState } from '../../../model/method/methodAsyncDebounce'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export type ExperimentDebounceAsyncIterateIdThenReceiveInMethodPayload = { setId: number; diff --git a/src/concepts/experiment/qualities/debounceAsyncNextActionNode.quality.ts b/src/concepts/experiment/qualities/debounceAsyncNextActionNode.quality.ts index d5b7e522..0b420bdc 100644 --- a/src/concepts/experiment/qualities/debounceAsyncNextActionNode.quality.ts +++ b/src/concepts/experiment/qualities/debounceAsyncNextActionNode.quality.ts @@ -3,9 +3,9 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep in the ongoing strategy. $>*/ /*<#*/ +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; +import { createAsyncMethodDebounce } from '../../../model/method/methodAsyncDebounce'; import { defaultReducer } from '../../../model/quality'; -import { createAsyncMethodDebounce } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; import { createQualityCard } from '../../../model/quality'; export const experimentAsyncDebounceNextActionNode = createQualityCard({ diff --git a/src/concepts/experiment/qualities/debounceIterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/debounceIterateIdThenReceiveInMethod.quality.ts index 529852d9..61d4d27e 100644 --- a/src/concepts/experiment/qualities/debounceIterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/debounceIterateIdThenReceiveInMethod.quality.ts @@ -5,10 +5,10 @@ That will finally unify the state id and setId from the payload into the most re $>*/ /*<#*/ import { ExperimentState } from '../experiment.concept'; -import { createMethodDebounceWithState } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCardWithPayload } from '../../../model/quality'; +import { createMethodDebounceWithState } from '../../../model/method/methodDebounce'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export type ExperimentDebounceIterateIdThenReceiveInMethodPayload = { setId: number; diff --git a/src/concepts/experiment/qualities/debounceNextActionNode.quality.ts b/src/concepts/experiment/qualities/debounceNextActionNode.quality.ts index 93cd0459..19ef21c1 100644 --- a/src/concepts/experiment/qualities/debounceNextActionNode.quality.ts +++ b/src/concepts/experiment/qualities/debounceNextActionNode.quality.ts @@ -3,9 +3,9 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep recent. Then dispatch the most recent's next action via the supplied action strategy. $>*/ /*<#*/ +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; +import { createMethodDebounce } from '../../../model/method/methodDebounce'; import { nullReducer } from '../../../model/quality'; -import { createMethodDebounce } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; import { createQualityCard } from '../../../model/quality'; export const experimentDebounceNextActionNode = createQualityCard({ diff --git a/src/concepts/experiment/qualities/iterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/iterateIdThenReceiveInMethod.quality.ts index bd45a731..0f73af26 100644 --- a/src/concepts/experiment/qualities/iterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/iterateIdThenReceiveInMethod.quality.ts @@ -4,10 +4,10 @@ set the id supplied to the method into the strategy's data field. $>*/ /*<#*/ import { ExperimentState } from '../experiment.concept'; -import { createMethodWithState } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; +import { createMethodWithState } from '../../../model/method/method'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCard } from '../../../model/quality'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const experimentIterateIdThenReceiveInMethod = createQualityCard({ type: 'Experiment iterate ID then receive in Method via State', diff --git a/src/concepts/experiment/qualities/recurseIncrementId.quality.ts b/src/concepts/experiment/qualities/recurseIncrementId.quality.ts index ea5ca66a..54b59ad9 100644 --- a/src/concepts/experiment/qualities/recurseIncrementId.quality.ts +++ b/src/concepts/experiment/qualities/recurseIncrementId.quality.ts @@ -3,15 +3,12 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep limited via a control variable that is an arbitrary string array that is shifted until depleted. $>*/ /*<#*/ -import { Concepts } from '../../../model/concept'; import { ExperimentState } from '../experiment.concept'; -import { MuxifiedSubject } from '../../../model/stagePlanner'; -import { createAsyncMethodWithState } from '../../../model/method'; -import { selectPayload } from '../../../model/selector'; -import { strategyRecurse, strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; -import { Subject } from 'rxjs'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCardWithPayload } from '../../../model/quality'; +import { createAsyncMethodWithState } from '../../../model/method/methodAsync'; +import { strategyRecurse } from '../../../model/action/strategy/actionStrategyConsumersAdvanced'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export type ExperimentRecurseIterateId = { controlling: string[] diff --git a/src/concepts/experiment/qualities/throttleAsyncIterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/throttleAsyncIterateIdThenReceiveInMethod.quality.ts index 3a16ce32..0e2dd7be 100644 --- a/src/concepts/experiment/qualities/throttleAsyncIterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/throttleAsyncIterateIdThenReceiveInMethod.quality.ts @@ -4,10 +4,10 @@ asynchronously dispatch the next action in the incoming strategy, then throttle $>*/ /*<#*/ import { ExperimentState } from '../experiment.concept'; -import { createAsyncMethodThrottleWithState } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCardWithPayload } from '../../../model/quality'; +import { createAsyncMethodThrottleWithState } from '../../../model/method/methodAsyncThrottle'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export type ExperimentThrottleAsyncIterateIdThenReceiveInMethodPayload = { setId: number; diff --git a/src/concepts/experiment/qualities/throttleIterateIdThenReceiveInMethod.quality.ts b/src/concepts/experiment/qualities/throttleIterateIdThenReceiveInMethod.quality.ts index c002cc9e..bc88bc50 100644 --- a/src/concepts/experiment/qualities/throttleIterateIdThenReceiveInMethod.quality.ts +++ b/src/concepts/experiment/qualities/throttleIterateIdThenReceiveInMethod.quality.ts @@ -3,15 +3,11 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep dispatch the next action in the incoming strategy, then throttle the quality for a period of time. $>*/ /*<#*/ -import { Concepts } from '../../../model/concept'; import { ExperimentState } from '../experiment.concept'; -import { MuxifiedSubject } from '../../../model/stagePlanner'; -import { createMethodThrottleWithState } from '../../../model/method'; -import { selectPayload } from '../../../model/selector'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; -import { Subject } from 'rxjs'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { createQualityCardWithPayload } from '../../../model/quality'; +import { createMethodThrottleWithState } from '../../../model/method/methodThrottle'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export type ExperimentThrottleIterateIdThenReceiveInMethodPayload = { setId: number; diff --git a/src/concepts/experiment/qualities/timerEmitAction.quality.ts b/src/concepts/experiment/qualities/timerEmitAction.quality.ts index e843f895..5deaff11 100644 --- a/src/concepts/experiment/qualities/timerEmitAction.quality.ts +++ b/src/concepts/experiment/qualities/timerEmitAction.quality.ts @@ -4,10 +4,10 @@ action in the incoming strategy via an inner timer. $>*/ /*<#*/ import { nullReducer } from '../../../model/quality'; -import { createAsyncMethod } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; import { muxiumConclude } from '../../muxium/qualities/conclude.quality'; import { createQualityCard } from '../../../model/quality'; +import { createAsyncMethod } from '../../../model/method/methodAsync'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const experimentTimerEmitAction = createQualityCard({ type: 'Experiment create async method with timer, to return action', diff --git a/src/concepts/experiment/qualities/timerEmitActionWithState.quality.ts b/src/concepts/experiment/qualities/timerEmitActionWithState.quality.ts index 3f38ee3a..638972b9 100644 --- a/src/concepts/experiment/qualities/timerEmitActionWithState.quality.ts +++ b/src/concepts/experiment/qualities/timerEmitActionWithState.quality.ts @@ -3,12 +3,12 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep next action in the ActionStrategy via a timeout. While appending to the strategy's data field the current mock value from state. $>*/ /*<#*/ -import { createAsyncMethodWithState } from '../../../model/method'; -import { strategySuccess } from '../../../model/actionStrategy'; import { muxiumConclude } from '../../muxium/qualities/conclude.quality'; -import { strategyData_muxifyData } from '../../../model/actionStrategyData'; +import { strategyData_muxifyData } from '../../../model/action/strategy/actionStrategyData'; import { ExperimentState } from '../experiment.concept'; import { createQualityCard, nullReducer } from '../../../model/quality'; +import { createAsyncMethodWithState } from '../../../model/method/methodAsync'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const experimentTimerEmitActionWithState = createQualityCard({ type: 'Experiment create async method with timer and state, to return action', diff --git a/src/concepts/experiment/strategies/asyncDebounceAddOne.strategy.ts b/src/concepts/experiment/strategies/asyncDebounceAddOne.strategy.ts index 4de489f6..9ba3d4d6 100644 --- a/src/concepts/experiment/strategies/asyncDebounceAddOne.strategy.ts +++ b/src/concepts/experiment/strategies/asyncDebounceAddOne.strategy.ts @@ -1,44 +1,45 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Experiment Concept, generate a strategy that will debounce next action to be dispatched. -Then when the debounce time expires enacts the counter add one quality. -$>*/ -/*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; -import { Deck } from '../../../model/deck'; -import { CounterDeck } from '../../counter/counter.concept'; -import { ExperimentState } from '../experiment.concept'; -import { experimentAsyncDebounceNextActionNode } from '../qualities/debounceAsyncNextActionNode.quality'; - -const qs = {experimentAsyncDebounceNextActionNode}; -type ExperimentDeck = { - experiment : Concept -} -export type ExperimentAsyncDebounceStrategyDeck = Deck - -export const experimentAsyncDebounceAddOneTopic = 'Async debounce add one'; -export function experimentAsyncDebounceAddOneStrategy(deck: ExperimentAsyncDebounceStrategyDeck): ActionStrategy { - const stepTwo = createActionNode(deck.counter.e.counterAdd(), { - successNotes: { - preposition: '', - denoter: 'One;', - }, - agreement: 1000, - }); - const stepOne = createActionNode(deck.experiment.e.experimentAsyncDebounceNextActionNode(), { - successNode: stepTwo, - successNotes: { - preposition: '', - denoter: 'One;', - }, - agreement: 1000, - }); - - const params: ActionStrategyParameters = { - topic: experimentAsyncDebounceAddOneTopic, - initialNode: stepOne, - }; - - return createStrategy(params); -} +/*<$ +For the asynchronous graph programming framework Stratimux and Experiment Concept, generate a strategy that will debounce next action to be dispatched. +Then when the debounce time expires enacts the counter add one quality. +$>*/ +/*<#*/ +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; +import { Deck } from '../../../model/deck'; +import { CounterDeck } from '../../counter/counter.concept'; +import { ExperimentState } from '../experiment.concept'; +import { experimentAsyncDebounceNextActionNode } from '../qualities/debounceAsyncNextActionNode.quality'; + +const qs = {experimentAsyncDebounceNextActionNode}; +type ExperimentDeck = { + experiment : Concept +} +export type ExperimentAsyncDebounceStrategyDeck = Deck + +export const experimentAsyncDebounceAddOneTopic = 'Async debounce add one'; +export function experimentAsyncDebounceAddOneStrategy(deck: ExperimentAsyncDebounceStrategyDeck): ActionStrategy { + const stepTwo = createActionNode(deck.counter.e.counterAdd(), { + successNotes: { + preposition: '', + denoter: 'One;', + }, + agreement: 1000, + }); + const stepOne = createActionNode(deck.experiment.e.experimentAsyncDebounceNextActionNode(), { + successNode: stepTwo, + successNotes: { + preposition: '', + denoter: 'One;', + }, + agreement: 1000, + }); + + const params: ActionStrategyParameters = { + topic: experimentAsyncDebounceAddOneTopic, + initialNode: stepOne, + }; + + return createStrategy(params); +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/strategies/asyncIterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/asyncIterateIdThenAddToData.strategy.ts index 3562798f..333e2764 100644 --- a/src/concepts/experiment/strategies/asyncIterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/asyncIterateIdThenAddToData.strategy.ts @@ -3,8 +3,9 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep async iterate id that will later notify the Muxium of its conclusion. $>*/ /*<#*/ -import { ActionStrategy, ActionStrategyParameters, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentAsyncIterateIdThenReceiveInMethod } from '../qualities/asyncIterateIdThenReceiveInMethod.quality'; diff --git a/src/concepts/experiment/strategies/debounceAddOne.strategy.ts b/src/concepts/experiment/strategies/debounceAddOne.strategy.ts index 66bc2e8f..9981d06c 100644 --- a/src/concepts/experiment/strategies/debounceAddOne.strategy.ts +++ b/src/concepts/experiment/strategies/debounceAddOne.strategy.ts @@ -1,43 +1,43 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Experiment Concept, generate a strategy that will debounce the step in the strategy. -The final step of the strategy will increment the Counter's count by one. -$>*/ -/*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; -import { Deck } from '../../../model/deck'; -import { CounterDeck } from '../../counter/counter.concept'; -import { counterAdd } from '../../counter/qualities/add.quality'; -import { ExperimentState } from '../experiment.concept'; -import { experimentDebounceNextActionNode } from '../qualities/debounceNextActionNode.quality'; - -const qs = {experimentDebounceNextActionNode}; -type ExperimentDeck = { - experiment : Concept -} -export type ExperimentAsyncIterateIdThenAddToDataDeck = Deck - -export const experimentDebounceAddOneTopic = 'Debounce add one'; -export function experimentDebounceAddOneStrategy(deck: ExperimentAsyncIterateIdThenAddToDataDeck): ActionStrategy { - const stepTwo = createActionNode(deck.counter.e.counterAdd(), { - successNotes: { - preposition: '', - denoter: 'One;', - }, - agreement: 1000, - }); - const stepOne = createActionNode(deck.experiment.e.experimentDebounceNextActionNode(), { - successNode: stepTwo, - successNotes: { - preposition: '', - denoter: 'One;', - }, - agreement: 1000, - }); - - return createStrategy({ - topic: experimentDebounceAddOneTopic, - initialNode: stepOne, - }); -} +/*<$ +For the asynchronous graph programming framework Stratimux and Experiment Concept, generate a strategy that will debounce the step in the strategy. +The final step of the strategy will increment the Counter's count by one. +$>*/ +/*<#*/ +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; +import { Deck } from '../../../model/deck'; +import { CounterDeck } from '../../counter/counter.concept'; +import { ExperimentState } from '../experiment.concept'; +import { experimentDebounceNextActionNode } from '../qualities/debounceNextActionNode.quality'; + +const qs = {experimentDebounceNextActionNode}; +type ExperimentDeck = { + experiment : Concept +} +export type ExperimentAsyncIterateIdThenAddToDataDeck = Deck + +export const experimentDebounceAddOneTopic = 'Debounce add one'; +export function experimentDebounceAddOneStrategy(deck: ExperimentAsyncIterateIdThenAddToDataDeck): ActionStrategy { + const stepTwo = createActionNode(deck.counter.e.counterAdd(), { + successNotes: { + preposition: '', + denoter: 'One;', + }, + agreement: 1000, + }); + const stepOne = createActionNode(deck.experiment.e.experimentDebounceNextActionNode(), { + successNode: stepTwo, + successNotes: { + preposition: '', + denoter: 'One;', + }, + agreement: 1000, + }); + + return createStrategy({ + topic: experimentDebounceAddOneTopic, + initialNode: stepOne, + }); +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/strategies/debounceAsyncIterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/debounceAsyncIterateIdThenAddToData.strategy.ts index c7f45299..3fa199bc 100644 --- a/src/concepts/experiment/strategies/debounceAsyncIterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/debounceAsyncIterateIdThenAddToData.strategy.ts @@ -4,8 +4,9 @@ generate a single step strategy that will iterate the Experiment state ID, then debounce and asynchronously notify the Muxium of the strategy's conclusion. $>*/ /*<#*/ -import { ActionStrategy, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentDebounceAsyncIterateIdThenReceiveInMethod } from '../qualities/debounceAsyncIterateIdThenReceiveInMethod.quality'; diff --git a/src/concepts/experiment/strategies/debounceIterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/debounceIterateIdThenAddToData.strategy.ts index 74686b5a..93a9ca9b 100644 --- a/src/concepts/experiment/strategies/debounceIterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/debounceIterateIdThenAddToData.strategy.ts @@ -3,8 +3,9 @@ For the asynchronous graph programming framework Stratimux and Experiment Concep then debounce notify the Muxium of its conclusion while appending the ID to its data field. $>*/ /*<#*/ -import { ActionStrategy, ActionStrategyParameters, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentDebounceIterateIdThenReceiveInMethod } from '../qualities/debounceIterateIdThenReceiveInMethod.quality'; diff --git a/src/concepts/experiment/strategies/experimentCounting.strategy.ts b/src/concepts/experiment/strategies/experimentCounting.strategy.ts index 200f7681..44476c50 100644 --- a/src/concepts/experiment/strategies/experimentCounting.strategy.ts +++ b/src/concepts/experiment/strategies/experimentCounting.strategy.ts @@ -4,16 +4,16 @@ generate a strategy that will take ownership of the Counter's count state proper Then proceed to increment and decrement the count over a sequence that in total only increments to count by one. $>*/ /*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concept, } from '../../../model/concept'; +import { Concept, } from '../../../model/concept/concept.type'; import { CounterDeck, } from '../../counter/counter.concept'; import { counterSelectCount } from '../../counter/counter.selector'; import { OwnershipDeck } from '../../ownership/ownership.concept'; import { experimentCheckInStrategy } from '../qualities/checkInStrategy.quality'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; -import { Quality } from '../../../model/quality'; import { MuxiumDeck } from '../../muxium/muxium.concept'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; const qs = {experimentCheckInStrategy}; type ExperimentDeck = {experiment: Concept}; diff --git a/src/concepts/experiment/strategies/iterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/iterateIdThenAddToData.strategy.ts index 0ecb49e0..9346e031 100644 --- a/src/concepts/experiment/strategies/iterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/iterateIdThenAddToData.strategy.ts @@ -4,8 +4,9 @@ generate an ActionStrategy that will iterate the Experiment's state ID. Then notify the Muxium of its conclusion while appending the ID to the strategy's data field. $>*/ /*<#*/ -import { ActionStrategy, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentIterateIdThenReceiveInMethod } from '../qualities/iterateIdThenReceiveInMethod.quality'; diff --git a/src/concepts/experiment/strategies/puntCounting.strategy.ts b/src/concepts/experiment/strategies/puntCounting.strategy.ts index 5cf58694..74a2a2b7 100644 --- a/src/concepts/experiment/strategies/puntCounting.strategy.ts +++ b/src/concepts/experiment/strategies/puntCounting.strategy.ts @@ -1,27 +1,29 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Experiment Concept, -generate a strategy that will punt a counting strategy in favor of a new -strategy that will check in the punted strategy into an actionQue. That will later be dispatched via a principle. -$>*/ -/*<#*/ -import { ActionStrategy, createActionNode, createStrategy, strategyPunt } from '../../../model/actionStrategy'; -import { counterSelectCount } from '../../counter/counter.selector'; -import { additionalCountingStrategy } from '../../counter/strategies/counting.strategy'; -import { ExperimentCountingDeck } from './experimentCounting.strategy'; - -export const experimentPuntCountingStrategyTopic = 'This will Punt the Counting Strategy into the Experiment\'s Action Que'; -export function experimentPuntCountingStrategy(deck: ExperimentCountingDeck): ActionStrategy | undefined { - const stepOne = createActionNode(deck.experiment.e.experimentCheckInStrategy(), { - keyedSelectors: [counterSelectCount] - }); - - const strategy = additionalCountingStrategy(deck); - if (strategy) { - return strategyPunt(strategy, createStrategy({ - topic: experimentPuntCountingStrategyTopic, - initialNode: stepOne, - })); - } - return undefined; -} +/*<$ +For the asynchronous graph programming framework Stratimux and Experiment Concept, +generate a strategy that will punt a counting strategy in favor of a new +strategy that will check in the punted strategy into an actionQue. That will later be dispatched via a principle. +$>*/ +/*<#*/ +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { strategyPunt } from '../../../model/action/strategy/actionStrategyConsumersAdvanced'; +import { counterSelectCount } from '../../counter/counter.selector'; +import { additionalCountingStrategy } from '../../counter/strategies/counting.strategy'; +import { ExperimentCountingDeck } from './experimentCounting.strategy'; + +export const experimentPuntCountingStrategyTopic = 'This will Punt the Counting Strategy into the Experiment\'s Action Que'; +export function experimentPuntCountingStrategy(deck: ExperimentCountingDeck): ActionStrategy | undefined { + const stepOne = createActionNode(deck.experiment.e.experimentCheckInStrategy(), { + keyedSelectors: [counterSelectCount] + }); + + const strategy = additionalCountingStrategy(deck); + if (strategy) { + return strategyPunt(strategy, createStrategy({ + topic: experimentPuntCountingStrategyTopic, + initialNode: stepOne, + })); + } + return undefined; +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/strategies/recursivelyIterateId.strategy.ts b/src/concepts/experiment/strategies/recursivelyIterateId.strategy.ts index 2fd2db16..dd3d75da 100644 --- a/src/concepts/experiment/strategies/recursivelyIterateId.strategy.ts +++ b/src/concepts/experiment/strategies/recursivelyIterateId.strategy.ts @@ -1,27 +1,28 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Experiment Concept, -generate a strategy that will cursively iterate the Experiment's state ID, -that is limited by an incoming array of strings. -$>*/ -/*<#*/ -import { ActionStrategy, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; -import { Deck } from '../../../model/deck'; -import { ExperimentState } from '../experiment.concept'; -import { experimentRecurseIterateId } from '../qualities/recurseIncrementId.quality'; - -const qs = {experimentRecurseIterateId}; -type ExperimentDeck = {experiment: Concept}; -export type ExperimentIterateIdThenAddToDataDeck = Deck - -export const experimentRecursivelyIterateIdTopic = 'Recursively iterate experiment ID then add to strategy data'; -export function experimentRecursivelyIterateId( - deck: ExperimentIterateIdThenAddToDataDeck, - controlling: string[] -): ActionStrategy { - return createStrategy({ - topic: experimentRecursivelyIterateIdTopic, - initialNode: createActionNode(deck.experiment.e.experimentRecurseIterateId({controlling})) - }); -} +/*<$ +For the asynchronous graph programming framework Stratimux and Experiment Concept, +generate a strategy that will cursively iterate the Experiment's state ID, +that is limited by an incoming array of strings. +$>*/ +/*<#*/ +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; +import { Deck } from '../../../model/deck'; +import { ExperimentState } from '../experiment.concept'; +import { experimentRecurseIterateId } from '../qualities/recurseIncrementId.quality'; + +const qs = {experimentRecurseIterateId}; +type ExperimentDeck = {experiment: Concept}; +export type ExperimentIterateIdThenAddToDataDeck = Deck + +export const experimentRecursivelyIterateIdTopic = 'Recursively iterate experiment ID then add to strategy data'; +export function experimentRecursivelyIterateId( + deck: ExperimentIterateIdThenAddToDataDeck, + controlling: string[] +): ActionStrategy { + return createStrategy({ + topic: experimentRecursivelyIterateIdTopic, + initialNode: createActionNode(deck.experiment.e.experimentRecurseIterateId({controlling})) + }); +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/strategies/throttleAsyncIterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/throttleAsyncIterateIdThenAddToData.strategy.ts index 65781f02..f70acba4 100644 --- a/src/concepts/experiment/strategies/throttleAsyncIterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/throttleAsyncIterateIdThenAddToData.strategy.ts @@ -5,8 +5,9 @@ then throttle the next action to be asynchronously dispatched from the quality's to the strategy's data field. $>*/ /*<#*/ -import { ActionStrategy, ActionStrategyParameters, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { MuxiumDeck } from '../../muxium/muxium.concept'; import { ExperimentState } from '../experiment.concept'; diff --git a/src/concepts/experiment/strategies/throttleIterateIdThenAddToData.strategy.ts b/src/concepts/experiment/strategies/throttleIterateIdThenAddToData.strategy.ts index 19d6a834..38836966 100644 --- a/src/concepts/experiment/strategies/throttleIterateIdThenAddToData.strategy.ts +++ b/src/concepts/experiment/strategies/throttleIterateIdThenAddToData.strategy.ts @@ -6,8 +6,9 @@ unify the the ID the method has received onto the strategy's state field. Then f strategy's conclusion. $>*/ /*<#*/ -import { ActionStrategy, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentThrottleIterateIdThenReceiveInMethod } from '../qualities/throttleIterateIdThenReceiveInMethod.quality'; diff --git a/src/concepts/experiment/strategies/timedMockToTrue.strategy.ts b/src/concepts/experiment/strategies/timedMockToTrue.strategy.ts index 3b26b968..9d3f2108 100644 --- a/src/concepts/experiment/strategies/timedMockToTrue.strategy.ts +++ b/src/concepts/experiment/strategies/timedMockToTrue.strategy.ts @@ -1,33 +1,34 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Experiment Concept, -generate a strategy that will eventually set the Experiment's mock property -to true. This is accomplished via a timer emit action quality. That will then finally dispatch the setting action. -$>*/ -/*<#*/ -import { ActionStrategy, ActionStrategyParameters, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; -import { Deck } from '../../../model/deck'; -import { ExperimentState } from '../experiment.concept'; -import { experimentMockToTrue } from '../qualities/mockToTrue.quality'; -import { experimentTimerEmitAction } from '../qualities/timerEmitAction.quality'; - -const qs = { - experimentMockToTrue, - experimentTimerEmitAction -}; -type ExperimentDeck = {experiment: Concept}; -export type ExperimentTimedMockToTrueDeck = Deck - -export const experimentTimedMockToTrueTopic = 'This will use a async method to eventually set mock to True'; -export function experimentTimedMockToTrue(deck: ExperimentTimedMockToTrueDeck): ActionStrategy { - const stepTwo = createActionNode(deck.experiment.e.experimentMockToTrue()); - const stepOne = createActionNode(deck.experiment.e.experimentTimerEmitAction(), { - successNode: stepTwo, - }); - - return createStrategy({ - topic: experimentTimedMockToTrueTopic, - initialNode: stepOne, - }); -} +/*<$ +For the asynchronous graph programming framework Stratimux and Experiment Concept, +generate a strategy that will eventually set the Experiment's mock property +to true. This is accomplished via a timer emit action quality. That will then finally dispatch the setting action. +$>*/ +/*<#*/ +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; +import { Deck } from '../../../model/deck'; +import { ExperimentState } from '../experiment.concept'; +import { experimentMockToTrue } from '../qualities/mockToTrue.quality'; +import { experimentTimerEmitAction } from '../qualities/timerEmitAction.quality'; + +const qs = { + experimentMockToTrue, + experimentTimerEmitAction +}; +type ExperimentDeck = {experiment: Concept}; +export type ExperimentTimedMockToTrueDeck = Deck + +export const experimentTimedMockToTrueTopic = 'This will use a async method to eventually set mock to True'; +export function experimentTimedMockToTrue(deck: ExperimentTimedMockToTrueDeck): ActionStrategy { + const stepTwo = createActionNode(deck.experiment.e.experimentMockToTrue()); + const stepOne = createActionNode(deck.experiment.e.experimentTimerEmitAction(), { + successNode: stepTwo, + }); + + return createStrategy({ + topic: experimentTimedMockToTrueTopic, + initialNode: stepOne, + }); +} /*#>*/ \ No newline at end of file diff --git a/src/concepts/experiment/strategies/timedMockToTrueWithState.strategy.ts b/src/concepts/experiment/strategies/timedMockToTrueWithState.strategy.ts index 646f1bc3..d52bc5de 100644 --- a/src/concepts/experiment/strategies/timedMockToTrueWithState.strategy.ts +++ b/src/concepts/experiment/strategies/timedMockToTrueWithState.strategy.ts @@ -5,8 +5,9 @@ true. While attaching the original mock value to the strategy's data field. Then step that will finally set the value to true. Then notify the muxium of the strategy's successful conclusion. $>*/ /*<#*/ -import { ActionStrategy, ActionStrategyParameters, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { Concept } from '../../../model/concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { Concept } from '../../../model/concept/concept.type'; import { Deck } from '../../../model/deck'; import { ExperimentState } from '../experiment.concept'; import { experimentMockToTrue } from '../qualities/mockToTrue.quality'; diff --git a/src/concepts/muxium/model/gather.model.ts b/src/concepts/muxium/model/gather.model.ts index 015fe84e..cbf90348 100644 --- a/src/concepts/muxium/model/gather.model.ts +++ b/src/concepts/muxium/model/gather.model.ts @@ -5,9 +5,10 @@ Note this should be limited to actions that provably do not require error correc Otherwise you would want to use a Strategy Stitch instead. $>*/ /*<#*/ -import { Action, AnyAction, createAction } from '../../../model/action'; -import { ActionNode, ActionNodeOptions, createActionNode, createStrategy } from '../../../model/actionStrategy'; -import { muxiumLog } from '../qualities/log.quality'; +import { ActionNode, ActionNodeOptions } from '../../../model/action/strategy/actionStrategy.type'; +import { Action, AnyAction } from '../../../model/action/action.type'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { createAction } from '../../../model/action/action'; export type MuxiumGatherNode = { actions: Action[], diff --git a/src/concepts/muxium/model/stitch.model.ts b/src/concepts/muxium/model/stitch.model.ts index 31a44ae2..8170c518 100644 --- a/src/concepts/muxium/model/stitch.model.ts +++ b/src/concepts/muxium/model/stitch.model.ts @@ -4,9 +4,9 @@ This function allows for Strategy Stitches to be composed of only one action nod While calling the muxium's stitch quality to silently move to the next node assigned to the end of that stitch. $>*/ /*<#*/ -import { createAction } from '../../../model/action'; -import { ActionNodeOptions, createActionNode } from '../../../model/actionStrategy'; -import { muxiumStitch } from '../qualities/stitch.quality'; +import { createAction } from '../../../model/action/action'; +import { createActionNode } from '../../../model/action/strategy/actionStrategy'; +import { ActionNodeOptions } from '../../../model/action/strategy/actionStrategy.type'; /** * Must be used within an ActionStrategyStitch with only one ActionNode provided. diff --git a/src/concepts/muxium/muxium.close.principle.ts b/src/concepts/muxium/muxium.close.principle.ts index fae4d5b9..535fbc91 100644 --- a/src/concepts/muxium/muxium.close.principle.ts +++ b/src/concepts/muxium/muxium.close.principle.ts @@ -1,13 +1,10 @@ /*<$ For the asynchronous graph programming framework Stratimux and Muxium Concept, generate a principle that will manage the Muxium's close process. $>*/ -import { PrincipleFunction } from '../../model/principle'; -import { selectMuxifiedState } from '../../model/selector'; +import { selectMuxifiedState } from '../../model/selector/selector'; import { MuxiumPrinciple, MuxiumState } from './muxium.concept'; -import { muxiumClose } from './qualities/close.quality'; import { muxiumSelectPrepareClose } from './muxium.selector'; -import { MuxiumQualities } from './qualities'; -import { LoadConcepts } from '../../model/concept'; +import { LoadConcepts } from '../../model/concept/concept.type'; /*<#*/ export const muxiumClosePrinciple: MuxiumPrinciple = ( { diff --git a/src/concepts/muxium/muxium.concept.ts b/src/concepts/muxium/muxium.concept.ts index 073169c9..7ab771cb 100644 --- a/src/concepts/muxium/muxium.concept.ts +++ b/src/concepts/muxium/muxium.concept.ts @@ -29,18 +29,19 @@ import { muxiumPreClose } from './qualities/preClose.quality'; import { muxiumStitch } from './qualities/stitch.quality'; import { muxiumRegisterTimeOut } from './qualities/registerTimeOut.quality'; import { Subject, Subscription } from 'rxjs'; -import { AnyConcept, Concept, ConceptDeck, Concepts, LoadConcepts } from '../../model/concept'; -import { Action, AnyAction } from '../../model/action'; +import { AnyConcept, Concept, Concepts, LoadConcepts } from '../../model/concept/concept.type'; import { muxiumPrinciple } from './muxium.principle'; import { muxiumClosePrinciple } from './muxium.close.principle'; import { blockingMode, permissiveMode } from './muxium.mode'; export { initializationStrategy } from './strategies/initialization.strategy'; -import { createConcept } from '../../model/concept'; -import { NamedStagePlanner, Plan, MuxifiedSubject } from '../../model/stagePlanner'; +import { createConcept } from '../../model/concept/concept'; +import { MuxifiedSubject } from '../../model/stagePlanner/stagePlanner'; import { MuxiumQualities } from './qualities'; -import { Deck, Decks } from '../../model/deck'; -import { MuxiumLoad } from '../../model/muxium'; +import { Decks } from '../../model/deck'; +import { MuxiumLoad } from '../../model/muxium/muxium.type'; import { PrincipleFunction } from '../../model/principle'; +import { Action, AnyAction } from '../../model/action/action.type'; +import { NamedStagePlanner, Plan } from '../../model/stagePlanner/stagePlanner.type'; export type SelectorFunction = (obj: Record) => unknown | undefined; export type KeyedSelector = { diff --git a/src/concepts/muxium/muxium.mode.ts b/src/concepts/muxium/muxium.mode.ts index a7447c01..c64475a3 100644 --- a/src/concepts/muxium/muxium.mode.ts +++ b/src/concepts/muxium/muxium.mode.ts @@ -3,14 +3,15 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, g $>*/ /*<#*/ import { Subject } from 'rxjs'; -import { ActionDeck, Concepts, Mode } from '../../model/concept'; -import { Action, AnyAction, primeAction } from '../../model/action'; +import { ActionDeck, Concepts, Mode } from '../../model/concept/concept.type'; +import { primeAction } from '../../model/action/action'; import { MuxiumState } from './muxium.concept'; -import { MuxifiedSubject } from '../../model/stagePlanner'; -import { getMuxiumState } from '../../model/muxium'; +import { MuxifiedSubject } from '../../model/stagePlanner/stagePlanner'; +import { getMuxiumState } from '../../model/muxium/muxiumHelpers'; import { MuxiumBadActionPayload } from './qualities'; -import { KeyedSelector, updateAtomicSelects } from '../../model/selector'; +import { updateAtomicSelects } from '../../model/selector/selectorAdvanced'; import { Deck } from '../../model/deck'; +import { Action, AnyAction } from '../../model/action/action.type'; export const isActionable = (muxiumState: MuxiumState, action: Action): boolean => { let actionable = true; diff --git a/src/concepts/muxium/muxium.principle.ts b/src/concepts/muxium/muxium.principle.ts index b720f6e7..3f94ef9e 100644 --- a/src/concepts/muxium/muxium.principle.ts +++ b/src/concepts/muxium/muxium.principle.ts @@ -4,20 +4,26 @@ generate a principle that will allow for the modification of the Muxium's loaded $>*/ /*<#*/ import { Observable, Subscriber, catchError } from 'rxjs'; -import { AnyConcept, Concepts, Mode, forEachConcept, qualityToString } from '../../model/concept'; -import { PrincipleFunction, createPrinciple$ } from '../../model/principle'; -import { Action, Actions, createCachedSemaphores } from '../../model/action'; +import { AnyConcept, Concepts, Mode } from '../../model/concept/concept.type'; +import { forEachConcept, qualityToString } from '../../model/concept/conceptHelpers'; +import { createPrinciple$ } from '../../model/principle'; import { MuxiumDeck, muxiumName, MuxiumPrinciple } from './muxium.concept'; -import { createActionNode, strategy, strategyBegin } from '../../model/actionStrategy'; import { addConceptsFromQueThenUnblockStrategy } from './strategies/addConcept.strategy'; import { removeConceptsViaQueThenUnblockStrategy } from './strategies/removeConcept.strategy'; import { blockingMode, permissiveMode } from './muxium.mode'; -import { MuxiumLoad, blockingMethodSubscription, demuxifyDeck, getMuxiumState } from '../../model/muxium'; -import { MuxiumQualities } from './qualities'; import { muxiumSelectAddConceptQue, muxiumSelectRemoveConceptQue } from './muxium.selector'; -import { Deck } from '../../model/deck'; +import { Deck, demuxifyDeck } from '../../model/deck'; import { Comparators } from '../../model/interface'; -import { BundledSelectors, createSelectors, updateKeyedSelectors } from '../../model/selector'; +import { createSelectors, updateKeyedSelectors } from '../../model/selector/selectorAdvanced'; +import { BundledSelectors } from '../../model/selector/selector.type'; +import { Action, Actions } from '../../model/action/action.type'; +import { createCachedSemaphores } from '../../model/action/actionSemaphore'; +import { strategyBegin } from '../../model/action/strategy/actionStrategyConsumers'; +import { createActionNode } from '../../model/action/strategy/actionStrategy'; +import { strata } from '../../model/action/strategy'; +import { getMuxiumState } from '../../model/muxium/muxiumHelpers'; +import { blockingMethodSubscription } from '../../model/method/methodSubscription'; +import { MuxiumLoad } from '../../model/muxium/muxium.type'; export const muxiumPrinciple: MuxiumPrinciple = ( { @@ -216,7 +222,7 @@ export const muxiumPrinciple: MuxiumPrinciple = ( } }, { selectors: [muxiumSelectRemoveConceptQue], priority: Infinity - 2}) ]); - observer.next(strategy.begin(strategy.create({ + observer.next(strata.begin(strata.create({ topic: 'Register Muxium Add/Remove Plans', initialNode: createActionNode(e_.muxiumRegisterStagePlanner({conceptName: muxiumName, stagePlanner: addConceptsPlan}), { successNode: diff --git a/src/concepts/muxium/muxium.selector.ts b/src/concepts/muxium/muxium.selector.ts index 184310d2..21038396 100644 --- a/src/concepts/muxium/muxium.selector.ts +++ b/src/concepts/muxium/muxium.selector.ts @@ -2,8 +2,9 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, generate a series of KeyedSelectors for the MuxiumState. $>*/ /*<#*/ -import { LoadConcepts } from '../../model/concept'; -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; +import { LoadConcepts } from '../../model/concept/concept.type'; +import { createConceptKeyedSelector } from '../../model/selector/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; import { MuxiumState } from './muxium.concept'; export const muxiumSelectOpen: KeyedSelector = createConceptKeyedSelector>('muxium', 'open'); diff --git a/src/concepts/muxium/qualities/addConceptsFromQue.quality.ts b/src/concepts/muxium/qualities/addConceptsFromQue.quality.ts index d3ef1816..9d350494 100644 --- a/src/concepts/muxium/qualities/addConceptsFromQue.quality.ts +++ b/src/concepts/muxium/qualities/addConceptsFromQue.quality.ts @@ -6,7 +6,7 @@ $>*/ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCard } from '../../../model/quality'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumAddConceptsFromQue = createQualityCard>({ diff --git a/src/concepts/muxium/qualities/appendActionListToDialog.quality.ts b/src/concepts/muxium/qualities/appendActionListToDialog.quality.ts index 67dc3d49..072181e2 100644 --- a/src/concepts/muxium/qualities/appendActionListToDialog.quality.ts +++ b/src/concepts/muxium/qualities/appendActionListToDialog.quality.ts @@ -6,7 +6,7 @@ $>*/ import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { AppendActionListToDialogPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumAppendActionListToDialog = createQualityCardWithPayload, AppendActionListToDialogPayload>({ diff --git a/src/concepts/muxium/qualities/appendConceptsToAddQue.quality.ts b/src/concepts/muxium/qualities/appendConceptsToAddQue.quality.ts index 7e06e54b..0ebbe49b 100644 --- a/src/concepts/muxium/qualities/appendConceptsToAddQue.quality.ts +++ b/src/concepts/muxium/qualities/appendConceptsToAddQue.quality.ts @@ -3,7 +3,7 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, g addConceptQue. This will then be observed via the Muxium's principle. $>*/ /*<#*/ -import { AnyConcept, Concept, LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumAppendConceptsToAddQuePayload } from '.'; diff --git a/src/concepts/muxium/qualities/appendConceptsToRemoveQue.quality.ts b/src/concepts/muxium/qualities/appendConceptsToRemoveQue.quality.ts index 46257e91..e2d58979 100644 --- a/src/concepts/muxium/qualities/appendConceptsToRemoveQue.quality.ts +++ b/src/concepts/muxium/qualities/appendConceptsToRemoveQue.quality.ts @@ -6,7 +6,7 @@ $>*/ import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumAppendConceptsToRemoveQuePayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumAppendConceptsToRemoveQue = createQualityCardWithPayload, MuxiumAppendConceptsToRemoveQuePayload>({ diff --git a/src/concepts/muxium/qualities/badAction.quality.ts b/src/concepts/muxium/qualities/badAction.quality.ts index 2caeac0f..c03b27ef 100644 --- a/src/concepts/muxium/qualities/badAction.quality.ts +++ b/src/concepts/muxium/qualities/badAction.quality.ts @@ -6,7 +6,7 @@ of the bad action that was received. $>*/ /*<#*/ import { MuxiumBadActionPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; diff --git a/src/concepts/muxium/qualities/clearBadActionTypeFromBadActionList.quality.ts b/src/concepts/muxium/qualities/clearBadActionTypeFromBadActionList.quality.ts index e833e4d0..a9190231 100644 --- a/src/concepts/muxium/qualities/clearBadActionTypeFromBadActionList.quality.ts +++ b/src/concepts/muxium/qualities/clearBadActionTypeFromBadActionList.quality.ts @@ -8,7 +8,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumClearBadActionTypeFromBadActionListPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumClearBadActionTypeFromBadActionList = createQualityCardWithPayload, MuxiumClearBadActionTypeFromBadActionListPayload>({ diff --git a/src/concepts/muxium/qualities/clearBadPlanFromBadPlanList.quality.ts b/src/concepts/muxium/qualities/clearBadPlanFromBadPlanList.quality.ts index 74c02744..d0e6341f 100644 --- a/src/concepts/muxium/qualities/clearBadPlanFromBadPlanList.quality.ts +++ b/src/concepts/muxium/qualities/clearBadPlanFromBadPlanList.quality.ts @@ -7,7 +7,7 @@ $>*/ import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { MuxiumClearBadPlanFromBadPlanListPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumClearBadPlanFromBadPlanList = createQualityCardWithPayload, MuxiumClearBadPlanFromBadPlanListPayload>({ diff --git a/src/concepts/muxium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts b/src/concepts/muxium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts index 32f6aae8..e8d067d8 100644 --- a/src/concepts/muxium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts +++ b/src/concepts/muxium/qualities/clearBadStrategyTopicFromBadActionList.quality.ts @@ -8,7 +8,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumClearBadStrategyTopicFromBadActionListPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumClearBadStrategyTopicFromBadActionList = createQualityCardWithPayload, MuxiumClearBadStrategyTopicFromBadActionListPayload>({ diff --git a/src/concepts/muxium/qualities/clearDialog.quality.ts b/src/concepts/muxium/qualities/clearDialog.quality.ts index 846d9942..67c0c266 100644 --- a/src/concepts/muxium/qualities/clearDialog.quality.ts +++ b/src/concepts/muxium/qualities/clearDialog.quality.ts @@ -6,7 +6,7 @@ $>*/ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCard } from '../../../model/quality'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumClearDialog = createQualityCard>({ type: 'clear Muxium Dialog', diff --git a/src/concepts/muxium/qualities/close.quality.ts b/src/concepts/muxium/qualities/close.quality.ts index 84f1cace..47f31d40 100644 --- a/src/concepts/muxium/qualities/close.quality.ts +++ b/src/concepts/muxium/qualities/close.quality.ts @@ -5,10 +5,9 @@ This will also exit the current process. $>*/ /*<#*/ import { MuxiumState } from '../muxium.concept'; -import { selectPayload } from '../../../model/selector'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumClosePayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumClose = createQualityCardWithPayload, MuxiumClosePayload>({ type: 'Close Muxium', diff --git a/src/concepts/muxium/qualities/conclude.quality.ts b/src/concepts/muxium/qualities/conclude.quality.ts index 54d924fa..764172be 100644 --- a/src/concepts/muxium/qualities/conclude.quality.ts +++ b/src/concepts/muxium/qualities/conclude.quality.ts @@ -5,7 +5,10 @@ Functionally. This is a pure action with no method or reducer. That will instead within each qualities method if specified. As well as ownership if loaded in the Muxium's concept set. $>*/ /*<#*/ -import { ActionType, getSpecialSemaphore, prepareActionCreator } from '../../../model/action'; + +import { prepareActionCreator } from '../../../model/action/action'; +import { ActionType } from '../../../model/action/action.type'; +import { getSpecialSemaphore } from '../../../model/action/actionSemaphore'; /** * muxiumConcludeType diff --git a/src/concepts/muxium/qualities/index.ts b/src/concepts/muxium/qualities/index.ts index e96ee2d8..14b26840 100644 --- a/src/concepts/muxium/qualities/index.ts +++ b/src/concepts/muxium/qualities/index.ts @@ -3,11 +3,10 @@ For the asynchronous graph programming framework Stratimux generate the Muxium Q $>*/ /*<#*/ import { Subscription } from 'rxjs'; -import { Actions, AnyAction } from '../../../model/action'; import { Quality } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; -import { AnyConcept, Concepts } from '../../../model/concept'; -import { ActionType } from '../../../model/action'; +import { AnyConcept, Concepts } from '../../../model/concept/concept.type'; +import { ActionType, AnyAction } from '../../../model/action/action.type'; export type OpenPayload = { open: boolean diff --git a/src/concepts/muxium/qualities/initializePrinciples.quality.ts b/src/concepts/muxium/qualities/initializePrinciples.quality.ts index 6581e963..67e3765a 100644 --- a/src/concepts/muxium/qualities/initializePrinciples.quality.ts +++ b/src/concepts/muxium/qualities/initializePrinciples.quality.ts @@ -4,15 +4,17 @@ generate a quality that will initialize principles loaded into the Muxium's conc $>*/ /*<#*/ import { Subject, Subscriber } from 'rxjs'; -import { forEachConcept, LoadConcepts } from '../../../model/concept'; +import { forEachConcept } from '../../../model/concept/conceptHelpers'; +import { LoadConcepts } from '../../../model/concept/concept.type'; import { PrincipleFunction, createPrinciple$ } from '../../../model/principle'; -import { Action, Actions, } from '../../../model/action'; import { MuxiumState, muxiumName } from '../muxium.concept'; -import { Planning, MuxifiedSubject } from '../../../model/stagePlanner'; +import { MuxifiedSubject } from '../../../model/stagePlanner/stagePlanner'; import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumInitializePrinciplesPayload } from '.'; import { Comparators } from '../../../model/interface'; -import { BundledSelectors, Selectors } from '../../../model/selector'; +import { BundledSelectors } from '../../../model/selector/selector.type'; +import { Action, Actions } from '../../../model/action/action.type'; +import { Planning } from '../../../model/stagePlanner/stagePlanner.type'; export const muxiumInitializePrinciples = createQualityCardWithPayload, MuxiumInitializePrinciplesPayload>({ diff --git a/src/concepts/muxium/qualities/log.quality.ts b/src/concepts/muxium/qualities/log.quality.ts index 8a1ed9e3..1de1ed5b 100644 --- a/src/concepts/muxium/qualities/log.quality.ts +++ b/src/concepts/muxium/qualities/log.quality.ts @@ -4,9 +4,9 @@ This is used to trouble shoot strategies or simply notify the log of different s $>*/ /*<#*/ import { nullReducer } from '../../../model/quality'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { createMethod } from '../../../model/method'; +import { createMethod } from '../../../model/method/method'; import { createQualityCard } from '../../../model/quality'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const muxiumLog = createQualityCard({ type: 'logged a message passed to Muxium', diff --git a/src/concepts/muxium/qualities/open.quality.ts b/src/concepts/muxium/qualities/open.quality.ts index f52df637..cf31afdb 100644 --- a/src/concepts/muxium/qualities/open.quality.ts +++ b/src/concepts/muxium/qualities/open.quality.ts @@ -9,7 +9,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { OpenPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumOpen = createQualityCardWithPayload, OpenPayload>({ type: 'Open Muxium', diff --git a/src/concepts/muxium/qualities/preClose.quality.ts b/src/concepts/muxium/qualities/preClose.quality.ts index eb2be433..46187820 100644 --- a/src/concepts/muxium/qualities/preClose.quality.ts +++ b/src/concepts/muxium/qualities/preClose.quality.ts @@ -6,7 +6,7 @@ $>*/ import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumPreClosePayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumPreClose = createQualityCardWithPayload, MuxiumPreClosePayload>({ type: 'Prepare Close Muxium', diff --git a/src/concepts/muxium/qualities/registerStagePlanner.quality.ts b/src/concepts/muxium/qualities/registerStagePlanner.quality.ts index 0f206eba..2724f226 100644 --- a/src/concepts/muxium/qualities/registerStagePlanner.quality.ts +++ b/src/concepts/muxium/qualities/registerStagePlanner.quality.ts @@ -8,7 +8,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumRegisterStagePlannerPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumRegisterStagePlanner = createQualityCardWithPayload, MuxiumRegisterStagePlannerPayload>({ type: 'register Stage Planner to Muxium\'s Named Stage Planner list', diff --git a/src/concepts/muxium/qualities/registerSubscription.quality.ts b/src/concepts/muxium/qualities/registerSubscription.quality.ts index 8e4fff98..6c6c8864 100644 --- a/src/concepts/muxium/qualities/registerSubscription.quality.ts +++ b/src/concepts/muxium/qualities/registerSubscription.quality.ts @@ -4,13 +4,11 @@ generate a quality that will register a subscription to the concepts$ stream. This allows for the clean closure of concepts that are removed or when the muxium itself exits. $>*/ /*<#*/ -import { Subscription } from 'rxjs'; import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; -import { selectPayload } from '../../../model/selector'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumRegisterSubscriberPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumRegisterSubscriber = createQualityCardWithPayload, MuxiumRegisterSubscriberPayload>({ type: 'register Subscriber to Muxium\'s General Subscriber list', diff --git a/src/concepts/muxium/qualities/registerTimeOut.quality.ts b/src/concepts/muxium/qualities/registerTimeOut.quality.ts index d4942360..4dd06239 100644 --- a/src/concepts/muxium/qualities/registerTimeOut.quality.ts +++ b/src/concepts/muxium/qualities/registerTimeOut.quality.ts @@ -5,13 +5,12 @@ This allows for the clean closure of concepts that are removed or when the muxiu $>*/ /*<#*/ import { createQualityCardWithPayload, defaultReducer } from '../../../model/quality'; -import { createMethodWithConcepts } from '../../../model/method'; +import { createMethodWithConcepts } from '../../../model/method/method'; import { muxiumTimeOut } from '../../../model/time'; -import { AnyAction } from '../../../model/action'; -import { strategySuccess } from '../../../model/actionStrategy'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; import { MuxiumState } from '../muxium.concept'; import { MuxiumRegisterTimeOutPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumRegisterTimeOut = createQualityCardWithPayload, MuxiumRegisterTimeOutPayload>({ type: 'register an Action to Muxium\'s timerLedger', diff --git a/src/concepts/muxium/qualities/removeConceptsViaQue.quality.ts b/src/concepts/muxium/qualities/removeConceptsViaQue.quality.ts index d5c6b5d5..78bc61fa 100644 --- a/src/concepts/muxium/qualities/removeConceptsViaQue.quality.ts +++ b/src/concepts/muxium/qualities/removeConceptsViaQue.quality.ts @@ -7,9 +7,9 @@ $>*/ import { defaultMethodCreator } from '../../../model/quality'; import { NamedSubscription } from '../muxium.concept'; import { MuxiumState } from '../muxium.concept'; -import { NamedStagePlanner } from '../../../model/stagePlanner'; +import { NamedStagePlanner } from '../../../model/stagePlanner/stagePlanner.type'; import { createQualityCard } from '../../../model/quality'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumRemoveConceptsViaQue = createQualityCard>({ type: 'remove Concepts via Muxium\'s Removal Concept Que', diff --git a/src/concepts/muxium/qualities/setBlockingMode.quality.ts b/src/concepts/muxium/qualities/setBlockingMode.quality.ts index 1d2d80db..9d4e0eeb 100644 --- a/src/concepts/muxium/qualities/setBlockingMode.quality.ts +++ b/src/concepts/muxium/qualities/setBlockingMode.quality.ts @@ -4,12 +4,12 @@ generate a quality that will set the Muxium's mode to blocking. While in this mo the Muxium operates in a synchronous behavior to quickly modify the Muxium's conceptual set. $>*/ /*<#*/ -import { BehaviorSubject, Subject, Subscriber } from 'rxjs'; -import { Concepts, forEachConcept, LoadConcepts } from '../../../model/concept'; -import { Action } from '../../../model/action'; +import { Subscriber } from 'rxjs'; +import { LoadConcepts } from '../../../model/concept/concept.type'; +import { forEachConcept } from '../../../model/concept/conceptHelpers'; +import { Action } from '../../../model/action/action.type'; import { MuxiumState } from '../muxium.concept'; -import { blockingMethodSubscription } from '../../../model/muxium'; -import { selectPayload } from '../../../model/selector'; +import { blockingMethodSubscription } from '../../../model/method/methodSubscription'; import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumSetBlockingModePayload } from '.'; diff --git a/src/concepts/muxium/qualities/setDefaultMode.quality.ts b/src/concepts/muxium/qualities/setDefaultMode.quality.ts index 48102083..42b009e1 100644 --- a/src/concepts/muxium/qualities/setDefaultMode.quality.ts +++ b/src/concepts/muxium/qualities/setDefaultMode.quality.ts @@ -4,12 +4,14 @@ This mode likewise can be specified by changing the defaultModeIndex state prope $>*/ /*<#*/ import { Subscriber } from 'rxjs'; -import { forEachConcept, LoadConcepts } from '../../../model/concept'; -import { Action } from '../../../model/action'; +import { forEachConcept } from '../../../model/concept/conceptHelpers'; +import { LoadConcepts } from '../../../model/concept/concept.type'; +import { Action } from '../../../model/action/action.type'; import { MuxiumState } from '../muxium.concept'; -import { defaultMethodSubscription, getMuxiumState } from '../../../model/muxium'; +import { getMuxiumState } from '../../../model/muxium/muxiumHelpers'; import { createQualityCardWithPayload, defaultMethodCreator } from '../../../model/quality'; import { MuxiumSetDefaultModePayload } from '.'; +import { defaultMethodSubscription } from '../../../model/method/methodSubscription'; export const muxiumSetDefaultMode = createQualityCardWithPayload, MuxiumSetDefaultModePayload>({ type: 'set Muxium to its current Default Mode Index', diff --git a/src/concepts/muxium/qualities/setDefaultModeIndex.quality.ts b/src/concepts/muxium/qualities/setDefaultModeIndex.quality.ts index eb1b4a6b..ea540243 100644 --- a/src/concepts/muxium/qualities/setDefaultModeIndex.quality.ts +++ b/src/concepts/muxium/qualities/setDefaultModeIndex.quality.ts @@ -8,7 +8,7 @@ import { defaultMethodCreator } from '../../../model/quality'; import { MuxiumState } from '../muxium.concept'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumSetDefaultModeIndexPayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumSetDefaultModeIndex = createQualityCardWithPayload, MuxiumSetDefaultModeIndexPayload>({ diff --git a/src/concepts/muxium/qualities/setMode.quality.ts b/src/concepts/muxium/qualities/setMode.quality.ts index f6065aaa..2e00a804 100644 --- a/src/concepts/muxium/qualities/setMode.quality.ts +++ b/src/concepts/muxium/qualities/setMode.quality.ts @@ -3,11 +3,11 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, g $>*/ /*<#*/ import { MuxiumState } from '../muxium.concept'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { createMethod } from '../../../model/method'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; +import { createMethod } from '../../../model/method/method'; import { createQualityCardWithPayload } from '../../../model/quality'; import { MuxiumSetModePayload } from '.'; -import { LoadConcepts } from '../../../model/concept'; +import { LoadConcepts } from '../../../model/concept/concept.type'; export const muxiumSetMode = createQualityCardWithPayload, MuxiumSetModePayload>({ type: 'set Muxium Mode', diff --git a/src/concepts/muxium/qualities/stitch.quality.ts b/src/concepts/muxium/qualities/stitch.quality.ts index 619e8b17..b009b77e 100644 --- a/src/concepts/muxium/qualities/stitch.quality.ts +++ b/src/concepts/muxium/qualities/stitch.quality.ts @@ -3,9 +3,9 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, generate a quality that will silently start the next step in the strategy graph. $>*/ /*<#*/ -import { strategySuccess } from '../../../model/actionStrategy'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; import { defaultReducer } from '../../../model/quality'; -import { createMethod } from '../../../model/method'; +import { createMethod } from '../../../model/method/method'; import { createQualityCard } from '../../../model/quality'; export const muxiumStitch = createQualityCard({ diff --git a/src/concepts/muxium/strategies/addConcept.strategy.ts b/src/concepts/muxium/strategies/addConcept.strategy.ts index cdc79457..b1c9aac2 100644 --- a/src/concepts/muxium/strategies/addConcept.strategy.ts +++ b/src/concepts/muxium/strategies/addConcept.strategy.ts @@ -3,10 +3,11 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, generate an ActionStrategy that will add new concepts into the Muxium's conceptual set. $>*/ /*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { AnyConcept, Concepts } from '../../../model/concept'; -import { Actions } from '../../../model/action'; +import { AnyConcept, Concepts } from '../../../model/concept/concept.type'; +import { Actions } from '../../../model/action/action.type'; import { MuxiumQualities } from '../qualities'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; // Step One to Add Concepts to Muxium export const addConceptsToAddQueThenBlockTopic = 'Add Concepts to add que then set Muxium Mode to Blocking'; diff --git a/src/concepts/muxium/strategies/initialization.strategy.ts b/src/concepts/muxium/strategies/initialization.strategy.ts index bca9bc40..fc8ce466 100644 --- a/src/concepts/muxium/strategies/initialization.strategy.ts +++ b/src/concepts/muxium/strategies/initialization.strategy.ts @@ -4,9 +4,10 @@ generate a strategy that will initialize the muxium of its base functionality. Within the Stratimux paradigm. Principles act as the start up script, or main function. $>*/ /*<#*/ -import { createStrategy, ActionNode, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concepts } from '../../../model/concept'; -import { Actions } from '../../../model/action'; +import { Actions } from '../../../model/action/action.type'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionNode, ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; +import { Concepts } from '../../../model/concept/concept.type'; import { MuxiumQualities } from '../qualities'; export const initializeTopic = 'Muxium Initialization Strategy'; diff --git a/src/concepts/muxium/strategies/removeConcept.strategy.ts b/src/concepts/muxium/strategies/removeConcept.strategy.ts index 5f681542..0140534f 100644 --- a/src/concepts/muxium/strategies/removeConcept.strategy.ts +++ b/src/concepts/muxium/strategies/removeConcept.strategy.ts @@ -3,10 +3,11 @@ For the asynchronous graph programming framework Stratimux and Muxium Concept, g from the Muxium's concepts state property. $>*/ /*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { AnyConcept, Concepts } from '../../../model/concept'; -import { Actions } from '../../../model/action'; -import { MuxiumAppendConceptsToRemoveQuePayload, MuxiumQualities } from '../qualities'; +import { AnyConcept, Concepts } from '../../../model/concept/concept.type'; +import { Actions } from '../../../model/action/action.type'; +import { MuxiumQualities } from '../qualities'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionStrategy, ActionStrategyParameters } from '../../../model/action/strategy/actionStrategy.type'; export const addConceptsToRemovalQueThenBlockTopic = 'Add Concepts to removal Que then set Muxium Mode to Blocking'; // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/src/concepts/ownership/ownership.concept.ts b/src/concepts/ownership/ownership.concept.ts index 86b858d9..652f816c 100644 --- a/src/concepts/ownership/ownership.concept.ts +++ b/src/concepts/ownership/ownership.concept.ts @@ -5,8 +5,9 @@ This is accomplished via a ticketing system that will set actions to pending if that is currently performing operations within the Muxium. $>*/ /*<#*/ -import { Concept, createConcept } from '../../model/concept'; -import { Action } from '../../model/action'; +import { Concept } from '../../model/concept/concept.type'; +import { createConcept } from '../../model/concept/concept'; +import { Action } from '../../model/action/action.type'; import { ownershipMode } from './ownership.mode'; import { ownershipInitializeOwnership } from './qualities/initializeOwnership.quality'; import { ownershipExpirationPrinciple, ownershipPrinciple } from './ownership.principle'; diff --git a/src/concepts/ownership/ownership.mode.ts b/src/concepts/ownership/ownership.mode.ts index 44b4f07d..f69ffe01 100644 --- a/src/concepts/ownership/ownership.mode.ts +++ b/src/concepts/ownership/ownership.mode.ts @@ -9,17 +9,16 @@ a bad action that signifies that the associated action was invalidated. $>*/ /*<#*/ import { Subject } from 'rxjs'; -import { Action, AnyAction } from '../../model/action'; -import { Concepts } from '../../model/concept'; -import { Mode } from '../../model/concept'; +import { Action, AnyAction } from '../../model/action/action.type'; +import { Concepts } from '../../model/concept/concept.type'; +import { Mode } from '../../model/concept/concept.type'; import { permissiveMode, blockingMode } from '../muxium/muxium.mode'; import { checkIn, clearStubs, ownershipShouldBlock, updateAddToPendingActions } from '../../model/ownership'; -import { ActionStrategy, strategyFailed } from '../../model/actionStrategy'; -import { MuxifiedSubject } from '../../model/stagePlanner'; -import { muxiumAppendActionListToDialog } from '../muxium/qualities/appendActionListToDialog.quality'; -import { MuxiumState } from '../muxium/muxium.concept'; -import { failureConditions, strategyData_appendFailure } from '../../model/actionStrategyData'; -import { getMuxiumState } from '../../model/muxium'; +import { MuxifiedSubject } from '../../model/stagePlanner/stagePlanner'; +import { failureConditions, strategyData_appendFailure } from '../../model/action/strategy/actionStrategyData'; +import { getMuxiumState } from '../../model/muxium/muxiumHelpers'; +import { strategyFailed } from '../../model/action/strategy/actionStrategyConsumers'; +import { ActionStrategy } from '../../model/action/strategy/actionStrategy.type'; export const ownershipMode: Mode = ( [_action, _concepts, action$, concepts$] : [Action, Concepts, Subject, MuxifiedSubject] diff --git a/src/concepts/ownership/ownership.principle.ts b/src/concepts/ownership/ownership.principle.ts index 215df9a7..74eadcd4 100644 --- a/src/concepts/ownership/ownership.principle.ts +++ b/src/concepts/ownership/ownership.principle.ts @@ -5,16 +5,16 @@ ownershipLedger's contents. Only actions that are first in all lines of their ti may be dispatched into the Muxium. This principle will also clear duplicate strategies, and handle actions if their agreement has expired. $>*/ /*<#*/ -import { PrincipleFunction } from '../../model/principle'; -import { OwnershipDeck, OwnershipPrinciple, OwnershipQualities, OwnershipState, ownershipName} from '../ownership/ownership.concept'; +import { OwnershipPrinciple, OwnershipState, ownershipName} from '../ownership/ownership.concept'; import { ownershipSetOwnershipModeStrategy } from './strategies/setOwnerShipMode.strategy'; -import { Action, AnyAction, areSemaphoresEqual, createAction, primeAction } from '../../model/action'; -import { selectMuxifiedState } from '../../model/selector'; -import { strategyBegin } from '../../model/actionStrategy'; +import { selectMuxifiedState } from '../../model/selector/selector'; import { OwnershipTicket, createOwnershipLedger, isActionReady } from '../../model/ownership'; -import { StagePlanner } from '../../model/stagePlanner'; -import { failureConditions, strategyData_appendFailure } from '../../model/actionStrategyData'; +import { StagePlanner } from '../../model/stagePlanner/stagePlanner.type'; +import { failureConditions, strategyData_appendFailure } from '../../model/action/strategy/actionStrategyData'; import { MuxiumBadActionPayload } from '../muxium/qualities'; +import { Action, AnyAction } from '../../model/action/action.type'; +import { areSemaphoresEqual } from '../../model/action/actionSemaphore'; +import { strategyBegin } from '../../model/action/strategy/actionStrategyConsumers'; function denoteExpiredPending(action: Action): Action { if (action.strategy) { diff --git a/src/concepts/ownership/ownership.selector.ts b/src/concepts/ownership/ownership.selector.ts index 8c0a7f18..ed6f1085 100644 --- a/src/concepts/ownership/ownership.selector.ts +++ b/src/concepts/ownership/ownership.selector.ts @@ -1,11 +1,12 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Ownership Concept, generate a series of KeyedSelectors for the ownership state. -$>*/ -/*<#*/ -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; -import { OwnershipState } from './ownership.concept'; - -export const ownershipSelectLedger: KeyedSelector = createConceptKeyedSelector('ownership', 'ownershipLedger'); - -export const ownershipSelectInitialized: KeyedSelector = createConceptKeyedSelector('ownership', 'initialized'); +/*<$ +For the asynchronous graph programming framework Stratimux and Ownership Concept, generate a series of KeyedSelectors for the ownership state. +$>*/ +/*<#*/ +import { createConceptKeyedSelector } from '../../model/selector/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { OwnershipState } from './ownership.concept'; + +export const ownershipSelectLedger: KeyedSelector = createConceptKeyedSelector('ownership', 'ownershipLedger'); + +export const ownershipSelectInitialized: KeyedSelector = createConceptKeyedSelector('ownership', 'initialized'); /*#>*/ \ No newline at end of file diff --git a/src/concepts/ownership/qualities/backTrack.quality.ts b/src/concepts/ownership/qualities/backTrack.quality.ts index 37a48839..3d9982e7 100644 --- a/src/concepts/ownership/qualities/backTrack.quality.ts +++ b/src/concepts/ownership/qualities/backTrack.quality.ts @@ -3,10 +3,10 @@ For the asynchronous graph programming framework Stratimux and Ownership Concept $>*/ /*<#*/ import { nullReducer } from '../../../model/quality'; -import { strategyBackTrack } from '../../../model/actionStrategy'; -import { createMethod } from '../../../model/method'; +import { createMethod } from '../../../model/method/method'; import { createQualityCard } from '../../../model/quality'; import { OwnershipState } from '../ownership.concept'; +import { strategyBackTrack } from '../../../model/action/strategy/actionStrategyConsumersAdvanced'; export const ownershipBackTrack = createQualityCard({ type: 'backtracking to previous ActionNode', diff --git a/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts b/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts index 7e9f5cd7..86613096 100644 --- a/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts +++ b/src/concepts/ownership/qualities/clearPayloadStubs.quality.ts @@ -1,44 +1,44 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Ownership Concept, -generate a quality that will clear the provided stubs from the current Ownership Ledger. -If no tickets exist within a line, delete that line from the ledger. -$>*/ -/*<#*/ -import { defaultMethodCreator } from '../../../model/quality'; -import { OwnershipState } from '../ownership.concept'; -import { OwnershipTicket, OwnershipTicketStub } from '../../../model/ownership'; -import { selectPayload } from '../../../model/selector'; -import { createQualityCardWithPayload } from '../../../model/quality'; - -export type OwnershipClearPayloadStubsPayload = { - stubs: OwnershipTicketStub[] -}; - -export const ownershipClearPayloadStubs = createQualityCardWithPayload({ - type: 'clear payload Stubs from Ownership Ledger', - reducer: (state, action) => { - const stubs = selectPayload(action).stubs; - const ownershipLedger = state.ownershipLedger; - stubs.forEach(ticketStub => { - const line = ownershipLedger.get(ticketStub.key); - if (line) { - const newLine = [] as OwnershipTicket[]; - for (const stub of line) { - if (stub.ticket !== ticketStub.ticket) { - newLine.push(stub); - } - } - if (newLine.length === 0) { - ownershipLedger.delete(ticketStub.key); - } else { - ownershipLedger.set(ticketStub.key, newLine); - } - } - }); - return { - ownershipLedger: ownershipLedger - }; - }, - methodCreator: defaultMethodCreator -}); +/*<$ +For the asynchronous graph programming framework Stratimux and Ownership Concept, +generate a quality that will clear the provided stubs from the current Ownership Ledger. +If no tickets exist within a line, delete that line from the ledger. +$>*/ +/*<#*/ +import { defaultMethodCreator } from '../../../model/quality'; +import { OwnershipState } from '../ownership.concept'; +import { OwnershipTicket, OwnershipTicketStub } from '../../../model/ownership'; +import { selectPayload } from '../../../model/selector/selector'; +import { createQualityCardWithPayload } from '../../../model/quality'; + +export type OwnershipClearPayloadStubsPayload = { + stubs: OwnershipTicketStub[] +}; + +export const ownershipClearPayloadStubs = createQualityCardWithPayload({ + type: 'clear payload Stubs from Ownership Ledger', + reducer: (state, action) => { + const stubs = selectPayload(action).stubs; + const ownershipLedger = state.ownershipLedger; + stubs.forEach(ticketStub => { + const line = ownershipLedger.get(ticketStub.key); + if (line) { + const newLine = [] as OwnershipTicket[]; + for (const stub of line) { + if (stub.ticket !== ticketStub.ticket) { + newLine.push(stub); + } + } + if (newLine.length === 0) { + ownershipLedger.delete(ticketStub.key); + } else { + ownershipLedger.set(ticketStub.key, newLine); + } + } + }); + return { + ownershipLedger: ownershipLedger + }; + }, + methodCreator: defaultMethodCreator +}); /*#>*/ \ No newline at end of file diff --git a/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts b/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts index 16613fb7..02892365 100644 --- a/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts +++ b/src/concepts/ownership/qualities/clearPendingActionsOfStrategy.quality.ts @@ -1,34 +1,34 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and Ownership Concept, -generate a quality clear pending actions of the provided ActionStrategy topic. -$>*/ -/*<#*/ -import { Action } from '../../../model/action'; -import { OwnershipState } from '../ownership.concept'; -import { ActionStrategyTopic } from '../../../model/actionStrategy'; -import { selectPayload } from '../../../model/selector'; -import { createQualityCardWithPayload } from '../../../model/quality'; - -export type OwnershipClearPendingActionsOfStrategyPayload = { - topic: ActionStrategyTopic -}; - -export const ownershipClearPendingActionsOfStrategy = - createQualityCardWithPayload({ - type: 'clear Ownership\'s Pending Actions of Strategy Topic', - reducer: (state, action) => { - const {topic} = selectPayload(action); - const newPendingActions: Action[] = []; - for (const act of state.pendingActions) { - if (act.strategy?.topic) { - if (act.strategy.topic !== topic) { - newPendingActions.push(act); - } - } - } - return { - pendingActions: newPendingActions - }; - } - }); +/*<$ +For the asynchronous graph programming framework Stratimux and Ownership Concept, +generate a quality clear pending actions of the provided ActionStrategy topic. +$>*/ +/*<#*/ +import { OwnershipState } from '../ownership.concept'; +import { selectPayload } from '../../../model/selector/selector'; +import { createQualityCardWithPayload } from '../../../model/quality'; +import { ActionStrategyTopic } from '../../../model/action/strategy/actionStrategy.type'; +import { Action } from '../../../model/action/action.type'; + +export type OwnershipClearPendingActionsOfStrategyPayload = { + topic: ActionStrategyTopic +}; + +export const ownershipClearPendingActionsOfStrategy = + createQualityCardWithPayload({ + type: 'clear Ownership\'s Pending Actions of Strategy Topic', + reducer: (state, action) => { + const {topic} = selectPayload(action); + const newPendingActions: Action[] = []; + for (const act of state.pendingActions) { + if (act.strategy?.topic) { + if (act.strategy.topic !== topic) { + newPendingActions.push(act); + } + } + } + return { + pendingActions: newPendingActions + }; + } + }); /*#>*/ \ No newline at end of file diff --git a/src/concepts/ownership/qualities/clearStrategyStubsFromLedgerAndSelf.quality.ts b/src/concepts/ownership/qualities/clearStrategyStubsFromLedgerAndSelf.quality.ts index 4ed8dd40..ce8a3487 100644 --- a/src/concepts/ownership/qualities/clearStrategyStubsFromLedgerAndSelf.quality.ts +++ b/src/concepts/ownership/qualities/clearStrategyStubsFromLedgerAndSelf.quality.ts @@ -6,9 +6,9 @@ $>*/ /*<#*/ import { OwnershipState } from '../ownership.concept'; import { OwnershipTicket } from '../../../model/ownership'; -import { strategySuccess } from '../../../model/actionStrategy'; -import { createMethodDebounce } from '../../../model/method'; import { createQualityCard } from '../../../model/quality'; +import { createMethodDebounce } from '../../../model/method/methodDebounce'; +import { strategySuccess } from '../../../model/action/strategy/actionStrategyConsumers'; export const ownershipClearStrategyStubsFromLedgerAndSelf = createQualityCard({ type: 'clear current Strategy Stubs from Ownership Ledger and Itself', diff --git a/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts b/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts index 01a5d659..a87ca2d2 100644 --- a/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts +++ b/src/concepts/ownership/strategies/setOwnerShipMode.strategy.ts @@ -2,13 +2,13 @@ For the asynchronous graph programming framework Stratimux and Ownership Concept, generate a strategy that will set the Muxium's mode to Ownership. $>*/ /*<#*/ -import { createStrategy, ActionStrategy, ActionStrategyParameters, createActionNode } from '../../../model/actionStrategy'; -import { Concept, Concepts } from '../../../model/concept'; -import { getSemaphore } from '../../../model/action'; -import { OwnershipDeck, OwnershipQualities, OwnershipState, ownershipName } from '../ownership.concept'; -import { MuxiumDeck, MuxiumState } from '../../muxium/muxium.concept'; +import { Concepts } from '../../../model/concept/concept.type'; +import { OwnershipDeck, ownershipName } from '../ownership.concept'; +import { MuxiumDeck } from '../../muxium/muxium.concept'; import { Deck } from '../../../model/deck'; -import { getMuxiumState } from '../../../model/muxium'; +import { getMuxiumState } from '../../../model/muxium/muxiumHelpers'; +import { ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; export const ownershipSetOwnerShipModeTopic = 'Muxium set Mode to Ownership then Initialize Ownership Principle'; export function ownershipSetOwnershipModeStrategy>( diff --git a/src/index.ts b/src/index.ts index cbb82c82..b7c944e9 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,9 @@ For the asynchronous graph programming framework Stratimux, define the current index file that exports all public functionality for the framework as a module. $>*/ /*<#*/ -export { muxification, getMuxiumState, Muxium, isMuxiumOpen } from './model/muxium'; +export { muxification } from './model/muxium/muxium'; +export { getMuxiumState, isMuxiumOpen } from './model/muxium/muxiumHelpers'; +export { Muxium } from './model/muxium/muxium.type'; export type { ActionNode, ActionNotes, @@ -12,7 +14,7 @@ export type { ActionStrategyParameters, ActionStrategyStitch, ActionStrategyCreator -} from './model/actionStrategy'; +} from './model/action/strategy/actionStrategy.type'; export { Deck, Decks, @@ -21,17 +23,23 @@ export { createStrategy, createActionNode, createActionNodeFromStrategy, +} from './model/action/strategy/actionStrategy'; +export { strategyBegin, - strategySuccess, - strategyFailed, strategyDecide, + strategyFailed, + strategySuccess +} from './model/action/strategy/actionStrategyConsumers'; +export { + strategyBackTrack, strategyDetermine, strategyPunt, - strategySequence, - strategyBackTrack, strategyRecurse, - strategy -} from './model/actionStrategy'; + strategySequence +} from './model/action/strategy/actionStrategyConsumersAdvanced'; +export { + strata +} from './model/action/strategy'; export { failureConditions, strategyData_appendFailure, @@ -40,32 +48,44 @@ export { strategyData_select, strategyData_muxifyData, strategyData -} from './model/actionStrategyData'; +} from './model/action/strategy/actionStrategyData'; export { createMethod, - createAsyncMethod, createMethodWithState, + createMethodWithConcepts, +} from './model/method/method'; +export { + createAsyncMethod, createAsyncMethodWithState, - createMethodDebounce, + createAsyncMethodWithConcepts +} from './model/method/methodAsync'; +export { createAsyncMethodDebounce, - createMethodDebounceWithState, createAsyncMethodDebounceWithState, - createMethodThrottle, - createMethodThrottleWithState, + createAsyncMethodDebounceWithConcepts +} from './model/method/methodAsyncDebounce'; +export { createAsyncMethodThrottle, createAsyncMethodThrottleWithState, - createMethodWithConcepts, - createAsyncMethodWithConcepts, - createMethodThrottleWithConcepts, - createMethodDebounceWithConcepts, createAsyncMethodThrottleWithConcepts, - createAsyncMethodDebounceWithConcepts, +} from './model/method/methodAsyncThrottle'; +export { + createMethodDebounce, + createMethodDebounceWithState, + createMethodDebounceWithConcepts +} from './model/method/methodDebounce'; +export { + createMethodThrottle, + createMethodThrottleWithState, + createMethodThrottleWithConcepts +} from './model/method/methodThrottle'; +export { method } from './model/method'; export { debounceAction, throttleAction -} from './model/actionOperators'; +} from './model/action/actionOperators'; export type { Action, AnyAction, @@ -74,27 +94,37 @@ export type { ActionCreatorWithPayload, ActionOptions, ActionWithPayloadOptions -} from './model/action'; +} from './model/action/action.type'; export { primeAction, createAction, - getSemaphore, prepareActionCreator, prepareActionWithPayloadCreator, refreshAction, +} from './model/action/action'; +export { + getSemaphore +} from './model/action/actionSemaphore'; +export { act } from './model/action'; +export { + concept +} from './model/concept/'; export { createConcept, +} from './model/concept/concept'; +export { isConceptLoaded, areConceptsLoaded, - muxifyConcepts, forEachConcept, conceptToString, conceptsToString, getConceptSemaphore, - concept -} from './model/concept'; +} from './model/concept/conceptHelpers'; +export { + muxifyConcepts, +} from './model/concept/conceptAdvanced'; export type { Concept, Concepts, @@ -107,7 +137,7 @@ export type { AnyConcept, ConceptDeck, SpecificReducer -} from './model/concept'; +} from './model/concept/concept.type'; export { createQualityCard, createQualityCardWithPayload, @@ -118,7 +148,7 @@ export { quality, Qualities } from './model/quality'; -export type { KeyedSelector } from './model/selector'; +export type { KeyedSelector } from './model/selector/selector.type'; export { selectState, selectConcept, @@ -126,19 +156,22 @@ export { selectPayload, selectMuxifiedState, selectMuxifiedName, - updateMuxifiedKeyedSelector, createConceptKeyedSelector, createMuxifiedKeyedSelector, createAdvancedKeys, - select, -} from './model/selector'; +} from './model/selector/selector'; +export { + updateMuxifiedKeyedSelector, +} from './model/selector/selectorAdvanced'; +export { select } from './model/selector'; export type { DotPath } from './model/dotPath'; export { PrincipleFunction, principle } from './model/principle'; -export { createActionController$, actionController } from './model/actionController'; -export type { dispatchOptions, Staging, MuxifiedSubject, StagePlanner, NamedStagePlanner } from './model/stagePlanner'; -export { stageWaitForOpenThenIterate, stageWaitForOwnershipThenIterate, createStage } from './model/stagePlanner'; +export { createActionController$, actionController } from './model/action/actionController'; +export type { dispatchOptions, Staging, StagePlanner, NamedStagePlanner } from './model/stagePlanner/stagePlanner.type'; +export { stageWaitForOpenThenIterate, stageWaitForOwnershipThenIterate, createStage } from './model/stagePlanner/stagePlannerHelpers'; +export { MuxifiedSubject } from './model/stagePlanner/stagePlanner'; export type { OwnershipTicket, OwnershipTicketStub, OwnershipLedger } from './model/ownership'; export { ownership } from './model/ownership'; export { muxiumTimeOut } from './model/time'; @@ -147,7 +180,12 @@ export { muxiumTimeOut } from './model/time'; // Muxium export { MuxiumState, muxiumName, muxificationConcept, MuxiumDeck } from './concepts/muxium/muxium.concept'; export { blockingMode, permissiveMode } from './concepts/muxium/muxium.mode'; -export { muxiumSelectOpen, muxiumSelectLastStrategy, muxiumSelectBadActions, muxiumSelectBadPlans } from './concepts/muxium/muxium.selector'; +export { + muxiumSelectOpen, + muxiumSelectLastStrategy, + muxiumSelectBadActions, + muxiumSelectBadPlans +} from './concepts/muxium/muxium.selector'; // Models export { MuxiumGatherNode, diff --git a/src/model/access.ts b/src/model/access.ts index 75c5fdc0..59709dea 100644 --- a/src/model/access.ts +++ b/src/model/access.ts @@ -1,22 +1,23 @@ +/**/ /*<$ For the asynchronous graph programming framework Stratimux, define the Access model file. This file dictates the ability for an outside subscription to access Actions a foreign muxium. $>*/ /*<#*/ -import { Actions } from './action'; -import { Concepts } from './concept'; -import { KeyedSelectors } from './selector'; +import { Actions } from './action/action.type'; +import { Concepts } from './concept/concept.type'; +import { KeyedSelectors } from './selector/selector.type'; // PUNT we will be attaching this to the Muxium to create a public API. To restrict what actions a foreign Muxium may access. // Noting that the initial starting point for semaphores can be scrambled to a random value upon creation. // Within some Auth Concept we could use this as a means of black listing probing actors // Can also set the semaphore to a hash if we are truly in a sensitive situation then fall back to numbs in a private context. // LARGE PUNT with the hash -function access(concepts: Concepts, conceptName: string): [Actions, KeyedSelectors] { - return [ - {}, - {} - ]; -} +// function access(concepts: Concepts, conceptName: string): [Actions, KeyedSelectors] { +// return [ +// {}, +// {} +// ]; +// } /*#>*/ \ No newline at end of file diff --git a/src/model/action.ts b/src/model/action.ts deleted file mode 100644 index 2623cc9d..00000000 --- a/src/model/action.ts +++ /dev/null @@ -1,336 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Action model file. -This file dictates the functionality of Actions within Stratimux. -$>*/ -/*<#*/ -import { AnyConcept, Concept, Concepts, LoadConcepts } from './concept'; -import { ActionStrategy } from './actionStrategy'; -import { KeyedSelector } from './selector'; -import { MuxiumState } from '../concepts/muxium/muxium.concept'; -import { failureConditions, strategyData_appendFailure } from './actionStrategyData'; -import { Quality } from './quality'; -import { MuxiumBadActionPayload, MuxiumQualities } from '../concepts/muxium/qualities'; - -export const nullActionType: ActionType = 'null'; -// These need to be logical determined ahead of time. -// Logical determinations such as these will be determined in the future via generation over hand placement. -const muxiumConcludeType: ActionType = 'Conclude'; -const muxiumBadActionType: ActionType = 'Muxium received a Bad Action'; -const muxiumSetBlockingModeType: ActionType = 'set Muxium to Blocking Mode'; -const muxiumOpenType: ActionType = 'Open Muxium'; - -export type ActionType = string; -export type Action = { - type: ActionType; - semaphore: [number, number, number, number]; - conceptSemaphore?: number; - payload: T extends Record ? T : undefined; - strategy?: ActionStrategy; - keyedSelectors?: KeyedSelector[]; - agreement?: number; - expiration: number; - priority?: number; - muxium?: string; - origin?: string; -}; - -export type AnyAction = { - type: ActionType; - semaphore: [number, number, number, number]; - conceptSemaphore?: number; - payload: any; - strategy?: ActionStrategy; - keyedSelectors?: KeyedSelector[]; - agreement?: number; - expiration: number; - priority?: number; - muxium?: string; - origin?: string; -} - -export type ActionCreatorType = - T extends Record ? - ActionCreatorWithPayload : - ActionCreator; - -export type Actions = { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - [K in keyof T]: T[K] extends Quality, any, any> ? - T[K]['actionCreator'] : ActionCreator; -}; - -export type ActionCreator = ( - options?: ActionOptions -) => Action; - -export type ActionCreatorWithPayload> = ( - payload: T, - options?: ActionWithPayloadOptions -) => Action; - -export type ActionOptions = { - semaphore?: [number, number, number, number]; - conceptSemaphore?: number; - strategy?: ActionStrategy; - keyedSelectors?: KeyedSelector[]; - agreement?: number; - expiration?: number; - priority?: number; - muxium?: string; - origin?: string; -}; - -export type ActionWithPayloadOptions = { - semaphore?: [number, number, number, number]; - conceptSemaphore?: number; - payload?: T extends Record ? T : undefined; - strategy?: ActionStrategy; - keyedSelectors?: KeyedSelector[]; - agreement?: number; - expiration?: number; - priority?: number; - muxium?: string; - origin?: string; -}; - -const createPayload = >(payload: T) => payload; - -export function primeAction(concepts: Concepts, action: Action): Action { - const expired = action.expiration < Date.now(); - let semaphore: [number, number, number, number] = [-1, -1, -1, -1]; - if (!expired) { - if (action.conceptSemaphore) { - semaphore = getSemaphore(concepts, concepts[action.conceptSemaphore].name, action.type); - } else { - const conceptKeys = Object.keys(concepts); - for (const i of conceptKeys) { - const index = Number(i); - semaphore = getSemaphore(concepts, concepts[index].name, action.type); - if (semaphore[2] !== -1 && action.expiration) { - break; - } - } - } - } - if (semaphore[2] !== -1 && action.expiration) { - let muxium; - if (action.muxium) { - muxium = action.muxium; - } else { - muxium = (concepts[0].state as MuxiumState).name; - } - const newAction = { - ...action, - semaphore: semaphore, - muxium, - } as Action; - if (newAction.strategy) { - newAction.strategy.currentNode.action = newAction; - } - return newAction; - } - const badAction: Action = { - type: muxiumBadActionType, - payload: createPayload({badActions: [action]}), - expiration: Date.now() + 5000, - semaphore: getSemaphore(concepts, concepts[0].name, muxiumBadActionType) - }; - if (action.strategy) { - badAction.strategy = action.strategy; - badAction.strategy.currentNode.action = badAction as Action; - if (expired) { - badAction.strategy.data = strategyData_appendFailure(badAction.strategy, failureConditions.muxiumExpired); - } else { - badAction.strategy.data = strategyData_appendFailure(badAction.strategy, failureConditions.muxiumBadGeneration); - } - } - return badAction as Action; -} - -/** - * @param action A previously created action. - * @returns Returns a newly recomposed Action with a updated expiration, takes into account agreement if present. - */ -export const refreshAction = (action: Action): Action => { - const newAction = { - ...action, - }; - if (newAction.agreement) { - newAction.expiration = Date.now() + newAction.agreement; - } else { - newAction.expiration = Date.now() + 5000; - } - return newAction; -}; - -export function getSemaphore(concepts: Concepts, conceptName: string, actionType: ActionType): [number, number, number, number] { - const muxiumState = concepts[0].state as MuxiumState; - const cachedSemaphores = muxiumState.cachedSemaphores; - const conceptMap = cachedSemaphores.get(conceptName); - const special = getSpecialSemaphore(actionType); - if (conceptMap) { - const qualitySemaphore = conceptMap.get(actionType); - if (qualitySemaphore) { - qualitySemaphore[3] = special; - return qualitySemaphore; - } - } - return [0, 0, -1, special]; -} - -// For proper compilation -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const forEachConcept = (concepts: Concepts, each: (concept: AnyConcept, semaphore?: number) => void) => { - const conceptKeys = Object.keys(concepts); - for (const i of conceptKeys) { - const index = Number(i); - each(concepts[index], concepts[index].semaphore); - } -}; - -export function createCachedSemaphores(concepts: Concepts): Map> { - const generation = (concepts[0].state as MuxiumState).generation; - const newCachedSemaphores = new Map>(); - - forEachConcept(concepts, ((concept, ci) => { - const qualityMap = new Map(); - concept.qualities.forEach((quality, qi) => { - const semaphore: [number, number, number, number] = [ci as number, qi, generation, getSpecialSemaphore(quality.actionType)]; - quality.actionSemaphoreBucket.shift(); - quality.actionSemaphoreBucket.push(semaphore); - // console.log(quality.actionType, semaphore); - qualityMap.set(quality.actionType, semaphore); - }); - newCachedSemaphores.set(concept.name, qualityMap); - })); - return newCachedSemaphores; -} - -/** - * This allows us to logically determine these values in code. - * @returns The final value for the semaphore tuple. - */ -export function getSpecialSemaphore(type: ActionType) { - switch (type) { - case muxiumBadActionType: { - return 1; - } - case nullActionType: { - return 2; - } - case muxiumConcludeType: { - return 3; - } - case muxiumSetBlockingModeType: { - return 4; - } - // case muxiumOpenType: { - // return 5; - // } - default: { - return 0; - } - } -} - -export function createAction( - type: ActionType, - options?: ActionWithPayloadOptions, -): Action { - const special = getSpecialSemaphore(type); - - const semaphore = options?.semaphore !== undefined ? options.semaphore : [0, 0, -1, special] as [number, number, number, number]; - if (options) { - const { - payload, - keyedSelectors, - agreement, - conceptSemaphore, - priority, - origin - } = options; - return { - type, - semaphore: options.semaphore ? options.semaphore : semaphore, - payload: (payload ? payload : {}) as T extends Record ? T : undefined, - keyedSelectors, - agreement, - expiration: Date.now() + (agreement !== undefined ? agreement : 5000), - conceptSemaphore, - priority, - origin - }; - } else { - return { - type, - semaphore, - expiration: Date.now() + 5000, - payload: {} as T extends Record ? T : undefined - }; - } -} - -export function prepareActionCreator( - actionType: ActionType, - actionSemaphoreBucket: [number, number, number, number][] -) { - return ( - options?: ActionOptions - ) => { - if (options) { - return createAction(actionType, - { - ...options, - semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] - } - ); - } - return createAction( - actionType, { - semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] - } - ); - }; -} - -export function prepareActionWithPayloadCreator>( - actionType: ActionType, - actionSemaphoreBucket: [number, number, number, number][] -): ActionCreatorWithPayload { - return ( - payload: T, - options?: ActionOptions - ): Action => { - const opt: ActionWithPayloadOptions = { - ...options, - payload: payload as T extends Record ? T : undefined - }; - return createAction( - actionType, - { - ...opt, - semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] - } - ); - }; -} - -/** - * Should only be used after if you can logically determine that the semaphores have been primed. - * @returns boolean - */ -export function areSemaphoresEqual(first: Action, second: Action) { - return first.semaphore[0] === second.semaphore[0] && first.semaphore[1] === second.semaphore[1]; -} - -export const act = ({ - prime: primeAction, - refresh: refreshAction, - getSemaphore, - createCachedSemaphores, - create: createAction, - prepareActionCreator, - prepareActionWithPayloadCreator, - areSemaphoresEqual, -}); -/*#>*/ \ No newline at end of file diff --git a/src/model/action/action.ts b/src/model/action/action.ts new file mode 100644 index 00000000..47130341 --- /dev/null +++ b/src/model/action/action.ts @@ -0,0 +1,170 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Action model file. +This file dictates the functionality of Actions within Stratimux. +$>*/ +/*<#*/ +import { Concepts, LoadConcepts } from '../concept/concept.type'; +import { MuxiumState } from '../../concepts/muxium/muxium.concept'; +import { failureConditions, strategyData_appendFailure } from './strategy/actionStrategyData'; +import { MuxiumBadActionPayload, MuxiumQualities } from '../../concepts/muxium/qualities'; +import { Action, ActionCreatorWithPayload, ActionOptions, ActionType, ActionWithPayloadOptions } from './action.type'; +import { getSemaphore, getSpecialSemaphore } from './actionSemaphore'; + +export const nullActionType: ActionType = 'null'; +// These need to be logical determined ahead of time. +// Logical determinations such as these will be determined in the future via generation over hand placement. +const muxiumBadActionType: ActionType = 'Muxium received a Bad Action'; + +const createPayload = >(payload: T) => payload; + +export function primeAction(concepts: Concepts, action: Action): Action { + const expired = action.expiration < Date.now(); + let semaphore: [number, number, number, number] = [-1, -1, -1, -1]; + if (!expired) { + if (action.conceptSemaphore) { + semaphore = getSemaphore(concepts, concepts[action.conceptSemaphore].name, action.type); + } else { + const conceptKeys = Object.keys(concepts); + for (const i of conceptKeys) { + const index = Number(i); + semaphore = getSemaphore(concepts, concepts[index].name, action.type); + if (semaphore[2] !== -1 && action.expiration) { + break; + } + } + } + } + if (semaphore[2] !== -1 && action.expiration) { + let muxium; + if (action.muxium) { + muxium = action.muxium; + } else { + muxium = (concepts[0].state as MuxiumState).name; + } + const newAction = { + ...action, + semaphore: semaphore, + muxium, + } as Action; + if (newAction.strategy) { + newAction.strategy.currentNode.action = newAction; + } + return newAction; + } + const badAction: Action = { + type: muxiumBadActionType, + payload: createPayload({badActions: [action]}), + expiration: Date.now() + 5000, + semaphore: getSemaphore(concepts, concepts[0].name, muxiumBadActionType) + }; + if (action.strategy) { + badAction.strategy = action.strategy; + badAction.strategy.currentNode.action = badAction as Action; + if (expired) { + badAction.strategy.data = strategyData_appendFailure(badAction.strategy, failureConditions.muxiumExpired); + } else { + badAction.strategy.data = strategyData_appendFailure(badAction.strategy, failureConditions.muxiumBadGeneration); + } + } + return badAction as Action; +} + +/** + * @param action A previously created action. + * @returns Returns a newly recomposed Action with a updated expiration, takes into account agreement if present. + */ +export const refreshAction = (action: Action): Action => { + const newAction = { + ...action, + }; + if (newAction.agreement) { + newAction.expiration = Date.now() + newAction.agreement; + } else { + newAction.expiration = Date.now() + 5000; + } + return newAction; +}; + +export function createAction( + type: ActionType, + options?: ActionWithPayloadOptions, +): Action { + const special = getSpecialSemaphore(type); + + const semaphore = options?.semaphore !== undefined ? options.semaphore : [0, 0, -1, special] as [number, number, number, number]; + if (options) { + const { + payload, + keyedSelectors, + agreement, + conceptSemaphore, + priority, + origin + } = options; + return { + type, + semaphore: options.semaphore ? options.semaphore : semaphore, + payload: (payload ? payload : {}) as T extends Record ? T : undefined, + keyedSelectors, + agreement, + expiration: Date.now() + (agreement !== undefined ? agreement : 5000), + conceptSemaphore, + priority, + origin + }; + } else { + return { + type, + semaphore, + expiration: Date.now() + 5000, + payload: {} as T extends Record ? T : undefined + }; + } +} + +export function prepareActionCreator( + actionType: ActionType, + actionSemaphoreBucket: [number, number, number, number][] +) { + return ( + options?: ActionOptions + ) => { + if (options) { + return createAction(actionType, + { + ...options, + semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] + } + ); + } + return createAction( + actionType, { + semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] + } + ); + }; +} + +export function prepareActionWithPayloadCreator>( + actionType: ActionType, + actionSemaphoreBucket: [number, number, number, number][] +): ActionCreatorWithPayload { + return ( + payload: T, + options?: ActionOptions + ): Action => { + const opt: ActionWithPayloadOptions = { + ...options, + payload: payload as T extends Record ? T : undefined + }; + return createAction( + actionType, + { + ...opt, + semaphore: actionSemaphoreBucket[0] ? actionSemaphoreBucket[0] : [-1, -1, -1, -1] + } + ); + }; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/action/action.type.ts b/src/model/action/action.type.ts new file mode 100644 index 00000000..dccd3173 --- /dev/null +++ b/src/model/action/action.type.ts @@ -0,0 +1,85 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Action Type model file. +This file defines the types used for Stratimux Actions +$>*/ +/*<#*/ +import { KeyedSelector } from '../selector/selector.type'; +import { Quality } from '../quality'; +import { ActionStrategy } from './strategy/actionStrategy.type'; + +export const nullActionType: ActionType = 'null'; + +export type ActionType = string; +export type Action = { + type: ActionType; + semaphore: [number, number, number, number]; + conceptSemaphore?: number; + payload: T extends Record ? T : undefined; + strategy?: ActionStrategy; + keyedSelectors?: KeyedSelector[]; + agreement?: number; + expiration: number; + priority?: number; + muxium?: string; + origin?: string; +}; + +export type AnyAction = { + type: ActionType; + semaphore: [number, number, number, number]; + conceptSemaphore?: number; + payload: any; + strategy?: ActionStrategy; + keyedSelectors?: KeyedSelector[]; + agreement?: number; + expiration: number; + priority?: number; + muxium?: string; + origin?: string; +} + +export type ActionCreatorType = + T extends Record ? + ActionCreatorWithPayload : + ActionCreator; + +export type Actions = { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [K in keyof T]: T[K] extends Quality, any, any> ? + T[K]['actionCreator'] : ActionCreator; +}; + +export type ActionCreator = ( + options?: ActionOptions +) => Action; + +export type ActionCreatorWithPayload> = ( + payload: T, + options?: ActionWithPayloadOptions +) => Action; + +export type ActionOptions = { + semaphore?: [number, number, number, number]; + conceptSemaphore?: number; + strategy?: ActionStrategy; + keyedSelectors?: KeyedSelector[]; + agreement?: number; + expiration?: number; + priority?: number; + muxium?: string; + origin?: string; +}; + +export type ActionWithPayloadOptions = { + semaphore?: [number, number, number, number]; + conceptSemaphore?: number; + payload?: T extends Record ? T : undefined; + strategy?: ActionStrategy; + keyedSelectors?: KeyedSelector[]; + agreement?: number; + expiration?: number; + priority?: number; + muxium?: string; + origin?: string; +}; +/*#>*/ \ No newline at end of file diff --git a/src/model/actionController.ts b/src/model/action/actionController.ts similarity index 90% rename from src/model/actionController.ts rename to src/model/action/actionController.ts index b8f8ddb7..f9a94799 100644 --- a/src/model/actionController.ts +++ b/src/model/action/actionController.ts @@ -6,10 +6,13 @@ reached its expiration. Emitting a Strategy Failed if the Action was a Strategy, not provided. $>*/ /*<#*/ -import { Action, AnyAction, muxiumBadAction, createAction, Deck, strategyFailed } from '../index'; import { Subject } from 'rxjs'; -import { failureConditions, strategyData_appendFailure } from './actionStrategyData'; -import { ActionDeck, Self } from './concept'; +import { failureConditions, strategyData_appendFailure } from './strategy/actionStrategyData'; +import { ActionDeck, Self } from '../concept/concept.type'; +import { Action, AnyAction } from './action.type'; +import { createAction } from './action'; +import { Deck } from '../deck'; +import { strategyFailed } from './strategy/actionStrategyConsumers'; const badAction = (payload: { badActions: AnyAction[] diff --git a/src/model/actionOperators.ts b/src/model/action/actionOperators.ts similarity index 95% rename from src/model/actionOperators.ts rename to src/model/action/actionOperators.ts index f985e217..7dae2bf0 100644 --- a/src/model/actionOperators.ts +++ b/src/model/action/actionOperators.ts @@ -20,9 +20,9 @@ import { asyncScheduler, timer } from 'rxjs'; -import { Action } from './action'; -import { muxiumConclude } from '../concepts/muxium/qualities/conclude.quality'; -import { ActionDeck } from './concept'; +import { Action } from './action.type'; +import { muxiumConclude } from '../../concepts/muxium/qualities/conclude.quality'; +import { ActionDeck } from '../concept/concept.type'; function hasLift(source: any): source is { lift: InstanceType['lift'] } { return typeof source?.lift === 'function'; diff --git a/src/model/action/actionSemaphore.ts b/src/model/action/actionSemaphore.ts new file mode 100644 index 00000000..31a48510 --- /dev/null +++ b/src/model/action/actionSemaphore.ts @@ -0,0 +1,96 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Action model file. +This file dictates the functionality of Actions within Stratimux. +$>*/ +/*<#*/ +import { AnyConcept, Concepts, LoadConcepts } from '../concept/concept.type'; +import { MuxiumState } from '../../concepts/muxium/muxium.concept'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { Action, ActionType } from './action.type'; + +export const nullActionType: ActionType = 'null'; +// These need to be logical determined ahead of time. +// Logical determinations such as these will be determined in the future via generation over hand placement. +const muxiumConcludeType: ActionType = 'Conclude'; +const muxiumBadActionType: ActionType = 'Muxium received a Bad Action'; +const muxiumSetBlockingModeType: ActionType = 'set Muxium to Blocking Mode'; + +export function getSemaphore(concepts: Concepts, conceptName: string, actionType: ActionType): [number, number, number, number] { + const muxiumState = concepts[0].state as MuxiumState; + const cachedSemaphores = muxiumState.cachedSemaphores; + const conceptMap = cachedSemaphores.get(conceptName); + const special = getSpecialSemaphore(actionType); + if (conceptMap) { + const qualitySemaphore = conceptMap.get(actionType); + if (qualitySemaphore) { + qualitySemaphore[3] = special; + return qualitySemaphore; + } + } + return [0, 0, -1, special]; +} + +// For proper compilation +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const forEachConcept = (concepts: Concepts, each: (concept: AnyConcept, semaphore?: number) => void) => { + const conceptKeys = Object.keys(concepts); + for (const i of conceptKeys) { + const index = Number(i); + each(concepts[index], concepts[index].semaphore); + } +}; + +export function createCachedSemaphores(concepts: Concepts): Map> { + const generation = (concepts[0].state as MuxiumState).generation; + const newCachedSemaphores = new Map>(); + + forEachConcept(concepts, ((concept, ci) => { + const qualityMap = new Map(); + concept.qualities.forEach((quality, qi) => { + const semaphore: [number, number, number, number] = [ci as number, qi, generation, getSpecialSemaphore(quality.actionType)]; + quality.actionSemaphoreBucket.shift(); + quality.actionSemaphoreBucket.push(semaphore); + // console.log(quality.actionType, semaphore); + qualityMap.set(quality.actionType, semaphore); + }); + newCachedSemaphores.set(concept.name, qualityMap); + })); + return newCachedSemaphores; +} + +/** + * This allows us to logically determine these values in code. + * @returns The final value for the semaphore tuple. + */ +export function getSpecialSemaphore(type: ActionType) { + switch (type) { + case muxiumBadActionType: { + return 1; + } + case nullActionType: { + return 2; + } + case muxiumConcludeType: { + return 3; + } + case muxiumSetBlockingModeType: { + return 4; + } + // case muxiumOpenType: { + // return 5; + // } + default: { + return 0; + } + } +} + +/** + * Should only be used after if you can logically determine that the semaphores have been primed. + * @returns boolean + */ +export function areSemaphoresEqual(first: Action, second: Action) { + return first.semaphore[0] === second.semaphore[0] && first.semaphore[1] === second.semaphore[1]; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/action/index.ts b/src/model/action/index.ts new file mode 100644 index 00000000..fdfd1ea3 --- /dev/null +++ b/src/model/action/index.ts @@ -0,0 +1,30 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Action Index file. +This file creates an object that collects all action oriented functions required for Stratimux. +$>*/ +/*<#*/ +import { + createAction, + prepareActionCreator, + prepareActionWithPayloadCreator, + primeAction, + refreshAction +} from './action'; + +import { + areSemaphoresEqual, + createCachedSemaphores, + getSemaphore, +} from './actionSemaphore'; + +export const act = ({ + prime: primeAction, + refresh: refreshAction, + getSemaphore, + createCachedSemaphores, + create: createAction, + prepareActionCreator, + prepareActionWithPayloadCreator, + areSemaphoresEqual, +}); +/*#>*/ \ No newline at end of file diff --git a/src/model/action/strategy/actionStrategy.ts b/src/model/action/strategy/actionStrategy.ts new file mode 100644 index 00000000..b89ce14b --- /dev/null +++ b/src/model/action/strategy/actionStrategy.ts @@ -0,0 +1,104 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy model file. +This file is what allows for Stratimux to be provably terminating. +As each strategy constitutes a finite set of symbols that must reach a conclusion. +Using this data structure we can constrain the Muxium's recursive functionality to the length +of the strategies that currently exist within it. +$>*/ +/*<#*/ +import { createAction } from '../action'; +import { Action, nullActionType } from '../action.type'; +import { ActionNode, ActionNodeOptions, ActionStrategy, ActionStrategyParameters } from './actionStrategy.type'; + +/** + * Decomposes an action into an ActionNode to be later Recomposed. + * @param action Action properties of KeyedSelector, Agreement, and Semaphore take priority over options. + * @param options successNode and failureNodes are always required. If using decisionNodes, set both to null. + * @returns ActionNode + */ +export function createActionNode(action: Action, options?: ActionNodeOptions): ActionNode { + if (options) { + return { + actionType: action.type, + payload: action.payload, + keyedSelectors: action.keyedSelectors ? action.keyedSelectors : options.keyedSelectors, + conceptSemaphore: action.conceptSemaphore ? action.conceptSemaphore : options.conceptSemaphore, + priority: action.priority ? action.priority : options.priority, + agreement: action.agreement ? action.agreement : options.agreement, + semaphore: action.semaphore ? action.semaphore : options.semaphore, + successNode: options.successNode ? options.successNode : null, + successNotes: options.successNotes, + failureNode: options.failureNode ? options.failureNode : null, + failureNotes: options.failureNotes, + decisionNodes: options.decisionNodes, + decisionNotes: options.decisionNotes, + lastActionNode: options.lastActionNode + }; + } + return { + actionType: action.type, + payload: action.payload, + successNode: null, + failureNode: null + }; +} + +/** + * Note that this will be a new ActionNode and not the original created within the provided strategy. + * @param strategy Will return a recomposed ActionNode of the provided strategy. + * @returns ActionNode + */ +export const createActionNodeFromStrategy = (strategy: ActionStrategy): ActionNode => { + const currentNode = strategy.currentNode; + let action; + if (currentNode.action) { + action = {...currentNode.action}; + } else { + action = createAction( + currentNode.actionType, + { + payload: currentNode.payload, + keyedSelectors: currentNode.keyedSelectors, + agreement: currentNode.agreement, + semaphore: currentNode.semaphore, + conceptSemaphore: currentNode.conceptSemaphore, + priority: currentNode.priority + } + ); + } + return createActionNode(action, { + successNode: currentNode.successNode, + successNotes: currentNode.successNotes, + failureNode: currentNode.failureNode, + failureNotes: currentNode.failureNotes, + decisionNodes: currentNode.decisionNodes, + decisionNotes: currentNode.decisionNotes, + lastActionNode: currentNode.lastActionNode + }); +}; + +export function createStrategy( + params: ActionStrategyParameters, +): ActionStrategy { + const data: Record | undefined = params.data; + const currentNode: ActionNode = params.initialNode; + const priority = params.priority; + currentNode.lastActionNode = { + // This logically determines that all ActionNodes will have a Action associated. + action: createAction(nullActionType), + actionType: nullActionType, + successNode: null, + failureNode: null + }; + const actionList: Array = [params.topic + '.']; + return { + topic: params.topic, + data, + currentNode, + actionList, + priority, + step: 0 + }; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/action/strategy/actionStrategy.type.ts b/src/model/action/strategy/actionStrategy.type.ts new file mode 100644 index 00000000..9ef2222f --- /dev/null +++ b/src/model/action/strategy/actionStrategy.type.ts @@ -0,0 +1,119 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy Type model file. +$>*/ +/*<#*/ +import { Action, ActionType } from '../action.type'; +import { OwnershipTicketStub } from '../../ownership'; +import { KeyedSelector } from '../../selector/selector.type'; + +/** + * ActionNode - Control Structure used by ActionStrategy + * @param action - Action to be dispatched. + * @param successNode - Upon ActionStrategy.success() the Strategy will update itself to this node. + * * If set to null, will default to Muxium Conclude Type on ActionStrategy.success(). + * @param failureNode - `optional` ActionStrategy.failed() will fire Muxium Conclude Type if left blank or set to null. + * @param payload - `optional` Will set the payload of the action. + * @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore(). + * @param conceptSemaphore - `optional` Used for Muxified Qualities. Must be specified via that principle's passed semaphore value. + * @param priority - `optional` Will allow the action to be placed in the body que accordingly. + * @param agreement - `optional` Is time in milliseconds of the actions intended lifetime. + * @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows. + * @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList. + * @param denoter - `optional` String that denotes the end of the ActionList sentence. + * If placed dynamically, allows for the explicit appending of information at the end of the sentence + * @ExampleSentence ${preposition: 'Via'} Muxium set Mode to ${denoter: 'Ownership Mode.'} + * @Output Via Muxium set Mode to Ownership Mode. + */ +export interface ActionNode { + action?: Action; + actionType: ActionType; + payload?: Record; + conceptSemaphore?: number; + priority?: number; + keyedSelectors?: KeyedSelector[]; + semaphore?: [number, number, number, number]; + agreement?: number; + decisionNodes?: Record; + decisionNotes?: ActionNotes; + successNode: ActionNode | null; + successNotes?: ActionNotes; + failureNode: ActionNode | null; + failureNotes?: ActionNotes; + lastActionNode?: ActionNode; +} +/** + * Options list + * @param successNode - Upon ActionStrategy.success() the Strategy will update itself to this node. + * * If set to null, will default to Muxium Conclude Type on ActionStrategy.success(). + * @param failureNode - `optional` ActionStrategy.failed() will fire Muxium Conclude Type if left blank or set to null. + * @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore(). + * @param conceptSemaphore - `optional` Used for Muxified Qualities. Must be specified via that principle's passed semaphore value. + * @param priority - `optional` Will allow the action to be placed in the body que accordingly. + * @param agreement - `optional` Is time in milliseconds of the actions intended lifetime. + * @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows. + * @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList. + * @param denoter - `optional` String that denotes the end of the ActionList sentence. + * If placed dynamically, allows for the explicit appending of information at the end of the sentence + * @ExampleSentence ${preposition: 'Via'} Muxium set Mode to ${denoter: 'Ownership Mode.'} + * @Output Via Muxium set Mode to Ownership Mode. + */ +export interface ActionNodeOptions { + keyedSelectors?: KeyedSelector[]; + conceptSemaphore?: number; + priority?: number; + semaphore?: [number, number, number, number]; + agreement?: number; + decisionNodes?: Record; + decisionNotes?: ActionNotes; + successNode?: ActionNode | null; + successNotes?: ActionNotes; + failureNode?: ActionNode | null; + failureNotes?: ActionNotes; + lastActionNode?: ActionNode; +} + +/** + * Use this as an argument, this should be a "Curried Function" with your arguments carried over. + * */ +export type ActionStrategyStitch = () => [ActionNode, ActionStrategy]; +/** + * Use this as an argument, as we lose type checking of your functions arguments, + * due to the current implementation of Typescript argument generics. + */ +export type ActionStrategyCreator = (...arg0: unknown[]) => ActionStrategy; + +/** + * Will decorate the final Stratimux sentence + * @preposition - Would append your string. + * @denoter - Would include some string ending in punctuation. + */ +export interface ActionNotes { + preposition?: string; + denoter?: string; +} + +/** + * ActionStrategyParams + * Interface of ActionStrategy Construction + * @param data - Payload to be carried throughout the strategy. + * @param initialNode - Starting point of your ActionStrategy + */ +export interface ActionStrategyParameters { + topic: string; + data?: Record; + initialNode: ActionNode; + priority?: number; +} +export interface ActionStrategy { + topic: string; + data?: Record; + currentNode: ActionNode; + actionList: Array; + puntedStrategy?: ActionStrategy[]; + stubs?: OwnershipTicketStub[]; + priority?: number; + step?: number; +} + +export type ActionStrategyTopic = string; +/*#>*/ \ No newline at end of file diff --git a/src/model/action/strategy/actionStrategyConsumers.ts b/src/model/action/strategy/actionStrategyConsumers.ts new file mode 100644 index 00000000..3533bcda --- /dev/null +++ b/src/model/action/strategy/actionStrategyConsumers.ts @@ -0,0 +1,207 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy model file. +This file defines a series of consumer functions that accept an ActionStrategy and data parameter; that +then returns a new ActionStrategy based on the inputs. +$>*/ +/*<#*/ +import { muxiumConclude, muxiumConcludeType } from '../../../concepts/muxium/qualities/conclude.quality'; +import { createAction } from '../action'; +import { Action } from '../action.type'; +import { ActionNode, ActionNotes, ActionStrategy } from './actionStrategy.type'; +import { createSentence } from './actionStrategyHelpers'; + +export const strategyBegin = (strategy: ActionStrategy, data?: Record): Action => { + const currentNode = strategy.currentNode; + let priority; + if (currentNode.priority) { + priority = currentNode.priority; + } else if (strategy.priority) { + priority = strategy.priority; + } + strategy.currentNode.action = createAction( + currentNode.actionType, + { + payload: currentNode.payload, + keyedSelectors: currentNode.keyedSelectors, + agreement: currentNode.agreement, + semaphore: currentNode.semaphore, + conceptSemaphore: currentNode.conceptSemaphore, + priority + } + ); + strategy.currentNode.action.strategy = { + ...strategy, + topic: strategy.topic, + data: data ? data : strategy.data, + currentNode: strategy.currentNode, + actionList: strategy.actionList, + priority: strategy.priority, + step: strategy.step ? strategy.step + 1 : 1 + }; + if (strategy.currentNode.action !== null) { + return strategy.currentNode.action; + } else { + return muxiumConclude(); + } +}; + +/** + * strategySuccess(strategy: ActionStrategy, data?: any) + * Returns the failure stage's Action and reassigns ActionStrategy to that Action's strategy parameter. + * If no failureNode is found, will return EndOfActionStrategy instead. + * @param data - OPTIONAL, if used will override the ActionStrategy's payload + */ +const strategyConsumer = ( + _strategy: ActionStrategy, + nextNode: ActionNode | null, + defaultPreposition: string, + notes?: ActionNotes, + data?: Record +) => { + const strategy = {..._strategy}; + let nextAction: Action; + const actionListEntry = createSentence( + strategy.currentNode, + notes, + notes?.preposition ? notes.preposition : defaultPreposition + ); + if (nextNode !== null) { + const origin = strategy.currentNode.action?.origin; + let priority; + if (nextNode.priority) { + priority = nextNode.priority; + } else if (strategy.priority) { + priority = strategy.priority; + } + nextAction = createAction( + nextNode.actionType, + { + payload: nextNode.payload, + keyedSelectors: nextNode.keyedSelectors, + agreement: nextNode.agreement, + semaphore: nextNode.semaphore, + conceptSemaphore: nextNode.conceptSemaphore, + priority, + origin + } + ); + nextNode.action = nextAction; + nextNode.lastActionNode = strategy.currentNode; + nextAction.strategy = { + ...strategy, + topic: strategy.topic, + data: data ? data : strategy.data, + currentNode: nextNode, + actionList: [...strategy.actionList, actionListEntry], + step: strategy.step ? strategy.step + 1 : 1 + }; + return nextAction; + } else { + strategy.actionList = [...strategy.actionList, actionListEntry, '\n']; + if ( + strategy.puntedStrategy !== undefined && + strategy.puntedStrategy?.length !== 0 + ) { + const nextStrategy = + strategy.puntedStrategy.shift() as ActionStrategy; + nextStrategy.puntedStrategy = strategy.puntedStrategy; + const nextEntry = `${nextStrategy.topic}.`; + nextStrategy.actionList = [ + ...strategy.actionList, + nextEntry, + ]; + + nextStrategy.stubs = strategy.stubs; + nextStrategy.currentNode.lastActionNode = strategy.currentNode; + + const act = strategyBegin(nextStrategy); + act.origin = strategy.currentNode.action?.origin; + return act; + } + const origin = strategy.currentNode.action?.origin; + const conclude: ActionNode = { + actionType: muxiumConcludeType, + successNode: null, + failureNode: null, + lastActionNode: strategy.currentNode, + priority: strategy.priority + }; + conclude.action = createAction(conclude.actionType, { + origin + }); + conclude.action.priority = strategy.priority; + conclude.action.strategy = { + ...strategy, + currentNode: conclude, + data: data ? data : strategy.data, + step: strategy.step ? strategy.step + 1 : 1 + }; + return conclude.action; + } +}; + +/** + * strategySuccess(strategy: ActionStrategy, data?: any) + * Returns the failure stage's Action and reassigns ActionStrategy to that Action's strategy parameter. + * If no failureNode is found, will return Conclude instead. + * @param data - OPTIONAL, if used will override the ActionStrategy's payload + */ +export const strategySuccess = (_strategy: ActionStrategy, data?: Record) => { + return strategyConsumer( + _strategy, + _strategy.currentNode.successNode, + 'Success with', + _strategy.currentNode.successNotes, + data + ); +}; +/** + * strategyFailed(strategy: ActionStrategy, data?: any) + * Returns the failure stage's Action and reassigns ActionStrategy to that Action's strategy parameter. + * If no failureNode is found, will return Conclude instead. + * @param data - OPTIONAL, if used will override the ActionStrategy's payload + */ +export function strategyFailed(_strategy: ActionStrategy, data?: Record) { + return strategyConsumer( + _strategy, + _strategy.currentNode.failureNode, + 'Failed with', + _strategy.currentNode.failureNotes + ); +} + +/** + * strategyDecide(strategy: ActionStrategy, index:number, data?: any) + * Returns the DecisionNode of Index reassigns ActionStrategy to that Action's strategy parameter. + * If no decisionNode is found, will return Conclude instead. + * @param data - OPTIONAL, if used will override the ActionStrategy's payload + */ +export const strategyDecide = ( + _strategy: ActionStrategy, + decideKey: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data?: Record, +) => { + if (_strategy.currentNode.decisionNodes) { + const decisionNodes = _strategy.currentNode.decisionNodes as Record; + if ( + decisionNodes[decideKey] !== null + ) { + const nextNode = decisionNodes[decideKey]; + return strategyConsumer( + _strategy, + nextNode, + decideKey, + _strategy.currentNode.decisionNotes, + data + ); + } + } + return strategyConsumer( + _strategy, + null, + 'No decision' + ); +}; + +/*#>*/ \ No newline at end of file diff --git a/src/model/action/strategy/actionStrategyConsumersAdvanced.ts b/src/model/action/strategy/actionStrategyConsumersAdvanced.ts new file mode 100644 index 00000000..425c1d90 --- /dev/null +++ b/src/model/action/strategy/actionStrategyConsumersAdvanced.ts @@ -0,0 +1,115 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy Consumers Advanced model file. +This provides additional functionality for the consumption of ActionStrategies not offered by the base Consumer Functions. +$>*/ +/*<#*/ +import { muxiumConclude } from '../../../concepts/muxium/qualities/conclude.quality'; +import { Action, nullActionType } from '../action.type'; +import { ActionNode, ActionStrategy } from './actionStrategy.type'; +import { createActionNode, createStrategy } from './actionStrategy'; +import { createSentence } from './actionStrategyHelpers'; +import { strategyBegin } from './actionStrategyConsumers'; + +// Remember Water Boy +export const strategyPunt = ( + puntedStrategy: ActionStrategy, + newStrategy: ActionStrategy, +) => { + let puntList: ActionStrategy[] = []; + if (puntedStrategy.puntedStrategy !== undefined) { + puntList = [...puntedStrategy.puntedStrategy, puntedStrategy]; + } else { + puntList.push(puntedStrategy); + } + newStrategy.puntedStrategy = puntList; + return newStrategy; +}; + +export const strategySequence = (strategies: ActionStrategy[]): ActionStrategy | undefined => { + if (strategies.length > 0) { + const first = strategies[0]; + const list = []; + for (let i = 1; i < strategies.length; i++) { + list.push(strategies[i]); + } + first.puntedStrategy = list; + return first; + } else { + return undefined; + } +}; + +export const strategyBackTrack = (_strategy: ActionStrategy): Action => { + const strategy = _strategy; + if (strategy.currentNode.lastActionNode?.actionType !== nullActionType) { + const newNode = strategy.currentNode.lastActionNode as ActionNode; + if (newNode.action?.strategy?.actionList) { + newNode.action.strategy.actionList = [ + ...newNode.action.strategy.actionList, + strategy.actionList[strategy.actionList.length - 1], + ]; + strategy.step = strategy.step ? strategy.step + 1 : 1; + } + return {...newNode.action} as Action; + } else { + return muxiumConclude({origin: _strategy.currentNode.action?.origin}); + } +}; + +export const strategyDetermine = >( + action: Action, + options: { + topic?: string, + priority?: number, + data?: T + }): Action => { + return strategyBegin(createStrategy({ + topic: options.topic ? options.topic : 'STRATEGY DETERMINED', + initialNode: createActionNode(action), + priority: options.priority, + data: options.data + })); +}; + +/** + * The main functionality of this helper function is to allow for asynchronous recursion within your strategies. + * As the difficulty of working with async code within a node, is that you must use a then operation + * This simplifies the process of asynchronously depleting a list until your call the next strategy decision function. + * Likewise this should be used within the context of a method, not within a strategy creator function. + * @param _strategy Target ActionStrategy. + * @param control A depleting list should be either the payload or data passed into this function to allow this to be halting complete. + * @param payload If set will set the payload for both action and the newly created ActionNode. + * @param data If set will set the data on the ActionStrategy attached to the returned action. + * @returns Action + */ +export const strategyRecurse = + (_strategy: ActionStrategy, control: {payload?: Record, data?: Record}): Action => { + const strategy = { + ..._strategy + }; + const currentNode = { + ..._strategy.currentNode + }; + const action = { + ...currentNode.action + } as Action; + action.payload = control.payload ? control.payload : (_strategy.currentNode.action as Action).payload; + currentNode.payload = control.payload ? control.payload : _strategy.currentNode.payload; + currentNode.lastActionNode = _strategy.currentNode; + strategy.data = control.data ? control.data : _strategy.data; + strategy.actionList = [ + ...strategy.actionList, + createSentence( + _strategy.currentNode, + _strategy.currentNode.successNotes, + ) + ]; + currentNode.action = action; + strategy.currentNode = currentNode; + + strategy.step = strategy.step ? strategy.step + 1 : 1; + action.strategy = strategy; + return action; + }; + +/*#>*/ \ No newline at end of file diff --git a/src/model/actionStrategyData.ts b/src/model/action/strategy/actionStrategyData.ts similarity index 95% rename from src/model/actionStrategyData.ts rename to src/model/action/strategy/actionStrategyData.ts index 47d10718..cc644d9e 100644 --- a/src/model/actionStrategyData.ts +++ b/src/model/action/strategy/actionStrategyData.ts @@ -8,7 +8,8 @@ if being observed via a plan or subscription. $>*/ /*<#*/ // eslint-disable-next-line no-shadow -import { ActionStrategy } from './actionStrategy'; + +import { ActionStrategy } from './actionStrategy.type'; // eslint-disable-next-line no-shadow export enum failureConditions { diff --git a/src/model/action/strategy/actionStrategyHelpers.ts b/src/model/action/strategy/actionStrategyHelpers.ts new file mode 100644 index 00000000..32a514bd --- /dev/null +++ b/src/model/action/strategy/actionStrategyHelpers.ts @@ -0,0 +1,36 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy Helper model file. +Here we are defining the necessary functions to aid in dialog creation within the Stratimux Paradigm. +Noting that this is an additional degree of abstraction with associated computation cost. +$>*/ +/*<#*/ +import { ActionNode, ActionNotes, ActionStrategy, ActionStrategyParameters } from './actionStrategy.type'; + +export function isNotPunctuated(str: string): boolean { + const punctuatedList = ['.', ',', '?', '!', ';']; + let notPunctuated = true; + for (const punctuated of punctuatedList) { + if (str.charAt(0) === punctuated) { + notPunctuated = false; + break; + } + } + return notPunctuated; +} + +export function createSentence(actionNode: ActionNode, actionNotes?: ActionNotes , decisionKey?: string): string { + const preposition = actionNotes?.preposition ? `${actionNotes.preposition} ` : ''; + const decision = decisionKey ? `${decisionKey} ` : ''; + const body = `${actionNode.actionType}`; + let denoter = '.'; + if (actionNotes?.denoter) { + if (isNotPunctuated(actionNotes.denoter)) { + denoter = ` ${actionNotes.denoter}`; + } else { + denoter = actionNotes.denoter; + } + } + return preposition + decision + body + denoter; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/action/strategy/index.ts b/src/model/action/strategy/index.ts new file mode 100644 index 00000000..5074727c --- /dev/null +++ b/src/model/action/strategy/index.ts @@ -0,0 +1,28 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the ActionStrategy Index model file. +This file defines the strategy object that bundles all necessary ActionStrategy consumer functions needed for production. +$>*/ +/*<#*/ +import { + createActionNode, + createActionNodeFromStrategy, + createStrategy, +} from './actionStrategy'; +import { strategyBegin, strategyDecide, strategyFailed, strategySuccess } from './actionStrategyConsumers'; +import { strategyBackTrack, strategyDetermine, strategyPunt, strategyRecurse, strategySequence } from './actionStrategyConsumersAdvanced'; + +export const strata = ({ + createActionNode, + createActionNodeFromStrategy, + create: createStrategy, + begin: strategyBegin, + success: strategySuccess, + failed: strategyFailed, + decide: strategyDecide, + determine: strategyDetermine, + punt: strategyPunt, + sequence: strategySequence, + backTrack: strategyBackTrack, + recurse: strategyRecurse, +}); +/*#>*/ \ No newline at end of file diff --git a/src/model/actionStrategy.ts b/src/model/actionStrategy.ts deleted file mode 100644 index 300cb9da..00000000 --- a/src/model/actionStrategy.ts +++ /dev/null @@ -1,672 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the ActionStrategy model file. -This file is what allows for Stratimux to be provably terminating. -As each strategy constitutes a finite set of symbols that must reach a conclusion. -Using this data structure we can constrain the Muxium's recursive functionality to the length -of the strategies that currently exist within it. -This file likewise defines a series of consumer functions that accept an ActionStrategy and data parameter; that -then returns a new ActionStrategy based on the inputs. -$>*/ -/*<#*/ -import { muxiumConclude, muxiumConcludeType } from '../concepts/muxium/qualities/conclude.quality'; -import { Action, ActionType, createAction, nullActionType } from './action'; -import { OwnershipTicketStub } from './ownership'; -import { KeyedSelector } from './selector'; - -/** - * ActionNode - Control Structure used by ActionStrategy - * @param action - Action to be dispatched. - * @param successNode - Upon ActionStrategy.success() the Strategy will update itself to this node. - * * If set to null, will default to Muxium Conclude Type on ActionStrategy.success(). - * @param failureNode - `optional` ActionStrategy.failed() will fire Muxium Conclude Type if left blank or set to null. - * @param payload - `optional` Will set the payload of the action. - * @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore(). - * @param conceptSemaphore - `optional` Used for Muxified Qualities. Must be specified via that principle's passed semaphore value. - * @param priority - `optional` Will allow the action to be placed in the body que accordingly. - * @param agreement - `optional` Is time in milliseconds of the actions intended lifetime. - * @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows. - * @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList. - * @param denoter - `optional` String that denotes the end of the ActionList sentence. - * If placed dynamically, allows for the explicit appending of information at the end of the sentence - * @ExampleSentence ${preposition: 'Via'} Muxium set Mode to ${denoter: 'Ownership Mode.'} - * @Output Via Muxium set Mode to Ownership Mode. - */ -export interface ActionNode { - action?: Action; - actionType: ActionType; - payload?: Record; - conceptSemaphore?: number; - priority?: number; - keyedSelectors?: KeyedSelector[]; - semaphore?: [number, number, number, number]; - agreement?: number; - decisionNodes?: Record; - decisionNotes?: ActionNotes; - successNode: ActionNode | null; - successNotes?: ActionNotes; - failureNode: ActionNode | null; - failureNotes?: ActionNotes; - lastActionNode?: ActionNode; -} -/** - * Options list - * @param successNode - Upon ActionStrategy.success() the Strategy will update itself to this node. - * * If set to null, will default to Muxium Conclude Type on ActionStrategy.success(). - * @param failureNode - `optional` ActionStrategy.failed() will fire Muxium Conclude Type if left blank or set to null. - * @param semaphore - `optional` This will prime the action to avoid look up at run time. Best practice use getSemaphore(). - * @param conceptSemaphore - `optional` Used for Muxified Qualities. Must be specified via that principle's passed semaphore value. - * @param priority - `optional` Will allow the action to be placed in the body que accordingly. - * @param agreement - `optional` Is time in milliseconds of the actions intended lifetime. - * @param decisionNodes - `optional` The third or more option, may override success or failure in your workflows. - * @param preposition - `optional` String that prefixes the ActionType when added to the Strategy's ActionList. - * @param denoter - `optional` String that denotes the end of the ActionList sentence. - * If placed dynamically, allows for the explicit appending of information at the end of the sentence - * @ExampleSentence ${preposition: 'Via'} Muxium set Mode to ${denoter: 'Ownership Mode.'} - * @Output Via Muxium set Mode to Ownership Mode. - */ -export interface ActionNodeOptions { - keyedSelectors?: KeyedSelector[]; - conceptSemaphore?: number; - priority?: number; - semaphore?: [number, number, number, number]; - agreement?: number; - decisionNodes?: Record; - decisionNotes?: ActionNotes; - successNode?: ActionNode | null; - successNotes?: ActionNotes; - failureNode?: ActionNode | null; - failureNotes?: ActionNotes; - lastActionNode?: ActionNode; -} - -/** - * Use this as an argument, this should be a "Curried Function" with your arguments carried over. - * */ -export type ActionStrategyStitch = () => [ActionNode, ActionStrategy]; -/** - * Use this as an argument, as we lose type checking of your functions arguments, - * due to the current implementation of Typescript argument generics. - */ -export type ActionStrategyCreator = (...arg0: unknown[]) => ActionStrategy; - -/** - * Decomposes an action into an ActionNode to be later Recomposed. - * @param action Action properties of KeyedSelector, Agreement, and Semaphore take priority over options. - * @param options successNode and failureNodes are always required. If using decisionNodes, set both to null. - * @returns ActionNode - */ -export function createActionNode(action: Action, options?: ActionNodeOptions): ActionNode { - if (options) { - return { - actionType: action.type, - payload: action.payload, - keyedSelectors: action.keyedSelectors ? action.keyedSelectors : options.keyedSelectors, - conceptSemaphore: action.conceptSemaphore ? action.conceptSemaphore : options.conceptSemaphore, - priority: action.priority ? action.priority : options.priority, - agreement: action.agreement ? action.agreement : options.agreement, - semaphore: action.semaphore ? action.semaphore : options.semaphore, - successNode: options.successNode ? options.successNode : null, - successNotes: options.successNotes, - failureNode: options.failureNode ? options.failureNode : null, - failureNotes: options.failureNotes, - decisionNodes: options.decisionNodes, - decisionNotes: options.decisionNotes, - lastActionNode: options.lastActionNode - }; - } - return { - actionType: action.type, - payload: action.payload, - successNode: null, - failureNode: null - }; -} - -/** - * Note that this will be a new ActionNode and not the original created within the provided strategy. - * @param strategy Will return a recomposed ActionNode of the provided strategy. - * @returns ActionNode - */ -export const createActionNodeFromStrategy = (strategy: ActionStrategy): ActionNode => { - const currentNode = strategy.currentNode; - let action; - if (currentNode.action) { - action = {...currentNode.action}; - } else { - action = createAction( - currentNode.actionType, - { - payload: currentNode.payload, - keyedSelectors: currentNode.keyedSelectors, - agreement: currentNode.agreement, - semaphore: currentNode.semaphore, - conceptSemaphore: currentNode.conceptSemaphore, - priority: currentNode.priority - } - ); - } - return createActionNode(action, { - successNode: currentNode.successNode, - successNotes: currentNode.successNotes, - failureNode: currentNode.failureNode, - failureNotes: currentNode.failureNotes, - decisionNodes: currentNode.decisionNodes, - decisionNotes: currentNode.decisionNotes, - lastActionNode: currentNode.lastActionNode - }); -}; - -/** - * Will decorate the final Stratimux sentence - * @preposition - Would append your string. - * @denoter - Would include some string ending in punctuation. - */ -export interface ActionNotes { - preposition?: string; - denoter?: string; -} - -/** - * ActionStrategyParams - * Interface of ActionStrategy Construction - * @param data - Payload to be carried throughout the strategy. - * @param initialNode - Starting point of your ActionStrategy - */ -export interface ActionStrategyParameters { - topic: string; - data?: Record; - initialNode: ActionNode; - priority?: number; -} -export interface ActionStrategy { - topic: string; - data?: Record; - currentNode: ActionNode; - actionList: Array; - puntedStrategy?: ActionStrategy[]; - stubs?: OwnershipTicketStub[]; - priority?: number; - step?: number; -} - -export type ActionStrategyTopic = string; - -function isNotPunctuated(str: string): boolean { - const punctuatedList = ['.', ',', '?', '!', ';']; - let notPunctuated = true; - for (const punctuated of punctuatedList) { - if (str.charAt(0) === punctuated) { - notPunctuated = false; - break; - } - } - return notPunctuated; -} - -function createSentence(actionNode: ActionNode, actionNotes?: ActionNotes , decisionKey?: string): string { - const preposition = actionNotes?.preposition ? `${actionNotes.preposition} ` : ''; - const decision = decisionKey ? `${decisionKey} ` : ''; - const body = `${actionNode.actionType}`; - let denoter = '.'; - if (actionNotes?.denoter) { - if (isNotPunctuated(actionNotes.denoter)) { - denoter = ` ${actionNotes.denoter}`; - } else { - denoter = actionNotes.denoter; - } - } - return preposition + decision + body + denoter; -} - -export function createStrategy( - params: ActionStrategyParameters, -): ActionStrategy { - const data: Record | undefined = params.data; - const currentNode: ActionNode = params.initialNode; - const priority = params.priority; - currentNode.lastActionNode = { - // This logically determines that all ActionNodes will have a Action associated. - action: createAction(nullActionType), - actionType: nullActionType, - successNode: null, - failureNode: null - }; - const actionList: Array = [params.topic + '.']; - return { - topic: params.topic, - data, - currentNode, - actionList, - priority, - step: 0 - }; -} - -export const strategyBegin = (strategy: ActionStrategy, data?: Record): Action => { - const currentNode = strategy.currentNode; - let priority; - if (currentNode.priority) { - priority = currentNode.priority; - } else if (strategy.priority) { - priority = strategy.priority; - } - strategy.currentNode.action = createAction( - currentNode.actionType, - { - payload: currentNode.payload, - keyedSelectors: currentNode.keyedSelectors, - agreement: currentNode.agreement, - semaphore: currentNode.semaphore, - conceptSemaphore: currentNode.conceptSemaphore, - priority - } - ); - strategy.currentNode.action.strategy = { - ...strategy, - topic: strategy.topic, - data: data ? data : strategy.data, - currentNode: strategy.currentNode, - actionList: strategy.actionList, - priority: strategy.priority, - step: strategy.step ? strategy.step + 1 : 1 - }; - if (strategy.currentNode.action !== null) { - return strategy.currentNode.action; - } else { - return muxiumConclude(); - } -}; - -/** - * strategySuccess(strategy: ActionStrategy, data?: any) - * Returns the failure stage's Action and reassigns ActionStrategy to that Action's strategy parameter. - * If no failureNode is found, will return EndOfActionStrategy instead. - * @param data - OPTIONAL, if used will override the ActionStrategy's payload - */ -export const strategySuccess = (_strategy: ActionStrategy, data?: Record) => { - const strategy = {..._strategy}; - let nextAction: Action; - const actionListEntry = createSentence( - strategy.currentNode, - strategy.currentNode?.successNotes, - strategy.currentNode.successNotes?.preposition !== undefined ? '' : 'Success with' - ); - if (strategy.currentNode.successNode !== null) { - const nextNode = strategy.currentNode.successNode; - const origin = strategy.currentNode.action?.origin; - let priority; - if (nextNode.priority) { - priority = nextNode.priority; - } else if (strategy.priority) { - priority = strategy.priority; - } - nextAction = createAction( - nextNode.actionType, - { - payload: nextNode.payload, - keyedSelectors: nextNode.keyedSelectors, - agreement: nextNode.agreement, - semaphore: nextNode.semaphore, - conceptSemaphore: nextNode.conceptSemaphore, - priority, - origin - } - ); - nextNode.action = nextAction; - nextNode.lastActionNode = strategy.currentNode; - nextAction.strategy = { - ...strategy, - topic: strategy.topic, - data: data ? data : strategy.data, - currentNode: nextNode, - actionList: [...strategy.actionList, actionListEntry], - step: strategy.step ? strategy.step + 1 : 1 - }; - return nextAction; - } else { - strategy.actionList = [...strategy.actionList, actionListEntry, '\n']; - if ( - strategy.puntedStrategy !== undefined && - strategy.puntedStrategy?.length !== 0 - ) { - const nextStrategy = - strategy.puntedStrategy.shift() as ActionStrategy; - nextStrategy.puntedStrategy = strategy.puntedStrategy; - const nextEntry = `${nextStrategy.topic}.`; - nextStrategy.actionList = [ - ...strategy.actionList, - nextEntry, - ]; - - nextStrategy.stubs = strategy.stubs; - nextStrategy.currentNode.lastActionNode = strategy.currentNode; - - const act = strategyBegin(nextStrategy); - act.origin = strategy.currentNode.action?.origin; - return act; - } - const origin = strategy.currentNode.action?.origin; - const conclude: ActionNode = { - actionType: muxiumConcludeType, - successNode: null, - failureNode: null, - lastActionNode: strategy.currentNode, - priority: strategy.priority - }; - conclude.action = createAction(conclude.actionType, { - origin - }); - conclude.action.priority = strategy.priority; - conclude.action.strategy = { - ...strategy, - currentNode: conclude, - data: data ? data : strategy.data, - step: strategy.step ? strategy.step + 1 : 1 - }; - return conclude.action; - } -}; -/** - * strategyFailed(strategy: ActionStrategy, data?: any) - * Returns the failure stage's Action and reassigns ActionStrategy to that Action's strategy parameter. - * If no failureNode is found, will return EndOfActionStrategy instead. - * @param data - OPTIONAL, if used will override the ActionStrategy's payload - */ -export function strategyFailed(_strategy: ActionStrategy, data?: Record) { - const strategy = {..._strategy}; - let nextAction: Action; - const actionListEntry = createSentence( - strategy.currentNode, - strategy.currentNode.failureNotes, - strategy.currentNode.failureNotes?.preposition !== undefined ? '' : 'Failed with' - ); - if ( - strategy.currentNode.failureNode !== null - ) { - const nextNode = strategy.currentNode.failureNode; - const origin = strategy.currentNode.action?.origin; - let priority; - if (nextNode.priority) { - priority = nextNode.priority; - } else if (strategy.priority) { - priority = strategy.priority; - } - nextAction = createAction( - nextNode.actionType, - { - payload: nextNode.payload, - keyedSelectors: nextNode.keyedSelectors, - agreement: nextNode.agreement, - semaphore: nextNode.semaphore, - conceptSemaphore: nextNode.conceptSemaphore, - priority, - origin - } - ); - nextNode.action = nextAction; - nextNode.lastActionNode = strategy.currentNode; - strategy.actionList = [...strategy.actionList, actionListEntry]; - nextAction = { ...nextAction }; - nextAction.strategy = { - ...strategy, - topic: strategy.topic, - data: strategy.data, - currentNode: nextNode, - actionList: strategy.actionList, - step: strategy.step ? strategy.step + 1 : 1 - }; - return nextAction; - } else { - strategy.actionList = [...strategy.actionList, actionListEntry, '\n']; - if ( - strategy.puntedStrategy !== undefined && - strategy.puntedStrategy?.length !== 0 - ) { - const nextStrategy = - strategy.puntedStrategy.shift() as ActionStrategy; - nextStrategy.puntedStrategy = strategy.puntedStrategy; - const nextEntry = `${nextStrategy.topic}.`; - nextStrategy.actionList = [ - ...strategy.actionList, - nextEntry, - ]; - - nextStrategy.stubs = strategy.stubs; - nextStrategy.currentNode.lastActionNode = strategy.currentNode; - const act = strategyBegin(nextStrategy); - act.origin = strategy.currentNode.action?.origin; - return act; - } - const conclude: ActionNode = { - actionType: muxiumConcludeType, - successNode: null, - failureNode: null, - lastActionNode: strategy.currentNode, - priority: strategy.priority - }; - conclude.action = createAction(conclude.actionType); - conclude.action.priority = strategy.priority; - conclude.action.strategy = { - ...strategy, - currentNode: conclude, - data: data ? data : strategy.data, - step: strategy.step ? strategy.step + 1 : 1 - }; - return conclude.action; - } -} - -/** - * strategyDecide(strategy: ActionStrategy, index:number, data?: any) - * Returns the DecisionNode of Index reassigns ActionStrategy to that Action's strategy parameter. - * If no decisionNode is found, will return EndOfActionStrategy instead. - * @param data - OPTIONAL, if used will override the ActionStrategy's payload - */ -export const strategyDecide = ( - _strategy: ActionStrategy, - decideKey: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - data?: Record, -) => { - const strategy = {..._strategy}; - let nextAction: Action; - const actionListEntry = createSentence( - strategy.currentNode, - strategy.currentNode.decisionNotes, - decideKey - ); - - if (strategy.currentNode.decisionNodes) { - const decisionNodes = strategy.currentNode.decisionNodes as Record; - if ( - decisionNodes[decideKey] !== null - ) { - const nextNode = decisionNodes[decideKey]; - const origin = strategy.currentNode.action?.origin; - let priority; - if (nextNode.priority) { - priority = nextNode.priority; - } else if (strategy.priority) { - priority = strategy.priority; - } - nextAction = createAction( - nextNode.actionType, - { - payload: nextNode.payload, - keyedSelectors: nextNode.keyedSelectors, - agreement: nextNode.agreement, - semaphore: nextNode.semaphore, - conceptSemaphore: nextNode.conceptSemaphore, - priority, - origin - } - ); - nextNode.action = nextAction; - nextNode.lastActionNode = strategy.currentNode; - strategy.actionList = [...strategy.actionList, actionListEntry]; - nextAction.strategy = { - ...strategy, - topic: strategy.topic, - data: data ? data : strategy.data, - currentNode: nextNode, - actionList: strategy.actionList, - step: strategy.step ? strategy.step + 1 : 1 - }; - return nextAction; - } - } - strategy.actionList = [...strategy.actionList, actionListEntry, '\n']; - if ( - strategy.puntedStrategy !== undefined && - strategy.puntedStrategy?.length !== 0 - ) { - const nextStrategy = - strategy.puntedStrategy.shift() as ActionStrategy; - nextStrategy.puntedStrategy = strategy.puntedStrategy; - const nextEntry = `${nextStrategy.topic}.`; - nextStrategy.actionList = [ - ...strategy.actionList, - nextEntry, - ]; - nextStrategy.stubs = strategy.stubs; - nextStrategy.currentNode.lastActionNode = strategy.currentNode; - - const act = strategyBegin(nextStrategy); - act.origin = strategy.currentNode.action?.origin; - return act; - } - const conclude: ActionNode = { - actionType: muxiumConcludeType, - successNode: null, - failureNode: null, - lastActionNode: strategy.currentNode, - priority: strategy.priority - }; - const origin = strategy.currentNode.action?.origin; - conclude.action = createAction(conclude.actionType, {origin}); - conclude.action.priority = strategy.priority; - conclude.action.strategy = { - ...strategy, - currentNode: conclude, - data: data ? data : strategy.data, - step: strategy.step ? strategy.step + 1 : 1 - }; - return conclude.action; -}; -// Remember Water Boy -export const strategyPunt = ( - puntedStrategy: ActionStrategy, - newStrategy: ActionStrategy, -) => { - let puntList: ActionStrategy[] = []; - if (puntedStrategy.puntedStrategy !== undefined) { - puntList = [...puntedStrategy.puntedStrategy, puntedStrategy]; - } else { - puntList.push(puntedStrategy); - } - newStrategy.puntedStrategy = puntList; - return newStrategy; -}; - -export const strategySequence = (strategies: ActionStrategy[]): ActionStrategy | undefined => { - if (strategies.length > 0) { - const first = strategies[0]; - const list = []; - for (let i = 1; i < strategies.length; i++) { - list.push(strategies[i]); - } - first.puntedStrategy = list; - return first; - } else { - return undefined; - } -}; - -export const strategyBackTrack = (_strategy: ActionStrategy): Action => { - const strategy = _strategy; - if (strategy.currentNode.lastActionNode?.actionType !== nullActionType) { - const newNode = strategy.currentNode.lastActionNode as ActionNode; - if (newNode.action?.strategy?.actionList) { - newNode.action.strategy.actionList = [ - ...newNode.action.strategy.actionList, - strategy.actionList[strategy.actionList.length - 1], - ]; - strategy.step = strategy.step ? strategy.step + 1 : 1; - } - return {...newNode.action} as Action; - } else { - return muxiumConclude({origin: _strategy.currentNode.action?.origin}); - } -}; - -export const strategyDetermine = >( - action: Action, - options: { - topic?: string, - priority?: number, - data?: T - }): Action => { - return strategyBegin(createStrategy({ - topic: options.topic ? options.topic : 'STRATEGY DETERMINED', - initialNode: createActionNode(action), - priority: options.priority, - data: options.data - })); -}; - -/** - * The main functionality of this helper function is to allow for asynchronous recursion within your strategies. - * As the difficulty of working with async code within a node, is that you must use a then operation - * This simplifies the process of asynchronously depleting a list until your call the next strategy decision function. - * Likewise this should be used within the context of a method, not within a strategy creator function. - * @param _strategy Target ActionStrategy. - * @param control A depleting list should be either the payload or data passed into this function to allow this to be halting complete. - * @param payload If set will set the payload for both action and the newly created ActionNode. - * @param data If set will set the data on the ActionStrategy attached to the returned action. - * @returns Action - */ -export const strategyRecurse = - (_strategy: ActionStrategy, control: {payload?: Record, data?: Record}): Action => { - const strategy = { - ..._strategy - }; - const currentNode = { - ..._strategy.currentNode - }; - const action = { - ...currentNode.action - } as Action; - action.payload = control.payload ? control.payload : (_strategy.currentNode.action as Action).payload; - currentNode.payload = control.payload ? control.payload : _strategy.currentNode.payload; - currentNode.lastActionNode = _strategy.currentNode; - strategy.data = control.data ? control.data : _strategy.data; - strategy.actionList = [ - ...strategy.actionList, - createSentence( - _strategy.currentNode, - _strategy.currentNode.successNotes, - ) - ]; - currentNode.action = action; - strategy.currentNode = currentNode; - - strategy.step = strategy.step ? strategy.step + 1 : 1; - action.strategy = strategy; - return action; - }; - -export const strategy = ({ - createActionNode, - createActionNodeFromStrategy, - create: createStrategy, - begin: strategyBegin, - success: strategySuccess, - failed: strategyFailed, - decide: strategyDecide, - determine: strategyDetermine, - punt: strategyPunt, - sequence: strategySequence, - backTrack: strategyBackTrack, - recurse: strategyRecurse, -}); -/*#>*/ \ No newline at end of file diff --git a/src/model/concept.ts b/src/model/concept.ts deleted file mode 100644 index d65a7cb8..00000000 --- a/src/model/concept.ts +++ /dev/null @@ -1,476 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Concept model file. -This file defines the Concept abstraction that the Muxium uses to Transform its functionality. -A concept is composed of name, muxified, state, qualities, semaphore, principles, and some meta attributes if necessary. -$>*/ -/*<#*/ -import { Observable, Observer, Subject, Subscription } from 'rxjs'; -import { Action, ActionCreator, ActionCreatorType, ActionCreatorWithPayload, ActionType, Actions } from './action'; -import { PrincipleFunction } from '../model/principle'; -import { - BundledSelectors, - KeyedSelector, - KeyedSelectors, - Selectors, - createDummyKeyedSelectors, - createDummySelectors, - createMuxifiedKeyedSelector -} from './selector'; -import { MuxifiedSubject } from './stagePlanner'; -import { Comparators, createComparator } from './interface'; -import { Qualities, Quality } from './quality'; -import { Deck } from './deck'; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export type Reducer< - S extends Record, - T = void -> = (state: S, action: Action) => S | null; - -export type SpecificReducer, T = void, C = void> = - (state: S, action: Action, deck: Deck) => Partial | null; - -export type Method = Observable<[Action, boolean]>; -export type Principle = Observable; -export type Self = T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -export type ActionDeck = {action: Action, deck: Deck, self: Self}; - -export type Mode = ([action, concept, action$, concepts$]: [ - Action, - Concepts, - Subject, - MuxifiedSubject, -]) => void; - -export type MethodCreatorStep, T = void, C = void> = () => MethodCreator; - -export type MethodCreator, T = void, C = void> = - (concept$: Subject, semaphore: number) => [Method, Subject>]; -// export type MethodCreator = (concept$?: MuxifiedSubject, semaphore?: number) => [Method, Subject]; - -type Muxified = { - stateMap: string[]; - actionMap: string[]; -}; - -export type Concept, Q = void> = { - name: string; - muxifiedRecord: Record; - state: S; - actions: Actions; - comparators: Comparators; - keyedSelectors: KeyedSelectors; - selectors: Selectors; - qualities: Quality>[]; - q: Q extends Qualities ? - Q - : - Qualities; - semaphore: number; - principles?: PrincipleFunction[]; - mode?: Mode[]; - meta?: Record; -}; - -// export type AnyConcept = Concept, any> | Concept, void>; -export type AnyConcept = - Concept, Qualities> - | - // Concept, void> - // | -// eslint-disable-next-line @typescript-eslint/no-explicit-any - Concept; - -export type Concepts = Record; -export type LoadConcepts = Record; - -export type ConceptDeck = { - [K in keyof T]: - T[K] extends Concept, void> ? - Concept, void> - : - T[K] extends Concept, Qualities> ? - Concept, T[K]['q']> - : - Concept, any> -}; - -export type ConceptsSubscriber = (observerOrNext?: Partial> | ((value: Concepts) => void) | undefined) => Subscription; - -export function createConcept, Q = void>( - name: string, - state: S, - _qualities?: Record, - principles?: PrincipleFunction[], - mode?: Mode[], - meta?: Record, -// eslint-disable-next-line @typescript-eslint/no-explicit-any -): AnyConcept { - if (mode) { - mode.forEach((m, i) => { - m.toString = () => `MODE: ${name} ${i}`; - }); - } - if (principles) { - principles.forEach((p, i) => { - p.toString = () => `PRINCIPLE: ${name} ${i}`; - }); - } - const actions: Record = {}; - const comparators: Comparators = {}; - const qualities: Quality>[] = []; - if (_qualities) { - Object.keys(_qualities).forEach(q => { - try { - actions[q] = (_qualities[q] as Quality).actionCreator; - comparators[q] = createComparator((_qualities[q] as Quality).actionSemaphoreBucket); - qualities.push(_qualities[q] as Quality>); - } catch (error) { - console.error('ERROR @: ', q, _qualities[q]); - // console.warn('Check: ', _qualities); - } - }); - } - return { - name, - muxifiedRecord: {}, - state, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - actions: actions as Actions, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - comparators: comparators as Comparators, - keyedSelectors: createDummyKeyedSelectors(state), - selectors: createDummySelectors(), - qualities: qualities ? qualities : [], - q: (_qualities ? _qualities : {}) as Q extends Qualities ? Q : Qualities, - semaphore: -1, - principles, - mode, - meta - }; -} - -export function createQuality, T = void, C = void>( - actionType: ActionType, - actionSemaphoreBucket: [number, number, number, number][], - actionCreator: ActionCreatorType, - reducer: SpecificReducer, - methodCreator?: MethodCreatorStep, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - keyedSelectors?: KeyedSelector[], - meta?: Record, - analytics?: Record, -): Quality { - return { - actionType, - actionCreator, - actionSemaphoreBucket, - reducer, - methodCreator, - keyedSelectors, - meta, - analytics - }; -} -/** - * This will remove any duplicate qualities, principles, and modes. - * Note that for now the check for mode and principle are based on concept name and loaded index; - */ -function filterSimilarQualities(concept: AnyConcept) { - const newQualities: Quality>[] = []; - const newMuxified: Record = {}; - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const newPrinciples: PrincipleFunction>[] = []; - const newMode: Mode[] = []; - for (let i = 0; i < concept.qualities.length; i++) { - let found = false; - for (let j = i + 1; j < concept.qualities.length; j++) { - if (concept.qualities[i].actionType === concept.qualities[j].actionType) { - found = true; - break; - } - } - if (!found) { - newQualities.push(concept.qualities[i]); - } - } - concept.qualities = newQualities; - const muxifiedKeys = Object.keys(concept.muxifiedRecord); - for (let i = 0; i < muxifiedKeys.length; i++) { - let found = false; - for (let j = i + 1; j < muxifiedKeys.length; j++) { - if (muxifiedKeys[i] === muxifiedKeys[j]) { - found = true; - break; - } - } - if (!found) { - newMuxified[muxifiedKeys[i]] = concept.muxifiedRecord[muxifiedKeys[i]]; - } - } - concept.muxifiedRecord = newMuxified; - if (concept.principles) { - for (let i = 0; i < concept.principles.length; i++) { - let found = false; - for (let j = i + 1; j < concept.principles.length; j++) { - if (concept.principles[i].toString() === concept.principles[j].toString()) { - found = true; - break; - } - } - if (!found) { - newPrinciples.push(concept.principles[i]); - } - } - concept.principles = newPrinciples; - } - if (concept.mode) { - for (let i = 0; i < concept.mode.length; i++) { - let found = false; - for (let j = i + 1; j < concept.mode.length; j++) { - if (concept.mode[i].toString() === concept.mode[j].toString()) { - found = true; - break; - } - } - if (!found) { - newMode.push(concept.mode[i]); - } - } - concept.mode = newMode; - } - return concept; -} - -function muxify( - base: Concept, T>, - target: Concept, K> | AnyConcept -): Concept, T & K> { - if (target.name !== '') { - base.muxifiedRecord[target.name] = { - actionMap: Object.keys(target.actions), - stateMap: Object.keys(target.state) - }; - } - base.muxifiedRecord = { - ...base.muxifiedRecord, - ...target.muxifiedRecord - }; - base.state = { - ...base.state, - ...target.state, - }; - base.qualities = [ - ...base.qualities, - ...target.qualities, - ]; - base.actions = { - ...base.actions, - ...target.actions - }; - base.comparators = { - ...base.comparators, - ...target.comparators - }; - base.keyedSelectors = { - ...base.keyedSelectors, - ...target.keyedSelectors - }; - if (target.principles) { - if (base.principles) { - const principles = [ - ...base.principles, - ...target.principles - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ] as any; - base.principles = principles; - } else { - const principles = [ - ...target.principles - // eslint-disable-next-line @typescript-eslint/no-explicit-any - ] as any; - base.principles = principles; - } - } - if (target.mode) { - if (base.mode) { - base.mode = [ - ...base.mode, - ...target.mode - ]; - } else { - base.mode = [ - ...target.mode - ]; - } - } - if (target.meta) { - if (base.meta) { - base.meta = { - ...base.meta, - ...target.meta - }; - } else { - base.meta = { - ...target.mode - }; - } - } - return base as Concept, T & K>; -} -/** - * This will muxify concepts while prioritizing qualities later in the provided concepts list via recomposition. - * Then finally muxify the emergent concept with final priority. - */ -export function muxifyConcepts, T extends Qualities>( - concepts: AnyConcept[], - emergentConcept: AnyConcept -): AnyConcept { - const dummy: Record = {}; - let newConcept = createConcept('', dummy); - forEachConcept(concepts, (concept => { - newConcept = muxify(newConcept, concept); - })); - newConcept = muxify(newConcept, emergentConcept); - const newMuxifiedRecord: Record = {}; - Object.keys(newConcept.muxifiedRecord).forEach(name => { - if (name !== emergentConcept.name) { - newMuxifiedRecord[name] = newConcept.muxifiedRecord[name]; - } - }); - newConcept.muxifiedRecord = newMuxifiedRecord; - newConcept.name = emergentConcept.name; - if (newConcept.mode) { - newConcept.mode.forEach((m, i) => { - m.toString = () => `MODE: ${newConcept.name} ${i}`; - }); - } - if (newConcept.principles) { - newConcept.principles.forEach((p, i) => { - p.toString = () => `PRINCIPLE: ${newConcept.name} ${i}`; - }); - } - return filterSimilarQualities(newConcept as AnyConcept) as Concept; -} - -export const getMuxifiedName = (concepts: Concepts, semaphore: number): string | undefined => (concepts[semaphore]?.name); - -// Will return -1 if not found -export const getConceptSemaphore = (concepts: Concepts, conceptName: string): number => { - // eslint-disable-next-line consistent-return - forEachConcept(concepts, (concept, semaphore) => { - if (concept.name === conceptName) { - return semaphore; - } - }); - return -1; -}; - -export const isConceptLoaded = (concepts: Concepts, conceptName: string): boolean => { - const conceptKeys = Object.keys(concepts); - for (const i of conceptKeys) { - const index = Number(i); - if (concepts[index].name === conceptName) { - return true; - } - } - return false; -}; - -export const areConceptsLoaded = (concepts: Concepts, conceptNames: string[]): boolean => { - let allExists = true; - const conceptKeys = Object.keys(concepts); - for (const name of conceptNames) { - let found = false; - for (const i of conceptKeys) { - const index = Number(i); - if (name === concepts[index].name) { - found = true; - break; - } - } - if (!found) { - allExists = false; - break; - } - } - return allExists; -}; - -export const forEachConcept = (concepts: Concepts, each: (concept: AnyConcept, semaphore: number) => void) => { - const conceptKeys = Object.keys(concepts); - for (const i of conceptKeys) { - const index = Number(i); - each(concepts[index], index); - } -}; - -const stateToString = (state: Record): string => { - let final = '{\n'; - const keys = Object.keys(state); - for (const key of keys) { - let input = ''; - try { - input += `${key}: ${JSON.stringify(state[key])},\n`; - } catch (err) { - input = `${key}: [CIRCULAR],\n`; - } - final += input; - } - final += '}'; - return final; -}; - -export const conceptToString = (concept: AnyConcept): string => { - let output = ''; - output += `{\nname: ${concept.name},`; - const muxifiedKeys = Object.keys(concept.muxifiedRecord); - if (muxifiedKeys.length > 0) { - output += `\nmuxified: ${muxifiedKeys},`; - } - output += `\nqualities: [ ${concept.qualities.toString()}\n],`; - output += `\nstate: ${stateToString(concept.state)}, `; - if (concept.principles) { - output += `\nprinciples: [ ${concept.principles.map(p => p.toString()).join(',')} ]`; - } - if (concept.mode) { - output += `\nmode: [ ${concept.mode.map(m => m.toString()).join(',')} ]`; - } - if (concept.meta) { - output += `\nmeta: ${JSON.stringify(concept.meta)}`; - } - output += '\n}'; - return output; -}; - -export const conceptsToString = (concepts: Concepts): string => { - const conceptStringArray: string[] = []; - forEachConcept(concepts, (concept) => { - conceptStringArray.push(conceptToString(concept)); - }); - conceptStringArray.push(']'); - return '[\n' + conceptStringArray.join(',\n'); -}; - -export const qualityToString = (quality: Quality>) => () => { - const actionType = quality.actionType; - const r = quality.reducer.toString(); - const reducer = r === 'Default Reducer' ? r : 'Reducer'; - const method = quality.method?.toString(); - return (`\n{\nactionType: ${actionType},\nreducer: ${reducer},\nmethod: ${method}\n}`); -}; - -export const concept = { - create: createConcept, - muxify: muxifyConcepts, - isLoaded: isConceptLoaded, - areLoaded: areConceptsLoaded, - forEach: forEachConcept, - toString: conceptToString, - toStringConcepts: conceptsToString, - toStringQuality: qualityToString, -}; -/*#>*/ \ No newline at end of file diff --git a/src/model/concept/concept.ts b/src/model/concept/concept.ts new file mode 100644 index 00000000..cfba9aa9 --- /dev/null +++ b/src/model/concept/concept.ts @@ -0,0 +1,67 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Concept model file. +This file defines the Concept abstraction that the Muxium uses to Transform its functionality. +A concept is composed of name, muxified, state, qualities, semaphore, principles, and some meta attributes if necessary. +$>*/ +/*<#*/ +import { PrincipleFunction } from '../principle'; +import { createDummyKeyedSelectors, createDummySelectors } from '../selector/selectorAdvanced'; +import { Comparators, createComparator } from '../interface'; +import { Qualities, Quality } from '../quality'; +import { Actions } from '../action/action.type'; +import { AnyConcept, Mode } from './concept.type'; + +export function createConcept, Q = void>( + name: string, + state: S, + _qualities?: Record, + principles?: PrincipleFunction[], + mode?: Mode[], + meta?: Record, +// eslint-disable-next-line @typescript-eslint/no-explicit-any +): AnyConcept { + if (mode) { + mode.forEach((m, i) => { + m.toString = () => `MODE: ${name} ${i}`; + }); + } + if (principles) { + principles.forEach((p, i) => { + p.toString = () => `PRINCIPLE: ${name} ${i}`; + }); + } + const actions: Record = {}; + const comparators: Comparators = {}; + const qualities: Quality>[] = []; + if (_qualities) { + Object.keys(_qualities).forEach(q => { + try { + actions[q] = (_qualities[q] as Quality).actionCreator; + comparators[q] = createComparator((_qualities[q] as Quality).actionSemaphoreBucket); + qualities.push(_qualities[q] as Quality>); + } catch (error) { + console.error('ERROR @: ', q, _qualities[q]); + // console.warn('Check: ', _qualities); + } + }); + } + return { + name, + muxifiedRecord: {}, + state, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + actions: actions as Actions, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + comparators: comparators as Comparators, + keyedSelectors: createDummyKeyedSelectors(state), + selectors: createDummySelectors(), + qualities: qualities ? qualities : [], + q: (_qualities ? _qualities : {}) as Q extends Qualities ? Q : Qualities, + semaphore: -1, + principles, + mode, + meta + }; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/concept/concept.type.ts b/src/model/concept/concept.type.ts new file mode 100644 index 00000000..61f243a1 --- /dev/null +++ b/src/model/concept/concept.type.ts @@ -0,0 +1,93 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Concept Type model file. +This file defines the type definitions associated to a Stratimux Concept and their utilization within the Muxification Paradigm. +$>*/ +/*<#*/ +import { Observable, Observer, Subject, Subscription } from 'rxjs'; +import { PrincipleFunction } from '../principle'; +import { KeyedSelectors, Selectors } from '../selector/selector.type'; +import { MuxifiedSubject } from '../stagePlanner/stagePlanner'; +import { Comparators } from '../interface'; +import { Qualities, Quality } from '../quality'; +import { Deck } from '../deck'; +import { Action, ActionCreator, ActionCreatorWithPayload, Actions } from '../action/action.type'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export type Reducer< + S extends Record, + T = void +> = (state: S, action: Action) => S | null; + +export type SpecificReducer, T = void, C = void> = + (state: S, action: Action, deck: Deck) => Partial | null; + +export type Method = Observable<[Action, boolean]>; +export type Principle = Observable; +export type Self = T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +export type ActionDeck = {action: Action, deck: Deck, self: Self}; + +export type Mode = ([action, concept, action$, concepts$]: [ + Action, + Concepts, + Subject, + MuxifiedSubject, +]) => void; + +export type MethodCreatorStep, T = void, C = void> = () => MethodCreator; + +export type MethodCreator, T = void, C = void> = + (concept$: Subject, semaphore: number) => [Method, Subject>]; +// export type MethodCreator = (concept$?: MuxifiedSubject, semaphore?: number) => [Method, Subject]; + +export type Muxified = { + stateMap: string[]; + actionMap: string[]; +}; + +export type Concept, Q = void> = { + name: string; + muxifiedRecord: Record; + state: S; + actions: Actions; + comparators: Comparators; + keyedSelectors: KeyedSelectors; + selectors: Selectors; + qualities: Quality>[]; + q: Q extends Qualities ? + Q + : + Qualities; + semaphore: number; + principles?: PrincipleFunction[]; + mode?: Mode[]; + meta?: Record; +}; + +// export type AnyConcept = Concept, any> | Concept, void>; +export type AnyConcept = + Concept, Qualities> + | + // Concept, void> + // | +// eslint-disable-next-line @typescript-eslint/no-explicit-any + Concept; + +export type Concepts = Record; +export type LoadConcepts = Record; + +export type ConceptDeck = { + [K in keyof T]: + T[K] extends Concept, void> ? + Concept, void> + : + T[K] extends Concept, Qualities> ? + Concept, T[K]['q']> + : + Concept, any> +}; + +export type ConceptsSubscriber = (observerOrNext?: Partial> | ((value: Concepts) => void) | undefined) => Subscription; +/*#>*/ \ No newline at end of file diff --git a/src/model/concept/conceptAdvanced.ts b/src/model/concept/conceptAdvanced.ts new file mode 100644 index 00000000..8e324fc1 --- /dev/null +++ b/src/model/concept/conceptAdvanced.ts @@ -0,0 +1,196 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Concept Advanced model file. +This file defines the advanced utilization of concepts via the ability to muxify concepts into new emergent concepts. +Specifically what is defined here is a general utilization that uses ordering of concepts when attempting to muxify such into a new concept. +Users may also define their own process of muxifying concepts in order to handle specific creation of new concepts. +$>*/ +/*<#*/ +import { PrincipleFunction } from '../principle'; +import { Qualities, Quality } from '../quality'; +import { createConcept } from './concept'; +import { AnyConcept, Concept, Mode, Muxified } from './concept.type'; +import { forEachConcept } from './conceptHelpers'; + +/** + * This will remove any duplicate qualities, principles, and modes. + * Note that for now the check for mode and principle are based on concept name and loaded index; + */ +function filterSimilarQualities(concept: AnyConcept) { + const newQualities: Quality>[] = []; + const newMuxified: Record = {}; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const newPrinciples: PrincipleFunction>[] = []; + const newMode: Mode[] = []; + for (let i = 0; i < concept.qualities.length; i++) { + let found = false; + for (let j = i + 1; j < concept.qualities.length; j++) { + if (concept.qualities[i].actionType === concept.qualities[j].actionType) { + found = true; + break; + } + } + if (!found) { + newQualities.push(concept.qualities[i]); + } + } + concept.qualities = newQualities; + const muxifiedKeys = Object.keys(concept.muxifiedRecord); + for (let i = 0; i < muxifiedKeys.length; i++) { + let found = false; + for (let j = i + 1; j < muxifiedKeys.length; j++) { + if (muxifiedKeys[i] === muxifiedKeys[j]) { + found = true; + break; + } + } + if (!found) { + newMuxified[muxifiedKeys[i]] = concept.muxifiedRecord[muxifiedKeys[i]]; + } + } + concept.muxifiedRecord = newMuxified; + if (concept.principles) { + for (let i = 0; i < concept.principles.length; i++) { + let found = false; + for (let j = i + 1; j < concept.principles.length; j++) { + if (concept.principles[i].toString() === concept.principles[j].toString()) { + found = true; + break; + } + } + if (!found) { + newPrinciples.push(concept.principles[i]); + } + } + concept.principles = newPrinciples; + } + if (concept.mode) { + for (let i = 0; i < concept.mode.length; i++) { + let found = false; + for (let j = i + 1; j < concept.mode.length; j++) { + if (concept.mode[i].toString() === concept.mode[j].toString()) { + found = true; + break; + } + } + if (!found) { + newMode.push(concept.mode[i]); + } + } + concept.mode = newMode; + } + return concept; +} + +function muxify( + base: Concept, T>, + target: Concept, K> | AnyConcept +): Concept, T & K> { + if (target.name !== '') { + base.muxifiedRecord[target.name] = { + actionMap: Object.keys(target.actions), + stateMap: Object.keys(target.state) + }; + } + base.muxifiedRecord = { + ...base.muxifiedRecord, + ...target.muxifiedRecord + }; + base.state = { + ...base.state, + ...target.state, + }; + base.qualities = [ + ...base.qualities, + ...target.qualities, + ]; + base.actions = { + ...base.actions, + ...target.actions + }; + base.comparators = { + ...base.comparators, + ...target.comparators + }; + base.keyedSelectors = { + ...base.keyedSelectors, + ...target.keyedSelectors + }; + if (target.principles) { + if (base.principles) { + const principles = [ + ...base.principles, + ...target.principles + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ] as any; + base.principles = principles; + } else { + const principles = [ + ...target.principles + // eslint-disable-next-line @typescript-eslint/no-explicit-any + ] as any; + base.principles = principles; + } + } + if (target.mode) { + if (base.mode) { + base.mode = [ + ...base.mode, + ...target.mode + ]; + } else { + base.mode = [ + ...target.mode + ]; + } + } + if (target.meta) { + if (base.meta) { + base.meta = { + ...base.meta, + ...target.meta + }; + } else { + base.meta = { + ...target.mode + }; + } + } + return base as Concept, T & K>; +} +/** + * This will muxify concepts while prioritizing qualities later in the provided concepts list via recomposition. + * Then finally muxify the emergent concept with final priority. + */ +export function muxifyConcepts, T extends Qualities>( + concepts: AnyConcept[], + emergentConcept: AnyConcept +): AnyConcept { + const dummy: Record = {}; + let newConcept = createConcept('', dummy); + forEachConcept(concepts, (concept => { + newConcept = muxify(newConcept, concept); + })); + newConcept = muxify(newConcept, emergentConcept); + const newMuxifiedRecord: Record = {}; + Object.keys(newConcept.muxifiedRecord).forEach(name => { + if (name !== emergentConcept.name) { + newMuxifiedRecord[name] = newConcept.muxifiedRecord[name]; + } + }); + newConcept.muxifiedRecord = newMuxifiedRecord; + newConcept.name = emergentConcept.name; + if (newConcept.mode) { + newConcept.mode.forEach((m, i) => { + m.toString = () => `MODE: ${newConcept.name} ${i}`; + }); + } + if (newConcept.principles) { + newConcept.principles.forEach((p, i) => { + p.toString = () => `PRINCIPLE: ${newConcept.name} ${i}`; + }); + } + return filterSimilarQualities(newConcept as AnyConcept) as Concept; +} + + +/*#>*/ \ No newline at end of file diff --git a/src/model/concept/conceptHelpers.ts b/src/model/concept/conceptHelpers.ts new file mode 100644 index 00000000..df33bc57 --- /dev/null +++ b/src/model/concept/conceptHelpers.ts @@ -0,0 +1,116 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Concept Helpers model file. +This file defines a series of helper functions that handle the utilization of concepts. +$>*/ +/*<#*/ +import { Quality } from '../quality'; +import { AnyConcept, Concepts } from './concept.type'; + +export const getMuxifiedName = (concepts: Concepts, semaphore: number): string | undefined => (concepts[semaphore]?.name); + +// Will return -1 if not found +export const getConceptSemaphore = (concepts: Concepts, conceptName: string): number => { + // eslint-disable-next-line consistent-return + forEachConcept(concepts, (concept, semaphore) => { + if (concept.name === conceptName) { + return semaphore; + } + }); + return -1; +}; + +export const isConceptLoaded = (concepts: Concepts, conceptName: string): boolean => { + const conceptKeys = Object.keys(concepts); + for (const i of conceptKeys) { + const index = Number(i); + if (concepts[index].name === conceptName) { + return true; + } + } + return false; +}; + +export const areConceptsLoaded = (concepts: Concepts, conceptNames: string[]): boolean => { + let allExists = true; + const conceptKeys = Object.keys(concepts); + for (const name of conceptNames) { + let found = false; + for (const i of conceptKeys) { + const index = Number(i); + if (name === concepts[index].name) { + found = true; + break; + } + } + if (!found) { + allExists = false; + break; + } + } + return allExists; +}; + +export const forEachConcept = (concepts: Concepts, each: (concept: AnyConcept, semaphore: number) => void) => { + const conceptKeys = Object.keys(concepts); + for (const i of conceptKeys) { + const index = Number(i); + each(concepts[index], index); + } +}; + +const stateToString = (state: Record): string => { + let final = '{\n'; + const keys = Object.keys(state); + for (const key of keys) { + let input = ''; + try { + input += `${key}: ${JSON.stringify(state[key])},\n`; + } catch (err) { + input = `${key}: [CIRCULAR],\n`; + } + final += input; + } + final += '}'; + return final; +}; + +export const conceptToString = (concept: AnyConcept): string => { + let output = ''; + output += `{\nname: ${concept.name},`; + const muxifiedKeys = Object.keys(concept.muxifiedRecord); + if (muxifiedKeys.length > 0) { + output += `\nmuxified: ${muxifiedKeys},`; + } + output += `\nqualities: [ ${concept.qualities.toString()}\n],`; + output += `\nstate: ${stateToString(concept.state)}, `; + if (concept.principles) { + output += `\nprinciples: [ ${concept.principles.map(p => p.toString()).join(',')} ]`; + } + if (concept.mode) { + output += `\nmode: [ ${concept.mode.map(m => m.toString()).join(',')} ]`; + } + if (concept.meta) { + output += `\nmeta: ${JSON.stringify(concept.meta)}`; + } + output += '\n}'; + return output; +}; + +export const conceptsToString = (concepts: Concepts): string => { + const conceptStringArray: string[] = []; + forEachConcept(concepts, (concept) => { + conceptStringArray.push(conceptToString(concept)); + }); + conceptStringArray.push(']'); + return '[\n' + conceptStringArray.join(',\n'); +}; + +export const qualityToString = (quality: Quality>) => () => { + const actionType = quality.actionType; + const r = quality.reducer.toString(); + const reducer = r === 'Default Reducer' ? r : 'Reducer'; + const method = quality.method?.toString(); + return (`\n{\nactionType: ${actionType},\nreducer: ${reducer},\nmethod: ${method}\n}`); +}; + +/*#>*/ \ No newline at end of file diff --git a/src/model/concept/index.ts b/src/model/concept/index.ts new file mode 100644 index 00000000..48d3f915 --- /dev/null +++ b/src/model/concept/index.ts @@ -0,0 +1,21 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Concept Index model file. +This file defines a bundled concept object, that enables ease of access to the handling of concepts within +a Muxium. +$>*/ +/*<#*/ +import { createConcept } from './concept'; +import { muxifyConcepts } from './conceptAdvanced'; +import { areConceptsLoaded, conceptsToString, conceptToString, forEachConcept, isConceptLoaded, qualityToString } from './conceptHelpers'; + +export const concept = { + create: createConcept, + muxify: muxifyConcepts, + isLoaded: isConceptLoaded, + areLoaded: areConceptsLoaded, + forEach: forEachConcept, + toString: conceptToString, + toStringConcepts: conceptsToString, + toStringQuality: qualityToString, +}; +/*#>*/ \ No newline at end of file diff --git a/src/model/deck.ts b/src/model/deck.ts index f6440c2d..662f0597 100644 --- a/src/model/deck.ts +++ b/src/model/deck.ts @@ -2,12 +2,12 @@ For the asynchronous graph programming framework Stratimux, define the Deck Model File $>*/ /*<#*/ -import { Actions } from './action'; -import { accessMuxium, getMuxiumState } from './muxium'; -import { AnyConcept, Concept, Concepts, conceptsToString } from './concept'; +import { getMuxiumState } from './muxium/muxiumHelpers'; +import { AnyConcept, Concept, Concepts } from './concept/concept.type'; import { Comparators } from './interface'; import { Qualities } from './quality'; -import { BundledSelectors, KeyedSelectors, Selectors } from './selector'; +import { BundledSelectors, KeyedSelectors, Selectors } from './selector/selector.type'; +import { Actions } from './action/action.type'; export type Decks = { d: Deck; @@ -73,4 +73,30 @@ export const accessECK = (concept: AnyConcept) => { }; }; +export const demuxifyDeck = (concept: AnyConcept): {name: string, eck: ECK}[] => { + const final: {name: string, eck: ECK}[] = []; + const keys = Object.keys(concept.muxifiedRecord); + keys.forEach(name => { + const e: Actions = {}; + const c: Comparators = {}; + const k = {...concept.selectors} as BundledSelectors; + concept.muxifiedRecord[name].actionMap.forEach(ky => { + e[ky] = concept.actions[ky]; + c[ky] = concept.comparators[ky]; + }); + concept.muxifiedRecord[name].stateMap.forEach(ky => { + k[ky] = concept.keyedSelectors[ky]; + }); + const eck: ECK = { + e, + c, + k + }; + final.push({ + name, + eck + }); + }); + return final; +}; /*#>*/ \ No newline at end of file diff --git a/src/model/interface.ts b/src/model/interface.ts index ff4bcf1d..e5a7e39c 100644 --- a/src/model/interface.ts +++ b/src/model/interface.ts @@ -2,11 +2,10 @@ For the asynchronous graph programming framework Stratimux, define the Interface model file. $>*/ -import { MuxiumQualities } from '../concepts/muxium/qualities'; -import { Action, Actions } from './action'; -import { AnyConcept, Concept, LoadConcepts } from './concept'; +import { Action, Actions } from './action/action.type'; +import { LoadConcepts } from './concept/concept.type'; import { Deck } from './deck'; -import { BundledSelectors, KeyedSelectors, Selectors } from './selector'; +import { BundledSelectors } from './selector/selector.type'; /*<#*/ /** diff --git a/src/model/method.ts b/src/model/method.ts deleted file mode 100644 index 207c38e7..00000000 --- a/src/model/method.ts +++ /dev/null @@ -1,690 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Method model file. -This file hold a series of helper functions that enable users to quickly create specific provably terminating methods -within their own defined qualities. -$>*/ -/*<#*/ -import { Observable, Subject, map, switchMap, withLatestFrom } from 'rxjs'; -import { ActionDeck, Concepts, MethodCreator } from './concept'; -import { ActionController, createActionController$ } from './actionController'; -import { ActionStrategy } from './actionStrategy'; -import { KeyedSelector, selectMuxifiedState } from './selector'; -import { debounceAction, throttleAction } from './actionOperators'; -import { ActionCreator, ActionCreatorWithPayload, createAction } from './action'; -import { Deck } from './deck'; - -const muxiumConclude = () => { - return createAction('Conclude'); -}; - -// DETERMINED IMPORT OF ACTION FROM action.ts -type ActionType = string; -type Action = { - type: ActionType; - semaphore: [number, number, number, number]; - conceptSemaphore?: number; - payload: T extends Record ? T : undefined; - strategy?: ActionStrategy; - keyedSelectors?: KeyedSelector[]; - agreement?: number; - expiration: number; - priority?: number; - muxium?: string; - origin?: string; -}; -type Method = Observable<[Action, boolean]> & {toString: () => string}; - -type MethodParams = { - action: Action, deck: Deck, self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} - -type MethodCreatorBase = , T = void, C = void>( - method: (params: MethodParams) => Action -) => MethodCreator; - -export const createMethod: MethodCreatorBase = - , T = void, C = void>( - method: (params: MethodParams) => Action - ): MethodCreator => (): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - map(({action, deck, self}) => { - defaultMethod.toString = () => ('Method: ' + action.type); - const methodAction = method({action, deck, self}); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...action, - ...conclude, - }, false]; - }), - ) as Method; - defaultMethod.toString = () => ('Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodWithStateParams, T = void, C = void> = { - action: Action, state: S, deck: Deck, self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} - -type MethodCreatorBaseWithState = , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, -) => MethodCreator; - -export const createMethodWithState: MethodCreatorBaseWithState = - , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, - ): MethodCreator => ( - concepts$: Subject, - semaphore: number - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S]) - ), - map(([act, state] : [ActionDeck, S]) => { - const {action, deck, self} = act; - defaultMethod.toString = () => ('Method with State: ' + action.type); - const methodAction = methodWithState({action, state, deck, self}); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...act, - ...conclude, - }, false]; - }), - ); - defaultMethod.toString = () => ('Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodWithConceptsParams = { - action: Action, - concepts_: Concepts, - semaphore: number, - deck: Deck, self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} - -type MethodCreatorBaseWithConcepts = , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, -) => MethodCreator; - -export const createMethodWithConcepts: MethodCreatorBaseWithConcepts = - , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, - ): MethodCreator => (( - concepts$: Subject, - semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]) => { - const { action, deck, self } = act; - defaultMethod.toString = () => ('Method with Concepts: ' + action.type); const methodAction = methodWithConcepts({action, concepts_: concepts, deck, self, semaphore}); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...act, - ...conclude, - }, false]; - }), - ) as Method; - defaultMethod.toString = () => ('Method with Concepts'); - return [defaultMethod, defaultSubject]; - }); - -type MethodAsyncParams = { - action: Action, controller: ActionController, deck: Deck, self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} -type MethodCreatorAsync = , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void -) => MethodCreator; - -export const createAsyncMethod: MethodCreatorAsync = - , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void - ) : MethodCreator => ( - _concepts$: Subject, - _semaphore: number - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - switchMap((act: ActionDeck) => createActionController$(act, ( - params - ) => { - defaultMethod.toString = () => ('Async Method: ' + act.action.type); - asyncMethod(params); - })), - ); - defaultMethod.toString = () => ('Async Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodAsyncWithStateParams, T = void, C = void> = { - action: Action, - state: S, - deck: Deck, - controller: ActionController, - self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} - -type MethodCreatorAsyncWithState = , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, -) => MethodCreator; - -export const createAsyncMethodWithState: MethodCreatorAsyncWithState = - , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, - ) : MethodCreator => ( - concepts$: Subject, - semaphore: number - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - withLatestFrom(concepts$), - map( - ([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S]) - ), - switchMap( - ([act, state] : [ActionDeck, S]) => { - return createActionController$(act, (params) => { - defaultMethod.toString = () => ('Async Method with State: ' + params.action.type); - asyncMethodWithState({...params, state}); - }); - }), - ) as Method; - defaultMethod.toString = () => ('Async Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseDebounce = , T = void, C = void>( - method: (params: MethodParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodDebounce: MethodCreatorBaseDebounce = - , T = void, C = void>( - method: (params: MethodParams) => Action, - duration: number - ): MethodCreator => ( - _concepts$: Subject, - _semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - debounceAction(duration), - map((act: ActionDeck) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - defaultMethod.toString = () => ('Debounce Method: ' + act.action.type); - const methodAction = method(act); - if (methodAction.strategy) { - return [methodAction, true]; - } - const conclude = muxiumConclude(); - return [{ - ...act.action, - ...conclude, - }, false]; - } else { - return [act.action, true]; - } - }), - ) as Method; - defaultMethod.toString = () => ('Debounce Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseDebounceWithState = , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodDebounceWithState: MethodCreatorBaseDebounceWithState = - , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, - duration: number - ) : MethodCreator => ( - concepts$: Subject, - semaphore: number - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - debounceAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S])), - map(([act, state] : [ActionDeck, S]) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - const methodAction = methodWithState({...act, state}); - if (methodAction.strategy) { - return [methodAction, true]; - } - const conclude = muxiumConclude(); - return [{ - ...act.action, - ...conclude, - }, true]; - } else { - return [act.action, true]; - } - }), - ); - defaultMethod.toString = () => ('Debounce Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncDebounce = , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodDebounce: MethodCreatorAsyncDebounce = - , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void, - duration: number - ): MethodCreator => ( - _concepts$: Subject, - _semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - debounceAction(duration), - switchMap((act) => { - defaultMethod.toString = () => ('Async Debounce Method: ' + act.action.type); - return createActionController$(act, (params) => { - asyncMethod(params); - }); - }), - ); - defaultMethod.toString = () => ('Async Debounce Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncDebounceWithState = , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodDebounceWithState: MethodCreatorAsyncDebounceWithState = - , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - debounceAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S])), - switchMap(([act, state] : [ActionDeck, S]) => { - defaultMethod.toString = () => ('Async Debounce Method with State: ' + act.action.type); - return createActionController$(act, (params) => { - asyncMethodWithState({...params, state}); - }); - }) - ); - defaultMethod.toString = () => ('Async Debounce Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseThrottle = , T = void, C = void>( - method: (params: MethodParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodThrottle: MethodCreatorBaseThrottle = - , T = void, C = void>( - method: (params: MethodParams) => Action, - duration: number - ): MethodCreator => ( - _concepts$: Subject, - _semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - throttleAction(duration), - map((act: ActionDeck) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - defaultMethod.toString = () => ('Throttle Method: ' + act.action.type); - const methodAction = method(act); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...act.action, - ...conclude, - }, false]; - } else { - return [act.action, false]; - } - }), - ); - defaultMethod.toString = () => ('Throttle Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseThrottleWithState = , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodThrottleWithState: MethodCreatorBaseThrottleWithState = - , T = void, C = void>( - methodWithState: (params: MethodWithStateParams) => Action, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - throttleAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S])), - map(([act, state] : [ActionDeck, S]) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - defaultMethod.toString = () => ('Throttle Method with State: ' + act.action.type); - const methodAction = methodWithState({...act, state}); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...act.action, - ...conclude, - }, false]; - } else { - return [act.action, false]; - } - }), - ); - defaultMethod.toString = () => ('Throttle Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncThrottle = , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodThrottle: MethodCreatorAsyncThrottle = - , T = void, C = void>( - asyncMethod: (params: MethodAsyncParams) => void, - duration: number - ): MethodCreator => ( - _concepts$: Subject, - _semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - throttleAction(duration), - switchMap((act) => { - defaultMethod.toString = () => ('Async Throttle Method: ' + act.action.type); - return createActionController$(act, (params) => { - asyncMethod(params); - }); - }), - ); - defaultMethod.toString = () => ('Async Throttle Method'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncThrottleWithState = , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodThrottleWithState: MethodCreatorAsyncThrottleWithState = - , T = void, C = void>( - asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - throttleAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => - ([act, selectMuxifiedState(concepts, semaphore) as S])), - switchMap(([act, state] : [ActionDeck, S]) => { - defaultMethod.toString = () => ('Async Throttle Method with State: ' + act.action.type); - return createActionController$(act, (params) => { - asyncMethodWithState({...params, state}); - }); - }) - ); - defaultMethod.toString = () => ('Async Throttle Method with State'); - return [defaultMethod, defaultSubject]; - }; - -type MethodAsyncWithConceptsParams = { - action: Action, - controller: ActionController, - concepts_: Concepts, - semaphore: number, - deck: Deck, self: T extends void ? - ActionCreator - : - ActionCreatorWithPayload ? T : Record>; -} - -type MethodCreatorAsyncWithConcepts= , T = void, C = void>( - asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodWithConcepts: MethodCreatorAsyncWithConcepts = - , T = void, C = void>( - asyncMethodWithConcepts: ( - params: MethodAsyncWithConceptsParams - ) => void, - ): MethodCreator => ( - concepts$: Subject, - semaphore: number - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - withLatestFrom(concepts$), - switchMap(([act, concepts]: [ActionDeck, Concepts]) => - createActionController$(act, (params) => { - defaultMethod.toString = () => ('Async Method with Concepts: ' + act.action.type); - asyncMethodWithConcepts({...params, concepts_: concepts, semaphore}); - })), - ); - defaultMethod.toString = () => ('Async Method with Concepts'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseDebounceWithConcepts= , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodDebounceWithConcepts: MethodCreatorBaseDebounceWithConcepts = - , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ) : [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - debounceAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - defaultMethod.toString = () => ('Debounce Method with Concepts: ' + act.action.type); - const methodAction = methodWithConcepts({...act, concepts_: concepts, semaphore}); - if (methodAction.strategy) { - return [methodAction, true]; - } - const conclude = muxiumConclude(); - return [{ - ...act, - ...conclude, - }, false]; - } else { - return [act, true]; - } - }), - ) as Method; - defaultMethod.toString = () => ('Debounce Method with Concepts'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncDebounceWithConcepts= , T = void, C = void>( - asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, - duration: number, -) => MethodCreator; - -export const createAsyncMethodDebounceWithConcepts: MethodCreatorAsyncDebounceWithConcepts = - , T = void, C = void>( - asyncMethodWithConcepts: ( - params: MethodAsyncWithConceptsParams - ) => void, - duration: number, - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - debounceAction(duration), - withLatestFrom(concepts$), - switchMap(([act, concepts] : [ActionDeck, Concepts]) => { - defaultMethod.toString = () => ('Async Debounce Method with Concepts: ' + act.action.type); - return createActionController$(act, (params) => { - asyncMethodWithConcepts({...params, concepts_: concepts, semaphore }); - }); - }) - ); - defaultMethod.toString = () => ('Async Debounce Method with Concepts'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorBaseThrottleWithConcepts= , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, - duration: number -) => MethodCreator; - -export const createMethodThrottleWithConcepts: MethodCreatorBaseThrottleWithConcepts = - , T = void, C = void>( - methodWithConcepts: (params: MethodWithConceptsParams) => Action, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod = defaultSubject.pipe( - throttleAction(duration), - withLatestFrom(concepts$), - map(([act, concepts] : [ActionDeck, Concepts]) => { - // Logically Determined muxiumConclude - if (act.action.semaphore[3] !== 3) { - defaultMethod.toString = () => ('Throttle Method with Concepts: ' + act.action.type); - const methodAction = methodWithConcepts({...act, concepts_: concepts, semaphore}); - if (methodAction.strategy) { - return [methodAction, false]; - } - const conclude = muxiumConclude(); - return [{ - ...act, - ...conclude, - }, false]; - } else { - return [act, false]; - } - }), - ) as Method; - defaultMethod.toString = () => ('Throttle Method with Concepts'); - return [defaultMethod, defaultSubject]; - }; - -type MethodCreatorAsyncThrottleWithConcepts= , T = void, C = void>( - asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, - duration: number -) => MethodCreator; - -export const createAsyncMethodThrottleWithConcepts: MethodCreatorAsyncThrottleWithConcepts = - , T = void, C = void>( - asyncMethodWithConcepts: ( - params: MethodAsyncWithConceptsParams - ) => void, - duration: number - ): MethodCreator => ( - concepts$: Subject, - semaphore: number, - ): [Method, Subject>] => { - const defaultSubject = new Subject>(); - const defaultMethod: Method = defaultSubject.pipe( - throttleAction(duration), - withLatestFrom(concepts$), - switchMap(([act, concepts] : [ActionDeck, Concepts]) => { - return createActionController$(act, (params) => { - defaultMethod.toString = () => ('Async Throttle Method with Concepts: ' + act.action.type); - asyncMethodWithConcepts({...params, concepts_: concepts, semaphore}); - }); - }) - ); - defaultMethod.toString = () => ('Async Throttle Method with Concepts'); - return [defaultMethod, defaultSubject]; - }; - -export const method = ({ - create: createMethod, - createWithState: createMethodWithState, - createWithConcepts: createMethodWithConcepts, - createDebounce: createMethodDebounce, - createDebounceWithState: createMethodDebounceWithState, - createDebounceWithConcepts: createMethodDebounceWithConcepts, - createThrottle: createMethodThrottle, - createThrottleWithState: createMethodThrottleWithState, - createThrottleWithConcepts: createMethodThrottleWithConcepts, - createAsync: createAsyncMethod, - createAsyncDebounce: createAsyncMethodDebounce, - createAsyncDebounceWithState: createAsyncMethodDebounceWithState, - createAsyncDebounceWithConcepts: createAsyncMethodDebounceWithConcepts, - createAsyncThrottle: createAsyncMethodThrottle, - createAsyncThrottleWithState: createAsyncMethodThrottleWithState, - createAsyncThrottleWithConcepts: createAsyncMethodThrottleWithConcepts, -}); -/*#>*/ \ No newline at end of file diff --git a/src/model/method/index.ts b/src/model/method/index.ts new file mode 100644 index 00000000..d5d1ee1a --- /dev/null +++ b/src/model/method/index.ts @@ -0,0 +1,54 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method model file. +This file hold a series of helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ +import { createMethod, createMethodWithConcepts, createMethodWithState } from './method'; +import { + createAsyncMethod, + createAsyncMethodWithState, + createAsyncMethodWithConcepts +} from './methodAsync'; +import { + createAsyncMethodDebounce, + createAsyncMethodDebounceWithConcepts, + createAsyncMethodDebounceWithState +} from './methodAsyncDebounce'; +import { + createAsyncMethodThrottle, + createAsyncMethodThrottleWithConcepts, + createAsyncMethodThrottleWithState +} from './methodAsyncThrottle'; +import { + createMethodDebounce, + createMethodDebounceWithState, + createMethodDebounceWithConcepts +} from './methodDebounce'; +import { + createMethodThrottle, + createMethodThrottleWithState, + createMethodThrottleWithConcepts +} from './methodThrottle'; + +export const method = ({ + create: createMethod, + createWithState: createMethodWithState, + createWithConcepts: createMethodWithConcepts, + createDebounce: createMethodDebounce, + createDebounceWithState: createMethodDebounceWithState, + createDebounceWithConcepts: createMethodDebounceWithConcepts, + createThrottle: createMethodThrottle, + createThrottleWithState: createMethodThrottleWithState, + createThrottleWithConcepts: createMethodThrottleWithConcepts, + createAsync: createAsyncMethod, + createAsyncWithState: createAsyncMethodWithState, + createAsyncWithConcepts: createAsyncMethodWithConcepts, + createAsyncDebounce: createAsyncMethodDebounce, + createAsyncDebounceWithState: createAsyncMethodDebounceWithState, + createAsyncDebounceWithConcepts: createAsyncMethodDebounceWithConcepts, + createAsyncThrottle: createAsyncMethodThrottle, + createAsyncThrottleWithState: createAsyncMethodThrottleWithState, + createAsyncThrottleWithConcepts: createAsyncMethodThrottleWithConcepts, +}); +/*#>*/ \ No newline at end of file diff --git a/src/model/method/method.ts b/src/model/method/method.ts new file mode 100644 index 00000000..d3472d9a --- /dev/null +++ b/src/model/method/method.ts @@ -0,0 +1,109 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method model file. +This file hold a series of helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ +import { Subject, map, withLatestFrom } from 'rxjs'; +import { ActionDeck, Concepts, Method, MethodCreator } from '../concept/concept.type'; +import { selectMuxifiedState } from '../selector/selector'; +import { createAction } from '../action/action'; +import { Action } from '../action/action.type'; +import { + MethodCreatorBase, + MethodCreatorBaseWithConcepts, + MethodCreatorBaseWithState, + MethodParams, + MethodWithConceptsParams, + MethodWithStateParams +} from './method.type'; + +const muxiumConclude = () => { + return createAction('Conclude'); +}; + +// DETERMINED IMPORT OF ACTION FROM action.ts + +export const createMethod: MethodCreatorBase = + , T = void, C = void>( + method: (params: MethodParams) => Action + ): MethodCreator => (): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + map(({action, deck, self}) => { + defaultMethod.toString = () => ('Method: ' + action.type); + const methodAction = method({action, deck, self}); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...action, + ...conclude, + }, false]; + }), + ) as Method; + defaultMethod.toString = () => ('Method'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodWithState: MethodCreatorBaseWithState = + , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, + ): MethodCreator => ( + concepts$: Subject, + semaphore: number + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S]) + ), + map(([act, state] : [ActionDeck, S]) => { + const {action, deck, self} = act; + defaultMethod.toString = () => ('Method with State: ' + action.type); + const methodAction = methodWithState({action, state, deck, self}); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...act, + ...conclude, + }, false]; + }), + ); + defaultMethod.toString = () => ('Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodWithConcepts: MethodCreatorBaseWithConcepts = + , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, + ): MethodCreator => (( + concepts$: Subject, + semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]) => { + const { action, deck, self } = act; + defaultMethod.toString = () => ('Method with Concepts: ' + action.type); + const methodAction = methodWithConcepts({action, concepts_: concepts, deck, self, semaphore}); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...act, + ...conclude, + }, false]; + }), + ) as Method; + defaultMethod.toString = () => ('Method with Concepts'); + return [defaultMethod, defaultSubject]; + }); + +/*#>*/ \ No newline at end of file diff --git a/src/model/method/method.type.ts b/src/model/method/method.type.ts new file mode 100644 index 00000000..1a67b40a --- /dev/null +++ b/src/model/method/method.type.ts @@ -0,0 +1,167 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Type model file. +This file holds the type definitions required for the method helper functions. +$>*/ +/*<#*/ +import { Observable } from 'rxjs'; +import { ActionStrategy } from '../action/strategy/actionStrategy.type'; +import { KeyedSelector } from '../selector/selector.type'; +import { Deck } from '../deck'; +import { ActionCreator, ActionCreatorWithPayload } from '../action/action.type'; +import { Concepts, MethodCreator } from '../concept/concept.type'; +import { ActionController } from '../action/actionController'; + +type ActionType = string; +type Action = { + type: ActionType; + semaphore: [number, number, number, number]; + conceptSemaphore?: number; + payload: T extends Record ? T : undefined; + strategy?: ActionStrategy; + keyedSelectors?: KeyedSelector[]; + agreement?: number; + expiration: number; + priority?: number; + muxium?: string; + origin?: string; +}; +export type Method = Observable<[Action, boolean]> & {toString: () => string}; + +export type MethodParams = { + action: Action, deck: Deck, self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} + +export type MethodCreatorBase = , T = void, C = void>( + method: (params: MethodParams) => Action +) => MethodCreator; + +export type MethodWithStateParams, T = void, C = void> = { + action: Action, state: S, deck: Deck, self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} + +export type MethodCreatorBaseWithState = , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, +) => MethodCreator; + +export type MethodWithConceptsParams = { + action: Action, + concepts_: Concepts, + semaphore: number, + deck: Deck, self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} + +export type MethodCreatorBaseWithConcepts = , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, +) => MethodCreator; + +export type MethodAsyncParams = { + action: Action, controller: ActionController, deck: Deck, self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} +export type MethodCreatorAsync = , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void +) => MethodCreator; + +export type MethodAsyncWithStateParams, T = void, C = void> = { + action: Action, + state: S, + deck: Deck, + controller: ActionController, + self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} + +export type MethodCreatorAsyncWithState = , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, +) => MethodCreator; + +export type MethodCreatorAsyncDebounce = , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void, + duration: number +) => MethodCreator; + +export type MethodCreatorAsyncDebounceWithConcepts= , T = void, C = void>( + asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, + duration: number, +) => MethodCreator; + +export type MethodCreatorAsyncDebounceWithState = , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseThrottle = , T = void, C = void>( + method: (params: MethodParams) => Action, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseThrottleWithState = , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, + duration: number +) => MethodCreator; + +export type MethodCreatorAsyncThrottle = , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void, + duration: number +) => MethodCreator; + +export type MethodCreatorAsyncThrottleWithState = , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, + duration: number +) => MethodCreator; + +export type MethodAsyncWithConceptsParams = { + action: Action, + controller: ActionController, + concepts_: Concepts, + semaphore: number, + deck: Deck, self: T extends void ? + ActionCreator + : + ActionCreatorWithPayload ? T : Record>; +} + +export type MethodCreatorAsyncWithConcepts= , T = void, C = void>( + asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseThrottleWithConcepts= , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, + duration: number +) => MethodCreator; + +export type MethodCreatorAsyncThrottleWithConcepts= , T = void, C = void>( + asyncMethodWithConcepts: (params: MethodAsyncWithConceptsParams) => void, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseDebounce = , T = void, C = void>( + method: (params: MethodParams) => Action, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseDebounceWithState = , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, + duration: number +) => MethodCreator; + +export type MethodCreatorBaseDebounceWithConcepts= , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, + duration: number +) => MethodCreator; + +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodAsync.ts b/src/model/method/methodAsync.ts new file mode 100644 index 00000000..5ee84e97 --- /dev/null +++ b/src/model/method/methodAsync.ts @@ -0,0 +1,88 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Async model file. +This file holds the base asynchronous helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ +import { map, Subject, switchMap, withLatestFrom } from 'rxjs'; +import { ActionDeck, Concepts, MethodCreator } from '../concept/concept.type'; +import { + Method, + MethodAsyncParams, + MethodAsyncWithConceptsParams, + MethodAsyncWithStateParams, + MethodCreatorAsync, + MethodCreatorAsyncWithConcepts, + MethodCreatorAsyncWithState +} from './method.type'; +import { createActionController$ } from '../action/actionController'; +import { selectMuxifiedState } from '../selector/selector'; + +export const createAsyncMethod: MethodCreatorAsync = + , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void + ) : MethodCreator => ( + _concepts$: Subject, + _semaphore: number + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + switchMap((act: ActionDeck) => createActionController$(act, ( + params + ) => { + defaultMethod.toString = () => ('Async Method: ' + act.action.type); + asyncMethod(params); + })), + ); + defaultMethod.toString = () => ('Async Method'); + return [defaultMethod, defaultSubject]; + }; + +export const createAsyncMethodWithState: MethodCreatorAsyncWithState = + , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, + ) : MethodCreator => ( + concepts$: Subject, + semaphore: number + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + withLatestFrom(concepts$), + map( + ([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S]) + ), + switchMap( + ([act, state] : [ActionDeck, S]) => { + return createActionController$(act, (params) => { + defaultMethod.toString = () => ('Async Method with State: ' + params.action.type); + asyncMethodWithState({...params, state}); + }); + }), + ) as Method; + defaultMethod.toString = () => ('Async Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createAsyncMethodWithConcepts: MethodCreatorAsyncWithConcepts = + , T = void, C = void>( + asyncMethodWithConcepts: ( + params: MethodAsyncWithConceptsParams + ) => void, + ): MethodCreator => ( + concepts$: Subject, + semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + withLatestFrom(concepts$), + switchMap(([act, concepts]: [ActionDeck, Concepts]) => + createActionController$(act, (params) => { + defaultMethod.toString = () => ('Async Method with Concepts: ' + act.action.type); + asyncMethodWithConcepts({...params, concepts_: concepts, semaphore}); + })), + ); + defaultMethod.toString = () => ('Async Method with Concepts'); + return [defaultMethod, defaultSubject]; + }; +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodAsyncDebounce.ts b/src/model/method/methodAsyncDebounce.ts new file mode 100644 index 00000000..20011768 --- /dev/null +++ b/src/model/method/methodAsyncDebounce.ts @@ -0,0 +1,95 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Async Debounce model file. +This file holds the asynchronous debounce variant helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ + +import { map, Subject, switchMap, withLatestFrom } from 'rxjs'; +import { ActionDeck, Concepts, MethodCreator } from '../concept/concept.type'; +import { + Method, + MethodAsyncParams, + MethodAsyncWithConceptsParams, + MethodAsyncWithStateParams, + MethodCreatorAsyncDebounce, + MethodCreatorAsyncDebounceWithConcepts, + MethodCreatorAsyncDebounceWithState +} from './method.type'; +import { debounceAction } from '../action/actionOperators'; +import { createActionController$ } from '../action/actionController'; +import { selectMuxifiedState } from '../selector/selector'; + +export const createAsyncMethodDebounce: MethodCreatorAsyncDebounce = + , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void, + duration: number + ): MethodCreator => ( + _concepts$: Subject, + _semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + debounceAction(duration), + switchMap((act) => { + defaultMethod.toString = () => ('Async Debounce Method: ' + act.action.type); + return createActionController$(act, (params) => { + asyncMethod(params); + }); + }), + ); + defaultMethod.toString = () => ('Async Debounce Method'); + return [defaultMethod, defaultSubject]; + }; + +export const createAsyncMethodDebounceWithState: MethodCreatorAsyncDebounceWithState = + , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + debounceAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S])), + switchMap(([act, state] : [ActionDeck, S]) => { + defaultMethod.toString = () => ('Async Debounce Method with State: ' + act.action.type); + return createActionController$(act, (params) => { + asyncMethodWithState({...params, state}); + }); + }) + ); + defaultMethod.toString = () => ('Async Debounce Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createAsyncMethodDebounceWithConcepts: MethodCreatorAsyncDebounceWithConcepts = + , T = void, C = void>( + asyncMethodWithConcepts: ( + params: MethodAsyncWithConceptsParams + ) => void, + duration: number, + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + debounceAction(duration), + withLatestFrom(concepts$), + switchMap(([act, concepts] : [ActionDeck, Concepts]) => { + defaultMethod.toString = () => ('Async Debounce Method with Concepts: ' + act.action.type); + return createActionController$(act, (params) => { + asyncMethodWithConcepts({...params, concepts_: concepts, semaphore }); + }); + }) + ); + defaultMethod.toString = () => ('Async Debounce Method with Concepts'); + return [defaultMethod, defaultSubject]; + }; + +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodAsyncThrottle.ts b/src/model/method/methodAsyncThrottle.ts new file mode 100644 index 00000000..dc2f85bf --- /dev/null +++ b/src/model/method/methodAsyncThrottle.ts @@ -0,0 +1,96 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Async Throttle model file. +This file holds the asynchronous throttle variant helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ + +import { map, Subject, switchMap, withLatestFrom } from 'rxjs'; +import { ActionDeck, Concepts, MethodCreator } from '../concept/concept.type'; +import { + Method, + MethodAsyncParams, + MethodAsyncWithConceptsParams, + MethodAsyncWithStateParams, + MethodCreatorAsyncThrottle, + MethodCreatorAsyncThrottleWithConcepts, + MethodCreatorAsyncThrottleWithState +} from './method.type'; +import { throttleAction } from '../action/actionOperators'; +import { createActionController$ } from '../action/actionController'; +import { selectMuxifiedState } from '../selector/selector'; + +/*<#*/ +export const createAsyncMethodThrottle: MethodCreatorAsyncThrottle = + , T = void, C = void>( + asyncMethod: (params: MethodAsyncParams) => void, + duration: number + ): MethodCreator => ( + _concepts$: Subject, + _semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + throttleAction(duration), + switchMap((act) => { + defaultMethod.toString = () => ('Async Throttle Method: ' + act.action.type); + return createActionController$(act, (params) => { + asyncMethod(params); + }); + }), + ); + defaultMethod.toString = () => ('Async Throttle Method'); + return [defaultMethod, defaultSubject]; + }; + + + +export const createAsyncMethodThrottleWithState: MethodCreatorAsyncThrottleWithState = + , T = void, C = void>( + asyncMethodWithState: (params: MethodAsyncWithStateParams) => void, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + throttleAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S])), + switchMap(([act, state] : [ActionDeck, S]) => { + defaultMethod.toString = () => ('Async Throttle Method with State: ' + act.action.type); + return createActionController$(act, (params) => { + asyncMethodWithState({...params, state}); + }); + }) + ); + defaultMethod.toString = () => ('Async Throttle Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createAsyncMethodThrottleWithConcepts: MethodCreatorAsyncThrottleWithConcepts = + , T = void, C = void>( + asyncMethodWithConcepts: ( + params: MethodAsyncWithConceptsParams + ) => void, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + throttleAction(duration), + withLatestFrom(concepts$), + switchMap(([act, concepts] : [ActionDeck, Concepts]) => { + return createActionController$(act, (params) => { + defaultMethod.toString = () => ('Async Throttle Method with Concepts: ' + act.action.type); + asyncMethodWithConcepts({...params, concepts_: concepts, semaphore}); + }); + }) + ); + defaultMethod.toString = () => ('Async Throttle Method with Concepts'); + return [defaultMethod, defaultSubject]; + }; +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodDebounce.ts b/src/model/method/methodDebounce.ts new file mode 100644 index 00000000..84450640 --- /dev/null +++ b/src/model/method/methodDebounce.ts @@ -0,0 +1,128 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Debounce model file. +This file holds the debounce variant helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ +import { map, Subject, withLatestFrom } from 'rxjs'; +import { Action } from '../action/action.type'; +import { ActionDeck, Concepts, MethodCreator } from '../concept/concept.type'; +import { debounceAction } from '../action/actionOperators'; +import { createAction } from '../action/action'; +import { + Method, + MethodCreatorBaseDebounce, + MethodCreatorBaseDebounceWithConcepts, + MethodCreatorBaseDebounceWithState, + MethodParams, + MethodWithConceptsParams, + MethodWithStateParams +} from './method.type'; +import { selectMuxifiedState } from '../selector/selector'; + +const muxiumConclude = () => { + return createAction('Conclude'); +}; + +export const createMethodDebounce: MethodCreatorBaseDebounce = + , T = void, C = void>( + method: (params: MethodParams) => Action, + duration: number + ): MethodCreator => ( + _concepts$: Subject, + _semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + debounceAction(duration), + map((act: ActionDeck) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + defaultMethod.toString = () => ('Debounce Method: ' + act.action.type); + const methodAction = method(act); + if (methodAction.strategy) { + return [methodAction, true]; + } + const conclude = muxiumConclude(); + return [{ + ...act.action, + ...conclude, + }, false]; + } else { + return [act.action, true]; + } + }), + ) as Method; + defaultMethod.toString = () => ('Debounce Method'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodDebounceWithState: MethodCreatorBaseDebounceWithState = + , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, + duration: number + ) : MethodCreator => ( + concepts$: Subject, + semaphore: number + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + debounceAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S])), + map(([act, state] : [ActionDeck, S]) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + const methodAction = methodWithState({...act, state}); + if (methodAction.strategy) { + return [methodAction, true]; + } + const conclude = muxiumConclude(); + return [{ + ...act.action, + ...conclude, + }, true]; + } else { + return [act.action, true]; + } + }), + ); + defaultMethod.toString = () => ('Debounce Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodDebounceWithConcepts: MethodCreatorBaseDebounceWithConcepts = + , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + debounceAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + defaultMethod.toString = () => ('Debounce Method with Concepts: ' + act.action.type); + const methodAction = methodWithConcepts({...act, concepts_: concepts, semaphore}); + if (methodAction.strategy) { + return [methodAction, true]; + } + const conclude = muxiumConclude(); + return [{ + ...act, + ...conclude, + }, false]; + } else { + return [act, true]; + } + }), + ) as Method; + defaultMethod.toString = () => ('Debounce Method with Concepts'); + return [defaultMethod, defaultSubject]; + }; +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodSubscription.ts b/src/model/method/methodSubscription.ts new file mode 100644 index 00000000..d2528bc1 --- /dev/null +++ b/src/model/method/methodSubscription.ts @@ -0,0 +1,108 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Subscription model file. +This file defines the method subscriptions used for both the default and blocking modes of the muxium. +$>*/ +/*<#*/ +import { + Subject, +} from 'rxjs'; +import { + Concepts, +} from '../concept/concept.type'; +import { muxiumTimeOut } from '../time'; +import { handlePriority, isPriorityValid } from '../priority'; +import { Action } from '../action/action.type'; +import { accessMuxium, getMuxiumState } from '../muxium/muxiumHelpers'; +import { MuxiumOrigins } from '../muxium/muxium.type'; + +export const blockingMethodSubscription = ( + concepts: Concepts, + tail: Action[], + action: Action +) => { + if ( + action.strategy && + // Logical Determination: muxiumConcludeType + action.semaphore[3] === 3 + ) { + // Allows for reducer next in sequence + const appendToDialog = accessMuxium(concepts).e.muxiumAppendActionListToDialog({ + actionList: action.strategy.actionList, + strategyTopic: action.strategy.topic, + strategyData: action.strategy.data, + }); + if (isPriorityValid(action)) { + appendToDialog.priority = action.priority; + const state = getMuxiumState(concepts); + handlePriority(state, action); + handlePriority(state, appendToDialog); + } else { + action.origin = MuxiumOrigins.strategyTail; + tail.push(action); + tail.push(appendToDialog); + } + } else if ( + action.strategy && + // Logical Determination: muxiumBadType + action.semaphore[3] !== 1 + ) { + if (isPriorityValid(action)) { + handlePriority(getMuxiumState(concepts), action); + } else { + tail.push(action); + } + } +}; + +export const defaultMethodSubscription = ( + concepts: Concepts, + tail: Action[], + action$: Subject, + action: Action, + async: boolean +) => { + if ( + action.strategy && + // Logical Determination: muxiumConcludeType + action.semaphore[3] === 3 + ) { + // Allows for reducer next in sequence + const appendToDialog = accessMuxium(concepts).e.muxiumAppendActionListToDialog({ + actionList: action.strategy.actionList, + strategyTopic: action.strategy.topic, + strategyData: action.strategy.data + }); + // setTimeout(() => { + if (isPriorityValid(action)) { + const state = getMuxiumState(concepts); + handlePriority(state, action); + appendToDialog.priority = action.priority; + handlePriority(state, appendToDialog); + } else { + tail.push(action); + tail.push(appendToDialog); + } + if (async) { + muxiumTimeOut(concepts, () => { + return accessMuxium(concepts).e.muxiumKick(); + }, 0); + } + // }, 0); + } else if ( + action.strategy && + // Logical Determination: muxiumBadType + action.semaphore[3] !== 1 + ) { + if (isPriorityValid(action)) { + handlePriority(getMuxiumState(concepts), action); + } else { + tail.push(action); + } + if (async) { + muxiumTimeOut(concepts, () => { + return accessMuxium(concepts).e.muxiumKick(); + }, 0); + } + } +}; +/*#>*/ \ No newline at end of file diff --git a/src/model/method/methodThrottle.ts b/src/model/method/methodThrottle.ts new file mode 100644 index 00000000..ec14c034 --- /dev/null +++ b/src/model/method/methodThrottle.ts @@ -0,0 +1,130 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Method Throttle model file. +This file holds the throttle variant helper functions that enable users to quickly create specific provably terminating methods +within their own defined qualities. +$>*/ +/*<#*/ +import { map, Subject, withLatestFrom } from 'rxjs'; +import { Action } from '../action/action.type'; +import { ActionDeck, Concepts, MethodCreator } from '../concept/concept.type'; +import { + Method, + MethodCreatorBaseThrottle, + MethodCreatorBaseThrottleWithConcepts, + MethodCreatorBaseThrottleWithState, + MethodParams, + MethodWithConceptsParams, + MethodWithStateParams +} from './method.type'; +import { throttleAction } from '../action/actionOperators'; +import { createAction } from '../action/action'; +import { selectMuxifiedState } from '../selector/selector'; + +const muxiumConclude = () => { + return createAction('Conclude'); +}; + +export const createMethodThrottle: MethodCreatorBaseThrottle = + , T = void, C = void>( + method: (params: MethodParams) => Action, + duration: number + ): MethodCreator => ( + _concepts$: Subject, + _semaphore: number + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + throttleAction(duration), + map((act: ActionDeck) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + defaultMethod.toString = () => ('Throttle Method: ' + act.action.type); + const methodAction = method(act); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...act.action, + ...conclude, + }, false]; + } else { + return [act.action, false]; + } + }), + ); + defaultMethod.toString = () => ('Throttle Method'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodThrottleWithState: MethodCreatorBaseThrottleWithState = + , T = void, C = void>( + methodWithState: (params: MethodWithStateParams) => Action, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ) : [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod: Method = defaultSubject.pipe( + throttleAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]): [ActionDeck, S] => + ([act, selectMuxifiedState(concepts, semaphore) as S])), + map(([act, state] : [ActionDeck, S]) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + defaultMethod.toString = () => ('Throttle Method with State: ' + act.action.type); + const methodAction = methodWithState({...act, state}); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...act.action, + ...conclude, + }, false]; + } else { + return [act.action, false]; + } + }), + ); + defaultMethod.toString = () => ('Throttle Method with State'); + return [defaultMethod, defaultSubject]; + }; + +export const createMethodThrottleWithConcepts: MethodCreatorBaseThrottleWithConcepts = + , T = void, C = void>( + methodWithConcepts: (params: MethodWithConceptsParams) => Action, + duration: number + ): MethodCreator => ( + concepts$: Subject, + semaphore: number, + ): [Method, Subject>] => { + const defaultSubject = new Subject>(); + const defaultMethod = defaultSubject.pipe( + throttleAction(duration), + withLatestFrom(concepts$), + map(([act, concepts] : [ActionDeck, Concepts]) => { + // Logically Determined muxiumConclude + if (act.action.semaphore[3] !== 3) { + defaultMethod.toString = () => ('Throttle Method with Concepts: ' + act.action.type); + const methodAction = methodWithConcepts({...act, concepts_: concepts, semaphore}); + if (methodAction.strategy) { + return [methodAction, false]; + } + const conclude = muxiumConclude(); + return [{ + ...act, + ...conclude, + }, false]; + } else { + return [act, false]; + } + }), + ) as Method; + defaultMethod.toString = () => ('Throttle Method with Concepts'); + return [defaultMethod, defaultSubject]; + }; + +/*#>*/ \ No newline at end of file diff --git a/src/model/muxium.ts b/src/model/muxium.ts deleted file mode 100644 index a5261bf6..00000000 --- a/src/model/muxium.ts +++ /dev/null @@ -1,451 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Muxium model file. -This file dictates the creation of the Muxium itself and engages all necessary parts to ensure its functionality -as a provably recursive terminating function. -$>*/ -/*<#*/ -import { - Observable, - Subject, - withLatestFrom, - Subscriber, - catchError, - Subscription, - Observer, -} from 'rxjs'; -import { Action, Actions, createAction, createCachedSemaphores } from './action'; -import { strategyBegin } from './actionStrategy'; -import { AnyConcept, Concept, ConceptDeck, Concepts, LoadConcepts, Mode, forEachConcept, qualityToString } from './concept'; -import { - muxificationConcept, - MuxiumState, - initializationStrategy, - MuxiumDeck, -} from '../concepts/muxium/muxium.concept'; -import { Planner, Planning, StagePlanner } from './stagePlanner'; -import { muxiumTimeOut } from './time'; -import { handlePriority, isPriorityValid } from './priority'; -import { MuxiumQualities } from '../concepts/muxium/qualities'; -import { Deck, Decks, ECK } from './deck'; -import { BundledSelectors, createSelectors, updateKeyedSelectors } from './selector'; -import { Comparators } from './interface'; - -// eslint-disable-next-line no-shadow -export enum MuxiumOrigins { - strategyTail = 'strategyTail', - muxiumHead = 'muxiumHead' -} - -export const tailWhip = (muxiumState: MuxiumState) => { - if (muxiumState.tailTimer.length === 0) { - muxiumState.tailTimer.push(setTimeout(() => { - muxiumState.action$.next(createAction('Kick Muxium')); - }, 3)); - } -}; - -export const createOrigin = (location: unknown[]): string => { - let origin = ''; - let addSign = false; - location.forEach(l => { - if (addSign) { - origin += '+' + l; - } else { - origin += l; - addSign = true; - } - }); - return origin; -}; - -export const HandleOrigin = (state: MuxiumState, action: Action) => { - const { - body, - tail - } = state; - let found = false; - for (const [i, a] of body.entries()) { - if (a.origin && a.origin === action.origin) { - body[i] = action; - found = true; - break; - } - } - if (!found) { - for (const [i, a] of tail.entries()) { - if (a.origin && a.origin === action.origin) { - body[i] = action; - found = true; - break; - } - } - } - - if (!found) { - body.push(action); - } - tailWhip(state); -}; - -export const HandleHardOrigin = (state: MuxiumState, action: Action) => { - // Fill Bucket - // Empty Bucket - // Issue is I need to remove all origins and replace with hard overriding action at the earliest slot - const { - body, - tail - } = state; - let found = false; - const origin = action.origin?.split('+')[0]; - for (const [i, a] of body.entries()) { - const aOrigin = a.origin?.split('+')[0]; - if (aOrigin !== undefined && aOrigin === origin) { - body[i] = action; - found = true; - break; - } - } - if (!found) { - for (const [i, a] of tail.entries()) { - const aOrigin = a.origin?.split('+')[0]; - if (aOrigin !== undefined && aOrigin === action.origin) { - body[i] = action; - found = true; - break; - } - } - } - - if (!found) { - body.push(action); - } - tailWhip(state); -}; - -export const blockingMethodSubscription = ( - concepts: Concepts, - tail: Action[], - action: Action -) => { - if ( - action.strategy && - // Logical Determination: muxiumConcludeType - action.semaphore[3] === 3 - ) { - // Allows for reducer next in sequence - const appendToDialog = accessMuxium(concepts).e.muxiumAppendActionListToDialog({ - actionList: action.strategy.actionList, - strategyTopic: action.strategy.topic, - strategyData: action.strategy.data, - }); - if (isPriorityValid(action)) { - appendToDialog.priority = action.priority; - const state = getMuxiumState(concepts); - handlePriority(state, action); - handlePriority(state, appendToDialog); - } else { - action.origin = MuxiumOrigins.strategyTail; - tail.push(action); - tail.push(appendToDialog); - } - } else if ( - action.strategy && - // Logical Determination: muxiumBadType - action.semaphore[3] !== 1 - ) { - if (isPriorityValid(action)) { - handlePriority(getMuxiumState(concepts), action); - } else { - tail.push(action); - } - } -}; - -export const defaultMethodSubscription = ( - concepts: Concepts, - tail: Action[], - action$: Subject, - action: Action, - async: boolean -) => { - if ( - action.strategy && - // Logical Determination: muxiumConcludeType - action.semaphore[3] === 3 - ) { - // Allows for reducer next in sequence - const appendToDialog = accessMuxium(concepts).e.muxiumAppendActionListToDialog({ - actionList: action.strategy.actionList, - strategyTopic: action.strategy.topic, - strategyData: action.strategy.data - }); - // setTimeout(() => { - if (isPriorityValid(action)) { - const state = getMuxiumState(concepts); - handlePriority(state, action); - appendToDialog.priority = action.priority; - handlePriority(state, appendToDialog); - } else { - tail.push(action); - tail.push(appendToDialog); - } - if (async) { - muxiumTimeOut(concepts, () => { - return accessMuxium(concepts).e.muxiumKick(); - }, 0); - } - // }, 0); - } else if ( - action.strategy && - // Logical Determination: muxiumBadType - action.semaphore[3] !== 1 - ) { - if (isPriorityValid(action)) { - handlePriority(getMuxiumState(concepts), action); - } else { - tail.push(action); - } - if (async) { - muxiumTimeOut(concepts, () => { - return accessMuxium(concepts).e.muxiumKick(); - }, 0); - } - } -}; - -// export type MuxiumLoad = { -// muxium: Concept, MuxiumQualities>, -// [key: string] : AnyConcept; -// }; - -export type MuxiumLoad = { - [K in keyof C] : C[K] extends AnyConcept ? C[K] : AnyConcept -}; - -export const demuxifyDeck = (concept: AnyConcept): {name: string, eck: ECK}[] => { - const final: {name: string, eck: ECK}[] = []; - const keys = Object.keys(concept.muxifiedRecord); - keys.forEach(name => { - const e: Actions = {}; - const c: Comparators = {}; - const k = {...concept.selectors} as BundledSelectors; - concept.muxifiedRecord[name].actionMap.forEach(ky => { - e[ky] = concept.actions[ky]; - c[ky] = concept.comparators[ky]; - }); - concept.muxifiedRecord[name].stateMap.forEach(ky => { - k[ky] = concept.keyedSelectors[ky]; - }); - const eck: ECK = { - e, - c, - k - }; - final.push({ - name, - eck - }); - }); - return final; -}; - -export function muxification( - name: string, - // eslint-disable-next-line @typescript-eslint/no-explicit-any - deckLoad: C, - options?: { - logging?: boolean, - storeDialog?: boolean, - logActionStream?: boolean, - dynamic?: boolean, - } -): Muxium> { - const muxiumConcept = muxificationConcept( - name, - options?.storeDialog, - options?.logging, - options?.logActionStream, - options?.dynamic - ) as Concept, MuxiumQualities>; - const concepts: Concepts = { - 0: muxiumConcept - }; - // as Concept, MuxiumQualities>; - updateKeyedSelectors(concepts, muxiumConcept.keyedSelectors, 0); - muxiumConcept.selectors = createSelectors(0); - const bundledSelectors = { - ...muxiumConcept.keyedSelectors, - ...muxiumConcept.selectors - } as BundledSelectors>; - const baseDeck: Decks, MuxiumLoad> = { - d: { muxium: { - e: muxiumConcept.actions, - c: muxiumConcept.comparators, - k: bundledSelectors, - }, - } as Deck>, - e: muxiumConcept.actions, - c: muxiumConcept.comparators, - k: bundledSelectors, - }; - muxiumConcept.semaphore = 0; - Object.keys(deckLoad).forEach((key, i) => { - const semaphore = i + 1; - concepts[semaphore] = deckLoad[key]; - deckLoad[key].semaphore = semaphore; - updateKeyedSelectors(concepts, concepts[semaphore].keyedSelectors, semaphore); - concepts[semaphore].selectors = createSelectors(semaphore); - (baseDeck as any).d[key] = { - e: concepts[semaphore].actions, - c: concepts[semaphore].comparators, - k: {...concepts[semaphore].keyedSelectors, ...concepts[semaphore].selectors}, - }; - demuxifyDeck(concepts[semaphore]).forEach(u => { - (baseDeck as any).d[u.name] = u.eck; - }); - }); - - const deck = baseDeck as Decks, MuxiumLoad>; - baseDeck.d.muxium.c.muxiumAddConceptsFromQue; - let muxiumState = concepts[0].state as MuxiumState; - muxiumState.deck = deck; - muxiumState.cachedSemaphores = createCachedSemaphores(concepts); - forEachConcept(concepts, ((concept, semaphore) => { - muxiumState.conceptCounter += 1; - concept.qualities.forEach(quality => { - if (quality.methodCreator) { - [quality.method, quality.subject] = quality.methodCreator()(muxiumState.concepts$, semaphore); - quality.method.pipe( - catchError((err: unknown, caught: Observable<[Action, boolean]>) => { - if (muxiumState.logging) { - console.error('METHOD ERROR', err); - } - return caught; - })); - quality.toString = qualityToString(quality); - const methodSub = quality.method.subscribe(([action, _]) => { - blockingMethodSubscription(concepts, muxiumState.tail, action); - }) as Subscriber; - muxiumState = concepts[0].state as MuxiumState; - muxiumState.methodSubscribers.push({ - name: concept.name, - subscription: methodSub, - }); - } - }); - if (semaphore !== 0 && concept.mode !== undefined) { - muxiumState = concepts[0].state as MuxiumState; - const names = muxiumState.modeNames; - const modes = concepts[0].mode as Mode[]; - concept.mode.forEach((mode) => { - modes.push(mode); - names.push(concept.name); - }); - } - })); - muxiumState.action$ - .pipe( - withLatestFrom(muxiumState.actionConcepts$), - // This will be where the Ownership Principle will be Loaded - // As Such is a Unique Principle in the Scope of State Management - // This will also allow for Actions to be added to the Stream to Update to most Recent Values - catchError((err: unknown, caught: Observable<[Action, Concepts]>) => { - if (muxiumState.logging) { - console.error('ACTION STREAM ERROR', err); - } - return caught; - }), - ) - .subscribe(([action, _concepts]: [Action, Concepts]) => { - // Would be notifying methods - if (getMuxiumState(_concepts).logActionStream) { - console.log( - 'ACTION STREAM: ', action, - ' topic: ', action.strategy?.topic - ); - } - const _muxiumState = _concepts[0].state as MuxiumState; - if (_muxiumState.head.length === 0) { - action.origin = MuxiumOrigins.muxiumHead; - _muxiumState.head.push(action); - if (_muxiumState.tailTimer.length > 0) { - const timer = _muxiumState.tailTimer.shift(); - if (timer) { - clearTimeout(timer); - } - } - const modeIndex = _muxiumState.modeIndex; - const modes = _concepts[0].mode as Mode[]; - const mode = modes[modeIndex] as Mode; - mode([action, _concepts, _muxiumState.action$, _muxiumState.concepts$]); - _muxiumState.head.shift(); - if (_muxiumState.body.length === 0) { - const nextAction = getMuxiumState(concepts).tail.shift(); - if (nextAction) { - getMuxiumState(concepts).action$.next(nextAction); - } - } else { - const nextAction = getMuxiumState(concepts).body.shift(); - if (nextAction) { - getMuxiumState(concepts).action$.next(nextAction); - } - } - // An action dispatched from a priority stage, with a priority set to 0 - // Will override the need to handle priority - } else if (isPriorityValid(action)) { - handlePriority(_muxiumState, action); - } else { - _muxiumState.body.push(action); - } - }); - - muxiumState = concepts[0].state as MuxiumState; - const action$ = muxiumState.action$; - muxiumState.actionConcepts$.next(concepts); - muxiumState.concepts$.init(concepts); - muxiumState.action$.next( - strategyBegin(initializationStrategy(concepts[0].actions as unknown as Actions, concepts)), - ); - const close = (exit?: boolean) => { - action$.next(baseDeck.d.muxium.e.muxiumPreClose({ - exit: exit ? exit : false - })); - }; - return { - subscribe: muxiumState.concepts$.subscribe.bind(muxiumState.concepts$), - unsubscribe: muxiumState.concepts$.unsubscribe.bind(muxiumState.concepts$), - close: close, - dispatch: (action: Action) => { - action$.next(action); - }, - plan: (title: string, planner: Planner>) => ( - muxiumState.concepts$.outerPlan(title, planner as unknown as Planner)), - deck, - e: deck.d.muxium.e - } as unknown as Muxium>; -} - -// [TODO] - IMPORTANT - Point of providing access to white listed qualities organized by concepts. -export type Muxium, C extends LoadConcepts, S extends Record> = { - subscribe: (observerOrNext?: Partial> | ((value: Concepts) => void) | undefined) => Subscription; - unsubscribe: () => void; - close: (exit?: boolean) => void; - dispatch: (action: Action) => void; - plan: (title: string, planner: Planner>) => StagePlanner; - deck: Decks, MuxiumLoad>, - e: Actions -} - -export const getMuxiumState = (concepts: Concepts) => - (concepts[0].state as MuxiumState); - -export const accessMuxium = (concepts: Concepts) => (getMuxiumState(concepts).deck.d.muxium); - -export const isMuxiumOpen = (concepts: Concepts) => ((concepts[0].state as MuxiumState>).open); - -export const muxium = ({ - create: muxification, - getState: getMuxiumState, - isOpen: isMuxiumOpen -}); -/*#>*/ \ No newline at end of file diff --git a/src/model/muxium/index.ts b/src/model/muxium/index.ts new file mode 100644 index 00000000..46167ce2 --- /dev/null +++ b/src/model/muxium/index.ts @@ -0,0 +1,14 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Muxium Index model file. +This file defines the muxium bundled object that provides access to associated muxium functions. +$>*/ +/*<#*/ +import { muxification } from './muxium'; +import { getMuxiumState, isMuxiumOpen } from './muxiumHelpers'; + +export const muxium = ({ + create: muxification, + getState: getMuxiumState, + isOpen: isMuxiumOpen +}); +/*#>*/ \ No newline at end of file diff --git a/src/model/muxium/muxium.ts b/src/model/muxium/muxium.ts new file mode 100644 index 00000000..0dbde545 --- /dev/null +++ b/src/model/muxium/muxium.ts @@ -0,0 +1,208 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Muxium model file. +This file dictates the creation of a Muxium and engages all necessary parts to ensure its functionality +as a provably recursive terminating function. +$>*/ +/*<#*/ +import { Observable, withLatestFrom, Subscriber, catchError } from 'rxjs'; +import { + Concept, + Concepts, + LoadConcepts, + Mode, +} from '../concept/concept.type'; +import { + forEachConcept, + qualityToString +} from '../concept/conceptHelpers'; +import { muxificationConcept, MuxiumState, initializationStrategy, MuxiumDeck } from '../../concepts/muxium/muxium.concept'; +import { Planner } from '../stagePlanner/stagePlanner.type'; +import { handlePriority, isPriorityValid } from '../priority'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { Deck, Decks, demuxifyDeck } from '../deck'; +import { createSelectors, updateKeyedSelectors } from '../selector/selectorAdvanced'; +import { BundledSelectors } from '../selector/selector.type'; +import { Action, Actions } from '../action/action.type'; +import { createCachedSemaphores } from '../action/actionSemaphore'; +import { strategyBegin } from '../action/strategy/actionStrategyConsumers'; +import { Muxium, MuxiumLoad, MuxiumOrigins } from './muxium.type'; +import { blockingMethodSubscription } from '../method/methodSubscription'; +import { getMuxiumState } from './muxiumHelpers'; + +export function muxification( + name: string, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + deckLoad: C, + options?: { + logging?: boolean, + storeDialog?: boolean, + logActionStream?: boolean, + dynamic?: boolean, + } +): Muxium> { + const muxiumConcept = muxificationConcept( + name, + options?.storeDialog, + options?.logging, + options?.logActionStream, + options?.dynamic + ) as Concept, MuxiumQualities>; + const concepts: Concepts = { + 0: muxiumConcept + }; + // as Concept, MuxiumQualities>; + updateKeyedSelectors(concepts, muxiumConcept.keyedSelectors, 0); + muxiumConcept.selectors = createSelectors(0); + const bundledSelectors = { + ...muxiumConcept.keyedSelectors, + ...muxiumConcept.selectors + } as BundledSelectors>; + const baseDeck: Decks, MuxiumLoad> = { + d: { muxium: { + e: muxiumConcept.actions, + c: muxiumConcept.comparators, + k: bundledSelectors, + }, + } as Deck>, + e: muxiumConcept.actions, + c: muxiumConcept.comparators, + k: bundledSelectors, + }; + muxiumConcept.semaphore = 0; + Object.keys(deckLoad).forEach((key, i) => { + const semaphore = i + 1; + concepts[semaphore] = deckLoad[key]; + deckLoad[key].semaphore = semaphore; + updateKeyedSelectors(concepts, concepts[semaphore].keyedSelectors, semaphore); + concepts[semaphore].selectors = createSelectors(semaphore); + (baseDeck as any).d[key] = { + e: concepts[semaphore].actions, + c: concepts[semaphore].comparators, + k: {...concepts[semaphore].keyedSelectors, ...concepts[semaphore].selectors}, + }; + demuxifyDeck(concepts[semaphore]).forEach(u => { + (baseDeck as any).d[u.name] = u.eck; + }); + }); + + const deck = baseDeck as Decks, MuxiumLoad>; + baseDeck.d.muxium.c.muxiumAddConceptsFromQue; + let muxiumState = concepts[0].state as MuxiumState; + muxiumState.deck = deck; + muxiumState.cachedSemaphores = createCachedSemaphores(concepts); + forEachConcept(concepts, ((concept, semaphore) => { + muxiumState.conceptCounter += 1; + concept.qualities.forEach(quality => { + if (quality.methodCreator) { + [quality.method, quality.subject] = quality.methodCreator()(muxiumState.concepts$, semaphore); + quality.method.pipe( + catchError((err: unknown, caught: Observable<[Action, boolean]>) => { + if (muxiumState.logging) { + console.error('METHOD ERROR', err); + } + return caught; + })); + quality.toString = qualityToString(quality); + const methodSub = quality.method.subscribe(([action, _]) => { + blockingMethodSubscription(concepts, muxiumState.tail, action); + }) as Subscriber; + muxiumState = concepts[0].state as MuxiumState; + muxiumState.methodSubscribers.push({ + name: concept.name, + subscription: methodSub, + }); + } + }); + if (semaphore !== 0 && concept.mode !== undefined) { + muxiumState = concepts[0].state as MuxiumState; + const names = muxiumState.modeNames; + const modes = concepts[0].mode as Mode[]; + concept.mode.forEach((mode) => { + modes.push(mode); + names.push(concept.name); + }); + } + })); + muxiumState.action$ + .pipe( + withLatestFrom(muxiumState.actionConcepts$), + // This will be where the Ownership Principle will be Loaded + // As Such is a Unique Principle in the Scope of State Management + // This will also allow for Actions to be added to the Stream to Update to most Recent Values + catchError((err: unknown, caught: Observable<[Action, Concepts]>) => { + if (muxiumState.logging) { + console.error('ACTION STREAM ERROR', err); + } + return caught; + }), + ) + .subscribe(([action, _concepts]: [Action, Concepts]) => { + // Would be notifying methods + if (getMuxiumState(_concepts).logActionStream) { + console.log( + 'ACTION STREAM: ', action, + ' topic: ', action.strategy?.topic + ); + } + const _muxiumState = _concepts[0].state as MuxiumState; + if (_muxiumState.head.length === 0) { + action.origin = MuxiumOrigins.muxiumHead; + _muxiumState.head.push(action); + if (_muxiumState.tailTimer.length > 0) { + const timer = _muxiumState.tailTimer.shift(); + if (timer) { + clearTimeout(timer); + } + } + const modeIndex = _muxiumState.modeIndex; + const modes = _concepts[0].mode as Mode[]; + const mode = modes[modeIndex] as Mode; + mode([action, _concepts, _muxiumState.action$, _muxiumState.concepts$]); + _muxiumState.head.shift(); + if (_muxiumState.body.length === 0) { + const nextAction = getMuxiumState(concepts).tail.shift(); + if (nextAction) { + getMuxiumState(concepts).action$.next(nextAction); + } + } else { + const nextAction = getMuxiumState(concepts).body.shift(); + if (nextAction) { + getMuxiumState(concepts).action$.next(nextAction); + } + } + // An action dispatched from a priority stage, with a priority set to 0 + // Will override the need to handle priority + } else if (isPriorityValid(action)) { + handlePriority(_muxiumState, action); + } else { + _muxiumState.body.push(action); + } + }); + + muxiumState = concepts[0].state as MuxiumState; + const action$ = muxiumState.action$; + muxiumState.actionConcepts$.next(concepts); + muxiumState.concepts$.init(concepts); + muxiumState.action$.next( + strategyBegin(initializationStrategy(concepts[0].actions as unknown as Actions, concepts)), + ); + const close = (exit?: boolean) => { + action$.next(baseDeck.d.muxium.e.muxiumPreClose({ + exit: exit ? exit : false + })); + }; + return { + subscribe: muxiumState.concepts$.subscribe.bind(muxiumState.concepts$), + unsubscribe: muxiumState.concepts$.unsubscribe.bind(muxiumState.concepts$), + close: close, + dispatch: (action: Action) => { + action$.next(action); + }, + plan: (title: string, planner: Planner>) => ( + muxiumState.concepts$.outerPlan(title, planner as unknown as Planner)), + deck, + e: deck.d.muxium.e + } as unknown as Muxium>; +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/muxium/muxium.type.ts b/src/model/muxium/muxium.type.ts new file mode 100644 index 00000000..a33d4a43 --- /dev/null +++ b/src/model/muxium/muxium.type.ts @@ -0,0 +1,45 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Muxium Type model file. +This file defines all types and enums that are associated to the management of Muxiums. +$>*/ +/*<#*/ +import { + Subscription, + Observer, +} from 'rxjs'; +import { + AnyConcept, + Concepts, + LoadConcepts, +} from '../concept/concept.type'; +import { + MuxiumState, + MuxiumDeck, +} from '../../concepts/muxium/muxium.concept'; +import { Planner, StagePlanner } from '../stagePlanner/stagePlanner.type'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { Decks } from '../deck'; +import { Action, Actions } from '../action/action.type'; + +// eslint-disable-next-line no-shadow +export enum MuxiumOrigins { + strategyTail = 'strategyTail', + muxiumHead = 'muxiumHead' +} + +export type MuxiumLoad = { + [K in keyof C] : C[K] extends AnyConcept ? C[K] : AnyConcept +}; + +// [TODO] - IMPORTANT - Point of providing access to white listed qualities organized by concepts. +export type Muxium, C extends LoadConcepts, S extends Record> = { + subscribe: (observerOrNext?: Partial> | ((value: Concepts) => void) | undefined) => Subscription; + unsubscribe: () => void; + close: (exit?: boolean) => void; + dispatch: (action: Action) => void; + plan: (title: string, planner: Planner>) => StagePlanner; + deck: Decks, MuxiumLoad>, + e: Actions +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/muxium/muxiumHelpers.ts b/src/model/muxium/muxiumHelpers.ts new file mode 100644 index 00000000..b0f48c9f --- /dev/null +++ b/src/model/muxium/muxiumHelpers.ts @@ -0,0 +1,113 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Muxium Helper model file. +This file defines the necessary helper functions to aid in the management of a Muxium. +$>*/ +/*<#*/ +import { + Concepts, + LoadConcepts, +} from '../concept/concept.type'; +import { + MuxiumDeck, + MuxiumState, +} from '../../concepts/muxium/muxium.concept'; +import { createAction } from '../action/action'; +import { Action } from '../action/action.type'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { MuxiumLoad } from './muxium.type'; + +export const tailWhip = (muxiumState: MuxiumState) => { + if (muxiumState.tailTimer.length === 0) { + muxiumState.tailTimer.push(setTimeout(() => { + muxiumState.action$.next(createAction('Kick Muxium')); + }, 3)); + } +}; + +export const createOrigin = (location: unknown[]): string => { + let origin = ''; + let addSign = false; + location.forEach(l => { + if (addSign) { + origin += '+' + l; + } else { + origin += l; + addSign = true; + } + }); + return origin; +}; + +export const HandleOrigin = (state: MuxiumState, action: Action) => { + const { + body, + tail + } = state; + let found = false; + for (const [i, a] of body.entries()) { + if (a.origin && a.origin === action.origin) { + body[i] = action; + found = true; + break; + } + } + if (!found) { + for (const [i, a] of tail.entries()) { + if (a.origin && a.origin === action.origin) { + body[i] = action; + found = true; + break; + } + } + } + + if (!found) { + body.push(action); + } + tailWhip(state); +}; + +export const HandleHardOrigin = (state: MuxiumState, action: Action) => { + // Fill Bucket + // Empty Bucket + // Issue is I need to remove all origins and replace with hard overriding action at the earliest slot + const { + body, + tail + } = state; + let found = false; + const origin = action.origin?.split('+')[0]; + for (const [i, a] of body.entries()) { + const aOrigin = a.origin?.split('+')[0]; + if (aOrigin !== undefined && aOrigin === origin) { + body[i] = action; + found = true; + break; + } + } + if (!found) { + for (const [i, a] of tail.entries()) { + const aOrigin = a.origin?.split('+')[0]; + if (aOrigin !== undefined && aOrigin === action.origin) { + body[i] = action; + found = true; + break; + } + } + } + + if (!found) { + body.push(action); + } + tailWhip(state); +}; + +export const getMuxiumState = (concepts: Concepts) => + (concepts[0].state as MuxiumState); + +export const accessMuxium = (concepts: Concepts) => (getMuxiumState(concepts).deck.d.muxium); + +export const isMuxiumOpen = (concepts: Concepts) => ((concepts[0].state as MuxiumState>).open); + + +/*#>*/ \ No newline at end of file diff --git a/src/model/ownership.ts b/src/model/ownership.ts index 8f31dc2e..48de5bb8 100644 --- a/src/model/ownership.ts +++ b/src/model/ownership.ts @@ -4,14 +4,14 @@ This file will dictate functionality used within the Ownership Concept to engage $>*/ /*<#*/ /* eslint-disable max-depth */ -import { Action, areSemaphoresEqual } from '../model/action'; import { OwnershipState, ownershipName } from '../concepts/ownership/ownership.concept'; -import { Concepts } from './concept'; -import { selectState } from './selector'; -import { ActionNode, ActionStrategy } from './actionStrategy'; -import { MuxiumState } from '../concepts/muxium/muxium.concept'; +import { Concepts } from './concept/concept.type'; +import { selectState } from './selector/selector'; import { randomUUID } from 'crypto'; -import { getMuxiumState } from './muxium'; +import { getMuxiumState } from './muxium/muxiumHelpers'; +import { Action } from './action/action.type'; +import { ActionNode, ActionStrategy } from './action/strategy/actionStrategy.type'; +import { areSemaphoresEqual } from './action/actionSemaphore'; export type OwnershipLedger = Map; diff --git a/src/model/principle.ts b/src/model/principle.ts index 09cf9409..caada97d 100644 --- a/src/model/principle.ts +++ b/src/model/principle.ts @@ -5,15 +5,15 @@ within its recursive run time. $>*/ /*<#*/ import { Observable, Subscriber, Subscription } from 'rxjs'; -import { Concepts, ConceptsSubscriber, LoadConcepts } from './concept'; -import { Action, Actions } from './action'; -import { Planning } from './stagePlanner'; -import { BundledSelectors, KeyedSelectors, Selectors } from './selector'; +import { Concepts, ConceptsSubscriber, LoadConcepts } from './concept/concept.type'; +import { Action, Actions } from './action/action.type'; +import { BundledSelectors, KeyedSelectors, Selectors } from './selector/selector.type'; import { BInterface, Comparators } from './interface'; import { MuxiumQualities } from '../concepts/muxium/qualities'; import { Deck, accessDeck } from './deck'; import { access } from 'fs'; import { Qualities } from './quality'; +import { Planning } from './stagePlanner/stagePlanner.type'; export type PrincipleInterface = { observer: Subscriber, diff --git a/src/model/priority.ts b/src/model/priority.ts index 1ec24555..e589d87a 100644 --- a/src/model/priority.ts +++ b/src/model/priority.ts @@ -4,7 +4,7 @@ This muxified concept further enhances the ability to control the halting nature $>*/ /*<#*/ import { MuxiumState } from '../concepts/muxium/muxium.concept'; -import { Action } from './action'; +import { Action } from './action/action.type'; // Is only called if action has priority const fillBucket = (body: Action[], bucket: Action[], action: Action, _added = false) => { diff --git a/src/model/quality.ts b/src/model/quality.ts index 4a27a367..664a01b2 100644 --- a/src/model/quality.ts +++ b/src/model/quality.ts @@ -2,23 +2,18 @@ For the asynchronous graph programming framework Stratimux, define the Quality model file. This model allows for qualities to be made at a single point of entry, reducing the complexity of defining such. $>*/ - /*<#*/ - import { Subject, map } from 'rxjs'; import { - Action, - ActionCreator, - ActionCreatorType, - ActionCreatorWithPayload, prepareActionCreator, prepareActionWithPayloadCreator -} from './action'; -import { strategySuccess } from './actionStrategy'; -import { ActionDeck, Concepts, Method, MethodCreatorStep, SpecificReducer, createQuality } from './concept'; -import { ActionType } from './action'; -import { KeyedSelector } from './selector'; +} from './action/action'; +import { KeyedSelector } from './selector/selector.type'; import { muxiumConcludeType } from '../concepts/muxium/qualities/conclude.quality'; +import { Action, ActionCreator, ActionCreatorType, ActionCreatorWithPayload, ActionType } from './action/action.type'; +import { strategySuccess } from './action/strategy/actionStrategyConsumers'; +import { ActionDeck, Concepts, MethodCreatorStep, SpecificReducer } from './concept/concept.type'; +import { Method } from './method/method.type'; export type Quality, T = void, C = void> = { actionType: ActionType; @@ -41,6 +36,29 @@ export type Qualities = { // [s: string]: Quality> }; +export function createQuality, T = void, C = void>( + actionType: ActionType, + actionSemaphoreBucket: [number, number, number, number][], + actionCreator: ActionCreatorType, + reducer: SpecificReducer, + methodCreator?: MethodCreatorStep, + // eslint-disable-next-line @typescript-eslint/no-explicit-any + keyedSelectors?: KeyedSelector[], + meta?: Record, + analytics?: Record, +): Quality { + return { + actionType, + actionCreator, + actionSemaphoreBucket, + reducer, + methodCreator, + keyedSelectors, + meta, + analytics + }; +} + export function defaultReducer>(state: S, _: Action): S { return state; } diff --git a/src/model/selector.ts b/src/model/selector.ts deleted file mode 100644 index d6261ee7..00000000 --- a/src/model/selector.ts +++ /dev/null @@ -1,504 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Selector model file. -This file will contain a series of selectors that can be used to engage with different parts of the Muxium Conceptual Set. -$>*/ -/*<#*/ -import { Action } from './action'; -import { AnyConcept, Concept, Concepts } from './concept'; -import { DotPath } from './dotPath'; -import { Qualities } from './quality'; - -/** - * Will have such be a list of state keys separated by spaces until someone yells at me to change this. - */ -export type SelectorFunction = (obj: Record) => T extends void ? unknown : T | undefined; -export type KeyedSelector = { - conceptName: string, - conceptSemaphore: number, - keys: string, - select: () => T, - _selector: SelectorFunction, - setKeys?: (number | string)[] - setSelector?: SelectorFunction -}; -export type KeyedSelectors = { - [K in keyof S]: S[K] extends KeyedSelector ? - KeyedSelector - : - KeyedSelector -}; - - -/** - * Will create a new KeyedSelector based on a concept name comparison during runtime, mainly used for external usage - * @param keys - type string - Format is 'key0.key1.key3' for deep nested key values - * @tutorial *Note* This will only extend 6 levels into a deeply nested record. - * @tutorial **Use createAdvancedKeys** function in place of keys if attempted to scaffold into through arrays - */ -export const createConceptKeyedSelector = - >(conceptName: string, keys: DotPath, setKeys?: (number|string)[]): KeyedSelector => { - const selectorBase = [conceptName, ...keys.split('.')]; - if (setKeys) { - return { - conceptName, - conceptSemaphore: -1, - keys: conceptName + '.' + keys, - select: () => undefined, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - setKeys, - setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) - }; - } - return { - conceptName, - conceptSemaphore: -1, - keys: conceptName + '.' + keys, - select: () => undefined, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - setKeys - }; - }; - -/** - * Will create a new KeyedSelector during runtime, for usage throughout Stratimux - * @param keys - type string - Format is 'key0.key1.key3' for deep nested key values - * Uses type DotPath to enable some DX in the IDE to quickly create the desired string format. - * @tutorial *Note* This will only extend 6 levels into a deeply nested record. - * @tutorial **Use createAdvancedKeys** function in place of keys if attempted to scaffold into through arrays - */ -export const createMuxifiedKeyedSelector = >( - concepts: Concepts, - semaphore: number, - keys: DotPath, - setKeys?: (number | string)[] -): KeyedSelector | undefined => { - const concept = concepts[semaphore]; - try { - if (concept) { - const selectorBase = [concept.name, ...keys.split('.')]; - if (setKeys) { - return { - conceptName: concept.name, - conceptSemaphore: semaphore, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - select: () => undefined, - keys: concept.name + '.' + keys, - setKeys, - setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) - }; - } - return { - conceptName: concept.name, - conceptSemaphore: semaphore, - select: () => undefined, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - keys: concept.name + '.' + keys, - }; - } - } catch (err) { - console.error(err); - console.warn('ERROR AT: ', keys); - } - return undefined; -}; - -export type CreateBufferedMuxifiedKeyedSelector = (semaphore: number) => - MuxifiedKeyedSelector; -export type MuxifiedKeyedSelector = ( - concepts: Concepts, - keys: DotPath ? T : Record>, - setKeys?: (number | string)[] -) => KeyedSelector | undefined; - -export const createBufferedMuxifiedKeyedSelector: CreateBufferedMuxifiedKeyedSelector = - > (semaphore: number) => ( - concepts: Concepts, - keys: DotPath, - setKeys?: (number | string)[] - ): KeyedSelector | undefined => { - const concept = concepts[semaphore]; - try { - if (concept) { - const selectorBase = [concept.name, ...keys.split('.')]; - if (setKeys) { - return { - conceptName: concept.name, - conceptSemaphore: semaphore, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - select: () => undefined, - keys: concept.name + '.' + keys, - setKeys, - setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) - }; - } - return { - conceptName: concept.name, - conceptSemaphore: semaphore, - select: () => undefined, - _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, - keys: concept.name + '.' + keys, - }; - } - } catch (err) { - console.error(err); - console.warn('ERROR AT: ', keys); - } - return undefined; - }; - -export type StateValidator = S extends Record ? S : Record; -export type CreateBufferedStateSelector = (semaphore: number) => - StateSelector; -export type StateSelector = (concepts: Concepts) => StateValidator | undefined; - -export const createBufferedStateSelector: CreateBufferedStateSelector = - (semaphore: number): StateSelector => (concepts: Concepts): - StateValidator | undefined => { - const concept = concepts[semaphore]; - if (concept) { - return concept.state as StateValidator; - } - return undefined; - }; - -export type CreateBufferedConceptSelector = (semaphore: number) => - ConceptSelector; -export type ConceptSelector = (concepts: Concepts) => C | undefined; - -export const createBufferedConceptSelector: CreateBufferedConceptSelector = - (semaphore: number): ConceptSelector => (concepts: Concepts) => { - const concept = concepts[semaphore]; - if (concept) { - return concept as C; - } - return undefined; - }; - - -export type MuxifiedNameSelector = (concepts: Concepts) => string | undefined; -export type CreateBufferedMuxifiedNameSelector = (semaphore: number) => MuxifiedNameSelector; -export const selectMuxifiedName = (concepts: Concepts, semaphore: number): string | undefined => (concepts[semaphore]?.name); -export const createBufferedMuxifiedNameSelector: CreateBufferedMuxifiedNameSelector = (semaphore) => (concepts) => selectMuxifiedName(concepts, semaphore); - -// export type Selectors = { -export type Selectors = { - create: MuxifiedKeyedSelector, - state: StateSelector, - name: MuxifiedNameSelector - // concept: ConceptSelector -} - -export type BundledSelectors = KeyedSelectors & Selectors - -export const createSelectors = ( - semaphore: number -): Selectors => ({ - create: createBufferedMuxifiedKeyedSelector(semaphore), - state: createBufferedStateSelector(semaphore), - name: createBufferedMuxifiedNameSelector(semaphore) - }); - -export const createDummySelectors = ( -): Selectors => { - return { - create: createBufferedMuxifiedKeyedSelector(-1), - // concept: createBufferedConceptSelector(semaphore), - state: createBufferedStateSelector(-1), - name: createBufferedMuxifiedNameSelector(-1) - }; -}; - -export const createDummyKeyedSelectors = ( - state: S -): KeyedSelectors => { - const selectors = {} as KeyedSelectors; - const keys = Object.keys(state as Record); - keys.forEach(key => { - selectors[key] = { - conceptName: '', - conceptSemaphore: -1, - select: () => undefined, - keys: 'dummy.' + key, - _selector: () => undefined - }; - }); - return selectors; -}; - -export const updateKeyedSelectors = ( - concepts: Concepts, - selectors: KeyedSelectors, - semaphore: number -): void => { - const keys = Object.keys(selectors); - keys.forEach(key => { - (selectors as any)[key] = updateMuxifiedKeyedSelector(concepts, semaphore, (selectors as any)[key]); - const keyed = (selectors as any)[key] as KeyedSelector; - const val = selectSlice(concepts, keyed); - keyed.select = () => val; - }); -}; - -export const updateSelects = ( - concepts: Concepts, - selectors: KeyedSelectors, -): void => { - const keys = Object.keys(selectors); - keys.forEach(key => { - const keyed = (selectors as any)[key] as KeyedSelector; - const val = selectSlice(concepts, keyed); - keyed.select = () => val; - }); -}; - -export const updateAtomicSelects = ( - concepts: Concepts, - selectors: KeyedSelectors, - partialState: Partial ? S : Record>, -): KeyedSelector[] => { - const kss: KeyedSelector[] = []; - Object.keys(partialState).forEach(key => { - const selector = ((selectors as any)[key] as KeyedSelector); - if (selector) { - const val = selectSlice(concepts, selector); - selector.select = () => val; - kss.push(selector); - } - }); - return kss; -}; - -/** - * This will update a concepts KeyedSelector to its currently muxified concept. - * @Note Use this in place of createMuxifiedSelector if you find yourself needing to lock deep values. - */ -export const updateMuxifiedKeyedSelector = - (concepts: Concepts, semaphore: number, keyedSelector: KeyedSelector): KeyedSelector | undefined => { - if (concepts[semaphore]) { - const selectorBase = keyedSelector.keys.split('.'); - selectorBase[0] = concepts[semaphore].name; - const _selector = creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction; - if (keyedSelector.setKeys) { - return { - conceptName: concepts[semaphore].name, - conceptSemaphore: semaphore, - _selector, - select: () => undefined, - keys: selectorBase.join('.'), - setKeys: keyedSelector.setKeys, - setSelector: keyedSelector.setSelector - }; - } - return { - conceptName: concepts[semaphore].name, - conceptSemaphore: semaphore, - _selector, - select: () => undefined, - keys: selectorBase.join('.') - }; - } else { - return undefined; - } - }; - -const recordReturn = (key: string, previous: SelectorFunction) => { - return (obj: Record) => { - if (obj[key] !== undefined) { - return previous(obj[key] as Record); - } else { - return undefined; - } - }; -}; -const finalReturn = (key: string) => { - return (obj: Record) => { - if (obj[key] !== undefined) { - return obj[key]; - } else { - return undefined; - } - }; -}; -const tupleReturn = (key: string | number, previous: SelectorFunction) => { - return (obj: Record) => { - if (obj[key] !== undefined) { - const previousSet = previous(obj); - if (previousSet) { - return [obj[key], ...previous(obj) as unknown[]]; - } - return [obj[key]]; - } else { - return undefined; - } - }; -}; -const finalTupleReturn = (key: string | number) => { - return (obj: Record) => { - if (obj[key] !== undefined) { - return [obj[key]]; - } else { - return undefined; - } - }; -}; - -const creation = (keys: string[], index: number, length: number, prev?: SelectorFunction | undefined): SelectorFunction | undefined => { - let previous: SelectorFunction | undefined = prev; - let i = index; - if (index === length - 1) { - previous = finalReturn(keys[i]); - i--; - } - if (i !== 0 && previous) { - previous = recordReturn(keys[i], previous); - return creation(keys, i - 1, length, previous); - } else if (previous) { - return previous; - } else { - return undefined; - } -}; - -const setCreation = - (keys: (string | number)[], index: number, length: number, prev?: SelectorFunction | undefined): SelectorFunction | undefined => { - let previous: SelectorFunction | undefined = prev; - let i = index; - if (index === length - 1) { - previous = finalTupleReturn(keys[i]); - i--; - } - if (i !== -1 && previous) { - previous = tupleReturn(keys[i], previous); - return setCreation(keys, i - 1, length, previous); - } else if (previous) { - return previous; - } else { - return undefined; - } - }; - -// Temporary until there is a better means to create this form of deep selection -// As already I am having to go off script for specific array indexes, despite being able to assemble the logic -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const assembleDynamicSelection = (selection: unknown[]): any => { - return selection.join('.'); -}; - -export function selectState(concepts: Concepts, name: string): T | undefined { - const conceptKeys = Object.keys(concepts).map(key => Number(key)); - const length = conceptKeys.length; - const select = (index: number): T | undefined => { - if (concepts[conceptKeys[index]].name === name) { - return concepts[conceptKeys[index]].state as T; - } else if (index < length - 1) { - return select(index + 1); - } else { - return undefined; - } - }; - return select(0); -} - -/** - * Simple helper function that returns payload casted to T. - */ -export function selectPayload(action: Action): T { - return action.payload as T; -} - -// Note: The Concept Key within the selector has to be set Explicitly for now -export function selectSlice( - concepts: Concepts, - keyed: KeyedSelector): T | undefined { - const concept: AnyConcept | undefined = (() => { - if (keyed.conceptSemaphore === -1) { - const name = keyed.conceptName; - const conceptKeys = Object.keys(concepts); - const length = conceptKeys.length; - const select = (index: number): AnyConcept | undefined => { - const i = Number(conceptKeys[index]); - const possible = concepts[i]; - if (possible && possible.name === name) { - return concepts[i]; - } else if (index < length) { - return select(index + 1); - } else { - return undefined; - } - }; - return select(0); - } else { - return concepts[keyed.conceptSemaphore]; - } - })(); - if (concept === undefined) {return undefined;} - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const cast = concept.state as Record; - return keyed._selector(cast) as T | undefined; -} - -export function selectSet(concepts: Concepts, keyed: KeyedSelector): T | undefined { - const state: T | undefined = selectSlice(concepts, keyed); - if (keyed.setSelector) { - return (keyed.setSelector(state as Record)) as T; - } - return undefined; -} - -export function selectConcept< - S extends Record, T = void ->(concepts: Concepts, name: string): Concept | undefined { - const conceptKeys = Object.keys(concepts); - const length = conceptKeys.length; - const select = (index: number): Concept | undefined => { - const i = Number(conceptKeys[index]); - if (concepts[i] && concepts[i].name === name) { - return concepts[i] as Concept; - } else if (index < length) { - return select(index + 1); - } else { - return undefined; - } - }; - return select(0); -} - -/** - * Advanced functionality, set a custom key path that may include array indexes. - * @example createAdvancedKeys(['some', 1, 'once', 2, 'me', 7, 'world', 4]) : some.1.once.2.m.7.world.4 - * @param arr a series of keys that points to your targeted slice - * @returns DotPath - */ -export function createAdvancedKeys(arr: unknown[]): DotPath { - return arr.join('.') as DotPath; -} - -//createConceptKeyedSelector<{something: unknown}>('something', 'something.1' as DotPath<{something:unknown}>); -/** - * Allows for the Muxification of Concepts and a form of Data Oriented Functional Inheritance. - * @within_principles Simply pass the supplied semaphore passed to your PrincipleFunction to gain access to that State. - * @outside_selection Use selectState targeting that Muxified Concept Name - */ - -// Either returns the current concept's muxified state, or informs that the concept has been removed and the principles needs shutdown -export function selectMuxifiedState(concepts: Concepts, semaphore: number): T | undefined { - if (concepts[semaphore]) { - return concepts[semaphore].state as T; - } else { - return undefined; - } -} - -export const select = ({ - createMuxifiedKeyedSelector, - createConceptKeyedSelector, - createAdvancedKeys, - updateMuxifiedKeyedSelector, - state: selectState, - set: selectSet, - payLoad: selectPayload, - slice: selectSlice, - concept: selectConcept, - muxifiedState: selectMuxifiedState, -}); -/*#>*/ \ No newline at end of file diff --git a/src/model/selector/index.ts b/src/model/selector/index.ts new file mode 100644 index 00000000..b9978850 --- /dev/null +++ b/src/model/selector/index.ts @@ -0,0 +1,31 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Selector Index model file. +This file imports all non-trivial selector functionality bundled into a 'select' object. +$>*/ +/*<#*/ +import { updateMuxifiedKeyedSelector } from '../..'; +import { + createAdvancedKeys, + createConceptKeyedSelector, + createMuxifiedKeyedSelector, + selectConcept, + selectMuxifiedState, + selectPayload, + selectSet, + selectSlice, + selectState +} from './selector'; + +export const select = ({ + createMuxifiedKeyedSelector, + createConceptKeyedSelector, + createAdvancedKeys, + updateMuxifiedKeyedSelector, + state: selectState, + set: selectSet, + payload: selectPayload, + slice: selectSlice, + concept: selectConcept, + muxifiedState: selectMuxifiedState, +}); +/*#>*/ \ No newline at end of file diff --git a/src/model/selector/selector.ts b/src/model/selector/selector.ts new file mode 100644 index 00000000..5dd82e05 --- /dev/null +++ b/src/model/selector/selector.ts @@ -0,0 +1,190 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Selector model file. +This file will contain a series of selectors that can be used to engage with different parts of the Muxium Conceptual Set. +$>*/ +/*<#*/ +import { Action } from '../action/action.type'; +import { AnyConcept, Concept, Concepts } from '../concept/concept.type'; +import { DotPath } from '../dotPath'; +import { KeyedSelector, SelectorFunction } from './selector.type'; +import { creation, setCreation } from './selectorHelpers'; + +/** + * Will create a new KeyedSelector based on a concept name comparison during runtime, mainly used for external usage + * @param keys - type string - Format is 'key0.key1.key3' for deep nested key values + * @tutorial *Note* This will only extend 6 levels into a deeply nested record. + * @tutorial **Use createAdvancedKeys** function in place of keys if attempted to scaffold into through arrays + */ +export const createConceptKeyedSelector = + >(conceptName: string, keys: DotPath, setKeys?: (number|string)[]): KeyedSelector => { + const selectorBase = [conceptName, ...keys.split('.')]; + if (setKeys) { + return { + conceptName, + conceptSemaphore: -1, + keys: conceptName + '.' + keys, + select: () => undefined, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + setKeys, + setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) + }; + } + return { + conceptName, + conceptSemaphore: -1, + keys: conceptName + '.' + keys, + select: () => undefined, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + setKeys + }; + }; + +/** + * Will create a new KeyedSelector during runtime, for usage throughout Stratimux + * @param keys - type string - Format is 'key0.key1.key3' for deep nested key values + * Uses type DotPath to enable some DX in the IDE to quickly create the desired string format. + * @tutorial *Note* This will only extend 6 levels into a deeply nested record. + * @tutorial **Use createAdvancedKeys** function in place of keys if attempted to scaffold into through arrays + */ +export const createMuxifiedKeyedSelector = >( + concepts: Concepts, + semaphore: number, + keys: DotPath, + setKeys?: (number | string)[] +): KeyedSelector | undefined => { + const concept = concepts[semaphore]; + try { + if (concept) { + const selectorBase = [concept.name, ...keys.split('.')]; + if (setKeys) { + return { + conceptName: concept.name, + conceptSemaphore: semaphore, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + select: () => undefined, + keys: concept.name + '.' + keys, + setKeys, + setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) + }; + } + return { + conceptName: concept.name, + conceptSemaphore: semaphore, + select: () => undefined, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + keys: concept.name + '.' + keys, + }; + } + } catch (err) { + console.error(err); + console.warn('ERROR AT: ', keys); + } + return undefined; +}; +export const selectMuxifiedName = (concepts: Concepts, semaphore: number): string | undefined => (concepts[semaphore]?.name); + +export function selectState(concepts: Concepts, name: string): T | undefined { + const conceptKeys = Object.keys(concepts).map(key => Number(key)); + const length = conceptKeys.length; + const select = (index: number): T | undefined => { + if (concepts[conceptKeys[index]].name === name) { + return concepts[conceptKeys[index]].state as T; + } else if (index < length - 1) { + return select(index + 1); + } else { + return undefined; + } + }; + return select(0); +} + +/** + * Simple helper function that returns payload casted to T. + */ +export function selectPayload(action: Action): T { + return action.payload as T; +} + +// Note: The Concept Key within the selector has to be set Explicitly for now +export function selectSlice( + concepts: Concepts, + keyed: KeyedSelector): T | undefined { + const concept: AnyConcept | undefined = (() => { + if (keyed.conceptSemaphore === -1) { + const name = keyed.conceptName; + const conceptKeys = Object.keys(concepts); + const length = conceptKeys.length; + const select = (index: number): AnyConcept | undefined => { + const i = Number(conceptKeys[index]); + const possible = concepts[i]; + if (possible && possible.name === name) { + return concepts[i]; + } else if (index < length) { + return select(index + 1); + } else { + return undefined; + } + }; + return select(0); + } else { + return concepts[keyed.conceptSemaphore]; + } + })(); + if (concept === undefined) {return undefined;} + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const cast = concept.state as Record; + return keyed._selector(cast) as T | undefined; +} + +export function selectSet(concepts: Concepts, keyed: KeyedSelector): T | undefined { + const state: T | undefined = selectSlice(concepts, keyed); + if (keyed.setSelector) { + return (keyed.setSelector(state as Record)) as T; + } + return undefined; +} + +export function selectConcept< + S extends Record, T = void +>(concepts: Concepts, name: string): Concept | undefined { + const conceptKeys = Object.keys(concepts); + const length = conceptKeys.length; + const select = (index: number): Concept | undefined => { + const i = Number(conceptKeys[index]); + if (concepts[i] && concepts[i].name === name) { + return concepts[i] as Concept; + } else if (index < length) { + return select(index + 1); + } else { + return undefined; + } + }; + return select(0); +} + +/** + * Advanced functionality, set a custom key path that may include array indexes. + * @example createAdvancedKeys(['some', 1, 'once', 2, 'me', 7, 'world', 4]) : some.1.once.2.m.7.world.4 + * @param arr a series of keys that points to your targeted slice + * @returns DotPath + */ +export function createAdvancedKeys(arr: unknown[]): DotPath { + return arr.join('.') as DotPath; +} + +//createConceptKeyedSelector<{something: unknown}>('something', 'something.1' as DotPath<{something:unknown}>); +/** + * Allows for the Muxification of Concepts and a form of Data Oriented Functional Inheritance. + * @within_principles Simply pass the supplied semaphore passed to your PrincipleFunction to gain access to that State. + * @outside_selection Use selectState targeting that Muxified Concept Name + */ + +// Either returns the current concept's muxified state, or informs that the concept has been removed and the principles needs shutdown +export function selectMuxifiedState(concepts: Concepts, semaphore: number): T | undefined { + if (concepts[semaphore]) { + return concepts[semaphore].state as T; + } else { + return undefined; + } +} +/*#>*/ \ No newline at end of file diff --git a/src/model/selector/selector.type.ts b/src/model/selector/selector.type.ts new file mode 100644 index 00000000..df445f2b --- /dev/null +++ b/src/model/selector/selector.type.ts @@ -0,0 +1,60 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Selector Type model file. +This file defines all types necessary for Stratimux Selector functionality. +$>*/ +/*<#*/ +import { AnyConcept, Concepts } from '../concept/concept.type'; +import { DotPath } from '../dotPath'; + +/** + * Will have such be a list of state keys separated by spaces until someone yells at me to change this. + */ +export type SelectorFunction = (obj: Record) => T extends void ? unknown : T | undefined; +export type KeyedSelector = { + conceptName: string, + conceptSemaphore: number, + keys: string, + select: () => T, + _selector: SelectorFunction, + setKeys?: (number | string)[] + setSelector?: SelectorFunction +}; + +export type KeyedSelectors = { + [K in keyof S]: S[K] extends KeyedSelector ? + KeyedSelector + : + KeyedSelector +}; + +export type CreateBufferedMuxifiedKeyedSelector = (semaphore: number) => + MuxifiedKeyedSelector; + +export type MuxifiedKeyedSelector = ( + concepts: Concepts, + keys: DotPath ? T : Record>, + setKeys?: (number | string)[] +) => KeyedSelector | undefined; + +export type StateValidator = S extends Record ? S : Record; +export type CreateBufferedStateSelector = (semaphore: number) => + StateSelector; +export type StateSelector = (concepts: Concepts) => StateValidator | undefined; + +export type CreateBufferedConceptSelector = (semaphore: number) => + ConceptSelector; +export type ConceptSelector = (concepts: Concepts) => C | undefined; + +export type MuxifiedNameSelector = (concepts: Concepts) => string | undefined; +export type CreateBufferedMuxifiedNameSelector = (semaphore: number) => MuxifiedNameSelector; + +// export type Selectors = { +export type Selectors = { + create: MuxifiedKeyedSelector, + state: StateSelector, + name: MuxifiedNameSelector + // concept: ConceptSelector +} + +export type BundledSelectors = KeyedSelectors & Selectors +/*#>*/ \ No newline at end of file diff --git a/src/model/selector/selectorAdvanced.ts b/src/model/selector/selectorAdvanced.ts new file mode 100644 index 00000000..de33b011 --- /dev/null +++ b/src/model/selector/selectorAdvanced.ts @@ -0,0 +1,199 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Selector Advanced model file. +This file sets the function definitions for advanced utilization of Stratimux Selector Functions. +$>*/ +/*<#*/ +import { AnyConcept, Concepts } from '../concept/concept.type'; +import { DotPath } from '../dotPath'; +import { selectMuxifiedName, selectSlice } from './selector'; +import { + ConceptSelector, + CreateBufferedConceptSelector, + CreateBufferedMuxifiedKeyedSelector, + CreateBufferedMuxifiedNameSelector, + CreateBufferedStateSelector, + KeyedSelector, + KeyedSelectors, + SelectorFunction, + Selectors, + StateSelector, + StateValidator +} from './selector.type'; +import { creation, setCreation } from './selectorHelpers'; + +export const createBufferedMuxifiedKeyedSelector: CreateBufferedMuxifiedKeyedSelector = + > (semaphore: number) => ( + concepts: Concepts, + keys: DotPath, + setKeys?: (number | string)[] + ): KeyedSelector | undefined => { + const concept = concepts[semaphore]; + try { + if (concept) { + const selectorBase = [concept.name, ...keys.split('.')]; + if (setKeys) { + return { + conceptName: concept.name, + conceptSemaphore: semaphore, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + select: () => undefined, + keys: concept.name + '.' + keys, + setKeys, + setSelector: setCreation(setKeys, setKeys.length - 1, setKeys.length) + }; + } + return { + conceptName: concept.name, + conceptSemaphore: semaphore, + select: () => undefined, + _selector: creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction, + keys: concept.name + '.' + keys, + }; + } + } catch (err) { + console.error(err); + console.warn('ERROR AT: ', keys); + } + return undefined; + }; + +export const createBufferedStateSelector: CreateBufferedStateSelector = + (semaphore: number): StateSelector => (concepts: Concepts): + StateValidator | undefined => { + const concept = concepts[semaphore]; + if (concept) { + return concept.state as StateValidator; + } + return undefined; + }; + +export const createBufferedConceptSelector: CreateBufferedConceptSelector = + (semaphore: number): ConceptSelector => (concepts: Concepts) => { + const concept = concepts[semaphore]; + if (concept) { + return concept as C; + } + return undefined; + }; + +export const createBufferedMuxifiedNameSelector: CreateBufferedMuxifiedNameSelector = (semaphore) => + (concepts) => selectMuxifiedName(concepts, semaphore); + +export const createSelectors = ( + semaphore: number +): Selectors => ({ + create: createBufferedMuxifiedKeyedSelector(semaphore), + state: createBufferedStateSelector(semaphore), + name: createBufferedMuxifiedNameSelector(semaphore) + }); + +export const createDummySelectors = ( +): Selectors => { + return { + create: createBufferedMuxifiedKeyedSelector(-1), + // concept: createBufferedConceptSelector(semaphore), + state: createBufferedStateSelector(-1), + name: createBufferedMuxifiedNameSelector(-1) + }; +}; + +export const createDummyKeyedSelectors = ( + state: S +): KeyedSelectors => { + const selectors = {} as KeyedSelectors; + const keys = Object.keys(state as Record); + keys.forEach(key => { + selectors[key] = { + conceptName: '', + conceptSemaphore: -1, + select: () => undefined, + keys: 'dummy.' + key, + _selector: () => undefined + }; + }); + return selectors; +}; + +export const updateKeyedSelectors = ( + concepts: Concepts, + selectors: KeyedSelectors, + semaphore: number +): void => { + const keys = Object.keys(selectors); + keys.forEach(key => { + (selectors as any)[key] = updateMuxifiedKeyedSelector(concepts, semaphore, (selectors as any)[key]); + const keyed = (selectors as any)[key] as KeyedSelector; + const val = selectSlice(concepts, keyed); + keyed.select = () => val; + }); +}; + +export const updateSelects = ( + concepts: Concepts, + selectors: KeyedSelectors, +): void => { + const keys = Object.keys(selectors); + keys.forEach(key => { + const keyed = (selectors as any)[key] as KeyedSelector; + const val = selectSlice(concepts, keyed); + keyed.select = () => val; + }); +}; + +export const updateAtomicSelects = ( + concepts: Concepts, + selectors: KeyedSelectors, + partialState: Partial ? S : Record>, +): KeyedSelector[] => { + const kss: KeyedSelector[] = []; + Object.keys(partialState).forEach(key => { + const selector = ((selectors as any)[key] as KeyedSelector); + if (selector) { + const val = selectSlice(concepts, selector); + selector.select = () => val; + kss.push(selector); + } + }); + return kss; +}; + +/** + * This will update a concepts KeyedSelector to its currently muxified concept. + * @Note Use this in place of createMuxifiedSelector if you find yourself needing to lock deep values. + */ +export const updateMuxifiedKeyedSelector = + (concepts: Concepts, semaphore: number, keyedSelector: KeyedSelector): KeyedSelector | undefined => { + if (concepts[semaphore]) { + const selectorBase = keyedSelector.keys.split('.'); + selectorBase[0] = concepts[semaphore].name; + const _selector = creation(selectorBase, selectorBase.length - 1, selectorBase.length) as SelectorFunction; + if (keyedSelector.setKeys) { + return { + conceptName: concepts[semaphore].name, + conceptSemaphore: semaphore, + _selector, + select: () => undefined, + keys: selectorBase.join('.'), + setKeys: keyedSelector.setKeys, + setSelector: keyedSelector.setSelector + }; + } + return { + conceptName: concepts[semaphore].name, + conceptSemaphore: semaphore, + _selector, + select: () => undefined, + keys: selectorBase.join('.') + }; + } else { + return undefined; + } + }; +// Temporary until there is a better means to create this form of deep selection +// As already I am having to go off script for specific array indexes, despite being able to assemble the logic +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const assembleDynamicSelection = (selection: unknown[]): any => { + return selection.join('.'); +}; + +/*#>*/ \ No newline at end of file diff --git a/src/model/selector/selectorHelpers.ts b/src/model/selector/selectorHelpers.ts new file mode 100644 index 00000000..cead1d7e --- /dev/null +++ b/src/model/selector/selectorHelpers.ts @@ -0,0 +1,89 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Selector Helper model file. +This file defines a series of functions that are used to aid in the creation of Selectors. +$>*/ +/*<#*/ +import { SelectorFunction } from './selector.type'; + +export const recordReturn = (key: string, previous: SelectorFunction) => { + return (obj: Record) => { + if (obj[key] !== undefined) { + return previous(obj[key] as Record); + } else { + return undefined; + } + }; +}; +export const finalReturn = (key: string) => { + return (obj: Record) => { + if (obj[key] !== undefined) { + return obj[key]; + } else { + return undefined; + } + }; +}; +export const tupleReturn = (key: string | number, previous: SelectorFunction) => { + return (obj: Record) => { + if (obj[key] !== undefined) { + const previousSet = previous(obj); + if (previousSet) { + return [obj[key], ...previous(obj) as unknown[]]; + } + return [obj[key]]; + } else { + return undefined; + } + }; +}; +export const finalTupleReturn = (key: string | number) => { + return (obj: Record) => { + if (obj[key] !== undefined) { + return [obj[key]]; + } else { + return undefined; + } + }; +}; + +export const creation = ( + keys: string[], + index: number, + length: number, + prev?: SelectorFunction | undefined +): SelectorFunction | undefined => { + let previous: SelectorFunction | undefined = prev; + let i = index; + if (index === length - 1) { + previous = finalReturn(keys[i]); + i--; + } + if (i !== 0 && previous) { + previous = recordReturn(keys[i], previous); + return creation(keys, i - 1, length, previous); + } else if (previous) { + return previous; + } else { + return undefined; + } +}; + +export const setCreation = + (keys: (string | number)[], index: number, length: number, prev?: SelectorFunction | undefined): SelectorFunction | undefined => { + let previous: SelectorFunction | undefined = prev; + let i = index; + if (index === length - 1) { + previous = finalTupleReturn(keys[i]); + i--; + } + if (i !== -1 && previous) { + previous = tupleReturn(keys[i], previous); + return setCreation(keys, i - 1, length, previous); + } else if (previous) { + return previous; + } else { + return undefined; + } + }; + +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner.ts b/src/model/stagePlanner.ts deleted file mode 100644 index a75cd5c5..00000000 --- a/src/model/stagePlanner.ts +++ /dev/null @@ -1,953 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux, define the Stage Planner model file. -This file introduces the Muxified Subject, that allows for users to stage plans based on observation of the Concepts stream. -The Stage Planner paradigm is what allows for the ease of working within a recursive run time, via setting plans to specific stages -in order to prevent action overflow. Action overflow is when a function is stuck within a recursive loop. This paradigm -also ensures Stratimux of its own provable termination in majority of configurations. -$>*/ -/*<#*/ -/* eslint-disable complexity */ -import { Subject } from 'rxjs'; -import { Concepts, LoadConcepts } from './concept'; -import { MuxiumDeck, MuxiumState } from '../concepts/muxium/muxium.concept'; -import { - BundledSelectors, - KeyedSelector, - createConceptKeyedSelector, - select, - selectSlice, -} from './selector'; -import { Action, ActionType, Actions, AnyAction, createAction } from './action'; -import { muxiumSelectOpen } from '../concepts/muxium/muxium.selector'; -import { ownershipSelectInitialized } from '../concepts/ownership/ownership.selector'; -import { HandleHardOrigin, HandleOrigin, createOrigin, getMuxiumState, isMuxiumOpen } from './muxium'; -import { ownershipSetOwnerShipModeTopic } from '../concepts/ownership/strategies/setOwnerShipMode.strategy'; -import { muxiumTimeOut } from './time'; -import { Comparators, HInterface, UInterface } from './interface'; -import { MuxiumQualities } from '../concepts/muxium/qualities'; -import { accessDeck } from './deck'; - -export type Plan = { - id: number; - space: number; - conceptSemaphore: number; - conceptName: string; - title: string; - stages: Staging[], - stage: number; - stageFailed: number; - beat: number; - offBeat: number; - timer: NodeJS.Timeout[]; - changeAggregator: Record; -} - -export type Stage = (params: StageParams) => void; - -export type StageParams = { - concepts: Concepts, - dispatch: (action: Action, options: dispatchOptions, ) => void, - changes: KeyedSelector[], - stagePlanner: StagePlanner -} & UInterface - -export type Planning = (title: string, planner: Planner) => StagePlanner; - -export type Planner = (uI: HInterface & { - stage: typeof createStage - stageO: typeof stageWaitForOpenThenIterate, - conclude: typeof stageConclude -}) => PartialStaging[]; - -export type Staging = { - stage: Stage; - selectors: KeyedSelector[]; - firstRun: boolean; - priority?: number - beat?: number, -}; - -export type PartialStaging = { - stage: Stage; - selectors?: KeyedSelector[]; - priority?: number - beat?: number, -}; - -export type StagePlanner = { - title: string; - planId: number; - conclude: () => void; -} - -export type NamedStagePlanner = { - name: string; - title: string; - planId: number; - conclude: () => void; -} - -export type dispatchOptions = { - override?: boolean; - hardOverride?: boolean; - runOnce?: boolean; - throttle?: number; - iterateStage?: boolean; - setStage?: number; - setStageSelectors?: { - stage: number, - selectors: KeyedSelector[] - }; - setStagePriority?: { - stage: number, - priority: number - }; - setStageBeat?: { - stage: number, - beat: number - }; - newSelectors?: KeyedSelector[]; - newPriority?: number; - newBeat?: number; -} - -export type Dispatcher = (action: Action, options: dispatchOptions) => void; - -export type StageDelimiter = { - stage: number, - prevActions: ActionType[], - unionExpiration: number[]; - runOnceMap: Map -} - -/** - * Used in principle plans that are loaded during muxium initialization - */ -export const stageWaitForOpenThenIterate = (func: () => AnyAction): Staging => (createStage(({concepts, dispatch}) => { - if (isMuxiumOpen(concepts)) { - dispatch(func(), { - iterateStage: true - }); - } -}, { selectors: [muxiumSelectOpen] })); - -export const stageConclude = (): Staging => createStage(({stagePlanner}) => {stagePlanner.conclude();}); - -export const stageWaitForOwnershipThenIterate = - (func: () => Action): Staging => (createStage(({concepts, dispatch}) => { - if (selectSlice(concepts, ownershipSelectInitialized) && getMuxiumState(concepts).lastStrategy === ownershipSetOwnerShipModeTopic) { - dispatch(func(), { - iterateStage: true - }); - } - }, { selectors: [ownershipSelectInitialized] })); -/** - * Helper function to aid readability of composing plans, otherwise you may directly create a Staging Entity, selectors non optional - * @param stage - (concepts, dispatch) => {} - * @param selectors - Array of observed dependencies to execute your stage - * @param priority - Adding this property will change the order in which your plan is notified on each state change - * @param beat - Will fire once, then if informed again within your supplied beat, will fire after such time - * @returns stage: Stage, selectors: KeyedSelector[], priority?: number, beat?: number - */ -export const createStage = ( - stage: Stage, - options?: { selectors?: KeyedSelector[], priority?: number, beat?: number} -): Staging => { - if (options) { - return { - stage, - selectors: options.selectors ? options.selectors : [], - firstRun: true, - priority: options.priority, - beat: options.beat - }; - } else { - return { - stage, - firstRun: true, - selectors: [] - }; - } -}; - -// Token to denote ALL, using a selector that utilizes this token should return undefined -const ALL = '*4||*'; -const ALL_KEYS = '*4||*.*4||*'; - -const handleRun = - (stageDelimiter: StageDelimiter, plan: Plan, action: Action, options?: dispatchOptions) - : [StageDelimiter, boolean] => { - if (options?.runOnce) { - const stageRunner = stageDelimiter.runOnceMap.get(action.type + plan.stage); - if (stageRunner === undefined) { - stageDelimiter.runOnceMap.set(action.type + plan.stage, true); - return [ - stageDelimiter, true - ]; - } else { - stageDelimiter.runOnceMap.set(action.type + plan.stage, false); - return [ - stageDelimiter, false - ]; - } - } - return [ - stageDelimiter, - true - ]; - }; - -const handleStageDelimiter = - (plan: Plan, action: Action, delimiter?: StageDelimiter, options?: dispatchOptions): [StageDelimiter, boolean] => { - let stageDelimiter = delimiter; - let goodAction = true; - if (stageDelimiter && - stageDelimiter.prevActions.includes(action.type) && - options?.throttle === undefined) { - if (plan.stage !== stageDelimiter?.stage) { - stageDelimiter = { - stage: plan.stage, - prevActions: [action.type], - unionExpiration: [action.expiration], - runOnceMap: new Map() - }; - } else { - goodAction = false; - } - } else if (stageDelimiter) { - if (stageDelimiter.prevActions.length > 4) { - stageDelimiter = { - stage: plan.stage, - prevActions: [ - stageDelimiter.prevActions[1], - stageDelimiter.prevActions[2], - stageDelimiter.prevActions[3], - stageDelimiter.prevActions[4], - action.type - ], - unionExpiration: [ - stageDelimiter.unionExpiration[1], - stageDelimiter.unionExpiration[2], - stageDelimiter.unionExpiration[3], - stageDelimiter.unionExpiration[4], - action.expiration - ], - runOnceMap: new Map() - }; - } else { - stageDelimiter = { - stage: plan.stage, - prevActions: [...stageDelimiter.prevActions, action.type], - unionExpiration: [...stageDelimiter.unionExpiration, action.expiration], - runOnceMap: new Map() - }; - } - } else { - stageDelimiter = { - stage: plan.stage, - prevActions: [action.type], - unionExpiration: [action.expiration], - runOnceMap: new Map() - }; - } - return [ - stageDelimiter, - goodAction - ]; - }; - -const Inner = 0; -const Base = 1; -const Outer = 2; - -export class MuxifiedSubject extends Subject { - private planId = -1; - private currentPlans: Map> = new Map(); - private stageDelimiters: Map = new Map(); - private concepts: Concepts = {}; - // Assemble front of line - private priorityQue: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[] = []; - private priorityExists: Map = new Map(); - private frequencyMap: Map = new Map(); - private selectors: Map = new Map(); - // Assemble back of line, exempts priority que members - private ques: { - priorityQue: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], - generalQue: number[], - }[] = [{generalQue: [], priorityQue: []}, {generalQue: [], priorityQue: []}, {generalQue: [], priorityQue: []}]; - // private generalQue: number[] = []; - // [TODO Unify Streams]: Simplify streams into one single MuxifiedSubject - // [Experiment notes]: When attempting to unify all streams the chain test presented a ghost count repeating at 14 with both 0 and 2 - // [Punt]: The main issue with this simplification is the order in which withLatest is notified - // In order to fully facilitate this change we would need to add an innerQue, but likewise can just have 3 streams - // private outerQue: number[] = []; - // The above approach is enhanced by a onChange dict - constructor() { - super(); - this.planId = 0; - } - - protected createPriorityKey(planId: number, stage: number) { - return `${planId}${stage}`; - } - - protected handleAddSelector(selectors: KeyedSelector[], id: number) { - if (selectors.length === 0) { - const ALL_SELECTOR = select.createConceptKeyedSelector(ALL, ALL); - this.addSelector(ALL_SELECTOR, id); - } - selectors.forEach(selector => this.addSelector(selector, id)); - } - - protected handleNewStageOptions = (plan: Plan, options: dispatchOptions, next: number): boolean => { - let evaluate = false; - if (options.newPriority) { - plan.stages[plan.stage].priority = options.newPriority; - evaluate = true; - } - if (options.newSelectors) { - this.handleRemoveSelector(plan.stages[plan.stage].selectors, plan.id); - plan.stages[plan.stage].selectors = options.newSelectors; - this.handleAddSelector(plan.stages[plan.stage].selectors, plan.id); - evaluate = true; - } - if (options.newBeat) { - plan.stages[plan.stage].beat = options.newBeat; - if (next === -1) { - plan.beat = options.newBeat; - } - evaluate = true; - } - return evaluate; - }; - - protected handleSetStageOptions = (plan: Plan, options: dispatchOptions) => { - if (options.setStageSelectors && plan.stages[options.setStageSelectors.stage]) { - plan.stages[options.setStageSelectors.stage].selectors = options.setStageSelectors.selectors; - } - if (options.setStagePriority && plan.stages[options.setStagePriority.stage]) { - plan.stages[options.setStagePriority.stage].priority = options.setStagePriority.priority; - } - if (options.setStageBeat && plan.stages[options.setStageBeat.stage]) { - plan.stages[options.setStageBeat.stage].beat = options.setStageBeat.beat; - } - }; - - protected addSelector(selector: KeyedSelector, id: number) { - const s = this.selectors.get(selector.keys); - if (s) { - this.selectors.set(selector.keys, {selector, ids: [...s.ids, id]}); - } else { - this.selectors.set(selector.keys, {selector, ids: [id]}); - } - } - - protected handleRemoveSelector(selectors: KeyedSelector[], id: number) { - if (selectors.length === 0) { - const ALL_SELECTOR = select.createConceptKeyedSelector(ALL, ALL); - this.removeSelector(ALL_SELECTOR, id); - } - selectors.forEach(selector => this.removeSelector(selector, id)); - } - - protected removeSelector(selector: KeyedSelector, id: number) { - const s = this.selectors.get(selector.keys); - if (s) { - if (s.ids.length - 1 === 0) { - this.selectors.delete(selector.keys); - } else { - this.selectors.set(selector.keys, {selector, ids: s.ids.filter(idx => idx !== id)}); - } - } - } - - protected createPlan = ( - title: string, - planner: Planner, - space: number, - conceptSemaphore: number - ): Plan => { - const stages = planner({ - d__: accessDeck(this.concepts), - e__: this.concepts[conceptSemaphore].actions as Actions, - c__: this.concepts[conceptSemaphore].comparators as Comparators, - k__: { - ...this.concepts[conceptSemaphore].keyedSelectors, - ...this.concepts[conceptSemaphore].selectors, - } as BundledSelectors, - stage: createStage, - stageO: stageWaitForOpenThenIterate, - conclude: stageConclude - }); - const planId = this.planId; - this.planId += 1; - const staged: Staging[] = stages.map>(s => { - return { - stage: s.stage, - selectors: s.selectors ? s.selectors : [], - firstRun: true, - priority: s.priority, - beat: s.beat - }; - }); - const beat = staged[0].beat; - return { - id: planId, - space, - conceptSemaphore, - conceptName: this.concepts[conceptSemaphore].name, - title, - stages: staged, - stage: 0, - stageFailed: -1, - beat: beat ? beat : -1, - offBeat: -1, - timer: [], - changeAggregator: {} - }; - }; - - protected initPlan(plan: Plan): StagePlanner { - this.currentPlans.set(plan.id, plan); - this.handleAddSelector(plan.stages[plan.stage].selectors, plan.id); - this.manageQues(); - const conclude = () => { - this.deletePlan(plan.id); - }; - muxiumTimeOut(this.concepts, () => { - this.next(this.concepts); - return createAction('Conclude'); - }, 0); - return { - title: plan.title, - planId: plan.id, - conclude: conclude.bind(this) - }; - } - - innerPlan: Planning = (title: string, planner: Planner) => { - return this.initPlan(this.createPlan(title, planner, Inner, 0)); - }; - - // [TODO] - IMPORTANT - LIMIT THIS TO WHITE LISTED VALUES - outerPlan: Planning = (title: string, planner: Planner) => { - return this.initPlan(this.createPlan(title, planner, Outer, 0)); - }; - - plan = (conceptSemaphore: number): Planning => (title: string, planner: Planner): StagePlanner => { - return this.initPlan(this.createPlan(title, planner, Base, conceptSemaphore)); - }; - - protected deletePlan(planId: number) { - const plan = this.currentPlans.get(planId); - if (plan) { - plan.timer.forEach(timer => clearTimeout(timer)); - plan.timer = []; - this.currentPlans.delete(planId); - const selectors = plan.stages[plan.stage]?.selectors; - if (selectors) { - this.handleRemoveSelector(selectors, plan.id); - } - this.manageQues(); - } - return plan; - } - - protected updateFrequencyMap() { - const que = this.priorityQue; - const map: typeof this.frequencyMap = new Map(); - - que.forEach(plan => { - plan.selectors.forEach(selector => { - const frequency = map.get(selector.keys); - if (frequency) { - map.set(selector.keys, frequency + plan.priority); - } else { - map.set(selector.keys, plan.priority); - } - }); - }); - - this.frequencyMap = map; - } - - protected assemblePriorityQue() { - let prioritize = false; - const priorityMap: typeof this.priorityExists = new Map(); - const newList: { - inner: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], - base: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], - outer: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[] - } = { - inner: [], - base: [], - outer: [] - }; - for (const [_, plan] of this.currentPlans) { - const stage = plan.stages[plan.stage]; - const priority = stage.priority; - if (priority) { - prioritize = true; - const key = this.createPriorityKey(plan.id, plan.stage); - const selectors = plan.stages[plan.stage].selectors; - priorityMap.set(key, true); - const entry = { - planID: plan.id, - priority, - stage: plan.stage, - selectors, - }; - switch (plan.space) { - case Inner: { - newList.inner.push(entry); - break; - } - case Base: { - newList.base.push(entry); - break; - } - case Outer: { - newList.outer.push(entry); - break; - } - default: { - // - } - } - this.priorityExists.set(key, true); - } - } - if (!prioritize) { - this.ques[Inner].priorityQue = []; - this.ques[Base].priorityQue = []; - this.ques[Outer].priorityQue = []; - } else { - this.ques[Inner].priorityQue = newList.inner.sort((a, b) => b.priority - a.priority); - this.ques[Base].priorityQue = newList.base.sort((a, b) => b.priority - a.priority); - this.ques[Outer].priorityQue = newList.outer.sort((a, b) => b.priority - a.priority); - } - // This will cause an issue - this.priorityExists = priorityMap; - this.updateFrequencyMap(); - } - - protected assembleGeneralQues() { - const generalMap: { - inner: Map - base: Map - outer: Map - } = { - inner: new Map(), - base: new Map(), - outer: new Map() - }; - for (const [_, plan] of this.currentPlans) { - // let map = generalMap; - const stage = plan.stages[plan.stage]; - const priority = stage.priority; - let target = generalMap.inner; - switch (plan.space) { - case Base: { - target = generalMap.base; - break; - } - case Outer: { - target = generalMap.outer; - break; - } - default: { - // - } - } - if (priority === undefined) { - const prepareMap = (selector: KeyedSelector) => { - const entry = target.get(selector.keys); - const frequency = this.frequencyMap.get(selector.keys); - if (entry) { - entry.planIDs.push(plan.id); - } else if (frequency) { - target.set(selector.keys, { - planIDs: [plan.id], - priorityAggregate: frequency, - selector: selector - }); - } else { - target.set(selector.keys, { - planIDs: [plan.id], - priorityAggregate: 0, - selector: selector - }); - } - }; - if (stage.selectors.length === 0) { - prepareMap(createConceptKeyedSelector(ALL, ALL)); - } else { - for (const selector of stage.selectors) { - prepareMap(selector); - } - } - } - } - const generalIdMap: { - inner: Map - base: Map - outer: Map - } = { - inner: new Map(), - base: new Map(), - outer: new Map() - }; - const handleSlice = (slice: {selector: KeyedSelector, planIDs: number[], priorityAggregate: number}, map: Map) => { - slice.planIDs.forEach(id => { - const priority = map.get(id); - if (priority) { - map.set(id, priority + slice.priorityAggregate); - } else { - map.set(id, slice.priorityAggregate); - } - }); - }; - generalMap.inner.forEach((slice) => { - handleSlice(slice, generalIdMap.inner); - }); - generalMap.base.forEach((slice) => { - handleSlice(slice, generalIdMap.base); - }); - generalMap.outer.forEach((slice) => { - handleSlice(slice, generalIdMap.outer); - }); - const flatten = (map: Map) => { - const flat = []; - for (const [id, frequency] of map.entries()) { - flat.push([id, frequency]); - } - flat.sort((a, b) => b[1] - a[1]); - // We should add a selector union - return flat.map(([id, _]) => id); - }; - this.ques[Inner].generalQue = flatten(generalIdMap.inner); - this.ques[Base].generalQue = flatten(generalIdMap.base); - this.ques[Outer].generalQue = flatten(generalIdMap.outer); - } - - protected manageQues() { - this.assemblePriorityQue(); - this.assembleGeneralQues(); - } - - protected _dispatch( - muxiumState: MuxiumState, - plan: Plan, - action: Action, - options: dispatchOptions): void { - let stageDelimiter = this.stageDelimiters.get(plan.id); - let throttle = false; - let goodAction = true; - let run = true; - [stageDelimiter, goodAction] = handleStageDelimiter(plan, action, stageDelimiter, options); - [stageDelimiter, run] = handleRun(stageDelimiter, plan, action, options); - this.stageDelimiters.set(plan.id, stageDelimiter); - if (goodAction && run) { - const action$ = muxiumState.action$ as Subject; - if (options?.throttle !== undefined) { - let previousExpiration = 0; - for (let i = 0; i < stageDelimiter.prevActions.length; i++) { - if (stageDelimiter.prevActions[i] === action.type) { - previousExpiration = stageDelimiter.unionExpiration[i]; - break; - } - } - if (previousExpiration !== action.expiration && action.expiration - previousExpiration < options?.throttle) { - throttle = true; - } else { - for (let i = 0; i < stageDelimiter.prevActions.length; i++) { - if (stageDelimiter.prevActions[i] === action.type) { - stageDelimiter.unionExpiration[i] = action.expiration; - break; - } - } - } - } - this.stageDelimiters.set(plan.id, stageDelimiter); - if (!throttle && run) { - let next = -1; - const evaluate = this.handleNewStageOptions(plan, options, next); - this.handleSetStageOptions(plan, options); - if (options?.iterateStage) { - next = plan.stage + 1; - // this.updatePlanSelector(plan, plan.stage, next < plan.stages.length ? next : undefined); - } - if (options?.setStage !== undefined) { - next = options.setStage; - } - if (next !== -1) { - // Don't like having to do this. - // Double check this logic while writing the unit test. - if (plan.stages[plan.stage]) { - this.handleRemoveSelector(plan.stages[plan.stage].selectors, plan.id); - } - plan.stage = next; - if (plan.stages[plan.stage]) { - this.handleAddSelector(plan.stages[plan.stage].selectors, plan.id); - } - this.manageQues(); - const beat = plan.stages[plan.stage].beat; - plan.beat = beat !== undefined ? beat : -1; - stageDelimiter.prevActions = []; - stageDelimiter.unionExpiration = []; - stageDelimiter.runOnceMap = new Map(); - plan.changeAggregator = {}; - this.stageDelimiters.set(plan.id, stageDelimiter); - } - if (evaluate && next === -1) { - this.manageQues(); - } - // Horrifying - // Keep in place, this prevents branch prediction from creating ghost actions if there is an action overflow. - if (plan.stageFailed === -1) { - // Will set a the current stage's priority if no priority is set. - action.origin = createOrigin([plan.title, plan.stage]); - const settleOrigin = () => { - if (options.hardOverride) { - HandleHardOrigin(muxiumState, action); - } else if (options.override) { - HandleOrigin(muxiumState, action); - } else { - action$.next(action); - } - }; - if (plan.stages[plan.stage].priority && action.priority === undefined) { - action.priority = plan.stages[plan.stage].priority; - settleOrigin(); - } else { - settleOrigin(); - } - } - } - } else if ( - options?.runOnce === undefined && - (!options.throttle && (options.iterateStage === undefined || options.setStage === plan.stage)) - ) { - plan.stageFailed = plan.stage; - plan.stage = plan.stages.length; - console.error('DELETED PLAN: ', plan.id); - const deleted = this.deletePlan(plan.id); - if (deleted) { - muxiumState.badPlans.push(plan); - } - } - } - - protected execute(plan: Plan, index: number, changes: KeyedSelector[]): void { - const muxiumState = getMuxiumState(this.concepts); - const dispatcher: Dispatcher = (() => (action: Action, options: dispatchOptions) => { - this._dispatch(muxiumState, plan, action, options); - }).bind(this)(); - const conclude = () => { - this.deletePlan(plan.id); - }; - // console.warn('CHECKING', Object.keys(getMuxiumState(this.concepts).head)); - if (this.concepts[plan.conceptSemaphore] === undefined) { - // console.error('CHECK', plan, Object.keys(getMuxiumState(this.concepts).head)); - } else { - plan.stages[index].stage({ - concepts: this.concepts, - dispatch: dispatcher, - changes, - stagePlanner: { - title: plan.title, - planId: plan.id, - conclude: conclude.bind(this) - }, - // [TODO WHY? BACK HERE AGAIN!?!?!? - // Triggered by ownership test, for some reason the muxium was the sole concept available here mid way through test] - d: accessDeck(this.concepts), - e: this.concepts[plan.conceptSemaphore].actions as Actions, - c: this.concepts[plan.conceptSemaphore].comparators as Comparators, - k: { - ...this.concepts[plan.conceptSemaphore].selectors, - ...this.concepts[plan.conceptSemaphore].keyedSelectors, - } as unknown as BundledSelectors, - }); - } - } - - protected nextPlans() { - this.currentPlans.forEach(plan => { - this.nextPlan(plan, []); - }); - } - - protected nextPlan(plan: Plan, changes: KeyedSelector[]) { - const index = plan.stage; - if (index < plan.stages.length) { - if (plan.beat > -1) { - const timer = plan.timer; - const now = Date.now(); - if (plan.offBeat < now) { - plan.offBeat = Date.now() + plan.beat; - this.execute(plan, index, changes); - } else if (timer.length === 0 && plan.offBeat > now) { - // Logic to push changes into aggregator - changes.forEach(key => { - plan.changeAggregator[key.keys] = key; - }); - timer.push(setTimeout(() => { - const changeAggregation = Object.keys(plan.changeAggregator).map(k => plan.changeAggregator[k]); - plan.changeAggregator = {}; - plan.timer = []; - plan.offBeat = Date.now() + plan.beat; - this.execute(plan, index, changeAggregation); - }, plan.offBeat - Date.now())); - } else { - changes.forEach(key => { - plan.changeAggregator[key.keys] = key; - }); - } - } else { - this.execute(plan, index, changes); - } - } - } - - protected nextSubs() { - const {observers} = this; - const len = observers.length; - const nextSub = (index: number) => { - if (observers[index]) { - observers[index].next(this.concepts); - } - if (index < len - 1) { - nextSub(index + 1); - } - }; - nextSub(0); - } - - protected handleChange(concepts: Concepts, blocking = false, keyedSelectors?: KeyedSelector[]) { - const oldConcepts = this.concepts; - this.concepts = concepts; - const notifyIds: Map = new Map(); - if (keyedSelectors) { - // Specific shortest path - const all = this.selectors.get(ALL_KEYS); - if (all) { - const {ids} = all; - ids.forEach(id => { - notifyIds.set(id, []); - }); - } - keyedSelectors.forEach(ks => { - const selectorSet = this.selectors.get(ks.keys); - if (selectorSet) { - let notify = false; - const incoming = ks.select(); - const original = select.slice(oldConcepts, ks); - if (typeof incoming === 'object' && !Object.is(incoming, original)) { - // stuff - notify = true; - } else if (incoming !== original) { - notify = true; - } - const {ids, selector} = selectorSet; - if (notify) { - ids.forEach(id => { - const n = notifyIds.get(id); - if (n) { - n.push(selector); - } else { - notifyIds.set(id, [selector]); - } - }); - } - } - }); - } else { - // Generalized search for user comfort - for (const [_, slice] of this.selectors) { - const {selector, ids} = slice; - let notify = false; - if (slice.selector.conceptName === ALL) { - notify = true; - } else { - const incoming = select.slice(this.concepts, selector); - const original = select.slice(oldConcepts, selector); - if (typeof incoming === 'object' && !Object.is(incoming, original)) { - // stuff - notify = true; - } else if (incoming !== original) { - notify = true; - } - } - if (notify) { - ids.forEach(id => { - const n = notifyIds.get(id); - if (n && selector.conceptName !== ALL) { - n.push(selector); - } else if (selector.conceptName !== ALL) { - notifyIds.set(id, [selector]); - } else { - notifyIds.set(id, []); - } - }); - } - } - } - const notification = (id: number) => { - const ready = notifyIds.get(id); - const plan = this.currentPlans.get(id); - if (plan && ready !== undefined) { - this.nextPlan(plan as Plan, ready); - } else if (plan && plan.stages[plan.stage].firstRun) { - plan.stages[plan.stage].firstRun = false; - this.nextPlan(plan as Plan, []); - } - }; - for (const p of this.ques[Inner].priorityQue) { - notification(p.planID); - } - for (const g of this.ques[Inner].generalQue) { - notification(g); - } - if (!blocking) { - for (const p of this.ques[Base].priorityQue) { - notification(p.planID); - } - for (const g of this.ques[Base].generalQue) { - notification(g); - } - for (const p of this.ques[Outer].priorityQue) { - notification(p.planID); - } - for (const g of this.ques[Outer].generalQue) { - notification(g); - } - } - } - - next(concepts: Concepts, keyedSelectors?: KeyedSelector[]) { - if (!this.closed) { - if (keyedSelectors && keyedSelectors.length !== 0) { - this.handleChange(concepts, false, keyedSelectors); - } else { - this.handleChange(concepts, false); - } - // We notify subs last to encourage actions being acted upon observations - // Then by utilizing a set quality we may inform the next observation of the change - this.nextSubs(); - } - } - init(concepts: Concepts) { - this.concepts = concepts; - } - nextBlocking(concepts: Concepts, keyedSelectors?: KeyedSelector[]) { - if (!this.closed) { - if (keyedSelectors && keyedSelectors.length !== 0) { - this.handleChange(concepts, true, keyedSelectors); - } else { - this.handleChange(concepts, true); - } - } - } -} -/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlanner.ts b/src/model/stagePlanner/stagePlanner.ts new file mode 100644 index 00000000..ab9fdeb1 --- /dev/null +++ b/src/model/stagePlanner/stagePlanner.ts @@ -0,0 +1,147 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner model file. +This file introduces the Muxified Subject, that allows for users to stage plans based on observation of the Concepts stream. +The Stage Planner paradigm is what allows for the ease of working within a recursive run time, via setting plans to specific stages +in order to prevent action overflow. Action overflow is when a function is stuck within a recursive loop. This paradigm +also ensures Stratimux of its own provable termination in logically consistent configurations. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { Subject } from 'rxjs'; +import { Concepts } from '../concept/concept.type'; +import { MuxiumDeck, MuxiumState } from '../../concepts/muxium/muxium.concept'; +import { KeyedSelector } from '../selector/selector.type'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { Action } from '../action/action.type'; +import { dispatchOptions, MuxifiedSubjectProperties, Plan, Planner, Planning, StagePlanner } from './stagePlanner.type'; +import { + addSelector, handleAddSelector, handleNewStageOptions, handleRemoveSelector, handleSetStageOptions, removeSelector +} from './stagePlannerHandlers'; +import { createPlan, deletePlan, initPlan, nextPlan, nextPlans } from './stagePlannerPlan'; +import { assembleGeneralQues, assemblePriorityQue, manageQues, updateFrequencyMap } from './stagePlannerQues'; +import { _dispatch, execute } from './stagePlannerEntropy'; +import { handleChange } from './stagePlannerHandleChange'; + +const Inner = 0; +const Base = 1; +const Outer = 2; + +export class MuxifiedSubject extends Subject { + private properties: MuxifiedSubjectProperties; + + constructor() { + super(); + this.properties = { + planId: 0, + currentPlans: new Map(), + stageDelimiters: new Map(), + concepts: {}, + priorityQue: [], + priorityExists: new Map(), + frequencyMap: new Map(), + mappedSelectors: new Map(), + // Assemble back of line, exempts priority que members + ques: [{generalQue: [], priorityQue: []}, {generalQue: [], priorityQue: []}, {generalQue: [], priorityQue: []}] + }; + } + + protected createPriorityKey = (planId: number, stage: number) => `${planId}${stage}`; + + protected handleAddSelector = (selectors: KeyedSelector[], id: number) => handleAddSelector(this.properties, selectors, id); + + protected handleNewStageOptions = (plan: Plan, options: dispatchOptions, next: number): boolean => + handleNewStageOptions(this.properties, plan, options, next); + + protected handleSetStageOptions = (plan: Plan, options: dispatchOptions) => + handleSetStageOptions(plan, options); + + protected addSelector = (selector: KeyedSelector, id: number) => addSelector(this.properties, selector, id); + + protected handleRemoveSelector = (selectors: KeyedSelector[], id: number) => handleRemoveSelector(this.properties, selectors, id); + + protected removeSelector = (selector: KeyedSelector, id: number) => removeSelector(this.properties, selector, id); + + protected createPlan = ( + title: string, + planner: Planner, + space: number, + conceptSemaphore: number + ): Plan => createPlan(this.properties, title, planner, space, conceptSemaphore); + protected initPlan = (plan: Plan): StagePlanner => initPlan(this.properties, plan, this.next.bind(this)); + + innerPlan: Planning = (title: string, planner: Planner) => this.initPlan(this.createPlan(title, planner, Inner, 0)); + + outerPlan: Planning = (title: string, planner: Planner) => this.initPlan(this.createPlan(title, planner, Outer, 0)); + + plan = (conceptSemaphore: number): Planning => + (title: string, planner: Planner): StagePlanner => this.initPlan(this.createPlan(title, planner, Base, conceptSemaphore)); + + protected deletePlan = (planId: number) => deletePlan(this.properties, planId); + + protected updateFrequencyMap = () => updateFrequencyMap(this.properties); + + protected assemblePriorityQue = () => assemblePriorityQue(this.properties); + + protected assembleGeneralQues = () => assembleGeneralQues(this.properties); + + protected manageQues = () => manageQues(this.properties); + + protected _dispatch = ( + muxiumState: MuxiumState, + plan: Plan, + action: Action, + options: dispatchOptions) => _dispatch(this.properties, muxiumState, plan, action, options); + + protected execute = (plan: Plan, index: number, changes: KeyedSelector[]) => + + execute(this.properties, plan, index, changes); + protected nextPlans = () => nextPlans(this.properties); + + protected nextPlan = (plan: Plan, changes: KeyedSelector[]) => nextPlan(this.properties, plan, changes); + + protected nextSubs() { + const {observers} = this; + const len = observers.length; + const nextSub = (index: number) => { + if (observers[index]) { + observers[index].next(this.properties.concepts); + } + if (index < len - 1) { + nextSub(index + 1); + } + }; + nextSub(0); + } + + protected handleChange = (concepts: Concepts, blocking = false, keyedSelectors?: KeyedSelector[]) => + handleChange(this.properties, concepts, blocking, keyedSelectors); + + next(concepts: Concepts, keyedSelectors?: KeyedSelector[]) { + if (!this.closed) { + if (keyedSelectors && keyedSelectors.length !== 0) { + this.handleChange(concepts, false, keyedSelectors); + } else { + this.handleChange(concepts, false); + } + // We notify subs last to encourage actions being acted upon observations + // Then by utilizing a set quality we may inform the next observation of the change + this.nextSubs(); + } + } + + init(concepts: Concepts) { + this.properties.concepts = concepts; + } + + nextBlocking(concepts: Concepts, keyedSelectors?: KeyedSelector[]) { + if (!this.closed) { + if (keyedSelectors && keyedSelectors.length !== 0) { + this.handleChange(concepts, true, keyedSelectors); + } else { + this.handleChange(concepts, true); + } + } + } +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlanner.type.ts b/src/model/stagePlanner/stagePlanner.type.ts new file mode 100644 index 00000000..4c960890 --- /dev/null +++ b/src/model/stagePlanner/stagePlanner.type.ts @@ -0,0 +1,123 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Type model file. +This file defines the type definitions necessary for the smooth operation of a Muxified Subject and the management of its +inner workings. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { Concepts } from '../concept/concept.type'; +import { KeyedSelector } from '../selector/selector.type'; +import { HInterface, UInterface } from '../interface'; +import { Action, ActionType } from '../action/action.type'; +import { createStage, stageConclude, stageWaitForOpenThenIterate } from './stagePlannerHelpers'; + +export type MuxifiedSubjectProperties = { + planId: number; + currentPlans: Map>; + stageDelimiters: Map; + concepts: Concepts; + // Assemble front of line + priorityQue: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[]; + priorityExists: Map; + frequencyMap: Map; + mappedSelectors: Map; + // Assemble back of line, exempts priority que members + ques: { + priorityQue: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], + generalQue: number[], + }[]; +} + +export type Plan = { + id: number; + space: number; + conceptSemaphore: number; + conceptName: string; + title: string; + stages: Staging[], + stage: number; + stageFailed: number; + beat: number; + offBeat: number; + timer: NodeJS.Timeout[]; + changeAggregator: Record; +} + +export type Stage = (params: StageParams) => void; + +export type StageParams = { + concepts: Concepts, + dispatch: (action: Action, options: dispatchOptions, ) => void, + changes: KeyedSelector[], + stagePlanner: StagePlanner +} & UInterface + +export type Planning = (title: string, planner: Planner) => StagePlanner; + +export type Planner = (uI: HInterface & { + stage: typeof createStage + stageO: typeof stageWaitForOpenThenIterate, + conclude: typeof stageConclude +}) => PartialStaging[]; + +export type Staging = { + stage: Stage; + selectors: KeyedSelector[]; + firstRun: boolean; + priority?: number + beat?: number, +}; + +export type PartialStaging = { + stage: Stage; + selectors?: KeyedSelector[]; + priority?: number + beat?: number, +}; + +export type StagePlanner = { + title: string; + planId: number; + conclude: () => void; +} + +export type NamedStagePlanner = { + name: string; + title: string; + planId: number; + conclude: () => void; +} + +export type dispatchOptions = { + override?: boolean; + hardOverride?: boolean; + runOnce?: boolean; + throttle?: number; + iterateStage?: boolean; + setStage?: number; + setStageSelectors?: { + stage: number, + selectors: KeyedSelector[] + }; + setStagePriority?: { + stage: number, + priority: number + }; + setStageBeat?: { + stage: number, + beat: number + }; + newSelectors?: KeyedSelector[]; + newPriority?: number; + newBeat?: number; +} + +export type Dispatcher = (action: Action, options: dispatchOptions) => void; + +export type StageDelimiter = { + stage: number, + prevActions: ActionType[], + unionExpiration: number[]; + runOnceMap: Map +} +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerEntropy.ts b/src/model/stagePlanner/stagePlannerEntropy.ts new file mode 100644 index 00000000..2a2f1898 --- /dev/null +++ b/src/model/stagePlanner/stagePlannerEntropy.ts @@ -0,0 +1,162 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Entropy model file. +This file defines the management of the dispatch functionality within a Stratimux Stage Planner, allowing for +smooth operation of Stratimux's provable termination. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { Subject } from 'rxjs'; +import { MuxiumDeck, MuxiumState } from '../../concepts/muxium/muxium.concept'; +import { BundledSelectors, KeyedSelector } from '../selector/selector.type'; +import { HandleHardOrigin, HandleOrigin, createOrigin, getMuxiumState } from '../muxium/muxiumHelpers'; +import { Comparators } from '../interface'; +import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { accessDeck } from '../deck'; +import { Action, Actions } from '../action/action.type'; +import { Dispatcher, dispatchOptions, MuxifiedSubjectProperties, Plan } from './stagePlanner.type'; +import { handleRun, handleStageDelimiter } from './stagePlannerHelpers'; +import { + handleAddSelector, handleNewStageOptions, handleRemoveSelector, handleSetStageOptions, removeSelector +} from './stagePlannerHandlers'; +import { deletePlan } from './stagePlannerPlan'; +import { manageQues } from './stagePlannerQues'; + +// Token to denote ALL, using a selector that utilizes this token should return undefined +export function _dispatch( + properties: MuxifiedSubjectProperties, + muxiumState: MuxiumState, + plan: Plan, + action: Action, + options: dispatchOptions): void { + let stageDelimiter = properties.stageDelimiters.get(plan.id); + let throttle = false; + let goodAction = true; + let run = true; + [stageDelimiter, goodAction] = handleStageDelimiter(plan, action, stageDelimiter, options); + [stageDelimiter, run] = handleRun(stageDelimiter, plan, action, options); + properties.stageDelimiters.set(plan.id, stageDelimiter); + if (goodAction && run) { + const action$ = muxiumState.action$ as Subject; + if (options?.throttle !== undefined) { + let previousExpiration = 0; + for (let i = 0; i < stageDelimiter.prevActions.length; i++) { + if (stageDelimiter.prevActions[i] === action.type) { + previousExpiration = stageDelimiter.unionExpiration[i]; + break; + } + } + if (previousExpiration !== action.expiration && action.expiration - previousExpiration < options?.throttle) { + throttle = true; + } else { + for (let i = 0; i < stageDelimiter.prevActions.length; i++) { + if (stageDelimiter.prevActions[i] === action.type) { + stageDelimiter.unionExpiration[i] = action.expiration; + break; + } + } + } + } + properties.stageDelimiters.set(plan.id, stageDelimiter); + if (!throttle && run) { + let next = -1; + const evaluate = handleNewStageOptions(properties, plan, options, next); + handleSetStageOptions(plan, options); + if (options?.iterateStage) { + next = plan.stage + 1; + // this.updatePlanSelector(plan, plan.stage, next < plan.stages.length ? next : undefined); + } + if (options?.setStage !== undefined) { + next = options.setStage; + } + if (next !== -1) { + // Don't like having to do this. + // Double check this logic while writing the unit test. + if (plan.stages[plan.stage]) { + handleRemoveSelector(properties, plan.stages[plan.stage].selectors, plan.id); + } + plan.stage = next; + if (plan.stages[plan.stage]) { + handleAddSelector(properties, plan.stages[plan.stage].selectors, plan.id); + } + manageQues(properties); + const beat = plan.stages[plan.stage].beat; + plan.beat = beat !== undefined ? beat : -1; + stageDelimiter.prevActions = []; + stageDelimiter.unionExpiration = []; + stageDelimiter.runOnceMap = new Map(); + plan.changeAggregator = {}; + properties.stageDelimiters.set(plan.id, stageDelimiter); + } + if (evaluate && next === -1) { + manageQues(properties); + } + // Horrifying + // Keep in place, this prevents branch prediction from creating ghost actions if there is an action overflow. + if (plan.stageFailed === -1) { + // Will set a the current stage's priority if no priority is set. + action.origin = createOrigin([plan.title, plan.stage]); + const settleOrigin = () => { + if (options.hardOverride) { + HandleHardOrigin(muxiumState, action); + } else if (options.override) { + HandleOrigin(muxiumState, action); + } else { + action$.next(action); + } + }; + if (plan.stages[plan.stage].priority && action.priority === undefined) { + action.priority = plan.stages[plan.stage].priority; + settleOrigin(); + } else { + settleOrigin(); + } + } + } + } else if ( + options?.runOnce === undefined && + (!options.throttle && (options.iterateStage === undefined || options.setStage === plan.stage)) + ) { + plan.stageFailed = plan.stage; + plan.stage = plan.stages.length; + console.error('DELETED PLAN: ', plan.id); + const deleted = deletePlan(properties, plan.id); + if (deleted) { + muxiumState.badPlans.push(plan); + } + } +} + +export function execute(properties: MuxifiedSubjectProperties, plan: Plan, index: number, changes: KeyedSelector[]): void { + const muxiumState = getMuxiumState(properties.concepts); + const dispatcher: Dispatcher = (() => (action: Action, options: dispatchOptions) => { + _dispatch(properties, muxiumState, plan, action, options); + })(); + const conclude = () => { + deletePlan(properties, plan.id); + }; + // console.warn('CHECKING', Object.keys(getMuxiumState(this.concepts).head)); + if (properties.concepts[plan.conceptSemaphore] === undefined) { + // console.error('CHECK', plan, Object.keys(getMuxiumState(this.concepts).head)); + } else { + plan.stages[index].stage({ + concepts: properties.concepts, + dispatch: dispatcher, + changes, + stagePlanner: { + title: plan.title, + planId: plan.id, + conclude: conclude + }, + // [TODO WHY? BACK HERE AGAIN!?!?!? + // Triggered by ownership test, for some reason the muxium was the sole concept available here mid way through test] + d: accessDeck(properties.concepts), + e: properties.concepts[plan.conceptSemaphore].actions as Actions, + c: properties.concepts[plan.conceptSemaphore].comparators as Comparators, + k: { + ...properties.concepts[plan.conceptSemaphore].selectors, + ...properties.concepts[plan.conceptSemaphore].keyedSelectors, + } as unknown as BundledSelectors, + }); + } +} +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerHandleChange.ts b/src/model/stagePlanner/stagePlannerHandleChange.ts new file mode 100644 index 00000000..6b4d6aed --- /dev/null +++ b/src/model/stagePlanner/stagePlannerHandleChange.ts @@ -0,0 +1,127 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Handle Change model file. +This file defines the handleChange function associated to the MuxifiedSubject. Which allows for the handling of +generalized notification of plans and shortest path of notification via specific handlers via the KeyedSelector Paradigm. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { Concepts } from '../concept/concept.type'; +import { select } from '../selector/'; +import { KeyedSelector } from '../selector/selector.type'; +import { MuxifiedSubjectProperties, Plan } from './stagePlanner.type'; +import { nextPlan } from './stagePlannerPlan'; + +const Inner = 0; +const Base = 1; +const Outer = 2; + +// Token to denote ALL, using a selector that utilizes this token should return undefined +const ALL = '*4||*'; +const ALL_KEYS = '*4||*.*4||*'; + +export function handleChange( + properties: MuxifiedSubjectProperties, + concepts: Concepts, + blocking = false, + keyedSelectors?: KeyedSelector[] +) { + const oldConcepts = properties.concepts; + properties.concepts = concepts; + const notifyIds: Map = new Map(); + if (keyedSelectors) { + // Specific shortest path + const all = properties.mappedSelectors.get(ALL_KEYS); + if (all) { + const {ids} = all; + ids.forEach(id => { + notifyIds.set(id, []); + }); + } + keyedSelectors.forEach(ks => { + const selectorSet = properties.mappedSelectors.get(ks.keys); + if (selectorSet) { + let notify = false; + const incoming = ks.select(); + const original = select.slice(oldConcepts, ks); + if (typeof incoming === 'object' && !Object.is(incoming, original)) { + // stuff + notify = true; + } else if (incoming !== original) { + notify = true; + } + const {ids, selector} = selectorSet; + if (notify) { + ids.forEach(id => { + const n = notifyIds.get(id); + if (n) { + n.push(selector); + } else { + notifyIds.set(id, [selector]); + } + }); + } + } + }); + } else { + // Generalized search for user comfort + for (const [_, slice] of properties.mappedSelectors) { + const {selector, ids} = slice; + let notify = false; + if (slice.selector.conceptName === ALL) { + notify = true; + } else { + const incoming = select.slice(properties.concepts, selector); + const original = select.slice(oldConcepts, selector); + if (typeof incoming === 'object' && !Object.is(incoming, original)) { + // stuff + notify = true; + } else if (incoming !== original) { + notify = true; + } + } + if (notify) { + ids.forEach(id => { + const n = notifyIds.get(id); + if (n && selector.conceptName !== ALL) { + n.push(selector); + } else if (selector.conceptName !== ALL) { + notifyIds.set(id, [selector]); + } else { + notifyIds.set(id, []); + } + }); + } + } + } + const notification = (id: number) => { + const ready = notifyIds.get(id); + const plan = properties.currentPlans.get(id); + if (plan && ready !== undefined) { + nextPlan(properties, plan as Plan, ready); + } else if (plan && plan.stages[plan.stage].firstRun) { + plan.stages[plan.stage].firstRun = false; + nextPlan(properties, plan as Plan, []); + } + }; + for (const p of properties.ques[Inner].priorityQue) { + notification(p.planID); + } + for (const g of properties.ques[Inner].generalQue) { + notification(g); + } + if (!blocking) { + for (const p of properties.ques[Base].priorityQue) { + notification(p.planID); + } + for (const g of properties.ques[Base].generalQue) { + notification(g); + } + for (const p of properties.ques[Outer].priorityQue) { + notification(p.planID); + } + for (const g of properties.ques[Outer].generalQue) { + notification(g); + } + } +} +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerHandlers.ts b/src/model/stagePlanner/stagePlannerHandlers.ts new file mode 100644 index 00000000..00a230e5 --- /dev/null +++ b/src/model/stagePlanner/stagePlannerHandlers.ts @@ -0,0 +1,89 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Handlers model file. +This file defines all variant handler functionality required for a Muxified Subject. Working with selectors and the +ability to alter different plans and their stage options. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { KeyedSelector } from '../selector/selector.type'; +import { select } from '../selector/'; +import { dispatchOptions, MuxifiedSubjectProperties, Plan } from './stagePlanner.type'; + +// Token to denote ALL, using a selector that utilizes this token should return undefined +const ALL = '*4||*'; + +export function handleAddSelector(properties: MuxifiedSubjectProperties, selectors: KeyedSelector[], id: number) { + if (selectors.length === 0) { + const ALL_SELECTOR = select.createConceptKeyedSelector(ALL, ALL); + addSelector(properties, ALL_SELECTOR, id); + } + selectors.forEach(selector => addSelector(properties, selector, id)); +} + +export function handleNewStageOptions( + properties: MuxifiedSubjectProperties, + plan: Plan, + options: dispatchOptions, + next: number +): boolean { + let evaluate = false; + if (options.newPriority) { + plan.stages[plan.stage].priority = options.newPriority; + evaluate = true; + } + if (options.newSelectors) { + handleRemoveSelector(properties, plan.stages[plan.stage].selectors, plan.id); + plan.stages[plan.stage].selectors = options.newSelectors; + handleAddSelector(properties, plan.stages[plan.stage].selectors, plan.id); + evaluate = true; + } + if (options.newBeat) { + plan.stages[plan.stage].beat = options.newBeat; + if (next === -1) { + plan.beat = options.newBeat; + } + evaluate = true; + } + return evaluate; +} + +export function handleSetStageOptions(plan: Plan, options: dispatchOptions) { + if (options.setStageSelectors && plan.stages[options.setStageSelectors.stage]) { + plan.stages[options.setStageSelectors.stage].selectors = options.setStageSelectors.selectors; + } + if (options.setStagePriority && plan.stages[options.setStagePriority.stage]) { + plan.stages[options.setStagePriority.stage].priority = options.setStagePriority.priority; + } + if (options.setStageBeat && plan.stages[options.setStageBeat.stage]) { + plan.stages[options.setStageBeat.stage].beat = options.setStageBeat.beat; + } +} + +export function handleRemoveSelector(properties: MuxifiedSubjectProperties, selectors: KeyedSelector[], id: number) { + if (selectors.length === 0) { + const ALL_SELECTOR = select.createConceptKeyedSelector(ALL, ALL); + removeSelector(properties, ALL_SELECTOR, id); + } + selectors.forEach(selector => removeSelector(properties, selector, id)); +} + +export function addSelector(properties: MuxifiedSubjectProperties, selector: KeyedSelector, id: number) { + const s = properties.mappedSelectors.get(selector.keys); + if (s) { + properties.mappedSelectors.set(selector.keys, {selector, ids: [...s.ids, id]}); + } else { + properties.mappedSelectors.set(selector.keys, {selector, ids: [id]}); + } +} + +export function removeSelector(properties: MuxifiedSubjectProperties, selector: KeyedSelector, id: number) { + const s = properties.mappedSelectors.get(selector.keys); + if (s) { + if (s.ids.length - 1 === 0) { + properties.mappedSelectors.delete(selector.keys); + } else { + properties.mappedSelectors.set(selector.keys, {selector, ids: s.ids.filter(idx => idx !== id)}); + } + } +} +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerHelpers.ts b/src/model/stagePlanner/stagePlannerHelpers.ts new file mode 100644 index 00000000..309c6fd6 --- /dev/null +++ b/src/model/stagePlanner/stagePlannerHelpers.ts @@ -0,0 +1,150 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Helpers model file. +This file defines a series of helper functions used internally in a Muxified Subject to ensure smooth +provably terminating operation of a Muxium. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { KeyedSelector } from '../selector/selector.type'; +import { selectSlice } from '../selector/selector'; +import { muxiumSelectOpen } from '../../concepts/muxium/muxium.selector'; +import { ownershipSelectInitialized } from '../../concepts/ownership/ownership.selector'; +import { getMuxiumState, isMuxiumOpen } from '../muxium/muxiumHelpers'; +import { ownershipSetOwnerShipModeTopic } from '../../concepts/ownership/strategies/setOwnerShipMode.strategy'; +import { Action, AnyAction } from '../action/action.type'; +import { dispatchOptions, Plan, Stage, StageDelimiter, Staging } from './stagePlanner.type'; + +export const createPriorityKey = (planId: number, stage: number) => `${planId}${stage}`; +/** + * Used in principle plans that are loaded during muxium initialization + */ +export const stageWaitForOpenThenIterate = (func: () => AnyAction): Staging => (createStage(({concepts, dispatch}) => { + if (isMuxiumOpen(concepts)) { + dispatch(func(), { + iterateStage: true + }); + } +}, { selectors: [muxiumSelectOpen] })); + +export const stageConclude = (): Staging => createStage(({stagePlanner}) => {stagePlanner.conclude();}); + +export const stageWaitForOwnershipThenIterate = + (func: () => Action): Staging => (createStage(({concepts, dispatch}) => { + if (selectSlice(concepts, ownershipSelectInitialized) && getMuxiumState(concepts).lastStrategy === ownershipSetOwnerShipModeTopic) { + dispatch(func(), { + iterateStage: true + }); + } + }, { selectors: [ownershipSelectInitialized] })); +/** + * Helper function to aid readability of composing plans, otherwise you may directly create a Staging Entity, selectors non optional + * @param stage - (concepts, dispatch) => {} + * @param selectors - Array of observed dependencies to execute your stage + * @param priority - Adding this property will change the order in which your plan is notified on each state change + * @param beat - Will fire once, then if informed again within your supplied beat, will fire after such time + * @returns stage: Stage, selectors: KeyedSelector[], priority?: number, beat?: number + */ +export const createStage = ( + stage: Stage, + options?: { selectors?: KeyedSelector[], priority?: number, beat?: number} +): Staging => { + if (options) { + return { + stage, + selectors: options.selectors ? options.selectors : [], + firstRun: true, + priority: options.priority, + beat: options.beat + }; + } else { + return { + stage, + firstRun: true, + selectors: [] + }; + } +}; + +export const handleRun = + (stageDelimiter: StageDelimiter, plan: Plan, action: Action, options?: dispatchOptions) + : [StageDelimiter, boolean] => { + if (options?.runOnce) { + const stageRunner = stageDelimiter.runOnceMap.get(action.type + plan.stage); + if (stageRunner === undefined) { + stageDelimiter.runOnceMap.set(action.type + plan.stage, true); + return [ + stageDelimiter, true + ]; + } else { + stageDelimiter.runOnceMap.set(action.type + plan.stage, false); + return [ + stageDelimiter, false + ]; + } + } + return [ + stageDelimiter, + true + ]; + }; + +export const handleStageDelimiter = + (plan: Plan, action: Action, delimiter?: StageDelimiter, options?: dispatchOptions): [StageDelimiter, boolean] => { + let stageDelimiter = delimiter; + let goodAction = true; + if (stageDelimiter && + stageDelimiter.prevActions.includes(action.type) && + options?.throttle === undefined) { + if (plan.stage !== stageDelimiter?.stage) { + stageDelimiter = { + stage: plan.stage, + prevActions: [action.type], + unionExpiration: [action.expiration], + runOnceMap: new Map() + }; + } else { + goodAction = false; + } + } else if (stageDelimiter) { + if (stageDelimiter.prevActions.length > 4) { + stageDelimiter = { + stage: plan.stage, + prevActions: [ + stageDelimiter.prevActions[1], + stageDelimiter.prevActions[2], + stageDelimiter.prevActions[3], + stageDelimiter.prevActions[4], + action.type + ], + unionExpiration: [ + stageDelimiter.unionExpiration[1], + stageDelimiter.unionExpiration[2], + stageDelimiter.unionExpiration[3], + stageDelimiter.unionExpiration[4], + action.expiration + ], + runOnceMap: new Map() + }; + } else { + stageDelimiter = { + stage: plan.stage, + prevActions: [...stageDelimiter.prevActions, action.type], + unionExpiration: [...stageDelimiter.unionExpiration, action.expiration], + runOnceMap: new Map() + }; + } + } else { + stageDelimiter = { + stage: plan.stage, + prevActions: [action.type], + unionExpiration: [action.expiration], + runOnceMap: new Map() + }; + } + return [ + stageDelimiter, + goodAction + ]; + }; + +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerPlan.ts b/src/model/stagePlanner/stagePlannerPlan.ts new file mode 100644 index 00000000..41faa721 --- /dev/null +++ b/src/model/stagePlanner/stagePlannerPlan.ts @@ -0,0 +1,143 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Plan model file. +This file defines how a Muxified Subject creates and manages plans within its Scope. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { Concepts } from '../concept/concept.type'; +import { BundledSelectors, KeyedSelector } from '../selector/selector.type'; +import { muxiumTimeOut } from '../time'; +import { Comparators } from '../interface'; +import { accessDeck } from '../deck'; +import { Actions } from '../action/action.type'; +import { createAction } from '../action/action'; +import { MuxifiedSubjectProperties, Plan, Planner, StagePlanner, Staging } from './stagePlanner.type'; +import { createStage, stageConclude, stageWaitForOpenThenIterate } from './stagePlannerHelpers'; +import { handleAddSelector, handleRemoveSelector } from './stagePlannerHandlers'; +import { manageQues } from './stagePlannerQues'; +import { execute } from './stagePlannerEntropy'; + +export function createPlan( + properties: MuxifiedSubjectProperties, + title: string, + planner: Planner, + space: number, + conceptSemaphore: number +): Plan { + const stages = planner({ + d__: accessDeck(properties.concepts), + e__: properties.concepts[conceptSemaphore].actions as Actions, + c__: properties.concepts[conceptSemaphore].comparators as Comparators, + k__: { + ...properties.concepts[conceptSemaphore].keyedSelectors, + ...properties.concepts[conceptSemaphore].selectors, + } as BundledSelectors, + stage: createStage, + stageO: stageWaitForOpenThenIterate, + conclude: stageConclude + }); + const staged: Staging[] = stages.map>(s => { + return { + stage: s.stage, + selectors: s.selectors ? s.selectors : [], + firstRun: true, + priority: s.priority, + beat: s.beat + }; + }); + + const planId = properties.planId; + properties.planId += 1; + const beat = staged[0].beat; + const plan = { + id: planId, + space, + conceptSemaphore, + conceptName: properties.concepts[conceptSemaphore].name, + title, + stages: staged, + stage: 0, + stageFailed: -1, + beat: beat ? beat : -1, + offBeat: -1, + timer: [], + changeAggregator: {} + }; + return plan; +} + +export function initPlan( + properties: MuxifiedSubjectProperties, + plan: Plan, + next: (concepts: Concepts, keyedSelectors?: KeyedSelector[]) => void +): StagePlanner { + properties.currentPlans.set(plan.id, plan); + handleAddSelector(properties, plan.stages[plan.stage].selectors, plan.id); + manageQues(properties); + const conclude = () => { + deletePlan(properties, plan.id); + }; + muxiumTimeOut(properties.concepts, () => { + next(properties.concepts); + return createAction('Conclude'); + }, 0); + return { + title: plan.title, + planId: plan.id, + conclude: conclude + }; +} + +export function deletePlan(properties: MuxifiedSubjectProperties, planId: number) { + const plan = properties.currentPlans.get(planId); + if (plan) { + plan.timer.forEach(timer => clearTimeout(timer)); + plan.timer = []; + properties.currentPlans.delete(planId); + const selectors = plan.stages[plan.stage]?.selectors; + if (selectors) { + handleRemoveSelector(properties, selectors, plan.id); + } + manageQues(properties); + } + return plan; +} + +export function nextPlans(properties: MuxifiedSubjectProperties) { + properties.currentPlans.forEach(plan => { + nextPlan(properties, plan, []); + }); +} + +export function nextPlan(properties: MuxifiedSubjectProperties, plan: Plan, changes: KeyedSelector[]) { + const index = plan.stage; + if (index < plan.stages.length) { + if (plan.beat > -1) { + const timer = plan.timer; + const now = Date.now(); + if (plan.offBeat < now) { + plan.offBeat = Date.now() + plan.beat; + execute(properties, plan, index, changes); + } else if (timer.length === 0 && plan.offBeat > now) { + // Logic to push changes into aggregator + changes.forEach(key => { + plan.changeAggregator[key.keys] = key; + }); + timer.push(setTimeout(() => { + const changeAggregation = Object.keys(plan.changeAggregator).map(k => plan.changeAggregator[k]); + plan.changeAggregator = {}; + plan.timer = []; + plan.offBeat = Date.now() + plan.beat; + execute(properties, plan, index, changeAggregation); + }, plan.offBeat - Date.now())); + } else { + changes.forEach(key => { + plan.changeAggregator[key.keys] = key; + }); + } + } else { + execute(properties, plan, index, changes); + } + } +} +/*#>*/ \ No newline at end of file diff --git a/src/model/stagePlanner/stagePlannerQues.ts b/src/model/stagePlanner/stagePlannerQues.ts new file mode 100644 index 00000000..785c2b91 --- /dev/null +++ b/src/model/stagePlanner/stagePlannerQues.ts @@ -0,0 +1,203 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, define the Stage Planner Que model file. +This file defines helper functions that handle the shortest path of notification within a Muxium and its +varying points of observation. Allowing for a Muxified Subject to be both General and Specific with its +notifications. Using generalities as a fallback for developer experience. +$>*/ +/*<#*/ +/* eslint-disable complexity */ +import { createConceptKeyedSelector } from '../selector/selector'; +import { KeyedSelector } from '../selector/selector.type'; +import { MuxifiedSubjectProperties } from './stagePlanner.type'; +import { createPriorityKey } from './stagePlannerHelpers'; + +const Inner = 0; +const Base = 1; +const Outer = 2; + +// Token to denote ALL, using a selector that utilizes this token should return undefined +const ALL = '*4||*'; + +export function updateFrequencyMap(properties: MuxifiedSubjectProperties) { + const que = properties.priorityQue; + const map: typeof properties.frequencyMap = new Map(); + + que.forEach(plan => { + plan.selectors.forEach(selector => { + const frequency = map.get(selector.keys); + if (frequency) { + map.set(selector.keys, frequency + plan.priority); + } else { + map.set(selector.keys, plan.priority); + } + }); + }); + + properties.frequencyMap = map; +} + +export function assemblePriorityQue(properties: MuxifiedSubjectProperties) { + let prioritize = false; + const priorityMap: typeof properties.priorityExists = new Map(); + const newList: { + inner: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], + base: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[], + outer: {planID: number, priority: number, stage: number, selectors: KeyedSelector[]}[] + } = { + inner: [], + base: [], + outer: [] + }; + for (const [_, plan] of properties.currentPlans) { + const stage = plan.stages[plan.stage]; + const priority = stage.priority; + if (priority) { + prioritize = true; + const key = createPriorityKey(plan.id, plan.stage); + const selectors = plan.stages[plan.stage].selectors; + priorityMap.set(key, true); + const entry = { + planID: plan.id, + priority, + stage: plan.stage, + selectors, + }; + switch (plan.space) { + case Inner: { + newList.inner.push(entry); + break; + } + case Base: { + newList.base.push(entry); + break; + } + case Outer: { + newList.outer.push(entry); + break; + } + default: { + // + } + } + properties.priorityExists.set(key, true); + } + } + if (!prioritize) { + properties.ques[Inner].priorityQue = []; + properties.ques[Base].priorityQue = []; + properties.ques[Outer].priorityQue = []; + } else { + properties.ques[Inner].priorityQue = newList.inner.sort((a, b) => b.priority - a.priority); + properties.ques[Base].priorityQue = newList.base.sort((a, b) => b.priority - a.priority); + properties.ques[Outer].priorityQue = newList.outer.sort((a, b) => b.priority - a.priority); + } + // properties will cause an issue + properties.priorityExists = priorityMap; + updateFrequencyMap(properties); +} + +export function assembleGeneralQues(properties: MuxifiedSubjectProperties) { + const generalMap: { + inner: Map + base: Map + outer: Map + } = { + inner: new Map(), + base: new Map(), + outer: new Map() + }; + for (const [_, plan] of properties.currentPlans) { + // let map = generalMap; + const stage = plan.stages[plan.stage]; + const priority = stage.priority; + let target = generalMap.inner; + switch (plan.space) { + case Base: { + target = generalMap.base; + break; + } + case Outer: { + target = generalMap.outer; + break; + } + default: { + // + } + } + if (priority === undefined) { + const prepareMap = (selector: KeyedSelector) => { + const entry = target.get(selector.keys); + const frequency = properties.frequencyMap.get(selector.keys); + if (entry) { + entry.planIDs.push(plan.id); + } else if (frequency) { + target.set(selector.keys, { + planIDs: [plan.id], + priorityAggregate: frequency, + selector: selector + }); + } else { + target.set(selector.keys, { + planIDs: [plan.id], + priorityAggregate: 0, + selector: selector + }); + } + }; + if (stage.selectors.length === 0) { + prepareMap(createConceptKeyedSelector(ALL, ALL)); + } else { + for (const selector of stage.selectors) { + prepareMap(selector); + } + } + } + } + const generalIdMap: { + inner: Map + base: Map + outer: Map + } = { + inner: new Map(), + base: new Map(), + outer: new Map() + }; + const handleSlice = (slice: {selector: KeyedSelector, planIDs: number[], priorityAggregate: number}, map: Map) => { + slice.planIDs.forEach(id => { + const priority = map.get(id); + if (priority) { + map.set(id, priority + slice.priorityAggregate); + } else { + map.set(id, slice.priorityAggregate); + } + }); + }; + generalMap.inner.forEach((slice) => { + handleSlice(slice, generalIdMap.inner); + }); + generalMap.base.forEach((slice) => { + handleSlice(slice, generalIdMap.base); + }); + generalMap.outer.forEach((slice) => { + handleSlice(slice, generalIdMap.outer); + }); + const flatten = (map: Map) => { + const flat = []; + for (const [id, frequency] of map.entries()) { + flat.push([id, frequency]); + } + flat.sort((a, b) => b[1] - a[1]); + // We should add a selector union + return flat.map(([id, _]) => id); + }; + properties.ques[Inner].generalQue = flatten(generalIdMap.inner); + properties.ques[Base].generalQue = flatten(generalIdMap.base); + properties.ques[Outer].generalQue = flatten(generalIdMap.outer); +} + +export function manageQues(properties: MuxifiedSubjectProperties) { + assemblePriorityQue(properties); + assembleGeneralQues(properties); +} + +/*#>*/ \ No newline at end of file diff --git a/src/model/time.ts b/src/model/time.ts index 2f348905..e125b942 100644 --- a/src/model/time.ts +++ b/src/model/time.ts @@ -4,10 +4,10 @@ This concept muxified into the muxium, manages how the timer functions interact $>*/ /*<#*/ import { MuxiumState } from '../concepts/muxium/muxium.concept'; -import { Action, createAction } from './action'; -import { getMuxiumState, tailWhip } from './muxium'; -import { Concepts } from './concept'; +import { getMuxiumState, tailWhip } from './muxium/muxiumHelpers'; +import { Concepts } from './concept/concept.type'; import { handlePriority, isPriorityValid } from './priority'; +import { Action } from './action/action.type'; // eslint-disable-next-line @typescript-eslint/no-explicit-any const handleTimedRun = (muxiumState: MuxiumState, func: (() => Action)[], timed: number) => { diff --git a/src/test/action.test.ts b/src/test/action.test.ts index 4e1239a2..334ccbba 100644 --- a/src/test/action.test.ts +++ b/src/test/action.test.ts @@ -2,7 +2,7 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure that actions are being created as intended. $>*/ /*<#*/ -import { createAction } from '../model/action'; +import { createAction } from '../model/action/action'; import { counterAdd } from '../concepts/counter/qualities/add.quality'; test('Muxium add Concepts Strategy Test', (done) => { diff --git a/src/test/actionController.test.ts b/src/test/actionController.test.ts index a8679f98..afa2480b 100644 --- a/src/test/actionController.test.ts +++ b/src/test/actionController.test.ts @@ -2,11 +2,11 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure that the ActionController model is working as intended. $>*/ /*<#*/ -import { ActionController, createActionController$ } from '../model/actionController'; import { muxiumLog } from '../concepts/muxium/qualities/log.quality'; import { muxiumBadAction } from '../concepts/muxium/qualities/badAction.quality'; import { Deck } from '../model/deck'; -import { ActionDeck } from '../model/concept'; +import { ActionDeck } from '../model/concept/concept.type'; +import { ActionController, createActionController$ } from '../model/action/actionController'; test('ActionController Expired Test', (done) => { // Using actionCreators directly from Qualities is reserved only for testing, in production use Deck Interface diff --git a/src/test/actions.test.ts b/src/test/actions.test.ts index c5822b62..87aa5912 100644 --- a/src/test/actions.test.ts +++ b/src/test/actions.test.ts @@ -3,10 +3,11 @@ For the asynchronous graph programming framework Stratimux, generate a test that And ensure that the semaphore is being set via the Muxium for the actions created using said qualities. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; +import { muxification } from '../model/muxium/muxium'; import { createQualityCard, createQualityCardWithPayload } from '../model/quality'; -import { Concept, Concepts, createConcept } from '../model/concept'; -import { Actions } from '../model/action'; +import { Concept, Concepts } from '../model/concept/concept.type'; +import { createConcept } from '../model/concept/concept'; +import { Actions } from '../model/action/action.type'; test('Quality Actions', (done) => { const something = createQualityCard({ diff --git a/src/test/addConcepts.test.ts b/src/test/addConcepts.test.ts index 56f58663..9d353fca 100644 --- a/src/test/addConcepts.test.ts +++ b/src/test/addConcepts.test.ts @@ -2,16 +2,17 @@ For the asynchronous graph programming framework Stratimux, generate a test that ensures that the Muxium can add concepts into its conceptual sets. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; -import { select, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { select } from '../model/selector/'; import { CounterState, createCounterConcept, countingStrategy, counterName, CounterDeck } from '../concepts/counter/counter.concept'; import { addConceptsToAddQueThenBlockStrategy } from '../concepts/muxium/strategies/addConcept.strategy'; import { countingTopic } from '../concepts/counter/strategies/counting.strategy'; -import { forEachConcept } from '../model/concept'; +import { forEachConcept } from '../model/concept/conceptHelpers'; import { muxiumSelectOpen } from '../concepts/muxium/muxium.selector'; import { Deck } from '../model/deck'; import { MuxiumDeck } from '../concepts/muxium/muxium.concept'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; test('Muxium add Concepts Strategy Test', (done) => { const muxium = muxification('muxiumAddConceptTest', {}, {logging: true, storeDialog: true, dynamic: true}); @@ -58,7 +59,7 @@ test('Muxium add Concepts Strategy Test', (done) => { console.log('Check for final counting topic', muxiumState.lastStrategy, concepts[1]?.state); if (muxiumState.lastStrategy === countingTopic) { console.log('CHECK CONCEPTS', concepts); - const counter = selectState(concepts, counterName); + const counter = select.state(concepts, counterName); console.log('FINAL COUNT', counter?.count); expect(counter?.count).toBe(1); expect(Object.keys(d).length).toBe(2); diff --git a/src/test/asynchronousRecursion.test.ts b/src/test/asynchronousRecursion.test.ts index baccaa22..ce927e3e 100644 --- a/src/test/asynchronousRecursion.test.ts +++ b/src/test/asynchronousRecursion.test.ts @@ -4,18 +4,16 @@ generate a test to ensure that the strategy consumer function strategyRecurse is $>*/ /*<#*/ import { muxiumSelectLastStrategy, muxiumSelectLastStrategyData, muxiumSelectLastStrategyDialog } from '../concepts/muxium/muxium.selector'; -import { muxiumKick } from '../concepts/muxium/qualities/kick.quality'; import { ExperimentState, createExperimentConcept, createExperimentState, experimentName } from '../concepts/experiment/experiment.concept'; import { experimentRecurseIterateId } from '../concepts/experiment/qualities/recurseIncrementId.quality'; import { experimentRecursivelyIterateId, experimentRecursivelyIterateIdTopic } from '../concepts/experiment/strategies/recursivelyIterateId.strategy'; -import { strategyBegin } from '../model/actionStrategy'; -import { muxification } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; -import { createStage, stageWaitForOpenThenIterate } from '../model/stagePlanner'; -import { Concept } from '../model/concept'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Asynchronous recursion', (done) => { const list = ['This', 'list', 'will', 'deplete', 'to', 'control', 'recursion', 'and', 'be', 'halting', 'complete']; diff --git a/src/test/axiumRegisterTimeOut/axiumRegisterTimeOut.test.ts b/src/test/axiumRegisterTimeOut/axiumRegisterTimeOut.test.ts index a7104339..1975ef53 100644 --- a/src/test/axiumRegisterTimeOut/axiumRegisterTimeOut.test.ts +++ b/src/test/axiumRegisterTimeOut/axiumRegisterTimeOut.test.ts @@ -4,9 +4,9 @@ $>*/ /*<#*/ import { CounterDeck, CounterState, counterName, createCounterConcept } from '../../concepts/counter/counter.concept'; import { counterSelectCount } from '../../concepts/counter/counter.selector'; -import { createAction } from '../../model/action'; -import { muxification } from '../../model/muxium'; -import { selectState } from '../../model/selector'; +import { createAction } from '../../model/action/action'; +import { muxification } from '../../model/muxium/muxium'; +import { selectState } from '../../model/selector/selector'; test('Muxium Register Time Out', (done) => { const muxium = muxification('timeout defer actions', {counter: createCounterConcept()}); diff --git a/src/test/beatSelectorChanges/beatSelectorChanges.concept.ts b/src/test/beatSelectorChanges/beatSelectorChanges.concept.ts index ad4764c2..4c93ab67 100644 --- a/src/test/beatSelectorChanges/beatSelectorChanges.concept.ts +++ b/src/test/beatSelectorChanges/beatSelectorChanges.concept.ts @@ -1,60 +1,61 @@ -/*<$ -For the asynchronous graph programming framework Stratimux generate an Experiment Concept that will be used to test deferred changes -accumulated for stage that has a beat and selectors -$>*/ -/*<#*/ -import { beatSelectorChangesAddToCountOne} from './qualities/addToCountOne.quality'; -import { Concept, createConcept } from '../../model/concept'; -import { beatSelectorChangesAddToCountTwo} from './qualities/addToCountTwo.quality'; -import { beatSelectorChangesAddToCountThree} from './qualities/addToCountThree.quality'; -import { beatSelectorChangesAddToCountFour} from './qualities/addToCountFour.quality'; -import { beatSelectorChangesAddToCountFive} from './qualities/addToCountFive.quality'; -import { beatSelectorChangesAddToCountSix} from './qualities/addToCountSix.quality'; -import { beatSelectorChangesAddToCountSeven } from './qualities/addToCountSeven.quality'; - -export type BeatSelectorChangesState = { - countOne: number - countTwo: number - countThree: number - countFour: number - countFive: number - countSix: number - countSeven: number -} - -export const beatSelectorChangesName = 'beatSelectorChanges'; - -const initialBeatSelectorChangesState: BeatSelectorChangesState = { - countOne: 0, - countTwo: 0, - countThree: 0, - countFour: 0, - countFive: 0, - countSix: 0, - countSeven: 0, -}; - -const beatSelectorChangesQualities = { - beatSelectorChangesAddToCountOne, - beatSelectorChangesAddToCountTwo, - beatSelectorChangesAddToCountThree, - beatSelectorChangesAddToCountFour, - beatSelectorChangesAddToCountFive, - beatSelectorChangesAddToCountSix, - beatSelectorChangesAddToCountSeven, -}; - -export type BeatSelectorChangesQualities = typeof beatSelectorChangesQualities; - -export type BeatSelectorChangesDeck = { - beatSelectors: Concept; -} - -export const createBeatSelectorChangesConcept = () => { - return createConcept( - beatSelectorChangesName, - initialBeatSelectorChangesState, - beatSelectorChangesQualities - ); -}; +/*<$ +For the asynchronous graph programming framework Stratimux generate an Experiment Concept that will be used to test deferred changes +accumulated for stage that has a beat and selectors +$>*/ +/*<#*/ +import { beatSelectorChangesAddToCountOne} from './qualities/addToCountOne.quality'; +import { Concept } from '../../model/concept/concept.type'; +import { createConcept } from '../../model/concept/concept'; +import { beatSelectorChangesAddToCountTwo} from './qualities/addToCountTwo.quality'; +import { beatSelectorChangesAddToCountThree} from './qualities/addToCountThree.quality'; +import { beatSelectorChangesAddToCountFour} from './qualities/addToCountFour.quality'; +import { beatSelectorChangesAddToCountFive} from './qualities/addToCountFive.quality'; +import { beatSelectorChangesAddToCountSix} from './qualities/addToCountSix.quality'; +import { beatSelectorChangesAddToCountSeven } from './qualities/addToCountSeven.quality'; + +export type BeatSelectorChangesState = { + countOne: number + countTwo: number + countThree: number + countFour: number + countFive: number + countSix: number + countSeven: number +} + +export const beatSelectorChangesName = 'beatSelectorChanges'; + +const initialBeatSelectorChangesState: BeatSelectorChangesState = { + countOne: 0, + countTwo: 0, + countThree: 0, + countFour: 0, + countFive: 0, + countSix: 0, + countSeven: 0, +}; + +const beatSelectorChangesQualities = { + beatSelectorChangesAddToCountOne, + beatSelectorChangesAddToCountTwo, + beatSelectorChangesAddToCountThree, + beatSelectorChangesAddToCountFour, + beatSelectorChangesAddToCountFive, + beatSelectorChangesAddToCountSix, + beatSelectorChangesAddToCountSeven, +}; + +export type BeatSelectorChangesQualities = typeof beatSelectorChangesQualities; + +export type BeatSelectorChangesDeck = { + beatSelectors: Concept; +} + +export const createBeatSelectorChangesConcept = () => { + return createConcept( + beatSelectorChangesName, + initialBeatSelectorChangesState, + beatSelectorChangesQualities + ); +}; /*#>*/ \ No newline at end of file diff --git a/src/test/beatSelectorChanges/beatSelectorChanges.selector.ts b/src/test/beatSelectorChanges/beatSelectorChanges.selector.ts index 58da4a26..5b026347 100644 --- a/src/test/beatSelectorChanges/beatSelectorChanges.selector.ts +++ b/src/test/beatSelectorChanges/beatSelectorChanges.selector.ts @@ -1,23 +1,24 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and BeatSelectorChanges Concept, -generate a KeyedSelector for the BeatSelectorChanges's count variants state properties. -$>*/ -/*<#*/ -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; -import { BeatSelectorChangesState } from './beatSelectorChanges.concept'; - -export const beatSelectorChangesSelectCountOne: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countOne'); -export const beatSelectorChangesSelectCountTwo: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countTwo'); -export const beatSelectorChangesSelectCountThree: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countThree'); -export const beatSelectorChangesSelectCountFour: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countFour'); -export const beatSelectorChangesSelectCountFive: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countFive'); -export const beatSelectorChangesSelectCountSix: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countSix'); -export const beatSelectorChangesSelectCountSeven: KeyedSelector = - createConceptKeyedSelector('beatSelectorChanges', 'countSeven'); +/*<$ +For the asynchronous graph programming framework Stratimux and BeatSelectorChanges Concept, +generate a KeyedSelector for the BeatSelectorChanges's count variants state properties. +$>*/ +/*<#*/ +import { createConceptKeyedSelector } from '../../model/selector/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { BeatSelectorChangesState } from './beatSelectorChanges.concept'; + +export const beatSelectorChangesSelectCountOne: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countOne'); +export const beatSelectorChangesSelectCountTwo: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countTwo'); +export const beatSelectorChangesSelectCountThree: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countThree'); +export const beatSelectorChangesSelectCountFour: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countFour'); +export const beatSelectorChangesSelectCountFive: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countFive'); +export const beatSelectorChangesSelectCountSix: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countSix'); +export const beatSelectorChangesSelectCountSeven: KeyedSelector = + createConceptKeyedSelector('beatSelectorChanges', 'countSeven'); /*#>*/ \ No newline at end of file diff --git a/src/test/beatSelectorChanges/beatSelectorChanges.test.ts b/src/test/beatSelectorChanges/beatSelectorChanges.test.ts index 2344853a..1c2ada74 100644 --- a/src/test/beatSelectorChanges/beatSelectorChanges.test.ts +++ b/src/test/beatSelectorChanges/beatSelectorChanges.test.ts @@ -3,12 +3,10 @@ For the asynchronous graph programming framework Stratimux generate a test that utilizing the provided BeatSelectorChanges concept $>*/ /*<#*/ -import { muxification, getMuxiumState, isMuxiumOpen } from '../../model/muxium'; -import { createStage } from '../../model/stagePlanner'; +import { muxification } from '../../model/muxium/muxium'; +import { getMuxiumState, isMuxiumOpen } from '../../model/muxium/muxiumHelpers'; import { generateRandomCountingStrategy } from './strategies/generateCountingStrategy.strategy'; -import { BeatSelectorChangesDeck, beatSelectorChangesName, createBeatSelectorChangesConcept } from './beatSelectorChanges.concept'; -import { initializeTopic } from '../../concepts/muxium/strategies/initialization.strategy'; -import { strategyBegin } from '../../model/actionStrategy'; +import { BeatSelectorChangesDeck, createBeatSelectorChangesConcept } from './beatSelectorChanges.concept'; import { beatSelectorChangesSelectCountFive, beatSelectorChangesSelectCountFour, @@ -18,9 +16,10 @@ import { beatSelectorChangesSelectCountThree, beatSelectorChangesSelectCountTwo } from './beatSelectorChanges.selector'; -import { selectSlice, selectState } from '../../model/selector'; +import { selectSlice } from '../../model/selector/selector'; import { Deck } from '../../model/deck'; import { MuxiumDeck } from '../../concepts/muxium/muxium.concept'; +import { strategyBegin } from '../../model/action/strategy/actionStrategyConsumers'; jest.setTimeout(30000); test('Deferred Beat Selector Changes Test', (done) => { const beat = 7000; @@ -28,15 +27,15 @@ test('Deferred Beat Selector Changes Test', (done) => { beatSelectors: createBeatSelectorChangesConcept() }); const [tally, strategy, topic] = generateRandomCountingStrategy(muxium.deck.d as Deck); - const plan = muxium.plan('Prolonged Counting Strategy', () => [ - createStage(({concepts, dispatch}) => { + const plan = muxium.plan('Prolonged Counting Strategy', ({stage}) => [ + stage(({concepts, dispatch}) => { if (isMuxiumOpen(concepts)) { dispatch(strategyBegin(strategy), { iterateStage: true }); } }), - createStage(({concepts, changes}) => { + stage(({concepts, changes}) => { if (getMuxiumState(concepts).lastStrategy === topic) { expect(selectSlice(concepts, beatSelectorChangesSelectCountOne)).toBe(tally[0]); expect(selectSlice(concepts, beatSelectorChangesSelectCountTwo)).toBe(tally[1]); diff --git a/src/test/beatSelectorChanges/strategies/generateCountingStrategy.strategy.ts b/src/test/beatSelectorChanges/strategies/generateCountingStrategy.strategy.ts index 2ef7609b..a83d7749 100644 --- a/src/test/beatSelectorChanges/strategies/generateCountingStrategy.strategy.ts +++ b/src/test/beatSelectorChanges/strategies/generateCountingStrategy.strategy.ts @@ -3,8 +3,9 @@ For the asynchronous graph programming framework Stratimux generate an ActionStr BeatSelectorChanges count variants for 100 steps. $>*/ /*<#*/ -import { ActionNode, ActionStrategy, createActionNode, createStrategy } from '../../../model/actionStrategy'; import { MuxiumDeck } from '../../../concepts/muxium/muxium.concept'; +import { createActionNode, createStrategy } from '../../../model/action/strategy/actionStrategy'; +import { ActionNode, ActionStrategy } from '../../../model/action/strategy/actionStrategy.type'; import { Deck } from '../../../model/deck'; import { BeatSelectorChangesDeck } from '../beatSelectorChanges.concept'; diff --git a/src/test/chain.test.ts b/src/test/chain.test.ts index 56186a8d..ac1b27b6 100644 --- a/src/test/chain.test.ts +++ b/src/test/chain.test.ts @@ -2,9 +2,9 @@ For the asynchronous graph programming framework Stratimux and Chain Concept, generate a test ensure that chain is working as intended. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; -import { Concepts } from '../model/concept'; -import { selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { Concepts } from '../model/concept/concept.type'; +import { selectState } from '../model/selector/selector'; import { CounterState, createCounterConcept, counterName } from '../concepts/counter/counter.concept'; import { ChainState, chainName, createChainConcept } from '../concepts/chain/chain.concept'; diff --git a/src/test/conceptToString.test.ts b/src/test/conceptToString.test.ts index e6158260..328dcb5c 100644 --- a/src/test/conceptToString.test.ts +++ b/src/test/conceptToString.test.ts @@ -2,9 +2,9 @@ For the asynchronous graph programming framework Stratimux, generate a test that logs how a concept would be parsed to a stream to the console. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; +import { muxification } from '../model/muxium/muxium'; import { createCounterConcept } from '../concepts/counter/counter.concept'; -import { conceptsToString } from '../model/concept'; +import { conceptsToString } from '../model/concept/conceptHelpers'; test('Muxium Counting Strategy Test', (done) => { const muxium = muxification('muxiumStrategyTest', {counter: createCounterConcept()}, {logging: true, storeDialog: true}); diff --git a/src/test/concepts.test.ts b/src/test/concepts.test.ts index 613cbf99..91f26ec9 100644 --- a/src/test/concepts.test.ts +++ b/src/test/concepts.test.ts @@ -4,9 +4,8 @@ generate a test to that ensures the functionality of is concept loaded and are c $>*/ /*<#*/ import { counterName, createCounterConcept } from '../concepts/counter/counter.concept'; -import { muxification } from '../model/muxium'; +import { muxification } from '../model/muxium/muxium'; import { areConceptsLoaded, chainName, createChainConcept, isConceptLoaded } from '../index'; -import { createStage } from '../model/stagePlanner'; test('Concepts exists', (done) => { const muxium = muxification('Mock Muxium', {counter: createCounterConcept()}); diff --git a/src/test/debounceMethods.test.ts b/src/test/debounceMethods.test.ts index f149f38c..d23673b8 100644 --- a/src/test/debounceMethods.test.ts +++ b/src/test/debounceMethods.test.ts @@ -25,11 +25,10 @@ import { experimentDebounceIterateIdThenAddToData, experimentDebounceIterateIdThenAddToDataTopic } from '../concepts/experiment/strategies/debounceIterateIdThenAddToData.strategy'; -import { strategyBegin } from '../model/actionStrategy'; -import { muxification } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; -import { createStage } from '../model/stagePlanner'; -import { concept, Concept } from '../model/concept'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; jest.setTimeout(30000); diff --git a/src/test/methodHelpers.test.ts b/src/test/methodHelpers.test.ts index a3a09bcf..636f15a8 100644 --- a/src/test/methodHelpers.test.ts +++ b/src/test/methodHelpers.test.ts @@ -24,10 +24,10 @@ import { timedMockToTrueWithState, experimentTimedMockToTrueWithStateTopic } from '../concepts/experiment/strategies/timedMockToTrueWithState.strategy'; -import { strategyBegin } from '../model/actionStrategy'; -import { muxification } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; -import { Concept } from '../model/concept'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Async Method Test', (done) => { const qualities = {experimentTimerEmitAction, experimentMockToTrue}; diff --git a/src/test/muxifyConcepts.test.ts b/src/test/muxifyConcepts.test.ts index aa2360d5..ab1e2924 100644 --- a/src/test/muxifyConcepts.test.ts +++ b/src/test/muxifyConcepts.test.ts @@ -1,5 +1,7 @@ -import { createConcept, muxifyConcepts } from '../model/concept'; -import { demuxifyDeck, muxification } from '../model/muxium'; +import { createConcept } from '../model/concept/concept'; +import { muxifyConcepts } from '../model/concept/conceptAdvanced'; +import { demuxifyDeck } from '../model/deck'; +import { muxification } from '../model/muxium/muxium'; import { createQualityCard, defaultReducer } from '../model/quality'; test('Concepts exists', (done) => { diff --git a/src/test/axium.test.ts b/src/test/muxium.test.ts similarity index 81% rename from src/test/axium.test.ts rename to src/test/muxium.test.ts index cd343876..929ca926 100644 --- a/src/test/axium.test.ts +++ b/src/test/muxium.test.ts @@ -5,20 +5,14 @@ $>*/ /*<#*/ import { muxiumSelectLastStrategy } from '../concepts/muxium/muxium.selector'; import { muxium_createStitchNode } from '../concepts/muxium/model/stitch.model'; -import { - ActionStrategy, - ActionStrategyStitch, - createActionNode, - createActionNodeFromStrategy, - createStrategy, - strategyBegin -} from '../model/actionStrategy'; -import { muxification, getMuxiumState } from '../model/muxium'; -import { selectSlice } from '../model/selector'; -import { createStage, stageWaitForOpenThenIterate } from '../model/stagePlanner'; -import { muxiumKick } from '../concepts/muxium/qualities/kick.quality'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice } from '../model/selector/selector'; import { createCounterConcept } from '../concepts/counter/counter.concept'; -import { createAction } from '../model/action'; +import { createAction } from '../model/action/action'; +import { ActionStrategy, ActionStrategyStitch } from '../model/action/strategy/actionStrategy.type'; +import { createActionNode, createActionNodeFromStrategy, createStrategy } from '../model/action/strategy/actionStrategy'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; test('Muxium advanced usage: StrategyStitch', (done) => { const yourStrategyStitch: ActionStrategyStitch = () => { diff --git a/src/test/newPlanOptions/mixedPlanOptions.test.ts b/src/test/newPlanOptions/mixedPlanOptions.test.ts index ac1d2ded..f3ed6b82 100644 --- a/src/test/newPlanOptions/mixedPlanOptions.test.ts +++ b/src/test/newPlanOptions/mixedPlanOptions.test.ts @@ -3,11 +3,9 @@ For the asynchronous graph programming framework Stratimux generate a test that $>*/ /*<#*/ import { createExperimentPlanOptionsConcept } from './newPlanOptions.concept'; -import { muxification } from '../../model/muxium'; -import { selectSlice } from '../../model/selector'; -import { experimentPlanOptionsIsReady } from './qualities/isReady.quality'; -import { experimentPlanOptionsReadySelector } from './newPlanOptions.selector'; -import { muxiumKick } from '../../concepts/muxium/qualities/kick.quality'; +import { muxification } from '../../model/muxium/muxium'; +import { selectSlice } from '../../model/selector/selector'; +import { experimentPlanOptionsReadySelector } from './newPlanOptions.selectors'; test('Mixed Plan Options Test', (done) => { const planMixedPlanOptions = muxification('Plan New Stage Priority Test', { diff --git a/src/test/newPlanOptions/newPlanOptions.concept.ts b/src/test/newPlanOptions/newPlanOptions.concept.ts index 746b79ac..1425a0ae 100644 --- a/src/test/newPlanOptions/newPlanOptions.concept.ts +++ b/src/test/newPlanOptions/newPlanOptions.concept.ts @@ -1,42 +1,48 @@ -import { createExperimentConcept } from '../../concepts/experiment/experiment.concept'; -import { experimentPlanOptionsAddValue } from './qualities/addValue.quality'; -import { experimentPlanOptionsIsReady } from './qualities/isReady.quality'; -import { experimentToggleAllSeven } from './qualities/toggleAllSeven.quality'; - -export type ExperimentPlanOptionsState = { - value: number; - ready: boolean; - one: boolean; - two: boolean; - three: boolean; - four: boolean; - five: boolean; - six: boolean; - seven: boolean; -} - -export const createExperimentPlanOptionsState = (): ExperimentPlanOptionsState => ({ - value: 0, - ready: false, - one: false, - two: false, - three: false, - four: false, - five: false, - six: false, - seven: false -}); - -const experimentPlanOptionsQualities = { - experimentToggleAllSeven, - experimentPlanOptionsAddValue, - experimentPlanOptionsIsReady -}; - -export type ExperimentPlanOptionsQualities = typeof experimentPlanOptionsQualities; - -export const createExperimentPlanOptionsConcept = () => createExperimentConcept( - createExperimentPlanOptionsState(), - experimentPlanOptionsQualities, - [] -); \ No newline at end of file +/*<$ +For the asynchronous graph programming framework Stratimux generate an Experiment Concept that will be used to test +the ability to change plan options at runtime. +$>*/ +/*<#*/ +import { createExperimentConcept } from '../../concepts/experiment/experiment.concept'; +import { experimentPlanOptionsAddValue } from './qualities/addValue.quality'; +import { experimentPlanOptionsIsReady } from './qualities/isReady.quality'; +import { experimentToggleAllSeven } from './qualities/toggleAllSeven.quality'; + +export type ExperimentPlanOptionsState = { + value: number; + ready: boolean; + one: boolean; + two: boolean; + three: boolean; + four: boolean; + five: boolean; + six: boolean; + seven: boolean; +} + +export const createExperimentPlanOptionsState = (): ExperimentPlanOptionsState => ({ + value: 0, + ready: false, + one: false, + two: false, + three: false, + four: false, + five: false, + six: false, + seven: false +}); + +const experimentPlanOptionsQualities = { + experimentToggleAllSeven, + experimentPlanOptionsAddValue, + experimentPlanOptionsIsReady +}; + +export type ExperimentPlanOptionsQualities = typeof experimentPlanOptionsQualities; + +export const createExperimentPlanOptionsConcept = () => createExperimentConcept( + createExperimentPlanOptionsState(), + experimentPlanOptionsQualities, + [] +); +/*#>*/ \ No newline at end of file diff --git a/src/test/newPlanOptions/newPlanOptions.selector.ts b/src/test/newPlanOptions/newPlanOptions.selector.ts deleted file mode 100644 index 9bd914b7..00000000 --- a/src/test/newPlanOptions/newPlanOptions.selector.ts +++ /dev/null @@ -1,14 +0,0 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and a Experiment PlanOptions Concept, generate both possible selectors -$>*/ -/*<#*/ -import { experimentName } from '../../concepts/experiment/experiment.concept'; -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; -import { ExperimentPlanOptionsState } from './newPlanOptions.concept'; - -export const experimentPlanOptionsReadySelector: KeyedSelector = - createConceptKeyedSelector(experimentName, 'ready'); - -export const experimentPlanOptionsValueSelector: KeyedSelector = - createConceptKeyedSelector(experimentName, 'value'); -/*#>*/ \ No newline at end of file diff --git a/src/test/newPlanOptions/newPlanOptions.selectors.ts b/src/test/newPlanOptions/newPlanOptions.selectors.ts index 3f91dbb7..c614eae9 100644 --- a/src/test/newPlanOptions/newPlanOptions.selectors.ts +++ b/src/test/newPlanOptions/newPlanOptions.selectors.ts @@ -1,27 +1,40 @@ -import { experimentName } from '../../concepts/experiment/experiment.concept'; -import { select } from '../../model/selector'; -import { ExperimentPlanOptionsState } from './newPlanOptions.concept'; - -const experimentSelectOne = select.createConceptKeyedSelector(experimentName, 'one'); - -const experimentSelectTwo = select.createConceptKeyedSelector(experimentName, 'two'); - -const experimentSelectThree = select.createConceptKeyedSelector(experimentName, 'three'); - -const experimentSelectFour = select.createConceptKeyedSelector(experimentName, 'four'); - -const experimentSelectFive = select.createConceptKeyedSelector(experimentName, 'five'); - -const experimentSelectSix = select.createConceptKeyedSelector(experimentName, 'six'); - -const experimentSelectSeven = select.createConceptKeyedSelector(experimentName, 'seven'); - -export const planOptionsSelect = { - one: experimentSelectOne, - two: experimentSelectTwo, - three: experimentSelectThree, - four: experimentSelectFour, - five: experimentSelectFive, - six: experimentSelectSix, - seven: experimentSelectSeven -}; +/*<$ +For the asynchronous graph programming framework Stratimux and a Experiment PlanOptions Concept, generate the possible selectors based on +the state declared in the concept file. +$>*/ +/*<#*/ +import { experimentName } from '../../concepts/experiment/experiment.concept'; +import { select } from '../../model/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { ExperimentPlanOptionsState } from './newPlanOptions.concept'; + +export const experimentPlanOptionsReadySelector: KeyedSelector = + select.createConceptKeyedSelector(experimentName, 'ready'); + +export const experimentPlanOptionsValueSelector: KeyedSelector = + select.createConceptKeyedSelector(experimentName, 'value'); + +const experimentSelectOne = select.createConceptKeyedSelector(experimentName, 'one'); + +const experimentSelectTwo = select.createConceptKeyedSelector(experimentName, 'two'); + +const experimentSelectThree = select.createConceptKeyedSelector(experimentName, 'three'); + +const experimentSelectFour = select.createConceptKeyedSelector(experimentName, 'four'); + +const experimentSelectFive = select.createConceptKeyedSelector(experimentName, 'five'); + +const experimentSelectSix = select.createConceptKeyedSelector(experimentName, 'six'); + +const experimentSelectSeven = select.createConceptKeyedSelector(experimentName, 'seven'); + +export const planOptionsSelect = { + one: experimentSelectOne, + two: experimentSelectTwo, + three: experimentSelectThree, + four: experimentSelectFour, + five: experimentSelectFive, + six: experimentSelectSix, + seven: experimentSelectSeven +}; +/*#>*/ \ No newline at end of file diff --git a/src/test/newPlanOptions/newPlanOptions.test.ts b/src/test/newPlanOptions/newPlanOptions.test.ts index 25280282..141b0300 100644 --- a/src/test/newPlanOptions/newPlanOptions.test.ts +++ b/src/test/newPlanOptions/newPlanOptions.test.ts @@ -4,11 +4,11 @@ test to ensure that they can change the priority of their stages and again for b $>*/ /*<#*/ import { createExperimentPlanOptionsConcept } from './newPlanOptions.concept'; -import { muxification } from '../../model/muxium'; -import { createStage } from '../../model/stagePlanner'; -import { KeyedSelector, selectSlice } from '../../model/selector'; -import { planOptionsSelect } from './newPlanOptions.selectors'; -import { experimentPlanOptionsReadySelector } from './newPlanOptions.selector'; +import { muxification } from '../../model/muxium/muxium'; +import { createStage } from '../../model/stagePlanner/stagePlannerHelpers'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { selectSlice } from '../../model/selector/selector'; +import { experimentPlanOptionsReadySelector, planOptionsSelect } from './newPlanOptions.selectors'; test('New Plan Options Selector Test', (done) => { const planNewStageSelectors = muxification('Plan New Stage Selectors Test', { diff --git a/src/test/newPlanOptions/prioritizedPlanSelectors.test.ts b/src/test/newPlanOptions/prioritizedPlanSelectors.test.ts index 7fb7e416..6dbac5e5 100644 --- a/src/test/newPlanOptions/prioritizedPlanSelectors.test.ts +++ b/src/test/newPlanOptions/prioritizedPlanSelectors.test.ts @@ -3,13 +3,12 @@ For the asynchronous graph programming framework Stratimux generate a test that $>*/ /*<#*/ import { createExperimentPlanOptionsConcept } from './newPlanOptions.concept'; -import { muxification, getMuxiumState } from '../../model/muxium'; -import { createStage } from '../../model/stagePlanner'; -import { selectSlice } from '../../model/selector'; -import { experimentPlanOptionsIsReady } from './qualities/isReady.quality'; -import { muxiumKick } from '../../concepts/muxium/qualities/kick.quality'; +import { muxification } from '../../model/muxium/muxium'; +import { selectSlice } from '../../model/selector/selector'; import { muxiumSelectOpen } from '../../concepts/muxium/muxium.selector'; + jest.setTimeout(30000); + test('prioritized plans with selectors Test', (done) => { const planPrioritizedSelectors = muxification('Plan New Stage Priority Test', { experiment: createExperimentPlanOptionsConcept() diff --git a/src/test/newPlanOptions/qualities/addValue.quality.ts b/src/test/newPlanOptions/qualities/addValue.quality.ts index fc4dc63b..2ff37dd5 100644 --- a/src/test/newPlanOptions/qualities/addValue.quality.ts +++ b/src/test/newPlanOptions/qualities/addValue.quality.ts @@ -1,30 +1,27 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will Add a value property from -the incoming action's payload -$>*/ -/*<#*/ -import { ExperimentState } from '../../../concepts/experiment/experiment.concept'; -import { Action } from '../../../model/action'; -import { quality } from '../../../model/quality'; -import { select } from '../../../model/selector'; -import { ExperimentPlanOptionsState } from '../newPlanOptions.concept'; - -export type ExperimentPlanOptionsAddValuePayload = { - newValue: number -}; - -export const experimentPlanOptionsAddValue = - quality.createWithPayload({ - type: 'experimentPlanOptions Add value', - reducer: (state, action) => { - const { newValue } = action.payload; - if (newValue) { - return { - value: newValue + state.value - }; - } - return { - }; - }, - }); +/*<$ +For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will Add a value property from +the incoming action's payload +$>*/ +/*<#*/ +import { quality } from '../../../model/quality'; +import { ExperimentPlanOptionsState } from '../newPlanOptions.concept'; + +export type ExperimentPlanOptionsAddValuePayload = { + newValue: number +}; + +export const experimentPlanOptionsAddValue = + quality.createWithPayload({ + type: 'experimentPlanOptions Add value', + reducer: (state, action) => { + const { newValue } = action.payload; + if (newValue) { + return { + value: newValue + state.value + }; + } + return { + }; + }, + }); /*#>*/ \ No newline at end of file diff --git a/src/test/newPlanOptions/qualities/isReady.quality.ts b/src/test/newPlanOptions/qualities/isReady.quality.ts index 3116bb8d..1a0015b0 100644 --- a/src/test/newPlanOptions/qualities/isReady.quality.ts +++ b/src/test/newPlanOptions/qualities/isReady.quality.ts @@ -1,15 +1,14 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will set a ready property to true -$>*/ -/*<#*/ -import { Action } from '../../../model/action'; -import { quality } from '../../../model/quality'; -import { ExperimentPlanOptionsState } from '../newPlanOptions.concept'; - -export const experimentPlanOptionsIsReady = quality.create({ - type: 'experimentPlanOptions is ready', - reducer: () => ({ - ready: true - }), -}); +/*<$ +For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will set a ready property to true +$>*/ +/*<#*/ +import { quality } from '../../../model/quality'; +import { ExperimentPlanOptionsState } from '../newPlanOptions.concept'; + +export const experimentPlanOptionsIsReady = quality.create({ + type: 'experimentPlanOptions is ready', + reducer: () => ({ + ready: true + }), +}); /*#>*/ \ No newline at end of file diff --git a/src/test/onChange.test.ts b/src/test/onChange.test.ts index 1894477f..82d1ba19 100644 --- a/src/test/onChange.test.ts +++ b/src/test/onChange.test.ts @@ -3,17 +3,18 @@ For the asynchronous graph programming framework Stratimux, generate a test that In addition utilize the onChange detection feature for the MuxifiedSubject is working as intended. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; -import { selectSlice, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; import { CounterState, createCounterConcept, countingStrategy, counterName, CounterDeck } from '../concepts/counter/counter.concept'; import { countingTopic } from '../concepts/counter/strategies/counting.strategy'; import { muxiumSelectLastStrategy } from '../concepts/muxium/muxium.selector'; import { initializeTopic } from '../concepts/muxium/strategies/initialization.strategy'; -import { Concepts } from '../model/concept'; +import { Concepts } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; test('Muxium onChange Test', (done) => { - const selectorRouter = { + const selectorRouter: Record = { [muxiumSelectLastStrategy.keys]: (concepts: Concepts) => console.log('CHECK: ', selectSlice(concepts, muxiumSelectLastStrategy)) }; diff --git a/src/test/origin.test.ts b/src/test/origin.test.ts index d825550f..e5840e0f 100644 --- a/src/test/origin.test.ts +++ b/src/test/origin.test.ts @@ -3,14 +3,15 @@ For the asynchronous graph programming framework Stratimux, generate a test to e $>*/ /*<#*/ import { counterAdd } from '../concepts/counter/qualities/add.quality'; -import { muxification, createOrigin, getMuxiumState } from '../model/muxium'; +import { createOrigin, getMuxiumState } from '../model/muxium/muxiumHelpers'; +import { muxification } from '../model/muxium/muxium'; import { createExperimentConcept, experimentName } from '../concepts/experiment/experiment.concept'; -import { CounterDeck, CounterState } from '../concepts/counter/counter.concept'; +import { CounterState } from '../concepts/counter/counter.concept'; import { counterSetCount } from '../concepts/counter/qualities/setCount.quality'; -import { selectState } from '../model/selector'; +import { selectState } from '../model/selector/selector'; import { PrincipleFunction } from '../model/principle'; import { MuxiumDeck } from '../concepts/muxium/muxium.concept'; -import { Concept } from '../model/concept'; +import { Concept } from '../model/concept/concept.type'; test('Origin Creation', (done) => { expect(createOrigin(['one'])).toBe('one'); diff --git a/src/test/ownership.test.ts b/src/test/ownership.test.ts index 2553db8a..340376c9 100644 --- a/src/test/ownership.test.ts +++ b/src/test/ownership.test.ts @@ -2,26 +2,24 @@ For the asynchronous graph programming framework Stratimux and Ownership Concept, devise a test that will ensure that the concept is working as intended. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { ConceptDeck, Concepts } from '../model/concept'; -import { selectConcept, selectState } from '../model/selector'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; +import { muxification } from '../model/muxium/muxium'; +import { Concepts } from '../model/concept/concept.type'; +import { selectConcept, selectState } from '../model/selector/selector'; import { OwnershipState, createOwnershipConcept, ownershipName } from '../concepts/ownership/ownership.concept'; -import { MuxiumState } from '../concepts/muxium/muxium.concept'; import { ownershipSetOwnerShipModeTopic } from '../concepts/ownership/strategies/setOwnerShipMode.strategy'; import { CounterState, counterName, createCounterConcept } from '../concepts/counter/counter.concept'; import { createExperimentState, createExperimentConcept } from '../concepts/experiment/experiment.concept'; import { experimentPuntCountingStrategy } from '../concepts/experiment/strategies/puntCounting.strategy'; -import { strategyBegin } from '../model/actionStrategy'; import { ExperimentCountingDeck, experimentCountingStrategy, experimentCountingTopic, } from '../concepts/experiment/strategies/experimentCounting.strategy'; -import { muxiumLog } from '../concepts/muxium/qualities/log.quality'; -import { counterSetCount } from '../concepts/counter/qualities/setCount.quality'; import { experimentCheckInStrategy } from '../concepts/experiment/qualities/checkInStrategy.quality'; import { experimentActionQuePrincipleCreator } from '../concepts/experiment/experiment.principle'; import { additionalCountingStrategyTopic } from '../concepts/counter/strategies/counting.strategy'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Ownership Test', (done) => { const orderOfTopics: string[] = []; diff --git a/src/test/priority/priority.selector.ts b/src/test/priority/priority.selector.ts index 7126cf64..bc4f6207 100644 --- a/src/test/priority/priority.selector.ts +++ b/src/test/priority/priority.selector.ts @@ -1,13 +1,14 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and a Experiment Priority Concept, generate both possible selectors -$>*/ -/*<#*/ -import { experimentName } from '../../concepts/experiment/experiment.concept'; -import { KeyedSelector, createConceptKeyedSelector } from '../../model/selector'; -import { ExperimentPriorityState } from './priority.concept'; - -export const experimentPriorityReadySelector: KeyedSelector = createConceptKeyedSelector(experimentName, 'ready'); - -export const experimentPriorityValueSelector: KeyedSelector = createConceptKeyedSelector(experimentName, 'value'); - +/*<$ +For the asynchronous graph programming framework Stratimux and a Experiment Priority Concept, generate both possible selectors +$>*/ +/*<#*/ +import { experimentName } from '../../concepts/experiment/experiment.concept'; +import { createConceptKeyedSelector } from '../../model/selector/selector'; +import { KeyedSelector } from '../../model/selector/selector.type'; +import { ExperimentPriorityState } from './priority.concept'; + +export const experimentPriorityReadySelector: KeyedSelector = createConceptKeyedSelector(experimentName, 'ready'); + +export const experimentPriorityValueSelector: KeyedSelector = createConceptKeyedSelector(experimentName, 'value'); + /*#>*/ \ No newline at end of file diff --git a/src/test/priority/priority.test.ts b/src/test/priority/priority.test.ts index c6c98eae..ff0a7f5a 100644 --- a/src/test/priority/priority.test.ts +++ b/src/test/priority/priority.test.ts @@ -6,9 +6,9 @@ $>*/ import { MuxiumDeck, MuxiumState } from '../../concepts/muxium/muxium.concept'; import { MuxiumQualities } from '../../concepts/muxium/qualities'; import { experimentName } from '../../concepts/experiment/experiment.concept'; -import { muxification } from '../../model/muxium'; -import { select } from '../../model/selector'; -import { createStage } from '../../model/stagePlanner'; +import { muxification } from '../../model/muxium/muxium'; +import { select } from '../../model/selector/'; +import { createStage } from '../../model/stagePlanner/stagePlannerHelpers'; import { ExperimentPriorityState, createExperimentPriorityConcept } from './priority.concept'; import { experimentPriorityReadySelector, experimentPriorityValueSelector } from './priority.selector'; diff --git a/src/test/priority/priorityAction.test.ts b/src/test/priority/priorityAction.test.ts index 3f182b0a..689fd94c 100644 --- a/src/test/priority/priorityAction.test.ts +++ b/src/test/priority/priorityAction.test.ts @@ -4,18 +4,17 @@ is managing plan notifications as intended. $>*/ /*<#*/ import { experimentName } from '../../concepts/experiment/experiment.concept'; -import { muxification, getMuxiumState } from '../../model/muxium'; -import { select, selectPayload, selectState } from '../../model/selector'; -import { StagePlanner, createStage } from '../../model/stagePlanner'; +import { muxification } from '../../model/muxium/muxium'; +import { getMuxiumState } from '../../model/muxium/muxiumHelpers'; +import { select } from '../../model/selector/'; import { ExperimentPriorityState, createExperimentPriorityConcept } from './priority.concept'; import { experimentPriorityReadySelector, experimentPriorityValueSelector } from './priority.selector'; -import { experimentPriorityIsReady } from './qualities/isReady.quality'; -import { experimentPriorityAddValue } from './qualities/addValue.quality'; import { handlePriority } from '../../model/priority'; import { CounterState, counterName, createCounterConcept } from '../../concepts/counter/counter.concept'; import { counterSetCount } from '../../concepts/counter/qualities/setCount.quality'; import { MuxiumDeck, MuxiumState } from '../../concepts/muxium/muxium.concept'; import { MuxiumQualities } from '../../concepts/muxium/qualities'; +import { createStage } from '../../model/stagePlanner/stagePlannerHelpers'; test('Priority Action Test', (done) => { console.log('Priority Test'); @@ -147,10 +146,10 @@ test('Priority Action Manual Test', (done) => { handlePriority(muxiumState, two); handlePriority(muxiumState, three); handlePriority(muxiumState, four); - expect(selectPayload(body[0]).newCount).toBe(selectPayload(one).newCount); - expect(selectPayload(body[1]).newCount).toBe(selectPayload(three).newCount); - expect(selectPayload(body[2]).newCount).toBe(selectPayload(two).newCount); - expect(selectPayload(body[3]).newCount).toBe(selectPayload(four).newCount); + expect(select.payload(body[0]).newCount).toBe(select.payload(one).newCount); + expect(select.payload(body[1]).newCount).toBe(select.payload(three).newCount); + expect(select.payload(body[2]).newCount).toBe(select.payload(two).newCount); + expect(select.payload(body[3]).newCount).toBe(select.payload(four).newCount); expect(body[4].type).toBe(kick.type); done(); }); @@ -191,10 +190,10 @@ test('Priority Action Close Test', (done) => { handlePriority(muxiumState, two); handlePriority(muxiumState, three); handlePriority(muxiumState, four); - expect(selectPayload(body[0]).newCount).toBe(selectPayload(one).newCount); - expect(selectPayload(body[1]).newCount).toBe(selectPayload(three).newCount); - expect(selectPayload(body[2]).newCount).toBe(selectPayload(two).newCount); - expect(selectPayload(body[3]).newCount).toBe(selectPayload(four).newCount); + expect(select.payload(body[0]).newCount).toBe(select.payload(one).newCount); + expect(select.payload(body[1]).newCount).toBe(select.payload(three).newCount); + expect(select.payload(body[2]).newCount).toBe(select.payload(two).newCount); + expect(select.payload(body[3]).newCount).toBe(select.payload(four).newCount); expect(body[4].type).toBe(kick.type); let dispatched = false; muxium.subscribe(cpts => { @@ -206,7 +205,7 @@ test('Priority Action Close Test', (done) => { preClose.priority = 100000; muxium.dispatch(preClose); } - expect(selectState(cpts, counterName)?.count).toBe(0); + expect(select.state(cpts, counterName)?.count).toBe(0); if (!dispatched) { setTimeout(() => { done(); diff --git a/src/test/priority/qualities/addValue.quality.ts b/src/test/priority/qualities/addValue.quality.ts index 912b02cf..99c82d7e 100644 --- a/src/test/priority/qualities/addValue.quality.ts +++ b/src/test/priority/qualities/addValue.quality.ts @@ -1,28 +1,26 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will Add a value property from -the incoming action's payload -$>*/ -/*<#*/ -import { Action, act } from '../../../model/action'; -import { quality } from '../../../model/quality'; -import { select } from '../../../model/selector'; -import { ExperimentPriorityState } from '../priority.concept'; - -export type ExperimentPriorityAddValuePayload = { - newValue: number -}; - -export const experimentPriorityAddValue = quality.createWithPayload({ - type: 'experimentPriority Add value', - reducer: (state, action) => { - const { newValue } = action.payload; - if (newValue) { - return { - value: newValue + state.value - }; - } - return { - }; - }, -}); +/*<$ +For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will Add a value property from +the incoming action's payload +$>*/ +/*<#*/ +import { quality } from '../../../model/quality'; +import { ExperimentPriorityState } from '../priority.concept'; + +export type ExperimentPriorityAddValuePayload = { + newValue: number +}; + +export const experimentPriorityAddValue = quality.createWithPayload({ + type: 'experimentPriority Add value', + reducer: (state, action) => { + const { newValue } = action.payload; + if (newValue) { + return { + value: newValue + state.value + }; + } + return { + }; + }, +}); /*#>*/ \ No newline at end of file diff --git a/src/test/priority/qualities/isReady.quality.ts b/src/test/priority/qualities/isReady.quality.ts index 675fcf25..b31de620 100644 --- a/src/test/priority/qualities/isReady.quality.ts +++ b/src/test/priority/qualities/isReady.quality.ts @@ -1,15 +1,14 @@ -/*<$ -For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will set a ready property to true -$>*/ -/*<#*/ -import { Action, act } from '../../../model/action'; -import { quality } from '../../../model/quality'; -import { ExperimentPriorityState } from '../priority.concept'; - -export const experimentPriorityIsReady = quality.create({ - type: 'experimentPriority is ready', - reducer: (state) => ({ - ready: true - }), -}); +/*<$ +For the asynchronous graph programming framework Stratimux and based on the Experiment Concept, generate a quality that will set a ready property to true +$>*/ +/*<#*/ +import { quality } from '../../../model/quality'; +import { ExperimentPriorityState } from '../priority.concept'; + +export const experimentPriorityIsReady = quality.create({ + type: 'experimentPriority is ready', + reducer: (state) => ({ + ready: true + }), +}); /*#>*/ \ No newline at end of file diff --git a/src/test/random/generateCountingStrategy.strategy.ts b/src/test/random/generateCountingStrategy.strategy.ts index 89aece76..cf438a51 100644 --- a/src/test/random/generateCountingStrategy.strategy.ts +++ b/src/test/random/generateCountingStrategy.strategy.ts @@ -1,6 +1,13 @@ -import { ActionNode, ActionStrategy, createActionNode, createStrategy } from '../../model/actionStrategy'; +/*<$ +For the asynchronous graph programming framework Stratimux generate an ActionStrategy of a random length. +To count via a randomly determined add and subtract actions to reach a final number. That is determined by the difference of +add and subtract actions used within the ActionStrategy. +$>*/ +/*<#*/ import { Deck } from '../../model/deck'; import { CounterDeck } from '../../concepts/counter/counter.concept'; +import { ActionNode, ActionStrategy } from '../../model/action/strategy/actionStrategy.type'; +import { createActionNode, createStrategy } from '../../model/action/strategy/actionStrategy'; function getRandomRange(min: number, max: number) { return Math.random() * (max - min) + min; @@ -52,4 +59,5 @@ export const generateRandomCountingStrategy = (deck: GenerateRandomCountingStrat initialNode: stepFirst, topic, })]; -}; \ No newline at end of file +}; +/*#>*/ \ No newline at end of file diff --git a/src/test/random/random.test.ts b/src/test/random/random.test.ts index bc83dc2a..f3bf99a3 100644 --- a/src/test/random/random.test.ts +++ b/src/test/random/random.test.ts @@ -1,9 +1,14 @@ -import { muxification, getMuxiumState } from '../../model/muxium'; -import { strategyBegin } from '../../model/actionStrategy'; -import { selectState } from '../../model/selector'; +/*<$ +For the asynchronous graph programming framework Stratimux generate a test that will ensure that a basic random number counting strategy +is working as intended. +$>*/ +/*<#*/ +import { getMuxiumState } from '../../model/muxium/muxiumHelpers'; +import { muxification } from '../../model/muxium/muxium'; +import { selectState } from '../../model/selector/selector'; import { CounterState, createCounterConcept, counterName, CounterDeck } from '../../concepts/counter/counter.concept'; import { generateRandomCountingStrategy } from './generateCountingStrategy.strategy'; -import { createStage, stageWaitForOpenThenIterate } from '../../model/stagePlanner'; +import { strategyBegin } from '../../model/action/strategy/actionStrategyConsumers'; test('Muxium Counting Strategy Test', (done) => { const muxium = muxification('muxiumStrategyTest', {counter: createCounterConcept()}, {logging: true, storeDialog: true}); @@ -14,9 +19,9 @@ test('Muxium Counting Strategy Test', (done) => { const repeat = 10; let steps = 0; const plan = muxium.plan('Counting Strategy Stage', - ({e__}) => [ - stageWaitForOpenThenIterate(() => e__.muxiumKick()), - createStage(({dispatch, d}) => { + ({e__, stage, stageO}) => [ + stageO(() => e__.muxiumKick()), + stage(({dispatch, d}) => { const [shouldBe, strategy] = generateRandomCountingStrategy(d, count); strategyTopic = strategy.topic; expectedOutput = shouldBe; @@ -27,7 +32,7 @@ test('Muxium Counting Strategy Test', (done) => { throttle: 1 }); }), - createStage(({concepts, dispatch, e}) => { + stage(({concepts, dispatch, e}) => { const muxiumState = getMuxiumState(concepts); const counter = selectState(concepts, counterName); console.log('HIT, AX', muxiumState.lastStrategy); @@ -55,4 +60,5 @@ test('Muxium Counting Strategy Test', (done) => { }) ]); muxium.subscribe(concepts => console.log(getMuxiumState(concepts).lastStrategy)); -}); \ No newline at end of file +}); +/*#>*/ \ No newline at end of file diff --git a/src/test/removeConcepts.test.ts b/src/test/removeConcepts.test.ts index a3158fcf..457b83ba 100644 --- a/src/test/removeConcepts.test.ts +++ b/src/test/removeConcepts.test.ts @@ -2,14 +2,15 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure that the muxium can properly remove concepts from its current load. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; +import { muxification } from '../model/muxium/muxium'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; import { createCounterConcept, counterName } from '../concepts/counter/counter.concept'; import { addConceptsToRemovalQueThenBlockStrategy, removeConceptsViaQueThenUnblockTopic } from '../concepts/muxium/strategies/removeConcept.strategy'; -import { forEachConcept } from '../model/concept'; +import { forEachConcept } from '../model/concept/conceptHelpers'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Muxium remove Concepts Strategy Test', (done) => { const muxium = muxification('muxiumRemoveConceptsTest', diff --git a/src/test/selectDataSlice.test.ts b/src/test/selectDataSlice.test.ts index 875a2d4b..1eebc92a 100644 --- a/src/test/selectDataSlice.test.ts +++ b/src/test/selectDataSlice.test.ts @@ -3,8 +3,10 @@ For the asynchronous graph programming framework Stratimux, generate a test to that selectSlice is capable of performing shallow and deep state selections. $>*/ /*<#*/ -import { Concept, Concepts, createConcept } from '../model/concept'; -import { KeyedSelector, assembleDynamicSelection, createMuxifiedKeyedSelector, selectSlice } from '../model/selector'; +import { createConcept } from '../model/concept/concept'; +import { Concept, Concepts } from '../model/concept/concept.type'; +import { createMuxifiedKeyedSelector, selectSlice } from '../model/selector/selector'; +import { assembleDynamicSelection } from '../model/selector/selectorAdvanced'; export type BaseDataSet = { prompt: string, diff --git a/src/test/selector.test.ts b/src/test/selector.test.ts index 435b881b..a7ea58c2 100644 --- a/src/test/selector.test.ts +++ b/src/test/selector.test.ts @@ -2,15 +2,13 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure that the base selector consumer functions are working as intended. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; -import { Concept, Concepts } from '../model/concept'; -import { select, selectPayload, selectSlice, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { Concept, Concepts } from '../model/concept/concept.type'; import { CounterState, createCounterConcept, counterName } from '../concepts/counter/counter.concept'; import { counterSelectCount } from '../concepts/counter/counter.selector'; import { CounterSetCountPayload, counterSetCount } from '../concepts/counter/qualities/setCount.quality'; import { createExperimentConcept, experimentName } from '../concepts/experiment/experiment.concept'; -import { createStage } from '../model/stagePlanner'; -import { MuxiumQualities } from '../concepts/muxium/qualities'; +import { select } from '../model/selector'; test('Muxium Selector Test', (done) => { const counter = createCounterConcept(); @@ -18,7 +16,7 @@ test('Muxium Selector Test', (done) => { counterState.count = 10; const muxium = muxification('muxiumSelectorTest', {counter}, {logging: true, storeDialog: true}); const sub = muxium.subscribe((concepts: Concepts) => { - const state = selectState(concepts, counterName); + const state = select.state(concepts, counterName); console.log('CHECK COUNT', state?.count); expect(state?.count).toBe(10); done(); @@ -32,7 +30,7 @@ test('Muxium Selector State Slice Test', (done) => { counterState.count = 10; const muxium = muxification('muxiumSelectorStateSlicedTest', {counter}, {logging: true, storeDialog: true}); muxium.subscribe((concepts: Concepts) => { - const count = selectSlice(concepts, counterSelectCount); + const count = select.slice(concepts, counterSelectCount); expect(count).toBe(10); setTimeout(() => {done();}, 500); }); @@ -41,7 +39,7 @@ test('Muxium Selector State Slice Test', (done) => { test('Muxium Selector Payload Test', (done) => { // For testing purposes only, access actionCreators via the Deck Interface in production. const setCount = counterSetCount.actionCreator({newCount: 10 }); - const payload = selectPayload(setCount); + const payload = select.payload(setCount); expect(payload.newCount).toBe(10); done(); }); diff --git a/src/test/setStageOptions.test.ts b/src/test/setStageOptions.test.ts index 815fbc96..ca2d7ae0 100644 --- a/src/test/setStageOptions.test.ts +++ b/src/test/setStageOptions.test.ts @@ -2,17 +2,13 @@ For the asynchronous graph programming framework Stratimux, generate a test that the setStageOption derivatives.are functioning as intended $>*/ /*<#*/ -import { muxification, getMuxiumState, isMuxiumOpen } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; -import { selectSlice, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { getMuxiumState, isMuxiumOpen } from '../model/muxium/muxiumHelpers'; +import { selectState } from '../model/selector/selector'; import { CounterState, createCounterConcept, countingStrategy, counterName, CounterQualities } from '../concepts/counter/counter.concept'; -import { MuxiumState } from '../concepts/muxium/muxium.concept'; import { countingTopic } from '../concepts/counter/strategies/counting.strategy'; -import { createStage } from '../model/stagePlanner'; -import { muxiumSelectLastStrategy } from '../concepts/muxium/muxium.selector'; -import { muxiumKick } from '../concepts/muxium/qualities/kick.quality'; -import { initializeTopic } from '../concepts/muxium/strategies/initialization.strategy'; -import { Concept } from '../model/concept'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Muxium setStageSelectors Test', (done) => { let tally = 0; diff --git a/src/test/stageDispatchOptions.test.ts b/src/test/stageDispatchOptions.test.ts index 0e65be56..454248e9 100644 --- a/src/test/stageDispatchOptions.test.ts +++ b/src/test/stageDispatchOptions.test.ts @@ -2,8 +2,9 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure the stage planner and its options are working as intended. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; +import { selectSlice, selectState } from '../model/selector/selector'; import { CounterState, createCounterConcept, counterName, CounterDeck } from '../concepts/counter/counter.concept'; import { counterSelectCount } from '../concepts/counter/counter.selector'; diff --git a/src/test/stagePlannerBeat.test.ts b/src/test/stagePlannerBeat.test.ts index 6de30386..4a1025c8 100644 --- a/src/test/stagePlannerBeat.test.ts +++ b/src/test/stagePlannerBeat.test.ts @@ -7,11 +7,11 @@ But if the beat has not been notified for a period. The first notification will This is a combination of throttle and debounce. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; import { muxiumSelectOpen } from '../concepts/muxium/muxium.selector'; import { CounterDeck, CounterState, counterName, createCounterConcept } from '../concepts/counter/counter.concept'; -import { createStage } from '../model/stagePlanner'; +import { createStage } from '../model/stagePlanner/stagePlannerHelpers'; jest.setTimeout(10000); test('Stage Planner Beat Test', (done) => { diff --git a/src/test/stagedPrinciple.test.ts b/src/test/stagedPrinciple.test.ts index 6a4d9fc6..b21c1f04 100644 --- a/src/test/stagedPrinciple.test.ts +++ b/src/test/stagedPrinciple.test.ts @@ -2,14 +2,12 @@ For the asynchronous graph programming framework Stratimux, generate a test to ensure that you can create a stage planner within a concept's principle. $>*/ /*<#*/ -import { muxification } from '../model/muxium'; -import { selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { selectState } from '../model/selector/selector'; import { createExperimentConcept, experimentName } from '../concepts/experiment/experiment.concept'; import { PrincipleFunction } from '../model/principle'; -import { Action } from '../model/action'; -import { muxiumPreClose } from '../concepts/muxium/qualities/preClose.quality'; +import { Action } from '../model/action/action.type'; import { createQualityCard } from '../model/quality'; -import { MuxiumQualities } from '../concepts/muxium/qualities'; import { MuxiumDeck } from '../concepts/muxium/muxium.concept'; type ExperimentState = { diff --git a/src/test/strategy.test.ts b/src/test/strategy.test.ts index 0fd770ef..23665b26 100644 --- a/src/test/strategy.test.ts +++ b/src/test/strategy.test.ts @@ -2,12 +2,13 @@ For the asynchronous graph programming framework Stratimux, generate a test that ensures that ActionStrategies are working as intended. $>*/ /*<#*/ -import { muxification, getMuxiumState } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; -import { selectState } from '../model/selector'; +import { muxification } from '../model/muxium/muxium'; +import { getMuxiumState } from '../model/muxium/muxiumHelpers'; +import { selectState } from '../model/selector/selector'; import { CounterState, createCounterConcept, countingStrategy, counterName, CounterQualities } from '../concepts/counter/counter.concept'; import { countingTopic } from '../concepts/counter/strategies/counting.strategy'; -import { Concept } from '../model/concept'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Muxium Counting Strategy Test', (done) => { const cpts = {counter: createCounterConcept()}; diff --git a/src/test/strategyPriority.test.ts b/src/test/strategyPriority.test.ts index a3a39dc3..dfe3a5df 100644 --- a/src/test/strategyPriority.test.ts +++ b/src/test/strategyPriority.test.ts @@ -3,18 +3,22 @@ For the asynchronous graph programming framework Stratimux, generate a test that with priority are working as intended. $>*/ /*<#*/ -import { muxification, getMuxiumState, isMuxiumOpen } from '../model/muxium'; -import { strategyBegin } from '../model/actionStrategy'; -import { selectState } from '../model/selector'; -import { CounterState, createCounterConcept, countingStrategy, counterName, CounterQualities, CounterDeck } from '../concepts/counter/counter.concept'; -import { MuxiumState } from '../concepts/muxium/muxium.concept'; -import { createStage } from '../model/stagePlanner'; +import { muxification } from '../model/muxium/muxium'; +import { getMuxiumState, isMuxiumOpen } from '../model/muxium/muxiumHelpers'; +import { selectState } from '../model/selector/selector'; +import { + CounterState, + createCounterConcept, + counterName, + CounterQualities, + CounterDeck +} from '../concepts/counter/counter.concept'; import { generateRandomCountingStrategy } from './random/generateCountingStrategy.strategy'; import { muxiumSelectLastStrategy } from '../concepts/muxium/muxium.selector'; -import { muxiumKick } from '../concepts/muxium/qualities/kick.quality'; import { handlePriority } from '../model/priority'; -import { Concept } from '../model/concept'; +import { Concept } from '../model/concept/concept.type'; import { Deck } from '../model/deck'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Muxium Counting Strategy Priority Test', (done) => { const muxium = muxification('muxiumStrategyTest', {counter: createCounterConcept()}, {logging: true, storeDialog: true}); diff --git a/src/test/throttleMethods.test.ts b/src/test/throttleMethods.test.ts index 08bd38c6..606b9e61 100644 --- a/src/test/throttleMethods.test.ts +++ b/src/test/throttleMethods.test.ts @@ -3,8 +3,6 @@ For the asynchronous graph programming framework Stratimux, generate a test that $>*/ /*<#*/ import { muxiumSelectLastStrategy, muxiumSelectLastStrategyData } from '../concepts/muxium/muxium.selector'; -import { muxiumKick } from '../concepts/muxium/qualities/kick.quality'; -import { muxiumLog } from '../concepts/muxium/qualities/log.quality'; import { ExperimentState, createExperimentConcept, createExperimentState, experimentName } from '../concepts/experiment/experiment.concept'; import { experimentThrottleAsyncIterateIdThenReceiveInMethod @@ -23,10 +21,10 @@ import { experimentThrottleIterateIdThenAddToDataTopic } from '../concepts/experiment/strategies/throttleIterateIdThenAddToData.strategy'; -import { strategyBegin } from '../model/actionStrategy'; -import { muxification } from '../model/muxium'; -import { selectSlice, selectState } from '../model/selector'; -import { Concept } from '../model/concept'; +import { muxification } from '../model/muxium/muxium'; +import { selectSlice, selectState } from '../model/selector/selector'; +import { Concept } from '../model/concept/concept.type'; +import { strategyBegin } from '../model/action/strategy/actionStrategyConsumers'; test('Action Throttle Method Test with Concepts id comparison', (done) => { const qualities = {experimentThrottleIterateIdThenReceiveInMethod}; diff --git a/src/test/unifiedNames.test.ts b/src/test/unifiedNames.test.ts index 468e96fe..5d4289ae 100644 --- a/src/test/unifiedNames.test.ts +++ b/src/test/unifiedNames.test.ts @@ -2,7 +2,8 @@ For the asynchronous graph programming framework Stratimux, generate a test that ensures that muxified concepts inherit their muxified names as intended. $>*/ /*<#*/ -import { createConcept, muxifyConcepts } from '../model/concept'; +import { createConcept } from '../model/concept/concept'; +import { muxifyConcepts } from '../model/concept/conceptAdvanced'; test('Muxified Names Test', (done) => { const one = createConcept( diff --git a/src/test/unifiedSelector.test.ts b/src/test/unifiedSelector.test.ts index 0700450a..8a999518 100644 --- a/src/test/unifiedSelector.test.ts +++ b/src/test/unifiedSelector.test.ts @@ -5,16 +5,10 @@ That specifically you can utilize the incoming semaphore to create new KeyedSele $>*/ /*<#*/ import { CounterState, counterName, createCounterConcept } from '../concepts/counter/counter.concept'; -import { muxification } from '../model/muxium'; -import { - KeyedSelector, - createConceptKeyedSelector, - createMuxifiedKeyedSelector, - select, - selectSlice, - updateMuxifiedKeyedSelector -} from '../model/selector'; -import { createStage } from '../model/stagePlanner'; +import { muxification } from '../model/muxium/muxium'; +import { select } from '../model/selector'; + +import { KeyedSelector } from '../model/selector/selector.type'; test('Muxified Selector Test', (done) => { const muxium = muxification('Selector Test via Counter', { @@ -23,9 +17,9 @@ test('Muxified Selector Test', (done) => { const plan = muxium.plan('Plan: Counter Selector', ({stage}) => [ stage(({concepts}) => { console.log('FIRED!!!'); - const concept = createConceptKeyedSelector(counterName, 'count'); - const updated = updateMuxifiedKeyedSelector(concepts, 1, concept) as KeyedSelector; - const muxified = createMuxifiedKeyedSelector(concepts, 1, 'count') as KeyedSelector; + const concept = select.createConceptKeyedSelector(counterName, 'count'); + const updated = select.updateMuxifiedKeyedSelector(concepts, 1, concept) as KeyedSelector; + const muxified = select.createMuxifiedKeyedSelector(concepts, 1, 'count') as KeyedSelector; console.log('CHECK SELECTORS', concept, updated, muxified); expect(select.slice(concepts, updated)).toBe(0); expect(select.slice(concepts, concept)).toBe(0);