Futurescale, Inc. PureMVC Home

The PureMVC Framework Code at the Speed of Thought


Over 10 years of community discussion and knowledge are maintained here as a read-only archive.

New discussions should be taken up in issues on the appropriate projects at https://github.com/PureMVC

Pages: 1 ... 7 8 [9] 10
Print
Author Topic: StateMachine - A PureMVC / AS3 Utility  (Read 101727 times)
nilsm
Jr. Member
**
Posts: 19


View Profile Email
« Reply #120 on: June 14, 2009, 05:49:02 »

Quick questions regarding the StateMachine:

Why is the 'currentState' getter on StateMachine protected, rather than public?

(Enjoying working with it, by the way, but this has thrown up some problems for me.)

Thanks - Nils.

[Edit: Question about multicore removed - found it in ZIP file]

« Last Edit: June 14, 2009, 05:59:49 by nilsm » Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #121 on: June 14, 2009, 06:01:26 »

You can get the current state trough the viewComponent property (but you will have to cast it)... mmm doesn't really seem intuitive.
The is no multi core, as there does n't need to be.  You can register a StateMachine in each core, and if necessary you can use the pipes util to communicate between them.

Though I guess a layer of abstraction above these two utils could make the whole easier to use.  Sounds like an interesting project ( I wonder if Fabrication has incorporate something of the like). I'm a bit busy with the FSMVisualiserat the mo - why don't you have a go ;~)

BTW, after my blog being hacked, and my head deep in bread and butter work, I've actually had a bit of time spare to work on the FSMVisualiser, so I might have something more solid to post next week.

cheers
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #122 on: June 14, 2009, 06:04:00 »

Ah, I took your question to mean why are the StateMachine utils exactly the same between standard and multicore (which they are).
Logged
nilsm
Jr. Member
**
Posts: 19


View Profile Email
« Reply #123 on: June 14, 2009, 06:20:12 »

Hi Neil,

thanks for the super-quick reply (esp on a Sunday).

I'll cast the viewComponent, that's easy enough. Don't know whether Fabrication uses FSM but communicating with pipes shouldn't be too hard. I'm also too busy to work on anything like that - but thanks for the suggestion ;)

Cheers - Nils.
Logged
nilsm
Jr. Member
**
Posts: 19


View Profile Email
« Reply #124 on: June 14, 2009, 06:55:29 »

ENTERING / EXITING in addition to CHANGE notifications

I'm just in the middle of writing some code to manage a state history and it occurred to me that it would be useful to have generic ENTERING / EXITING notifications sent by StateMachine, which also contains the additional notification body that is sent when sending the state-specific 'entering', 'exiting' notifications.

At the moment, you can only retrieve the state instance itself by listening to the StateMachine.CHANGED notification - but you can't record what additional information was sent when entering the state.

My question is: Is there a trick for retrieving that information when the CHANGED notification is received?

Just in the middle of coding, sorry if the post doesn't make much sense ;)
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #125 on: June 14, 2009, 08:48:45 »

What would you do with the data on these generic ENTERING and EXITING notes?

I see the state-specific entering, exiting and changed announcements as being very much internal to that transition. For instance, going between a COLLECTING and SAVING state, it's reasonable to expect that the COLLECTING state's exiting guard would know the data being sent and be able to make sure it's all there or cancel if not. It has specific knowledge of the COLLECTING state's purpose and output.

But a generic EXITING announcement would only be useful to some ungainly actor that knows about all the states and their outputs (specifically what to cast their note bodies to).

And to send a generic ENTERING and EXITING note is to tempt the developer to begin doing teardown/buildup of the interface and then wonder how to undo it if the transition is canceled.

-=Cliff>
Logged
Djaffy
Newbie
*
Posts: 2


View Profile Email
« Reply #126 on: December 17, 2009, 11:36:29 »

Hi everyone,

Is there any possibility in runtime to get the list of all possible transitions from current state and the list of actions initiating these transitions as well? For instance I want to make a mediator that handles StateMachine.CHANGED notification and creates the button for every possible transition (onClick handler initiates sendNotification(StateMachine.ACTION, null, Actions.SOME_ACTION)). How can I do that?

thanks in advance
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #127 on: December 17, 2009, 12:55:16 »

from the top of my head, you can get the current state using getViewComponent() on the StateMachine mediator.

For accessing stuff from the State, you 'ld need to subclass it, and add a "get all actions" method.
However, you couldn't use the standard FSMInjector for creating that class, but you could subclass it, or roll you own.

that answer you?

cheers
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #128 on: December 18, 2009, 10:19:42 »

Is there any possibility in runtime to get the list of all possible transitions from current state and the list of actions initiating these transitions as well?

Without subclassing or breaking the encapsulation of the StateMachine, you could instead preserve the XML that the InjectFSMCommand uses to initialize the FSMInjector. While the InjectFSMCommand has the XML in hand, have it instantiate and register a Proxy to hold onto the FSM for later recall:

