File Coverage

blib/lib/Chemistry/PeriodicTable.pm
Criterion Covered Total %
statement 93 93 100.0
branch 17 20 85.0
condition 16 18 88.8
subroutine 17 17 100.0
pod 7 7 100.0
total 150 155 96.7


line stmt bran cond sub pod time code
1             package Chemistry::PeriodicTable;
2             our $AUTHORITY = 'cpan:GENE';
3              
4             # ABSTRACT: Provide access to chemical element properties
5              
6             our $VERSION = '0.0400';
7              
8 1     1   1229 use Moo;
  1         11232  
  1         5  
9 1     1   1937 use strictures 2;
  1         1594  
  1         39  
10 1     1   195 use Carp qw(croak);
  1         3  
  1         45  
11 1     1   546 use File::ShareDir qw(dist_dir);
  1         27767  
  1         61  
12 1     1   542 use List::SomeUtils qw(first_index);
  1         9829  
  1         68  
13 1     1   960 use Text::CSV_XS ();
  1         19385  
  1         32  
14 1     1   472 use namespace::clean;
  1         7911  
  1         6  
15              
16              
17             has symbols => (is => 'lazy', init_args => undef);
18              
19             sub _build_symbols {
20 1     1   34 my ($self) = @_;
21 1         3 my $symbols = $self->as_hash;
22 1         9 return $symbols;
23             }
24              
25              
26             has header => (is => 'lazy', init_args => undef);
27              
28             sub _build_header {
29 1     1   38 my ($self) = @_;
30 1         4 my @headers = $self->headers;
31 1         9 return \@headers;
32             }
33              
34              
35             sub as_file {
36 5     5 1 2077 my ($self) = @_;
37              
38 5         11 my $file = eval { dist_dir('Chemistry-PeriodicTable') . '/Periodic-Table.csv' };
  5         13  
39 5 50 33     645 $file = 'share/Periodic-Table.csv'
40             unless $file && -e $file;
41              
42 5         22 return $file;
43             }
44              
45              
46             sub as_hash {
47 2     2 1 6 my ($self) = @_;
48              
49 2         6 my $file = $self->as_file;
50              
51 2         4 my %data;
52              
53 2         15 my $csv = Text::CSV_XS->new({ binary => 1 });
54              
55 2 50       301 open my $fh, '<', $file
56             or die "Can't read $file: $!";
57              
58 2         8 my $counter = 0;
59              
60 2         75 while (my $row = $csv->getline($fh)) {
61 238         8032 $counter++;
62              
63             # skip the first row
64 238 100       462 next if $counter == 1;
65              
66 236         4799 $data{ $row->[2] } = $row;
67             }
68              
69 2         91 close $fh;
70              
71 2         22 return \%data;
72             }
73              
74              
75             sub headers {
76 2     2 1 331 my ($self) = @_;
77              
78 2         6 my $file = $self->as_file;
79              
80 2         4 my @headers;
81              
82 2         22 my $csv = Text::CSV_XS->new({ binary => 1 });
83              
84 2 50       370 open my $fh, '<', $file
85             or die "Can't read $file: $!";
86              
87 2         115 while (my $row = $csv->getline($fh)) {
88 2         161 push @headers, @$row;
89 2         6 last;
90             }
91              
92 2         51 close $fh;
93              
94 2         39 return @headers;
95             }
96              
97              
98             sub number {
99 2     2 1 7 my ($self, $string) = @_;
100 2         5 my $n;
101 2 100       8 if (length $string < 4) {
102 1         40 $n = $self->symbols->{ ucfirst $string }[0];
103             }
104             else {
105 1         4 for my $symbol (keys %{ $self->symbols }) {
  1         25  
106 118 100       2422 if (lc $self->symbols->{$symbol}[1] eq lc $string) {
107 1         21 $n = $self->symbols->{$symbol}[0];
108             }
109             }
110             }
111 2         37 return $n;
112             }
113              
114              
115             sub name {
116 2     2 1 6 my ($self, $string) = @_;
117 2         5 my $n;
118 2         4 for my $symbol (keys %{ $self->symbols }) {
  2         45  
119 134 100 100     4243 if (
      100        
120             ($string =~ /^\d+$/ && $self->symbols->{$symbol}[0] == $string)
121             ||
122             (lc $self->symbols->{$symbol}[2] eq lc $string)
123             ) {
124 2         45 $n = $self->symbols->{$symbol}[1];
125 2         15 last;
126             }
127             }
128 2         18 return $n;
129             }
130              
131              
132             sub symbol {
133 4     4 1 10 my ($self, $string) = @_;
134 4         6 my $s;
135 4         8 for my $symbol (keys %{ $self->symbols }) {
  4         79  
136 232 100 100     7030 if (
      100        
137             ($string =~ /^\d+$/ && $self->symbols->{$symbol}[0] == $string)
138             ||
139             (lc $self->symbols->{$symbol}[1] eq lc $string)
140             ) {
141 4         33 $s = $symbol;
142 4         9 last;
143             }
144             }
145 4         33 return $s;
146             }
147              
148              
149             sub value {
150 3     3 1 9 my ($self, $key, $string) = @_;
151 3         4 my $v;
152 3     19   16 my $idx = first_index { $_ =~ /$string/i } @{ $self->header };
  19         80  
  3         70  
153 3 100 100     27 if ($key !~ /^\d+$/ && length $key < 4) {
154 1         20 $v = $self->symbols->{$key}[$idx];
155             }
156             else {
157 2         7 $key = $self->symbol($key);
158 2         5 for my $symbol (keys %{ $self->symbols }) {
  2         33  
159 98 100       199 next unless $symbol eq $key;
160 2         31 $v = $self->symbols->{$symbol}[$idx];
161 2         16 last;
162             }
163             }
164 3         32 return $v;
165             }
166              
167             1;
168              
169             __END__