Skip to content

Commit

Permalink
Tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
REllEK-IO committed Oct 19, 2023
1 parent 747546b commit c86ff8e
Show file tree
Hide file tree
Showing 12 changed files with 69 additions and 59 deletions.
5 changes: 3 additions & 2 deletions ActionStrategy.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ SomethingFactory<AnotherFactor<Factory>>
This was a purposeful design choice, if you find yourself doing such. Known this system is already complicated enough.

## Helper Functions for Standard Method Creators
*Note you still need to create a function of MethodCreator to use these Helpers*
*You still need to create a function of type MethodCreator to use these Helpers. :MethodCreator = () => methodCreator*
```typescript
export const createMethod =
(method: (action: Action) => Action): [Method, Subject<Action>] => {}
Expand All @@ -146,7 +146,8 @@ export const createAsyncMethodDebounceWithConcepts =
* createMethodWithConcepts - This will allow your method to have the most recent concepts to be accessed via the asyncMethod function.
* createAsyncMethod - Handled differently than the rest, you will have to use the passed controller to fire your actions back into the action stream.
* createAsyncMethodWithConcepts - Will also have access to the most recent concepts.
*Note if you are implementing your own debounceAction how these methods work. They are handling a passed conclude from debounceAction within their map/switchMap*
* createMethodDebounce - After the first action, this will filter actions within the duration to be set to the conclude action.
* createMethodDebounceWithConcepts - Will filter actions within the duration while providing access to the most recent concepts.
* createMethodDebounceWithConcepts - Will filter actions within the duration while providing access to the most recent concepts.
* createAsyncMethodDebounce - Will not disengage the initial ActionController, but will allow debounced actions to pass through when filtered as conclude actions. And will fire the first action upon its own conditions are met asynchronously.
* createAsyncMethodDebounceWithConcepts - Filters and then first the first action once conditions are met, and provides access to the most recent concepts.
1 change: 1 addition & 0 deletions Axium.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ Please avoid using these qualities, but are providing explanations to understand
* clearBadActionTypeFromBadActionList - This is to allow for plans to take into account for expired actions and clear such.
* clearBadStrategyTopicFromBadActionList - Allows plans to accounts for specific ActionStrategy topics that might find themselves in badActions and clear such.
* clearBadPlanFromBadPlanList - This additionally allows for concepts to take into account potentially failed plans that are set by axium.stage(). Via their topic as payload and clears such.
* kick - This is a pure action that will just trigger the next function via the UnifiedSubject to prime subscribers or stages. Noting that the downside of STRX's halting quality, is you have to kick it into gear if it hasn't received an action recently for your staged Plans to operate as intended.

## Axium Strategies Concept Set Transformation
```typescript
Expand Down
2 changes: 2 additions & 0 deletions src/concepts/axium/axium.concept.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { clearBadActionTypeFromBadActionListQuality } from './qualities/clearBad
import { clearBadStrategyTopicFromBadActionListQuality } from './qualities/clearBadStrategyTopicFromBadActionList.quality';
import { clearBadPlanFromBadPlanListQuality } from './qualities/clearBadPlanFromBadPlanList.quality';
import { registerStagePlannerQuality } from './qualities/registerStagePlanner.quality';
import { kickQuality } from './qualities/kick.quality';

