Although I agree with the DVK for the most part, I have to say that as soon as you begin to understand arrays of hash arrays, you will reach a level of code complexity that is difficult to maintain without a lot of goals and errors.
At this point, I will probably get to the object and class, for a little syntactic sugar.
my $transitions = TransitionGraph->new(); $transition->add( 1, { targets => [ 2, 5 ] }); $transition->add( 2, { targets => [ 1, 5 ] }); $transition->add( 2, { targets => [ 2 ], conditions => [ $some_condition ] }); $transition->add( 2, { targets => [ 3, 4 ], conditions => [ $other_condition, $more_cond ]}); $transition->add( 3, { targets => [4,2] } ); $transition->add( 4, { targets => [3,2] } ); $transition->add( 5, { targets => [] } ); if( $transition->allowed( 1 , 3 )){ }
The execution of the class is user-dependent, but I would use Moose.
The main advantages of this is that you encapsulate how the state graph works, so you can just use it and worry about how the graph works separately from where it was used.
pi in the above API, add () creates a new entry if it does not exist, and updates this entry if it exists. This turned out to be easier than the βupdateβ or βget this item and then change itβ methods.
Inside, he can do it or something like this:
sub add { my ( $self , $input_state, $rules ) = @_; my $state; if ( $self->has_state( $input_state ) ) { $state = $self->get_state( $input_state ); } else { $state = TransitionGraphState->new( source_id => $input_state ); $self->add_state( $input_state, $state ); } my $targets = delete $rules{targets}; for my $target ( @$targets ) { $state->add_target( $target, $rules ); } return $self; } sub allowed { my ( $self, $from, $to ) = @_; if ( not $self->has_state( $from ) ){ croak "NO source state $from in transition graph"; } my $state = $self->get_state( $from ); return $state->allowed_to( $to ); }
This also has a cool feature, because of which it is not required that one specific set of codes work on sub-nodes, you can create separate instances with their own behavior if you want one source state to be processed differently.
$transition->add_state( 2, $some_other_class_wich_works_like_transitiongraphstate );
Hope this is helpful =).