Features:
The easiest means of detecting if your application is starting to encounter such errors is to enable the dialog and logging options on your Axium. To avoid running into these branch prediction errors. Attempt to limit your strategy assembly, qualities, and plans to be less than O(n^3). You will find that your functions will suddenly become probabilistic in their ability execution deterministically.
Thankfully, this is the reason for the atomic behavior of your qualities combined with strategies and plans. As you may shrink time complexity into a series of steps. Or better yet, if you are relying on accessing some parameters from your state. Be sure to flattened those data structures into something that can readily be accessed.
When in doubt simplify.
npm i stratimux
src/ index.ts
src/ concepts / uX / qualities / qOfUX.quality.ts
concepts / uX / strategies / uXSome.strategy.ts
concepts / uX / uX.concept.ts
concepts / uX / uX.principle.ts
tests / uX.test.ts
This paradigm affords for a powerful separation of concerns. And is the key feature that allows the User Interface concept that is currently in the processing of moving out of MVP. That affords for the easy isolation of client and server logic. With even the ease of handling server side rendering based on what concept your Brand is being unified with: server or client.
Treat your concepts as libraries and modules. As that was the initial inspiration for this system. Beyond this initial release, there will be a growing library of Standardized Concepts for utilization within your Axium. Including the ability to finally have an easy means of composing "Web Components," into your system. While enhancing upon their functionality, versus just the drop in.
import { Action, Mode, Quality, createConcept, PrincipleFunction } from 'stratimux';
import { uXqOfUXQuality } from './qualities/qOfUx.quality'
import { uXPrinciple } from './uX.principle'
export type UXState = {
//
}
export const uXName = 'uX';
export const createUXState = (): UXState => {
return {
//
};
};
// Pass any arguments needed for your concept
export const createUXConcept = (
// state: Record<string, unknown>,
// qualities?: Quality[],
// principles?: PrincipleFunction[],
// mode?: Mode[]
) => {
return createConcept(
uXName,
createUXState(),
[
uXqOfUXQuality
],
[
uXPrinciple,
],
mode
);
};
This isolates all the parts necessary for your actions to have impact within this system. Be mindful of your types, 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 not setting the semaphore ahead of time.
The semaphore is the method of quality selection within the Axium. This is to reduce the time complexity of each look up. And if you applications are purely static with no planned dynamic changes to the Axium's conceptual load. This values can be hard coded ahead of time. This is one of the planned features for logixUX. In addition to other scaffolding improvements, AI assistance, and more.
import {
MethodCreator,
Action,
prepareActionCreator,
createQuality,
UnifiedSubject,
createMethodWithState,
strategySuccess,
strategyData_unifyData,
strategyFailed
} from 'stratimux';
import { UXState } from '../uX.concept';
export const uXqOfUXType = 'uX allows for easy selection of your qualities, qOfUX is your quality, and Type is the distinction';
export const uXqOfUX = prepareActionCreator(uXqOfUXType);
export type uXqOfUxField = {
state: UXState
};
function getRandomRange(min: number, max: number) {
return Math.random() * (max - min) + min;
}
const uXqOfUXCreator: MethodCreator = (concepts$?: Subject<Concepts>, semaphore?: number) =>
// Only if you need to access state, otherwise
createMethodWithState<UXState>((action, state) => {
if (action.strategy) {
// P/NP?
const even = Math.round(getRandomRange(1, 5)) % 2;
if (even) {
const strategy = strategySuccess(action.strategy, strategyData_unifyData(action.strategy, {
state
}));
return strategy;
} else {
const strategy = strategyFailed(action.strategy);
return strategy;
}
}
return action;
}, concepts$ as UnifiedSubject, semaphore as number);
function uXqOfUXReducer(state: UXState, _: Action): UXState {
return {
...state,
};
}
export const uXqOfUXQuality = createQuality(
uXqOfUXType,
uXqOfUXReducer,
uXqOfUXCreator
);
/* Below are the default functions available for your quality */
// export const qOfUXQuality = createQuality(
// qOfUXType,
// defaultReducer(Informs)/nullReducer(Doesn't Inform),
// The method is optional and is an advanced behavior
// defaultMethodCreator
// );
Your concept's "main" function. This will be called after the axium initializes.
import { Subscriber } from 'rxjs';
import {
Action,
Concepts,
PrincipleFunction,
UnifiedSubject,
axiumRegisterStagePlanner,
axiumSelectOpen,
getAxiumState,
primeAction,
selectUnifiedState,
strategyBegin,
createStage,
stageWaitForOpenThenIterate
} from 'stratimux';
import { UXState, uXName } from './uX.concept';
import { uXSomeStrategy, uXSomeStrategyTopic } from './strategies/uXSome.strategy';
export const uXPrinciple: PrincipleFunction = (
_obs: Subscriber<Action>,
_concepts: Concepts,
concepts$: UnifiedSubject,
semaphore: number
) => {
// There always needs to be atleast one subscriber or plan for the Axium to be active.
const plan = concepts$.plan('uX Plan', [
// This will register this plan to the axium, this allows for the axium to close or remove your concept cleanly.
stageWaitForOpenThenIterate(() => (axiumRegisterStagePlanner({conceptName: uXName, stagePlanner: plan}))),
createStage((concepts, dispatch) => {
const state = selectUnifiedState<UXState>(concepts, semaphore);
if (state) {
dispatch(strategyBegin(uXSomeStrategy()), {
iterateStage: true
});
}
}, {beat: 30}),
createStage((concepts) => {
const {lastStrategy} = getAxiumState(concepts);
if (lastStrategy === uXSomeStrategyTopic) {
plan.conclude();
}
}, {beat: 30})
]);
};
When you are creating your strategies within this system of design. You are optimizing towards success, and majority of your strategies should be taking place within that mind set. Failure is just a chance to get back on track and see the end of some strategy, but likewise you have to account for that failure ahead of time.
This approach to algorithm design is the core strength of Stratimux, but likewise its weakness due to branch prediction. Therefore be mindful if your strategies behave in unexpected ways. The Stage Planner paradigm, especially the beat attribute should be your first go to. As chances are your logic is becoming to complex and you need to tone down when parts of your application are notified changes to state.
import { ActionStrategy, axiumKick, axiumLog, createActionNode, createStrategy } from 'stratimux';
import { uXqOfUX } from '../qualities/qOfUx.quality';
export const uXSomeStrategyTopic = 'uX Some Error Correcting Strategy';
export const uXSomeStrategy = (): ActionStrategy => {
const stepSuccess = createActionNode(axiumLog(), {
successNode: null,
failureNode: null
});
const stepFailure = createActionNode(axiumKick(), {
successNode: stepSuccess,
failureNode: null
});
const stepBegin = createActionNode(uXqOfUX(), {
successNode: stepSuccess,
failureNode: stepFailure
});
return createStrategy({
topic: uXSomeStrategyTopic,
initialNode: stepBegin
});
};
Notice that beyond creating the axium, there is no need for additional input. As the axium is a recursive function. Your concepts are initialized internally via the principle that you have assigned to your concept. Note that you may still subscribe, stage, and dispatch actions into an axium.
import { createAxium } from 'stratimux';
import { createUXConcept } from './concepts/uX/uX.concept';
(() => {
const axiumName = 'Name of your axium';
// Sets logging to true and store dialog to true
// This will log to the console the dialog of each successive ActionStrategy
// And store the entire application context in the axium's dialog.
// The final boolean will allow the action stream to be logged to console
createAxium(axiumName, [createUXConcept()], true, true, true);
})();