File Coverage

blib/lib/Number/Phone/JP/AreaCode.pm
Criterion Covered Total %
statement 85 85 100.0
branch 12 12 100.0
condition 5 6 83.3
subroutine 17 17 100.0
pod 4 4 100.0
total 123 124 99.1


line stmt bran cond sub pod time code
1             package Number::Phone::JP::AreaCode;
2 5     5   5728 use 5.008005;
  5         18  
  5         261  
3 5     5   24 use strict;
  5         9  
  5         134  
4 5     5   34 use warnings;
  5         8  
  5         113  
5 5     5   3194 use utf8;
  5         29  
  5         20  
6 5     5   3976 use parent qw/Exporter/;
  5         1466  
  5         26  
7 5     5   9650 use Encode;
  5         64316  
  5         489  
8 5     5   4924 use Lingua::JA::Numbers;
  5         230053  
  5         844  
9 5     5   5064 use Lingua::JA::Regular::Unicode qw/alnum_h2z/;
  5         66165  
  5         541  
10 5     5   16499 use Number::Phone::JP::AreaCode::Data::Address2AreaCode;
  5         20  
  5         480  
11 5     5   7529 use Number::Phone::JP::AreaCode::Data::AreaCode2Address;
  5         21  
  5         5566  
12              
13             our $VERSION = "20131201.2";
14             our @EXPORT_OK = qw/
15             area_code_by_address
16             area_code_by_address_prefix_match
17             area_code_by_address_fuzzy
18             address_by_area_code
19             /;
20              
21             sub area_code_by_address {
22 9     9 1 32 my ($address) = @_;
23              
24 9         33 my ($prefecture, $town) = _separate_address($address);
25 9         45 return get_address2areacode_map()->{$prefecture}->{$town};
26             }
27              
28             sub area_code_by_address_prefix_match {
29 9     9 1 29 my ($address) = @_;
30              
31 9         29 my ($prefecture, $town) = _separate_address($address);
32 9         45 my $pref_map = get_address2areacode_map()->{$prefecture};
33 9         27 return _search_area_code_by_address_recursive($pref_map, $town);
34             }
35              
36             sub area_code_by_address_fuzzy {
37 4     4 1 20 my ($address) = @_;
38              
39 4         22 my ($prefecture, $town) = _separate_address($address);
40 4         24 my $pref_map = get_address2areacode_map()->{$prefecture};
41              
42 4 100       37 if (exists $pref_map->{$town}) {
43 1         15 return {"$prefecture$town" => $pref_map->{$town}};
44             }
45              
46 3         8 my $hits = {};
47 3         121 for my $key (keys %$pref_map) {
48 453 100 100     5497 if ($town =~ $key || $key =~ $town) {
49 5         27 $hits->{"$prefecture$key"} = $pref_map->{$key};
50             }
51             }
52 3         71 return $hits;
53             }
54              
55             sub address_by_area_code {
56 5     5 1 17 my ($area_code) = @_;
57              
58 5         19 $area_code =~ s/\A0//;
59 5         21 return get_areacode2address_map()->{$area_code};
60             }
61              
62             sub _search_area_code_by_address_recursive {
63 17     17   31 my ($pref_map, $town) = @_;
64              
65 17 100       59 if (exists $pref_map->{$town}) {
66 8         124 return $pref_map->{$town};
67             }
68              
69 9         109 $town = _minimum_substitute_by_municipality($town);
70              
71             # One character or less (e.g. "町")
72 9 100 66     58 if (!$town || length $town <= 1) {
73 1         10 return;
74             }
75              
76 8         40 return _search_area_code_by_address_recursive($pref_map, $town);
77             }
78              
79             sub _separate_address {
80 22     22   45 my ($address) = @_;
81              
82 22         42 eval { $address = Encode::decode_utf8($address) }; # decode (but not twice)
  22         105  
83              
84 22         878 my ($prefecture, $town) = $address =~ /\A(京都府|東京都|大阪府|北海道|.+?県)(.*)/;
85 22         77 $town =~ s/大字//g; # XXX ignore "大字"
86              
87             # Support numerical number (hankaku / zenkaku)
88 22         65 for my $num (0..9) {
89 220         792 my $kanji_num = num2ja($num);
90 220         18094 my $zenkaku_num = alnum_h2z($num);
91 220         11418 $town =~ s/(:?$num|$zenkaku_num)/$kanji_num/g;
92             }
93              
94 22         87 return ($prefecture, $town);
95             }
96              
97             sub _minimum_substitute_by_municipality {
98 9     9   203 my ($town) = @_;
99              
100 9         15 my @substitutes;
101 9         31 (my $block = $town) =~ s/区.*?\Z/区/; push @substitutes, $block;
  9         20  
102 9         54 (my $city = $town) =~ s/市.*?\Z/市/; push @substitutes, $city;
  9         21  
103 9         23 (my $group = $town) =~ s/郡.*?\Z/郡/; push @substitutes, $group;
  9         17  
104 9         42 (my $cho = $town) =~ s/町.*?\Z/町/; push @substitutes, $cho;
  9         21  
105 9         21 (my $village = $town) =~ s/村.*?\Z/村/; push @substitutes, $village;
  9         14  
106              
107 9         14 my $minimum_substituted = '';
108 9         19 for my $substituted (@substitutes) {
109 45 100       102 next if $substituted eq $town;
110 12 100       38 if (length $substituted > length $minimum_substituted) {
111 11         24 $minimum_substituted = $substituted;
112             }
113             }
114              
115 9         37 return $minimum_substituted;
116             }
117              
118             1;
119             __END__