First cut InjectFSMCommand
:
override public function execute ( note:INotification ) : void
{
// Create the FSM definition
var fsm:XML =
<fsm initial={FSMConstants.INTERNET_CHECKING}>

<state name={FSMConstants.INTERNET_CHECKING}>
<transition action={FSMConstants.INTERNET_ONLINE} target={FSMConstants.UPDATE_CHECKING}/>
<transition action={FSMConstants.INTERNET_OFFLINE} target={FSMConstants.INACTIVE}/>
</state>

<state name={FSMConstants.INACTIVE}>
<transition action={FSMConstants.INTERNET_ONLINE} target={FSMConstants.UPDATE_CHECKING}/>
</state>

<state name={FSMConstants.UPDATE_CHECKING} changed={FSMConstants.CHECK_FOR_UPDATE}>
<transition action={FSMConstants.UPDATE_PENDING} target={FSMConstants.UPDATE_AVAILABLE}/>
<transition action={FSMConstants.NO_UPDATE_PENDING} target={FSMConstants.LICENSE_CHECKING}/>
</state>
.
.
.
</fsm>;

// Create and inject the StateMachine
var injector:FSMInjector = new FSMInjector( fsm );
injector.initializeNotifier(this.multitonKey); // if using MultiCore
injector.inject();

// Stash the FSM for later reference
facade.registerProxy( new Proxy( FSMConstants.ProxyName, fsm ) );
}

Notice you don't even have to create a new Proxy class (unless you want to give it some convenience methods for querying the XML structure. Otherwise you just retrieve the proxy and get its data, casting to XML.

Later in your Mediator, you could do something like this:

First cut MyMediator
:
override public function handleNotification( note:INotification ):void
{
switch ( note.getName() )
{
case StateMachine.CHANGED:
var state:State = note.getBody() as State;
var fsm:XML = facade.retrieveProxy(FSMConstants.ProxyName).getData() as XML;
var transitions:XMLList = fsm.state.(@name==state.name)..transition;
var actions:Array;
for each (var transition:XML in transitions);
{
actions.push (transition.@action.toString);
}
myViewComponent.addButtons(actions);
break;

.
.
.
}
}

That should come close to solving the problem, but it's the brute force implementation though. It puts too much domain logic in the Mediator. What if another Mediator needed to do something a similar? You'd soon find your Mediators doing lots of local XML manipulation, and likely repeating some of it.

So, we would probably want to refactor/move this domain logic out of the mediator and into a custom FSMProxy class.

Second cut FSMProxy
:

public class FSMProxy extends Proxy
{
public static const NAME:String = 'FSMProxy';

public function FSMProxy( fsm:XML )
{
super ( NAME, fsm );
}

// Return a list of valid actions for the given state as an array of strings
public function getActionsForState( state:State ):Array
{
var transitions:XMLList = fsm.state.(@name==state.name)..transition;
var actions:Array;
for each (var transition:XML in transitions);
{
actions.push (transition.@action.toString);
}
return actions;
}

private function get fsm():XML
{
return data as XML;
}
}


Second cut InjectFSMCommand
:
override public function execute ( note:INotification ) : void
{
.
.
.

// Stash the FSM for later reference
facade.registerProxy( new FSMProxy( fsm ) );

}

Now we can simplify the Mediator and remove the domain logic:

Second cut MyMediator
:
private var fsmProxy:FSMProxy;
override public function onRegister():void
{
    facade.retrieveProxy(FSMProxy.NAME);
}

override public function handleNotification( note:INotification ):void
{
switch ( note.getName() )
{
case StateMachine.CHANGED:
var state:State = note.getBody() as State;
var actions:Array = fsmProxy.getActionsForState(state);
myViewComponent.addButtons( actions );
break;

.
.
.
}
}

-=Cliff>
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #129 on: December 18, 2009, 11:01:15 »

Hey, nice thinking cliff :)
Logged
Djaffy
Newbie
*
Posts: 2


View Profile Email
« Reply #130 on: December 18, 2009, 02:59:53 »

Cliff and Neil, thank you guys! ))
Logged
Neil Manuell
Courseware Beta
Sr. Member
***
Posts: 109


View Profile Email
« Reply #131 on: December 22, 2009, 05:16:43 »

Actually, Cliff, mind if I use this Idea for my Domino project... it's a nice solution for a similar problem I was pondering on...
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #132 on: December 27, 2009, 11:46:13 »

By all means, if it helps.
 :D
-=Cliff>
Logged
emurphy
Jr. Member
**
Posts: 19


View Profile Email
« Reply #133 on: May 07, 2010, 07:31:14 »

So I would like to be able to define sub-FSMs, for lack of a better term. Here is an example for why:

Say I have an application that has a menu with items/states A, B, and C. I select item B and I now am brought to a complex form with states X, Y, and Z. If the main menu is still accessible then I could be half way through the form and change to item C. I would want state B to be able to respond to this rather than having states X, Y, and Z be able to handle it. That would make things a lot simpler. Is this possible without having separate cores that have separate FSMs? Can I make a hierarchical FSM?

I'm new to using this utility and may be missing something.
Logged
puremvc
Global Moderator
Hero Member
*****
Posts: 2871



View Profile WWW Email
« Reply #134 on: May 08, 2010, 12:48:48 »

Two answers here.

First is separating view state from application state. That form with states x,y and z is actually a view component in charge of maintaining its own states. Flex has a very nice facility for this but even without it, its not much of a problem for a component to properly encapsulate this behavior.

Second is with MultiCore you can have an FSM per core.

-=Cliff>
Logged
Pages: 1 ... 7 8 [9] 10
Print