From 8791b8da465dcd6cd62856aa123395ddba90ab3d Mon Sep 17 00:00:00 2001 From: REllEK-IO Date: Wed, 15 May 2024 09:12:41 -0700 Subject: [PATCH] Strategy Priority v0.1.68 --- ActionStrategy.md | 11 +++-- README.md | 4 ++ package.json | 2 +- src/concepts/axium/axium.principle.ts | 1 - src/model/actionStrategy.ts | 61 +++++++++++++++++++++--- src/model/axium.ts | 26 ++++++++-- src/test/action.test.ts | 4 ++ src/test/strategyPriority.test.ts | 68 +++++++++++++++++++++++++++ 8 files changed, 160 insertions(+), 17 deletions(-) create mode 100644 src/test/strategyPriority.test.ts diff --git a/ActionStrategy.md b/ActionStrategy.md index c20743e..b03cb20 100644 --- a/ActionStrategy.md +++ b/ActionStrategy.md @@ -91,16 +91,19 @@ As this is an enhancement to the traditional understanding of higher order funct ```typescript export interface ActionStrategyParameters { topic: string; - data?: unknown; + data?: Record; initialNode: ActionNode; + priority?: number; } export interface ActionStrategy { topic: string; - data?: unknown; + data?: Record; currentNode: ActionNode; actionList: Array; - lastActionNode: ActionNode; puntedStrategy?: ActionStrategy[]; + stubs?: OwnershipTicketStub[]; + priority?: number; + step?: number; } ``` * topic - The topic string or the beginning sentence of a Stratimux dialog paragraph. Also stores itself temporarily upon strategy completion on the Axium as **lastStrategy**. We suggest using this field to determine when your strategies of concluding during testing, or when to dispatch some other strategy. @@ -110,6 +113,8 @@ export interface ActionStrategy { * lastActionNode - Primarily functions to clear ownership upon each successive action from the strategy. Likewise can be used to determine the current decision, or preposition of the current ActionNode at runtime. * puntedStrategy - This allows for strategies to be successively chained into one another by first in, first Out principle upon each strategy conclusion. * initialNode via ActionStrategyParameters - The initial node that is the head that is ran by the strategyBegin consumer function. +* priority - This will assign a default priority to each action issued from a strategy, but allows for actions to have their own atomically. +* step - Mainly for trouble shooting purposes, but likewise may be used via some analytics for insight. ## Consumer Functions ```typescript diff --git a/README.md b/README.md index 2d77569..40f5ed5 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,10 @@ When in doubt simplify. * [Unified Turing Machine](https://github.com/Phuire-Research/Stratimux/blob/main/The-Unified-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.svg) +### Strategy Priority v0.1.68 5/15/2024 +* Added priority to strategies, this priority will be assigned to each step issued by such. + * With this change you may now have strategies jump all lines upon creation, ensuring some change prior to other action's taking effect. + * Unless a ActionNode or incoming Action created by createActionNode has its own priority, then that takes precedents. But does not effect the Strategy's overall priority. ### **BREAKING** v0.1.67 5/13/2024 * Revamped the Action Creator Functions to follow behind the current creator with an **options** parameter design choice. * Note pure action creators will not provide an option for payload diff --git a/package.json b/package.json index 6aebf3d..b10513a 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "stratimux", "license": "GPL-3.0", - "version": "0.1.67", + "version": "0.1.68", "description": "Unified Turing Machine", "main": "dist/index.js", "module": "dist/index.mjs", diff --git a/src/concepts/axium/axium.principle.ts b/src/concepts/axium/axium.principle.ts index 9116dd8..b1ddfd9 100644 --- a/src/concepts/axium/axium.principle.ts +++ b/src/concepts/axium/axium.principle.ts @@ -38,7 +38,6 @@ export const axiumPrinciple: PrincipleFunction = ( forEachConcept(concepts, (concept, s) => { newConcepts[Number(s)] = concept; }); - axiumState.addConceptQue.forEach((concept, _index) => { concept.semaphore = axiumState.conceptCounter; if (concept.mode !== undefined) { diff --git a/src/model/actionStrategy.ts b/src/model/actionStrategy.ts index 2613ebd..5a82c10 100644 --- a/src/model/actionStrategy.ts +++ b/src/model/actionStrategy.ts @@ -176,6 +176,7 @@ export interface ActionStrategyParameters { topic: string; data?: Record; initialNode: ActionNode; + priority?: number; } export interface ActionStrategy { topic: string; @@ -184,6 +185,8 @@ export interface ActionStrategy { actionList: Array; puntedStrategy?: ActionStrategy[]; stubs?: OwnershipTicketStub[]; + priority?: number; + step?: number; } export type ActionStrategyTopic = string; @@ -220,6 +223,7 @@ export function createStrategy( ): 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), @@ -233,11 +237,19 @@ export function createStrategy( 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, { @@ -246,7 +258,7 @@ export const strategyBegin = (strategy: ActionStrategy, data?: Record { ...newNode.action.strategy.actionList, strategy.actionList[strategy.actionList.length - 1], ]; + strategy.step = strategy.step ? strategy.step + 1 : 1; } return newNode.action as Action; } else { @@ -571,6 +616,8 @@ export const strategyRecurse = ]; currentNode.action = action; strategy.currentNode = currentNode; + + strategy.step = strategy.step ? strategy.step + 1 : 1; action.strategy = strategy; return action; }; diff --git a/src/model/axium.ts b/src/model/axium.ts index aa8293c..2fa7a2e 100644 --- a/src/model/axium.ts +++ b/src/model/axium.ts @@ -42,10 +42,13 @@ export const blockingMethodSubscription = (concepts: Concepts, tail: Action[], a strategyTopic: action.strategy.topic, strategyData: action.strategy.data, }); - tail.push(appendToDialog); if (isPriorityValid(action)) { - handlePriority(getAxiumState(concepts), action); + const state = getAxiumState(concepts); + handlePriority(state, action); + appendToDialog.priority = action.priority; + handlePriority(state, appendToDialog); } else { + tail.push(appendToDialog); tail.push(action); } } else if ( @@ -53,6 +56,11 @@ export const blockingMethodSubscription = (concepts: Concepts, tail: Action[], a // Logical Determination: axiumBadType action.semaphore[3] !== 1 ) { + if (isPriorityValid(action)) { + handlePriority(getAxiumState(concepts), action); + } else { + tail.push(action); + } tail.push(action); } }; @@ -70,10 +78,13 @@ export const defaultMethodSubscription = (concepts: Concepts, tail: Action[], ac strategyData: action.strategy.data }); // setTimeout(() => { - tail.push(appendToDialog); if (isPriorityValid(action)) { - handlePriority(getAxiumState(concepts), action); + const state = getAxiumState(concepts); + handlePriority(state, action); + appendToDialog.priority = action.priority; + handlePriority(state, appendToDialog); } else { + tail.push(appendToDialog); tail.push(action); } if (async) { @@ -87,7 +98,11 @@ export const defaultMethodSubscription = (concepts: Concepts, tail: Action[], ac // Logical Determination: axiumBadType action.semaphore[3] !== 1 ) { - tail.push(action); + if (isPriorityValid(action)) { + handlePriority(getAxiumState(concepts), action); + } else { + tail.push(action); + } if (async) { axiumTimeOut(concepts, () => { return axiumKick(); @@ -120,6 +135,7 @@ export function createAxium( let axiumState = concepts[0].state as AxiumState; axiumState.cachedSemaphores = createCacheSemaphores(concepts); forEachConcept(concepts, ((concept, semaphore) => { + axiumState.conceptCounter += 1; concept.qualities.forEach(quality => { if (quality.methodCreator) { [quality.method, quality.subject] = quality.methodCreator(axiumState.concepts$, semaphore); diff --git a/src/test/action.test.ts b/src/test/action.test.ts index 9865e52..876ec61 100644 --- a/src/test/action.test.ts +++ b/src/test/action.test.ts @@ -8,6 +8,10 @@ import { counterAdd, counterAddType } from '../concepts/counter/qualities/add.qu test('Axium add Concepts Strategy Test', (done) => { const something = createAction('something'); expect(something.type).toBe('something'); + const somethingElse = createAction('somethingElse', {payload: { + name: 'somethingElse' + }}); + expect(somethingElse.payload?.name).toBe('somethingElse'); const add = counterAdd(); expect(add.type).toBe(counterAddType); console.log(add.type); diff --git a/src/test/strategyPriority.test.ts b/src/test/strategyPriority.test.ts new file mode 100644 index 0000000..64d2c6c --- /dev/null +++ b/src/test/strategyPriority.test.ts @@ -0,0 +1,68 @@ +/*<$ +For the asynchronous graph programming framework Stratimux, generate a test that ensures that ActionStrategies are working as intended. +$>*/ +/*<#*/ +import { createAxium, getAxiumState, isAxiumOpen } from '../model/axium'; +import { strategyBegin } from '../model/actionStrategy'; +import { selectState } from '../model/selector'; +import { CounterState, createCounterConcept, countingStrategy, counterName } from '../concepts/counter/counter.concept'; +import { AxiumState } from '../concepts/axium/axium.concept'; +import { createStage } from '../model/stagePlanner'; +import { generateRandomCountingStrategy } from './random/generateCountingStrategy.strategy'; +import { axiumSelectLastStrategy } from '../concepts/axium/axium.selector'; +import { axiumKick } from '../concepts/axium/qualities/kick.quality'; +import { handlePriority } from '../model/priority'; + +test('Axium Counting Strategy Priority Test', (done) => { + const concluded = [false, false, false]; + const [count1, strategy1] = generateRandomCountingStrategy(0); + strategy1.priority = 100; + const [count2, strategy2] = generateRandomCountingStrategy(0); + const [count3, strategy3] = generateRandomCountingStrategy(0); + strategy3.priority = 50; + const axium = createAxium('axiumStrategyTest', [createCounterConcept()], {logging: true, storeDialog: true}); + const plan = axium.plan('Counting Strategy with Priority Plan', + [ + createStage((concepts, dispatch) => { + if (isAxiumOpen(concepts)) { + handlePriority(getAxiumState(concepts), strategyBegin(strategy1)); + handlePriority(getAxiumState(concepts), strategyBegin(strategy2)); + handlePriority(getAxiumState(concepts), strategyBegin(strategy3)); + console.log('COUNT ONE STRATEGY OUTCOME: ', count1); + console.log('COUNT TWO STRATEGY OUTCOME: ', count2); + console.log('COUNT THREE STRATEGY OUTCOME: ', count3); + dispatch(axiumKick(), { + iterateStage: true + }); + } + }), + createStage((concepts) => { + const axiumState = concepts[0].state as AxiumState; + const counter = selectState(concepts, counterName); + // console.log('CHECK COUNT', counter, 'HEAD', axiumState.head, 'BODY', axiumState.body, 'TAIL', axiumState.tail); + if (axiumState.lastStrategy === strategy1.topic && !concluded[0]) { + console.log('CHECK COUNT ONE', counter?.count, count1); + concluded[0] = true; + expect(counter?.count).toBe(count1); + } + if (axiumState.lastStrategy === strategy2.topic && !concluded[1]) { + console.log('CHECK COUNT TWO', counter?.count, count2); + concluded[1] = true; + expect(counter?.count).toBe(count1 + count2 + count3); + } + if (axiumState.lastStrategy === strategy3.topic && !concluded[2]) { + console.log('CHECK COUNT THREE', counter?.count, count3); + concluded[2] = true; + expect(counter?.count).toBe(count1 + count3); + } + if (concluded[0] && concluded[1] && concluded[2]) { + expect(counter?.count).toBe(count1 + count2 + count3); + setTimeout(() => {done();}, 500); + plan.conclude(); + axium.close(); + } + }, {selectors: [axiumSelectLastStrategy]}) + // }) + ]); +}); +/*#>*/ \ No newline at end of file