export type NamedSubscription = {
name: string;
Expand Down Expand Up @@ -92,6 +93,7 @@ export const createAxiumConcept = (name: string, storeDialog?: boolean, logging?
axiumName,
createAxiumState(name, storeDialog, logging),
[
kickQuality,
openQuality,
badActionQuality,
closeQuality,
Expand Down
12 changes: 12 additions & 0 deletions src/concepts/axium/qualities/kick.quality.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { defaultMethodCreator, defaultReducer } from '../../../model/concept';
import { ActionType, prepareActionCreator } from '../../../model/action';
import { createQuality } from '../../../model/concept';

export const axiumKickType: ActionType = 'Kick Axium';
export const axiumKick = prepareActionCreator(axiumKickType);

export const kickQuality = createQuality(
axiumKickType,
defaultReducer,
defaultMethodCreator
);
9 changes: 8 additions & 1 deletion src/concepts/counter/qualities/add.quality.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@ import { defaultMethodCreator, Method, MethodCreator } from '../../../model/conc
import { Counter } from '../counter.concept';
import { createQuality } from '../../../model/concept';
import { counterSelectCount } from '../counter.selector';
// import { createMethod } from '../../../model/method';
// import { strategySuccess } from '../../../model/actionStrategy';

export const counterAddType: ActionType = 'Counter Add';

export const counterAdd = prepareActionCreator(counterAddType);

// const createAddMethodCreator: MethodCreator = () => createMethod((action) => {
// if (action.strategy) {
// return strategySuccess(action.strategy);
// }
// return action;
// });
export function addReducer(state: Counter, _: Action) {
return {
...state,
Expand Down
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ export { AxiumState, axiumName, createAxiumConcept } from './concepts/axium/axiu
export { blockingMode, permissiveMode } from './concepts/axium/axium.mode';
export { axiumSelectOpen, axiumSelectLastStrategy, axiumSelectBadActions, axiumSelectBadPlans } from './concepts/axium/axium.selector';
// Qualities
export { axiumKick, axiumKickType } from './concepts/axium/qualities/kick.quality';
export { axiumConclude, axiumConcludeType } from './concepts/axium/qualities/conclude.quality';
export { axiumOpen, axiumOpenType } from './concepts/axium/qualities/open.quality';
export { axiumLog, axiumLogType } from './concepts/axium/qualities/log.quality';
Expand Down
35 changes: 3 additions & 32 deletions src/model/actionController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Action, ActionStrategy, axiumBadAction, axiumConclude, axiumConcludeType, strategyFailed } from '../index';
import { Action, axiumBadAction, strategyFailed } from '../index';
import { Subject } from 'rxjs';
import { failureConditions, strategyData_appendFailure } from './actionStrategyData';

Expand All @@ -20,12 +20,6 @@ export class ActionController extends Subject<Action> {
strategyData_appendFailure(this.action.strategy, failureConditions.controllerExpired)
));
} else {
const badAction = axiumBadAction([this.action]);
if (this.action.strategy) {
badAction.strategy = this.action.strategy;
(badAction.strategy as ActionStrategy).currentNode.action = badAction;
(badAction.strategy as ActionStrategy).currentNode.actionType = badAction.type;
}
this.next(axiumBadAction([this.action]));
}
}, this.expiration - Date.now());
Expand All @@ -46,35 +40,12 @@ export class ActionController extends Subject<Action> {
clearTimeout(this.timer);
this.timer.unref();
}
let nextAction;
let end = true;
// Logically Determined axiumConclude
if (action.semaphore[3] === 3) {
end = false;
}
if (action.strategy) {
nextAction = action;
// Logically Determined axiumConclude
} else if (action.semaphore[3] === 3) {
nextAction = action;
// Logically Determined axiumBadAction
} else if (!action.strategy && action.semaphore[3] !== 1) {
const conclude = axiumConclude();
nextAction = {
...action,
...conclude
};
} else {
nextAction = action;
}
const { observers } = this;
const len = observers.length;
for (let i = 0; i < len; i++) {
observers[i].next(nextAction);
}
if (end) {
this.complete();
observers[i].next(action);
}
this.complete();
}
}
}
Expand Down
10 changes: 5 additions & 5 deletions src/model/debounceAction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,12 +142,12 @@ export function debounceAction(dueTime: number, scheduler: SchedulerLike = async
subscriber.add(activeTask);
} else {
// All this code just to place this code block.
const conclude = axiumConclude();
const conclude = {
...value,
...axiumConclude(),
};
subscriber.next(
{
...value,
...conclude,
}
conclude
);
}
},
Expand Down
32 changes: 22 additions & 10 deletions src/model/method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ type Action = {
};
type Method = Observable<Action>;




