);
sub naodash_xlog { ## no critic (RequireArgUnpacking)
+ my (%args, %exclude, %include);
+ %args = %{shift()} if ref $_[0] eq 'HASH'; ## no critic (Builtin)
+ %exclude = map { $_ => 1 } @{$args{exclude_versions} // []};
+ %include = map { $_ => 1 } @{$args{include_versions} // []};
my ($xlog) = join '', @_;
my %number_subs = (%sum_subs, %max_subs, %min_subs);
for (keys %game) {
delete $game{$_} if $game{$_} eq ''
}
+ next if $exclude{$game{version}} || %include && !$include{$game{version}};
next if $game{flags} & 3; # flag 0x01 is wizard mode, 0x02 is explore mode
push @checks, $_->(%game) for @check_subs;
push @{$numbers{$_}}, $number_subs{$_}->(%game) for keys %number_subs;
scalar read_file $file
}
-sub naodash_user {
+sub naodash_user { ## no critic (RequireArgUnpacking)
+ my $args = {};
+ $args = shift if ref $_[0] eq 'HASH';
my ($name) = @_;
my $xlog = _get_xlog $name;
die "No xlogfile found for user $name\n" unless defined $xlog;
- naodash_xlog $xlog;
+ naodash_xlog $args, $xlog;
}
1;
use NetHack::NAOdash;
my $stats = naodash_user 'mgv'; # Retrieve and analyze mgv's xlogfile from alt.org
- my @checks = @{$stats->{checks}}; # List of "achievements" obtained by mgv
+ my @checks = @{$stats->{checks}}; # List of 'achievements' obtained by mgv
my %checks = map { $_ => 1 } @checks;
- say "mgv has ascended an orcish rogue" if $checks{combo_rog_orc_cha};
- say "mgv has ascended an atheist character" if $checks{conduct_atheist};
+ say 'mgv has ascended an orcish rogue' if $checks{combo_rog_orc_cha};
+ say 'mgv has ascended an atheist character' if $checks{conduct_atheist};
my %numbers = %{$stats->{numbers}};
say "mgv has ascended $numbers{ascensions} out of $numbers{games} games";
say "mgv has spent $numbers{totalrealtime} seconds playing NetHack on NAO";
+ $stats = naodash_user {include_versions => ['3.6.0']}, 'mgv';
+ say 'mgv has ascended an orcish rogue in 3.6.0' if $checks{combo_rog_orc_cha};
+ $stats = naodash_user {exclude_versions => ['3.6.0']}, 'mgv';
+ say 'mgv has ascended an atheist character pre-3.6.0' if $checks{conduct_atheist};
+
use File::Slurp;
$stats = naodash_xlog read_file 'path/to/my/xlogfile';
%checks = map { $_ => 1 } @{$stats->{checks}};
- say "I have ascended a survivor" if $checks{uconduct_survivor};
+ say 'I have ascended a survivor' if $checks{uconduct_survivor};
=head1 DESCRIPTION
=over
-=item B<naodash_xlog>(I<@lines>)
+=item B<naodash_xlog>([\%args], I<@lines>)
+
+=item B<naodash_xlog>([\%args], I<$xlog>)
+
+Takes an optional hashref followed by the contents of an xlogfile and
+returns the results of the analysis. The contents are joined together
+then split by the newline character, so they can be specified as a
+single string, as a list of lines, or as a combination thereof.
+
+The following keys are recognised in the optional hashref:
+
+=over
-=item B<naodash_xlog>(I<$xlog>)
+=item include_versions
-Takes the contents of an xlogfile and returns the results of the
-analysis. The arguments are joined together then split by the newline
-character, so they can be specified as a single string, as a list of
-lines, or as a combination thereof.
+The associated value is an arrayref of NetHack versions that should be
+considered. Any game that was played on a version that is not in this
+arrayref will be ignored. If this key is not present or the value is
+an empty arrayref, all versions are considered.
+
+=item exclude_versions
+
+The associated value is an arrayref of NetHack versions that should
+not be considered. Any game that was played on a version that is in
+this arrayref will be ignored. If a version is both included and
+excluded at the same time, it will not be considered (in other words,
+exclude_versions overrides include_versions).
+
+=back
The return value is of the following form:
that are true and C<< %{$result->{numbers}} >> is a hash of
B<numbers>.
-=item B<naodash_user>(I<$nao_username>)
+=item B<naodash_user>([I<\%args>], I<$nao_username>)
Retrieves the xlogfile of a user from NAO and gives it to
B<naodash_xlog>. Dies if no xlogfile is found or if the server cannot
be contacted.
+An optional hashref can be passed as a first argument. In this case it
+will be supplied as a first argument to B<naodash_xlog>, see that
+function's documentation for an explanation of useful keys.
+
This method caches the downloaded xlogfiles for one day in the
directory named by the NAODASH_CACHE environment variable.
use strict;
use warnings;
-use Test::More tests => 2;
+use Test::More tests => 4;
BEGIN { use_ok 'NetHack::NAOdash' }
checks => [qw/achieve_amulet achieve_ascended achieve_astral achieve_bell achieve_book achieve_candelabrum achieve_endgame achieve_gehennom achieve_invocation achieve_luckstone achieve_medusa achieve_sokoban combo_arc_dwa_law combo_bar_orc_cha combo_cav_gno_neu combo_hea_gno_neu combo_kni_hum_law combo_mon_hum_neu combo_pri_hum_law combo_pri_hum_neu combo_ran_elf_cha combo_rog_orc_cha combo_sam_hum_law combo_tou_hum_neu combo_val_dwa_law combo_wiz_elf_cha conduct_artiwishless conduct_atheist conduct_genocideless conduct_polypileless conduct_polyselfless conduct_vegetarian conduct_weaponless uconduct_boneless uconduct_survivor/]
}, 'naodash_xlog';
+
+is_deeply naodash_xlog ({include_versions => ['3.6.0']}, @xlog), {
+ numbers => {
+ ascensions => 1,
+ games => 3,
+ maxconducts => 4,
+ maxhp => 397,
+ maxpoints => 2903014,
+ minrealtime => 86482,
+ minturns => 37729,
+ totalrealtime => 114994,
+ },
+
+ checks => [qw/achieve_amulet achieve_ascended achieve_astral achieve_bell achieve_book achieve_candelabrum achieve_endgame achieve_gehennom achieve_invocation achieve_luckstone achieve_medusa achieve_sokoban combo_pri_hum_law conduct_atheist conduct_genocideless conduct_polypileless conduct_polyselfless uconduct_survivor/]
+}, 'naodash_xlog';
+
+is_deeply naodash_xlog ({exclude_versions => ['3.6.0']}, @xlog), {
+ numbers => {
+ ascensions => 14,
+ games => 82,
+ maxconducts => 4,
+ maxhp => 422,
+ maxpoints => 3429164,
+ minrealtime => 43395,
+ minturns => 36028,
+ totalrealtime => 1368030,
+ },
+
+ checks => [qw/achieve_amulet achieve_ascended achieve_astral achieve_bell achieve_book achieve_candelabrum achieve_endgame achieve_gehennom achieve_invocation achieve_luckstone achieve_medusa achieve_sokoban combo_arc_dwa_law combo_bar_orc_cha combo_cav_gno_neu combo_hea_gno_neu combo_kni_hum_law combo_mon_hum_neu combo_pri_hum_neu combo_ran_elf_cha combo_rog_orc_cha combo_sam_hum_law combo_tou_hum_neu combo_val_dwa_law combo_wiz_elf_cha conduct_artiwishless conduct_genocideless conduct_polypileless conduct_polyselfless conduct_vegetarian conduct_weaponless uconduct_boneless uconduct_survivor/]
+}, 'naodash_xlog';
version=3.4.3:points=159:deathdnum=0:deathlev=1:maxlvl=1:hp=14:maxhp=14:deaths=0:deathdate=20150121:birthdate=20150121:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=quit:conduct=4032:turns=166:achieve=0:nconducts=6:nachieves=0:realtime=199:starttime=1421846431:endtime=1421846632:gamedelta=201:gender0=Mal:align0=Law:flags=0
version=3.4.3:points=6804:deathdnum=2:deathlev=5:maxlvl=6:hp=-1:maxhp=68:deaths=1:deathdate=20150124:birthdate=20150121:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=killed by a jaguar:conduct=3976:turns=3752:achieve=0:nconducts=6:nachieves=0:realtime=3581:starttime=1421846639:endtime=1422090230:gamedelta=243591:gender0=Mal:align0=Law:flags=32
version=3.4.3:points=113905:deathdnum=0:deathlev=26:maxlvl=26:hp=84:maxhp=84:deaths=1:deathdate=20150127:birthdate=20150124:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=drowned in a pool of water by an electric eel:conduct=3720:turns=18464:achieve=1024:nconducts=5:nachieves=1:realtime=23801:starttime=1422090240:endtime=1422395519:gamedelta=305279:gender0=Mal:align0=Law:flags=0
-version=3.4.3:points=80743:deathdnum=0:deathlev=15:maxlvl=18:hp=-5:maxhp=84:deaths=1:deathdate=20150204:birthdate=20150130:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=killed by a giant mummy:conduct=3720:turns=17783:achieve=0:nconducts=5:nachieves=0:realtime=25745:starttime=1422624841:endtime=1423076735:gamedelta=451894:gender0=Mal:align0=Law:flags=32
-version=3.4.3:points=3591:deathdnum=2:deathlev=5:maxlvl=5:hp=-4:maxhp=61:deaths=1:deathdate=20150208:birthdate=20150204:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=killed by a soldier ant:conduct=3976:turns=3172:achieve=0:nconducts=6:nachieves=0:realtime=2767:starttime=1423076771:endtime=1423382793:gamedelta=306022:gender0=Mal:align0=Law:flags=0
-version=3.4.3:points=2903014:deathdnum=7:deathlev=-5:maxlvl=52:hp=311:maxhp=397:deaths=0:deathdate=20150627:birthdate=20150208:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=ascended:conduct=2440:turns=37729:achieve=4095:nconducts=4:nachieves=12:realtime=86482:starttime=1423382814:endtime=1435429536:gamedelta=12046722:gender0=Mal:align0=Law:flags=32
+version=3.6.0:points=80743:deathdnum=0:deathlev=15:maxlvl=18:hp=-5:maxhp=84:deaths=1:deathdate=20150204:birthdate=20150130:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=killed by a giant mummy:conduct=3720:turns=17783:achieve=0:nconducts=5:nachieves=0:realtime=25745:starttime=1422624841:endtime=1423076735:gamedelta=451894:gender0=Mal:align0=Law:flags=32
+version=3.6.0:points=3591:deathdnum=2:deathlev=5:maxlvl=5:hp=-4:maxhp=61:deaths=1:deathdate=20150208:birthdate=20150204:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=killed by a soldier ant:conduct=3976:turns=3172:achieve=0:nconducts=6:nachieves=0:realtime=2767:starttime=1423076771:endtime=1423382793:gamedelta=306022:gender0=Mal:align0=Law:flags=0
+version=3.6.0:points=2903014:deathdnum=7:deathlev=-5:maxlvl=52:hp=311:maxhp=397:deaths=0:deathdate=20150627:birthdate=20150208:uid=5:role=Pri:race=Hum:gender=Mal:align=Law:name=mgv:death=ascended:conduct=2440:turns=37729:achieve=4095:nconducts=4:nachieves=12:realtime=86482:starttime=1423382814:endtime=1435429536:gamedelta=12046722:gender0=Mal:align0=Law:flags=32
version=3.4.3:points=17192:deathdnum=0:deathlev=6:maxlvl=6:hp=0:maxhp=64:deaths=1:deathdate=20150627:birthdate=20150627:uid=5:role=Mon:race=Hum:gender=Mal:align=Neu:name=mgv:death=killed by a rabid rat, while frozen by a monster's gaze:conduct=3988:turns=7550:achieve=1024:nconducts=7:nachieves=1:realtime=7266:starttime=1435431361:endtime=1435438629:gamedelta=7268:gender0=Mal:align0=Neu:flags=32
version=3.4.3:points=2765250:deathdnum=7:deathlev=-5:maxlvl=47:hp=264:maxhp=295:deaths=0:deathdate=20150701:birthdate=20150627:uid=5:role=Mon:race=Hum:gender=Mal:align=Cha:name=mgv:death=ascended:conduct=2436:turns=40262:achieve=4095:nconducts=4:nachieves=12:realtime=53850:starttime=1435438727:endtime=1435752162:gamedelta=313435:gender0=Mal:align0=Neu:flags=32