File Coverage

blib/lib/WWW/MetaForge/ArcRaiders/CLI/Cmd/Quest.pm
Criterion Covered Total %
statement 68 86 79.0
branch 21 40 52.5
condition 7 42 16.6
subroutine 7 7 100.0
pod 0 1 0.0
total 103 176 58.5


line stmt bran cond sub pod time code
1             package WWW::MetaForge::ArcRaiders::CLI::Cmd::Quest;
2             our $AUTHORITY = 'cpan:GETTY';
3             # ABSTRACT: Show details for a single quest
4             our $VERSION = '0.002';
5 1     1   12108 use Moo;
  1         3  
  1         14  
6 1     1   594 use MooX::Cmd;
  1         4  
  1         16  
7 1     1   5873 use MooX::Options;
  1         3  
  1         13  
8 1     1   3463 use JSON::MaybeXS;
  1         2  
  1         1281  
9              
10             sub execute {
11 3     3 0 6002 my ($self, $args, $chain) = @_;
12 3         12 my $app = $chain->[0];
13              
14 3         7 my $quest_id = $args->[0];
15 3 100       12 unless ($quest_id) {
16 1         100 print "Usage: arcraiders quest <id>\n";
17 1         35 print "Example: arcraiders quest a-bad-feeling\n";
18 1         10 return;
19             }
20              
21             # Try fetching by ID first (API supports id= query param)
22 2         82 my $result = $app->api->quests_paginated(id => $quest_id);
23 2         868 my $quests = $result->{data};
24              
25             # If not found by ID, search all quests
26 2 50       11 if (!@$quests) {
27 0         0 $quests = $app->api->quests_all;
28             my ($match) = grep {
29 0 0 0     0 ($_->id && lc($_->id) eq lc($quest_id)) ||
  0   0     0  
30             ($_->name && lc($_->name) eq lc($quest_id))
31             } @$quests;
32 0 0       0 $quests = $match ? [$match] : [];
33             }
34              
35 2 50       6 unless (@$quests) {
36 0         0 print "Quest '$quest_id' not found.\n";
37 0         0 return;
38             }
39              
40 2         5 my $quest = $quests->[0];
41              
42 2 100       12 if ($app->json) {
43 1         6 print JSON::MaybeXS->new(utf8 => 1, pretty => 1)->encode($quest->_raw);
44 1         85 return;
45             }
46              
47 1         5 _print_quest_details($quest);
48             }
49              
50             sub _print_quest_details {
51 1     1   15 my ($quest) = @_;
52              
53 1         66 print "=" x 60, "\n";
54 1   50     46 printf "%s\n", $quest->name // 'Unknown';
55 1         17 print "=" x 60, "\n";
56              
57 1         8 _print_field("ID", $quest->id);
58 1         8 _print_field("Type", $quest->type);
59              
60 1 50       5 if ($quest->description) {
61 1         17 print "\nDescription:\n";
62 1         6 my $desc = $quest->description;
63 1         21 $desc =~ s/(.{1,58})\s/$1\n /g; # Word wrap
64 1         19 print " $desc\n";
65             }
66              
67 1 50 33     10 if ($quest->objectives && @{$quest->objectives}) {
  1         8  
68 1         15 print "\nObjectives:\n";
69 1         3 my $i = 1;
70 1         2 for my $obj (@{$quest->objectives}) {
  1         5  
71 1         22 printf " %d. %s\n", $i++, $obj;
72             }
73             }
74              
75 1 50 33     7 if ($quest->required_items && @{$quest->required_items}) {
  1         7  
76 0         0 print "\nRequired Items:\n";
77 0         0 for my $req (@{$quest->required_items}) {
  0         0  
78 0   0     0 my $name = $req->{item} // $req->{name} // 'Unknown';
      0        
79 0   0     0 my $qty = $req->{quantity} // $req->{amount} // 1;
      0        
80 0         0 printf " %dx %s\n", $qty, $name;
81             }
82             }
83              
84 1         2 my @reward_parts;
85 1 50       17 push @reward_parts, $quest->xp_reward . " XP" if $quest->xp_reward;
86 1 50       6 push @reward_parts, $quest->reputation_reward . " Rep" if $quest->reputation_reward;
87              
88 1 50       4 if (@reward_parts) {
89 0         0 print "\nRewards:\n";
90 0         0 print " ", join(", ", @reward_parts), "\n";
91             }
92              
93 1 50 33     23 if ($quest->rewards && @{$quest->rewards}) {
  1         8  
94 1 50       34 print " Item Rewards:\n" unless @reward_parts;
95 1         3 for my $reward (@{$quest->rewards}) {
  1         4  
96 2 50       12 if (ref $reward eq 'HASH') {
97             # Handle both formats: {item => "Name"} and {item => {name => "Name"}}
98 2         6 my $item = $reward->{item};
99 2 50 33     20 my $name = ref $item eq 'HASH' ? $item->{name} : ($item // $reward->{name});
100 2 50       6 next unless defined $name;
101 2   33     7 my $qty = $reward->{quantity} // $reward->{amount} // 1;
      0        
102 2         52 printf " %dx %s\n", $qty, $name;
103             }
104             }
105             }
106              
107 1 50 33     13 if ($quest->prev_quest || $quest->next_quest) {
108 0         0 print "\nQuest Chain:\n";
109 0   0     0 printf " Previous: %s\n", $quest->prev_quest // '-';
110 0   0     0 printf " Next: %s\n", $quest->next_quest // '-';
111             }
112              
113 1 50       29 if ($quest->last_updated) {
114 0         0 print "\nLast Updated: ", $quest->last_updated, "\n";
115             }
116             }
117              
118             sub _print_field {
119 2     2   8 my ($label, $value) = @_;
120 2 100       7 return unless defined $value;
121 1         20 printf "%-15s %s\n", "$label:", $value;
122             }
123              
124             1;
125              
126             __END__
127              
128             =pod
129              
130             =encoding UTF-8
131              
132             =head1 NAME
133              
134             WWW::MetaForge::ArcRaiders::CLI::Cmd::Quest - Show details for a single quest
135              
136             =head1 VERSION
137              
138             version 0.002
139              
140             =head1 SYNOPSIS
141              
142             # Show quest details by ID
143             arcraiders quest a-bad-feeling
144              
145             # Show quest details by name
146             arcraiders quest "A Bad Feeling"
147              
148             # Output as JSON
149             arcraiders quest a-bad-feeling --json
150              
151             =head1 DESCRIPTION
152              
153             This command displays detailed information for a single quest. It accepts either
154             a quest ID or quest name as the argument.
155              
156             The command first attempts to fetch the quest by ID using the API. If not found,
157             it falls back to searching the complete quest list by matching against both the
158             ID and name fields (case-insensitive).
159              
160             Quest details displayed include:
161              
162             =over 4
163              
164             =item * Name and ID
165              
166             =item * Quest type
167              
168             =item * Description
169              
170             =item * Objectives list
171              
172             =item * Required items with quantities
173              
174             =item * Rewards (XP, reputation, and items)
175              
176             =item * Quest chain relationships (previous/next quests)
177              
178             =item * Last updated timestamp
179              
180             =back
181              
182             When the C<--json> flag is used, the raw quest data is output as JSON instead
183             of the formatted display.
184              
185             =head1 SUPPORT
186              
187             =head2 Issues
188              
189             Please report bugs and feature requests on GitHub at
190             L<https://github.com/Getty/p5-www-metaforge/issues>.
191              
192             =head2 IRC
193              
194             You can reach Getty on C<irc.perl.org> for questions and support.
195              
196             =head1 CONTRIBUTING
197              
198             Contributions are welcome! Please fork the repository and submit a pull request.
199              
200             =head1 AUTHOR
201              
202             Torsten Raudssus <torsten@raudssus.de>
203              
204             =head1 COPYRIGHT AND LICENSE
205              
206             This software is copyright (c) 2026 by Torsten Raudssus.
207              
208             This is free software; you can redistribute it and/or modify it under
209             the same terms as the Perl 5 programming language system itself.
210              
211             =cut