export const createMethod =
(method: (action: Action) => Action): [Method, Subject<Action>] => {
const defaultSubject = new Subject<Action>();
Expand Down Expand Up @@ -134,9 +131,17 @@ export const createAsyncMethodDebounce =
const defaultSubject = new Subject<Action>();
const defaultMethod: Method = defaultSubject.pipe(
debounceAction(duration),
switchMap(act => createActionController$(act, (controller: ActionController, action: Action) => {
asyncMethod(controller, action);
})),
switchMap((act) => {
if (act.semaphore[3] !== 3) {
return createActionController$(act, (controller: ActionController, action: Action) => {
asyncMethod(controller, action);
});
} else {
return createActionController$(act, (controller: ActionController, _) => {
controller.fire(act);
});
}
}),
);
return [defaultMethod, defaultSubject];
};
Expand All @@ -147,10 +152,17 @@ export const createAsyncMethodDebounceWithConcepts =
const defaultMethod: Method = defaultSubject.pipe(
debounceAction(duration),
withLatestFrom(concepts$ as UnifiedSubject),
switchMap(([act, concepts] : [Action, Concept[]]) =>
createActionController$(act, (controller: ActionController, action: Action) => {
asyncMethodWithConcepts(controller, action, concepts);
})),
switchMap(([act, concepts] : [Action, Concept[]]) => {
if (act.semaphore[3] !== 3) {
return createActionController$(act, (controller: ActionController, action: Action) => {
asyncMethodWithConcepts(controller, action, concepts);
});
} else {
return createActionController$(act, (controller: ActionController, _) => {
controller.fire(act);
});
}
})
);
return [defaultMethod, defaultSubject];
};
2 changes: 1 addition & 1 deletion src/model/stagePlanner.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,9 +196,9 @@ export class UnifiedSubject extends Subject<Concept[]> {
super();
}
stage(title: string, stages: Staging[]): StagePlanner {
this.currentStages.set(this.planId, {title, stages, stage: 0, stageFailed: -1});
const planId = this.planId;
this.planId++;
this.currentStages.set(planId, {title, stages, stage: 0, stageFailed: -1});
const conclude = () => {
this.currentStages.delete(planId);
};
Expand Down
4 changes: 2 additions & 2 deletions src/test/actionController.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ test('ActionController Next Test', (done) => {
const act = axiumLog(undefined, 200);
const cont = new ActionController(act);
cont.subscribe(action => {
expect(action.type).toBe(axiumConcludeType);
expect(action.type).toBe(axiumLogType);
done();
});
cont.fire(act);
Expand All @@ -41,7 +41,7 @@ test('ActionController createActionController$ Test', (done) => {
controller.fire(action);
});
cont.subscribe(action => {
expect(action.type).toBe(axiumConcludeType);
expect(action.type).toBe(axiumLogType);
done();
});
});
Expand Down
15 changes: 9 additions & 6 deletions src/test/debounceMethods.test.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { axiumKick } from '../concepts/axium/qualities/kick.quality';
import { Counter, counterName, createCounterConcept } from '../concepts/counter/counter.concept';
import { createExperimentConcept, createExperimentState } from '../concepts/experiment/experiment.concept';
import { asyncDebounceNextActionNodeQuality } from '../concepts/experiment/qualities/debounceAsyncNextActionNode.quality';
Expand All @@ -8,7 +9,6 @@ import { strategyBegin } from '../model/actionStrategy';
import { createAxium } from '../model/axium';
import { selectState } from '../model/selector';

jest.setTimeout(10000);
test('Debounce method prevent excess count', (done) => {
const experiment = createExperimentConcept(createExperimentState(), [debounceNextActionNodeQuality]);
const axium = createAxium('Experiment async method creator with Concepts', [createCounterConcept(), experiment]);
Expand Down Expand Up @@ -64,14 +64,14 @@ test('Async debounce method prevent excess count', (done) => {
const counterState = selectState<Counter>(concepts, counterName);
console.log('Async Debounce HIT 4', counterState);
if (counterState.count === 1) {
console.log('Async Debounce HIT 4', counterState);
console.log('FINAL Async Debounce HIT 4', counterState);
expect(counterState.count).toBe(1);
plan.conclude();
}
}
]);
setTimeout(() => {
const secondPlan = axium.stage('timed mock to true', [
const secondPlan = axium.stage('second timed mock', [
(_, dispatch) => {
dispatch(strategyBegin(experimentAsyncDebounceAddOneStrategy()), {
iterateStage: true
Expand All @@ -89,9 +89,9 @@ test('Async debounce method prevent excess count', (done) => {
},
(concepts, _) => {
const counterState = selectState<Counter>(concepts, counterName);
console.log('Async Plan 2 Debounce HIT 4', counterState);
console.log('Async 2 Debounce HIT 4', counterState);
if (counterState.count === 2) {
console.log('Async Plan 2 Debounce HIT 4', counterState);
console.log('FINAL Async 2 Debounce HIT 4', counterState);
expect(counterState.count).toBe(2);
secondPlan.conclude();
setTimeout(() => {
Expand All @@ -100,5 +100,8 @@ test('Async debounce method prevent excess count', (done) => {
}
}
]);
}, 600);
// Axium must be primed, therefore we kick it back into gear.
// Downside of halting quality.
axium.dispatch(axiumKick());
}, 1000);
});

0 comments on commit c86ff8e

Please sign in to comment.