File Coverage

blib/lib/Chess/PGN/Extract.pm
Criterion Covered Total %
statement 33 65 50.7
branch 0 8 0.0
condition n/a
subroutine 11 14 78.5
pod 1 1 100.0
total 45 88 51.1


line stmt bran cond sub pod time code
1             package Chess::PGN::Extract;
2 3     3   17535 use 5.008001;
  3         6  
  3         91  
3 3     3   13 use strict;
  3         5  
  3         87  
4 3     3   19 use warnings;
  3         4  
  3         138  
5              
6             our $VERSION = '0.02';
7              
8 3     3   12 use base 'Exporter::Tiny';
  3         2  
  3         1152  
9             our @EXPORT = qw| read_games |;
10              
11 3     3   4915 use Carp qw| carp croak |;
  3         4  
  3         223  
12 3     3   1493 use Data::Dump qw| dump |;
  3         14933  
  3         229  
13 3     3   1640 use Encode qw| encode_utf8 |;
  3         23676  
  3         224  
14 3     3   1011 use IO::Handle;
  3         9918  
  3         136  
15 3     3   1937 use JSON::XS qw| decode_json |;
  3         13328  
  3         245  
16 3     3   1487 use Sys::Cmd qw| spawn |;
  3         49890  
  3         19  
17 3     3   1773 use Try::Tiny;
  3         3308  
  3         1098  
18              
19             sub read_games {
20 0     0 1   my $pgn = shift;
21 0           my %opts = @_;
22             # TODO: add options to be passed to pgn-extract
23              
24 0           my $proc = spawn ( 'pgn-extract', '-s', '-Wjson', $pgn );
25 0           my $out = do { local $/; $proc->stdout->getline };
  0            
  0            
26 0           my @err = $proc->stderr->getlines;
27 0 0         if (@err) {
28 0 0         if ($err[0] =~ /Unknown output format json/) {
29 0           croak ("PGN parse error: pgn-extract has no '-Wjson' option");
30             }
31 0           STDERR->print ("pgn-extract: $_") for @err;
32             }
33 0           $proc->wait_child; # cleanup
34              
35             # Ad-hoc hack for a problem in parsing JSON
36             #
37             # PGN files may contain illegal characters and it hinders decoding by
38             # JSON::XS. At present, I've found the control 'B' and back quote in
39             # practice.
40 0 0         if ( $out =~ s/[\cB\\]//g ) {
41 0           STDERR->print ("Invalid characters found\n");
42             }
43              
44 0           $out = encode_utf8 ($out);
45 0           $out =~ s/\n//g;
46 0           $out =~ s/}/},/g;
47 0           chop $out;
48 0           $out = "[" . $out . "]";
49              
50             my $decoded = try {
51 0     0     decode_json ($out);
52             } catch {
53 0     0     croak ("JSON parse error: $out");
54 0           };
55              
56             # Filter valid PGNs
57             my @games = grep {
58 0 0         if ( $_->{chash} ) {
  0            
59 0           1;
60             }
61             else {
62 0           my $invalid_game = dump ($_);
63 0           STDERR->print ("Invalid PGN omitted: $invalid_game\n");
64 0           0;
65             }
66             } @$decoded;
67              
68 0           foreach (@games) {
69 0           delete $_->{chash};
70 0           delete $_->{fhash};
71             }
72              
73 0           return @games;
74             }
75              
76             1;
77             __END__