File Coverage

blib/lib/Lingua/ZH/ZhuYin.pm
Criterion Covered Total %
statement 60 106 56.6
branch 14 44 31.8
condition 4 15 26.6
subroutine 10 10 100.0
pod 3 3 100.0
total 91 178 51.1


line stmt bran cond sub pod time code
1             package Lingua::ZH::ZhuYin;
2              
3 2     2   46584 use warnings;
  2         6  
  2         57  
4 2     2   9 use strict;
  2         5  
  2         59  
5 2     2   6603 use utf8;
  2         24  
  2         11  
6              
7             =head1 NAME
8              
9             Lingua::ZH::ZhuYin - The great new Lingua::ZH::ZhuYin!
10              
11             =head1 VERSION
12              
13             Version 0.04
14              
15             =cut
16              
17             our $VERSION = '0.04';
18             our $AUTOLOAD;
19             our %ok_field;
20 2     2   1984 use Encode qw/decode/;
  2         24987  
  2         189  
21 2     2   18 use List::Util qw/min max/;
  2         4  
  2         194  
22 2     2   1331 use Lingua::ZH::ZhuYin::Dict;
  2         7  
  2         2730  
23              
24              
25             =head1 SYNOPSIS
26              
27             Quick summary of what the module does.
28              
29             Perhaps a little code snippet.
30              
31             use Lingua::ZH::ZhuYin;
32              
33             my $foo = Lingua::ZH::ZhuYin->new();
34             my $zhuyin = $foo->zhuyin($phrase);
35             ...
36              
37             =head1 EXPORT
38              
39             A list of functions that can be exported. You can delete this section
40             if you don't export anything, such as for a purely object-oriented module.
41              
42             =head1 FUNCTIONS
43              
44             =head2 AUTOLOAD
45              
46             =cut
47              
48             for my $attr ( qw(dictfile) ) { $ok_field{$attr}++; }
49              
50             sub AUTOLOAD {
51 4     4   6 my $self = shift;
52 4         7 my $attr = $AUTOLOAD;
53 4         19 $attr =~ s/.*:://;
54 4 50       11 return if $attr eq 'DESTROY';
55              
56 4 50       11 if ($ok_field{$attr}) {
57 4 50       10 $self->{lc $attr} = shift if @_;
58 4         26 return $self->{lc $attr};
59             } else {
60 0         0 my $superior = "SUPER::$attr";
61 0         0 $self->$superior(@_);
62             }
63             }
64              
65             =head2 new
66              
67             =cut
68              
69             sub new {
70 1     1 1 76 my $class = shift;
71 1         3 my $self = {
72             dictfile => undef,
73             };
74 1 50       4 if(@_) {
75 1         3 my %arg = @_;
76              
77 1         3 foreach (keys %arg) {
78 1         5 $self->{lc($_)} = $arg{$_};
79             }
80             }
81 1         2 bless ($self, $class);
82 1         3 return($self);
83             }
84              
85             =head2 zhuyin
86              
87             =cut
88              
89             sub zhuyin {
90 2     2 1 6 my $self = shift;
91 2         3 my $word = shift;
92 2 50       12 die "DictFile does not exist" unless $self->dictfile;
93 2         11 my $utf8word = decode('utf8',$word);
94 2         108 my @zhuyins = $self->guess_zhuyin($word);
95 2 50 33     8 push @zhuyins , $utf8word if (! @zhuyins and length($utf8word) == 1);
96 2 50       7 return '' if $zhuyins[0] eq '0';
97 2 50       5 warn 'no zhuyin found: '.$word if ! @zhuyins;
98 2         15 return \@zhuyins;
99             }
100              
101             =head2 guess_zhuyin
102              
103             =cut
104              
105             sub guess_zhuyin {
106 2     2 1 3 my $self = shift;
107 2         4 my $word = shift;
108             # perform guess zhuyin from ABCDE, ABCD E, ABC DE, AB CDE, A BCDE
109 2         4 my @zhuyins;
110 2         9 my $Dict = Lingua::ZH::ZhuYin::Dict->new($self->dictfile);
111 2         9 for my $i (0..(length($word) - 1)) {
112 2         4 @zhuyins = ();
113 2         3 my $offset = length($word) - $i;
114 2         6 my $pre_word = substr($word,0,$offset);
115 2         3 my $post_word = '';
116 2 50       5 $post_word = substr($word,$offset) if $i > 0;
117 2         3 my $skip = 1;
118 2 50       6 die "word error " unless $word eq $pre_word.$post_word;
119 2 50 33     20 if ($pre_word and $pre_word ne "") {
120 2         8 my @pre_zhuyins = $Dict->queryZhuYin($pre_word);
121 2 50       9 $skip = 0 if @pre_zhuyins;
122 2         5 push @zhuyins, @pre_zhuyins;
123             }
124 2 50 33     14 if ($skip == 0 and $post_word and $post_word ne "") {
      33        
125 0         0 $skip = 1;
126 0         0 my @post_zhuyins = $Dict->queryZhuYin($post_word);
127 0 0       0 $skip = 0 if @post_zhuyins;
128 0         0 my @tmp_zhuyins = ();
129 0         0 foreach my $j (0..$#zhuyins) {
130 0         0 foreach my $yin (@post_zhuyins) {
131 0         0 push @tmp_zhuyins, $zhuyins[$j] ." ". $yin;
132             }
133             }
134 0         0 @zhuyins = @tmp_zhuyins;
135             }
136 2 50       172 return @zhuyins if $skip == 0;
137             }
138              
139 0 0         return if length($word) == 1;
140             # preform A B C D E, if each term has unique zhuyin, then we done,
141             # otherwise need further process
142 0           my @array = ();
143 0           my @ambig = ();
144 0           @zhuyins = ();
145 0           my $skip = 0;
146 0           for my $i (0..(length($word) - 1)) {
147 0           my $unichar = substr($word,$i,1);
148 0           my @uni_zhuyins = $Dict->queryZhuYin($unichar);
149 0 0         return '0' unless @uni_zhuyins;
150 0 0         if (scalar @uni_zhuyins != 1) {
151 0           $array[$i] = 1;
152 0           push @ambig, $i;
153 0           $skip = 1;
154             } else {
155 0           $array[$i] = 0;
156 0           $zhuyins[$i] = $uni_zhuyins[0];
157             }
158             }
159 0 0         return @zhuyins if $skip == 0;
160              
161             # if B is amibiguos, we chcek AB, BC, ABC, BCD ...
162             # otherwise, return the first one
163 0           for my $amb (@ambig) {
164 0           my $max_length = min (max (length($word) - $amb, $amb), 4); # at most check 4-gram
165 0           my $not_found = 1;
166 0           my $len = 2;
167 0   0       while ($not_found && $len <= $max_length) {
168 0           my $pos_b = max (0, $amb - $len + 1);
169 0           my $pos_e = min (length($word), $amb);
170 0           for my $pos ($pos_b..$pos_e) {
171 0 0         next if $not_found == 0;
172 0           my @ngram_zhuyins = $Dict->queryZhuYin(substr($word,$pos,$len));
173 0 0         if (scalar @ngram_zhuyins == 1) { # yatta !!!
174 0           my @zhuyin_array = split / /,$ngram_zhuyins[0];
175 0           $zhuyins[$amb] = $zhuyin_array[$amb-$pos];
176 0           $not_found = 0;
177             }
178             }
179 0           $len++;
180             }
181 0 0         if ($not_found) { # still not found
182 0           my $unichar = substr($word,$amb,1);
183 0           my @uni_zhuyins = $Dict->queryZhuYin($unichar);
184 0           $zhuyins[$amb] = $uni_zhuyins[0];
185             }
186             }
187 0           return join " ",@zhuyins;
188             }
189              
190             =head1 AUTHOR
191              
192             Cheng-Lung Sung, C<< >>
193              
194             =head1 BUGS
195              
196             Please report any bugs or feature requests to C, or through
197             the web interface at L. I will be notified, and then you'll
198             automatically be notified of progress on your bug as I make changes.
199              
200              
201              
202              
203             =head1 SUPPORT
204              
205             You can find documentation for this module with the perldoc command.
206              
207             perldoc Lingua::ZH::ZhuYin
208              
209              
210             You can also look for information at:
211              
212             =over 4
213              
214             =item * RT: CPAN's request tracker
215              
216             L
217              
218             =item * AnnoCPAN: Annotated CPAN documentation
219              
220             L
221              
222             =item * CPAN Ratings
223              
224             L
225              
226             =item * Search CPAN
227              
228             L
229              
230             =back
231              
232              
233             =head1 ACKNOWLEDGEMENTS
234              
235              
236             =head1 COPYRIGHT & LICENSE
237              
238             Copyright 2008 Cheng-Lung Sung, all rights reserved.
239              
240             This program is free software; you can redistribute it and/or modify it
241             under the same terms as Perl itself.
242              
243              
244             =cut
245              
246             1; # End of Lingua::ZH::ZhuYin