File Coverage

blib/lib/Biblio/SICI/Util.pm
Criterion Covered Total %
statement 57 67 85.0
branch 8 14 57.1
condition 2 6 33.3
subroutine 10 14 71.4
pod 2 2 100.0
total 79 103 76.7


line stmt bran cond sub pod time code
1              
2             package Biblio::SICI::Util;
3             {
4             $Biblio::SICI::Util::VERSION = '0.04';
5             }
6              
7             # ABSTRACT: Utility functions
8              
9 4     4   23295 use strict;
  4         7  
  4         129  
10 4     4   21 use warnings;
  4         7  
  4         87  
11 4     4   68 use 5.010001;
  4         11  
  4         368  
12              
13             BEGIN {
14 4     4   183 $Biblio::SICI::Util::TITLE_CODE = qr/[0-9A-Z&ยด*\\\{\}\(\)\[\],\@\$=!#%.+?";\/^\`~_|-]/;
15             }
16              
17 4     4   30 use Exporter 'import';
  4         6  
  4         235  
18             our @EXPORT_OK = qw( calculate_check_char titleCode_from_title );
19              
20 4     4   3870 use Try::Tiny;
  4         6849  
  4         3280  
21              
22              
23             sub titleCode_from_title {
24 7     7 1 5743 my $title = shift;
25              
26 7 50 33     50 die "Expected title string as parameter" unless defined($title) and $title;
27              
28 7         13 my $code = '';
29              
30             try {
31 7     7   1643 require Text::Unidecode;
32             }
33             catch {
34 0     0   0 warn __PACKAGE__ . "::titleCode_from_title() - unable to load 'Text::Unidecode': " . $_;
35 7         233 };
36              
37             try {
38 7     7   1145 require Text::Undiacritic;
39             }
40             catch {
41 0     0   0 warn __PACKAGE__ . "::titleCode_from_title() - unable to load 'Text::Undiacritic': " . $_;
42 7         3637 };
43              
44 7         60115 my @words = split( /\s+/, $title );
45 7         14 my @chars = ();
46 7         141 foreach my $word (@words) {
47 41         79 my $firstChar = uc( substr( $word, 0, 1 ) );
48 41 50       200 if ( $firstChar =~ $Biblio::SICI::Util::TITLE_CODE ) {
49 41         84 push @chars, $firstChar;
50             }
51             else {
52             try {
53 0     0   0 $word = Text::Unidecode::unidecode($word);
54 0         0 };
55             try {
56 0     0   0 $word = Text::Undiacritic::undiacritic($word);
57 0         0 };
58 0         0 $firstChar = uc( substr( $word, 0, 1 ) );
59 0 0       0 if ( $firstChar =~ $Biblio::SICI::Util::TITLE_CODE ) {
60 0         0 push @chars, $firstChar;
61             }
62             }
63             }
64              
65 7 50       54 if ( @chars >= 1 ) {
66 7         25 $code = join( "", splice( @chars, 0, 6 ) );
67 7         35 return $code;
68             }
69              
70 0         0 return;
71             } ## end sub titleCode_from_title
72              
73              
74             sub calculate_check_char {
75 183     183 1 2485 my $str = shift;
76              
77 183 50 33     781 return unless defined($str) and $str;
78              
79 183         316 state $charValues = {
80             0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7,
81             8 => 8, 9 => 9, A => 10, B => 11, C => 12, D => 13, E => 14, F => 15,
82             G => 16, H => 17, I => 18, J => 19, K => 20, L => 21, M => 22, N => 23,
83             O => 24, P => 25, Q => 26, R => 27, S => 28, T => 29, U => 30, V => 31,
84             W => 32, X => 33, Y => 34, Z => 35, '#' => 36
85             };
86              
87 183         175 state $valueToChar = { reverse %{$charValues} };
  3         779  
88              
89 183         547 $str =~ s/\-[0-9A-Z#]\Z/-/o; # remove check char if present
90              
91 183         1934 my @chars = split( //, $str );
92 183         472 my @mapped = ();
93 183         204 my $i = 0;
94 183         285 foreach my $c (@chars) {
95 6759 100       9993 if ( exists $charValues->{$c} ) {
96 4773         6976 $mapped[$i] = $charValues->{$c};
97             }
98             else {
99 1986         2034 $mapped[$i] = 36;
100             }
101 6759         6462 $i++;
102             }
103              
104 183         290 my $sum = 0;
105 183         430 for ( my $j = $#mapped; $j >= 0; $j -= 2 ) {
106 3438         5542 $sum += $mapped[$j];
107             }
108              
109 183         224 $sum *= 3;
110              
111 183         454 for ( my $j = $#mapped - 1; $j >= 0; $j -= 2 ) {
112 3321         5502 $sum += $mapped[$j];
113             }
114              
115 183         236 my $mod = $sum % 37;
116              
117             # if remainder == 0; then 0 is the check char
118 183 100       387 return '0' if $mod == 0;
119              
120 179         213 my $checkVal = 37 - $mod;
121 179         301 my $checkChar = $valueToChar->{$checkVal};
122              
123 179         1452 return $checkChar;
124             } ## end sub calculate_check_char
125              
126              
127             1;
128              
129             __END__