File Coverage

blib/lib/POE/Component/AI/MegaHAL.pm
Criterion Covered Total %
statement 66 97 68.0
branch 13 32 40.6
condition 4 12 33.3
subroutine 14 17 82.3
pod 3 3 100.0
total 100 161 62.1


line stmt bran cond sub pod time code
1             package POE::Component::AI::MegaHAL;
2             $POE::Component::AI::MegaHAL::VERSION = '1.20';
3             #ABSTRACT: A non-blocking wrapper around AI::MegaHAL.
4              
5 1     1   22350 use strict;
  1         3  
  1         35  
6 1     1   5 use warnings;
  1         2  
  1         38  
7 1     1   650 use AI::MegaHAL;
  1         6734  
  1         118  
8 1     1   681 use POE qw(Wheel::Run Filter::Line Filter::Reference);
  1         33400  
  1         6  
9 1     1   63860 use Carp;
  1         1  
  1         851  
10              
11             sub spawn {
12 1     1 1 762 my $package = shift;
13 1         4 my %params = @_;
14              
15 1         9 $params{ lc $_ } = delete $params{$_} for keys %params;
16 1 50 33     9 $params{'autosave'} = 1 unless defined ( $params{'autosave'} ) and $params{'autosave'} eq '0';
17 1         2 my $options = delete $params{'options'};
18 1         2 my $self = bless \%params, $package;
19              
20 1 50       17 POE::Session->create(
21             object_states => [
22             $self => {
23             do_reply => '_megahal_function',
24             initial_greeting => '_megahal_function',
25             learn => '_megahal_function',
26             _cleanup => '_megahal_function',
27             },
28             $self => [ qw(_child_closed _child_error _child_stderr _child_stdout _start shutdown _sig_chld) ],
29             ],
30             ( ref ( $options ) eq 'HASH' ? ( options => $options ) : () ),
31             );
32              
33 1         180 return $self;
34             }
35              
36             sub session_id {
37 5     5 1 3801 return $_[0]->{session_id};
38             }
39              
40             sub _megahal_function {
41 4     4   355 my ($kernel,$self,$state) = @_[KERNEL,OBJECT,STATE];
42 4         10 my $sender = $_[SENDER]->ID();
43 4 50       42 return if $self->{shutdown};
44              
45 4         5 my $args;
46              
47 4 50       17 if ( ref( $_[ARG0] ) eq 'HASH' ) {
48 4         3 $args = { %{ $_[ARG0] } };
  4         13  
49             }
50             else {
51 0         0 warn "first parameter must be a hashref, trying to adjust. "
52             ."(fix this to get rid of this message)";
53 0         0 $args = { @_[ARG0..$#_] };
54             }
55              
56 4 50       12 unless ( $args->{event} ) {
57 0         0 warn "where am i supposed to send the output?";
58 0         0 return;
59             }
60              
61              
62 4 50 33     51 return if $state =~ /^(do_reply|learn)$/ and !defined $args->{text};
63              
64 4 50 33     16 delete $args->{text} if $state eq 'initial_greeting' and defined $args->{text};
65              
66 4 50 33     11 delete $args->{text} if $state eq '_cleanup' and defined $args->{text};
67              
68 4         6 $args->{sender} = $sender;
69 4         8 $args->{func} = $state;
70 4         19 $kernel->refcount_increment( $sender => __PACKAGE__ );
71 4         96 $args->{sender} = $sender;
72              
73 4 50       31 $self->{wheel}->put( $args ) if defined $self->{wheel};
74 4         512 return;
75             }
76              
77             sub _start {
78 1     1   197 my ($kernel,$self) = @_[KERNEL,OBJECT];
79 1         3 $self->{session_id} = $_[SESSION]->ID();
80              
81 1 50       5 if ( $self->{alias} ) {
82 0         0 $kernel->alias_set( $self->{alias} );
83             } else {
84 1         4 $kernel->refcount_increment( $self->{session_id} => __PACKAGE__ );
85             }
86              
87             $self->{wheel} = POE::Wheel::Run->new(
88             Program => \&_main,
89 1 50       36 ProgramArgs => [ AutoSave => $self->{autosave}, Path => $self->{path} ],
90             ErrorEvent => '_child_error',
91             CloseEvent => '_child_closed',
92             StdoutEvent => '_child_stdout',
93             StderrEvent => '_child_stderr',
94             StdioFilter => POE::Filter::Reference->new(),
95             StderrFilter => POE::Filter::Line->new(),
96             ( $^O eq 'MSWin32' ? ( CloseOnCall => 0 ) : ( CloseOnCall => 1 ) ),
97             );
98              
99 1         2705 $kernel->sig_child( $self->{wheel}->PID, '_sig_chld' );
100 1         223 return;
101             }
102              
103             sub _sig_chld {
104 1     1   1824 $_[KERNEL]->sig_handled();
105             }
106              
107             sub _child_closed {
108 0     0   0 delete $_[OBJECT]->{wheel};
109 0         0 return;
110             }
111              
112             sub _child_error {
113 1     1   653 delete $_[OBJECT]->{wheel};
114 1         230 return;
115             }
116              
117             sub _child_stderr {
118 1     1   1133808 my ($kernel,$self,$input) = @_[KERNEL,OBJECT,ARG0];
119 1 50       6 warn $input . "\n" if $self->{debug};
120 1         4 return;
121             }
122              
123             sub _child_stdout {
124 4     4   3518310 my ($kernel,$self,$input) = @_[KERNEL,OBJECT,ARG0];
125 4         12 my $sender = delete $input->{sender};
126 4         9 my $event = delete $input->{event};
127 4         19 $kernel->post( $sender => $event => $input );
128 4         460 $kernel->refcount_decrement( $sender => __PACKAGE__ );
129 4         153 return;
130             }
131              
132             sub shutdown {
133 1     1 1 41 my ($kernel,$self) = @_[KERNEL,OBJECT];
134 1         20 $kernel->alias_remove( $_ ) for $kernel->alias_list();
135 1 50       35 $kernel->refcount_decrement( $self->{session_id} => __PACKAGE__ ) unless $self->{alias};
136 1         27 $self->{shutdown} = 1;
137 1         5 $self->{wheel}->shutdown_stdin;
138 1         150 return;
139             }
140              
141             sub _main {
142 0     0     my %params = @_;
143 0 0         if ( $^O eq 'MSWin32' ) {
144 0           binmode(STDIN); binmode(STDOUT);
  0            
145             }
146 0           my $raw;
147 0           my $size = 4096;
148 0           my $filter = POE::Filter::Reference->new();
149 0           my $megahal;
150 0           eval {
151 0           $megahal = AI::MegaHAL->new( %params );
152             };
153              
154 0 0         if ( $@ ) {
155 0           print STDERR $@ . "\n";
156 0           return;
157             }
158              
159 0           while ( sysread ( STDIN, $raw, $size ) ) {
160 0           my $requests = $filter->get( [ $raw ] );
161 0           _process_requests( $megahal, $_, $filter ) for @{ $requests };
  0            
162             }
163 0 0         $megahal->_cleanup() if $params{'AutoSave'};
164 0           $megahal->DESTROY;
165             }
166              
167             sub _process_requests {
168 0     0     my ($megahal,$req,$filter) = @_;
169              
170 0           my $func = $req->{func};
171 0           $req->{reply} = $megahal->$func( $req->{text} );
172 0           my $response = $filter->put( [ $req ] );
173 0           print STDOUT @$response;
174             }
175              
176             qq[You talking to me];
177              
178             __END__