File Coverage

blib/lib/NetHack/NAOdash.pm
Criterion Covered Total %
statement 25 27 92.5
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 34 36 94.4


line stmt bran cond sub pod time code
1             package NetHack::NAOdash;
2              
3 1     1   21250 use 5.014000;
  1         4  
  1         45  
4 1     1   6 use strict;
  1         1  
  1         32  
5 1     1   6 use warnings;
  1         7  
  1         45  
6 1     1   6 use re '/saa';
  1         2  
  1         92  
7 1     1   592 use parent qw/Exporter/;
  1         258  
  1         4  
8              
9             our $VERSION = '0.001';
10             our @EXPORT_OK = qw/naodash_xlog naodash_user/;
11             our @EXPORT = @EXPORT_OK;
12              
13 1     1   1035 use HTTP::Tiny;
  1         60280  
  1         61  
14 1     1   11 use List::Util qw/max min sum/;
  1         2  
  1         120  
15 1     1   783 use List::MoreUtils qw/uniq/;
  1         13900  
  1         8  
16 1     1   938 use Text::XLogfile qw/parse_xlogline/;
  0            
  0            
17              
18             sub won_game {
19             my %game = @_;
20             $game{death} eq 'ascended'
21             }
22              
23             our @check_subs = (
24             sub { # Combos
25             my %game = @_;
26             return unless won_game %game;
27             $game{align0} //= $game{align};
28             "combo_$game{role}_$game{race}_$game{align0}"
29             },
30              
31             sub { # Achievements
32             my %game = @_;
33             my @achieves = qw/bell gehennom candelabrum book invocation amulet endgame astral ascended luckstone sokoban medusa/;
34             map { $game{achieve} & (1 << $_) ? "achieve_$achieves[$_]" : () } 0 .. $#achieves
35             },
36              
37             sub { # Conducts
38             my %game = @_;
39             return unless won_game %game;
40             my @conducts = qw/foodless vegan vegetarian atheist weaponless pacifist illiterate polypileless polyselfless wishless artiwishless genocideless/;
41             map { $game{conduct} & (1 << $_) ? "conduct_$conducts[$_]" : () } 0 .. $#conducts
42             },
43              
44             sub { # Unofficial conducts
45             my %game = @_;
46             return unless won_game %game;
47             my @uconducts;
48             push @uconducts, 'survivor' if $game{deaths} == 0;
49             push @uconducts, 'boneless' unless $game{flags} & 32;
50             push @uconducts, 'minscore' if $game{points} - 100 * ($game{maxlvl} - 45) == 24_400;
51             map { "uconduct_$_" } @uconducts
52             },
53             );
54              
55             our %sum_subs = (
56             games => sub { 1 },
57             ascensions => sub {
58             my %game = @_;
59             !!won_game %game
60             },
61             totalrealtime => sub {
62             my %game = @_;
63             $game{realtime} // 0
64             },
65             );
66              
67             sub make_attr_sub ($) { ## no critic (ProhibitSubroutinePrototypes)
68             my ($attr) = @_;
69             sub {
70             my %game = @_;
71             return unless won_game %game;
72             $game{$attr} // ()
73             },
74             }
75              
76             our %max_subs = (
77             maxhp => make_attr_sub 'maxhp',
78             maxpoints => make_attr_sub 'points',
79             maxconducts => make_attr_sub 'nconducts',
80             );
81              
82             our %min_subs = (
83             minturns => make_attr_sub 'turns',
84             minrealtime => make_attr_sub 'realtime',
85             );
86              
87             sub naodash_xlog { ## no critic (RequireArgUnpacking)
88             my ($xlog) = join '', @_;
89             my %number_subs = (%sum_subs, %max_subs, %min_subs);
90              
91             my @checks;
92             my %numbers = map { $_ => [] } keys %number_subs;
93              
94             for my $logline (split /\n/, $xlog) {
95             my %game = %{parse_xlogline $logline};
96             for (keys %game) {
97             delete $game{$_} if $game{$_} eq ''
98             }
99             next if $game{flags} & 3; # flag 0x01 is wizard mode, 0x02 is explore mode
100             push @checks, $_->(%game) for @check_subs;
101             push @{$numbers{$_}}, $number_subs{$_}->(%game) for keys %number_subs;
102             }
103              
104             $numbers{$_} = sum @{$numbers{$_}} for keys %sum_subs;
105             $numbers{$_} = max @{$numbers{$_}} for keys %max_subs;
106             $numbers{$_} = min @{$numbers{$_}} for keys %min_subs;
107             @checks = uniq map { lc } @checks;
108              
109             {checks => [sort @checks], numbers => \%numbers}
110             }
111              
112             my $ht = HTTP::Tiny->new(agent => "NetHack-NAOdash/$VERSION ");
113              
114             sub naodash_user {
115             my ($name) = @_;
116             my $ret = $ht->get("http://alt.org/nethack/player-all-xlog.php?player=$name");
117             die 'Error while retrieving xlogfile from alt.org: ' . $ret->{status} . ' ' . $ret->{reason} . "\n" unless $ret->{success};
118             my ($xlog) = $ret->{content} =~ m{
(.*)
}i;
119             die "No xlogfile found for user $name\n" unless defined $xlog;
120             naodash_xlog $xlog;
121             }
122              
123             1;
124             __END__