File Coverage

blib/lib/App/Gimei/Runner.pm
Criterion Covered Total %
statement 89 89 100.0
branch 26 28 92.8
condition 22 22 100.0
subroutine 15 15 100.0
pod 0 6 0.0
total 152 160 95.0


line stmt bran cond sub pod time code
1             package App::Gimei::Runner;
2              
3 7     7   15787 use warnings;
  7         53  
  7         217  
4 7     7   92 use v5.22;
  7         27  
5             binmode STDOUT, ":utf8";
6              
7 7     7   5413 use Getopt::Long;
  7         98476  
  7         47  
8 7     7   4622 use Pod::Usage;
  7         605225  
  7         891  
9 7     7   67 use Pod::Find qw( pod_where );
  7         14  
  7         420  
10              
11 7     7   3170 use App::Gimei;
  7         19  
  7         202  
12 7     7   3122 use Data::Gimei;
  7         285102  
  7         227  
13              
14 7     7   57 use Class::Tiny;
  7         12  
  7         28  
15              
16             #
17             # global vars
18             #
19              
20             my %conf = ( POD_FILE => pod_where( { -inc => 1 }, 'App::Gimei' ) );
21              
22             #
23             # methods
24             #
25              
26             sub parse_option {
27 36     36 0 90 my ( $self, $args_ref, $opts_ref ) = @_;
28              
29 36         85 $opts_ref->{n} = 1;
30 36         82 $opts_ref->{sep} = ', ';
31              
32 36         246 my $p = Getopt::Long::Parser->new( config => ["no_ignore_case"], );
33              
34 36     1   3193 local $SIG{__WARN__} = sub { die "Error: $_[0]" };
  1         640  
35 36         159 my $ok = $p->getoptionsfromarray( $args_ref, $opts_ref, "help|h", "version|v", "n=i",
36             "sep=s", );
37              
38 35 100       15489 if ( $opts_ref->{n} < 1 ) {
39 1         14 die
40             "Error: value $opts_ref->{n} invalid for option n (must be positive number)\n";
41             }
42             }
43              
44             sub execute {
45 36     36 0 137510 my ( $self, @args ) = @_;
46              
47 36         73 my %opts;
48 36         144 $self->parse_option( \@args, \%opts );
49              
50 34 100       143 if ( $opts{version} ) {
51 2         141 say "$App::Gimei::VERSION";
52 2         18 return 0;
53             }
54              
55 32 100       108 if ( $opts{help} ) {
56 2         12 pod2usage( -input => $conf{POD_FILE}, -exitval => 'noexit' );
57 2         30319 return 0;
58             }
59              
60 30 100       79 if ( !@args ) {
61 3         14 push @args, 'name:kanji';
62             }
63              
64 30         112 foreach ( 1 .. $opts{n} ) {
65 31         365 my %words = (
66             name => Data::Gimei::Name->new(),
67             male => Data::Gimei::Name->new( gender => 'male' ),
68             female => Data::Gimei::Name->new( gender => 'female' ),
69             address => Data::Gimei::Address->new()
70             );
71              
72 31         462557 my @results;
73 31         89 foreach my $arg (@args) {
74 32         160 my @tokens = split( /[-:]/, $arg );
75 32         100 push @results, execute_tokens( \@tokens, \%words );
76             }
77              
78 26         2619 say join $opts{sep}, @results;
79             }
80              
81 25         2690 return 0;
82             }
83              
84             #
85             # functions ...
86             #
87              
88             # ARG: [WORD_TYPE] [':' WORD_SUB_TYPE] [':' RENDERING]
89             # WORD_TYPE: 'name' | 'address'
90             # WORD_SUBTYPE(name): 'family' | 'given'
91             # WORD_SUBTYPE(address): 'prefecture' | 'city' | 'town'
92             # RENDERING: 'kanji' | 'hiragana' | 'katakana' | 'romaji'
93             sub execute_tokens {
94 32     32 0 67 my ( $tokens_ref, $words_ref ) = @_;
95 32         58 my ( $word_type, $word, $token );
96              
97 32         68 $token = shift @$tokens_ref;
98 32 100 100     206 if ( $token eq 'name' || $token eq 'male' || $token eq 'female' ) {
    100 100        
99 20         63 ( $word, $word_type ) = subtype_name( $tokens_ref, $words_ref->{$token} );
100             } elsif ( $token eq 'address' ) {
101 11         40 ( $word, $word_type ) = subtype_address( $tokens_ref, $words_ref->{$token} );
102             } else {
103 1         13 die "Error: unknown word_type: $token\n";
104             }
105              
106 31         84 return render( $tokens_ref, $word_type, $word );
107             }
108              
109             sub subtype_name {
110 20     20 0 43 my ( $tokens_ref, $word ) = @_;
111 20         34 my ( $token, $subtype, $call, $word_type );
112              
113 20         147 my %map = (
114             'family' => [ 'surname', 'name' ],
115             'last' => [ 'surname', 'name' ],
116             'given' => [ 'forename', 'name' ],
117             'first' => [ 'forename', 'name' ],
118             'gender' => [ 'gender', 'gender' ],
119             'sex' => [ 'gender', 'gender' ],
120             );
121              
122 20         38 $word_type = 'name';
123 20   100     97 $token = @$tokens_ref[0] // '';
124 20 100       63 if ( my $m = $map{$token} ) {
125 10         19 shift @$tokens_ref;
126 10 50       64 $call = $word->can( $m->[0] ) or die "system err";
127 10         212 $word = $word->$call();
128 10         80 $word_type = $m->[1];
129             }
130              
131 20         91 return ( $word, $word_type );
132             }
133              
134             sub subtype_address {
135 11     11 0 30 my ( $tokens_ref, $word ) = @_;
136              
137 11   100     40 my $token = @$tokens_ref[0] // '';
138 11 100 100     81 if ( $token eq 'prefecture' || $token eq 'city' || $token eq 'town' ) {
      100        
139 7         31 shift @$tokens_ref;
140 7         30 my $call = $word->can($token);
141 7 50       21 die "system error" if ( !$call );
142 7         156 $word = $word->$call();
143             }
144              
145 11         80 return ( $word, 'address' );
146             }
147              
148             # romaji not supported in WORD_TYPE = 'address'
149             sub render {
150 31     31 0 73 my ( $tokens_ref, $word_type, $word ) = @_;
151              
152 31         62 my $token = @$tokens_ref[0];
153 31 100 100     108 if ( !$token || $token eq 'name' ) {
154 21         36 $token = "kanji";
155             }
156              
157 31 100 100     106 if ( $word_type eq 'address' && $token eq 'romaji' ) {
158 2         24 die "Error: unknown subtype or rendering: $token\n";
159             }
160              
161 29 100       66 if ( $word_type eq 'gender' ) {
162 3         15 return $word;
163             }
164              
165 26         109 my $call = $word->can($token);
166 26 100       86 die "Error: unknown subtype or rendering: $token\n" if ( !$call );
167              
168 24         269 return $word->$call();
169             }
170              
171             1;