File Coverage

blib/lib/WWW/MetaForge/ArcRaiders/CLI/Cmd/Arc.pm
Criterion Covered Total %
statement 67 79 84.8
branch 18 38 47.3
condition 4 19 21.0
subroutine 7 7 100.0
pod 0 1 0.0
total 96 144 66.6


line stmt bran cond sub pod time code
1             package WWW::MetaForge::ArcRaiders::CLI::Cmd::Arc;
2             our $AUTHORITY = 'cpan:GETTY';
3             # ABSTRACT: Show details for a single arc
4             our $VERSION = '0.002';
5 1     1   7656 use Moo;
  1         3  
  1         13  
6 1     1   595 use MooX::Cmd;
  1         3  
  1         12  
7 1     1   3733 use MooX::Options;
  1         4  
  1         11  
8 1     1   2688 use JSON::MaybeXS;
  1         3  
  1         1269  
9              
10             sub execute {
11 2     2 0 4954 my ($self, $args, $chain) = @_;
12 2         7 my $app = $chain->[0];
13              
14 2         4 my $arc_id = $args->[0];
15 2 100       7 unless ($arc_id) {
16 1         61 print "Usage: arcraiders arc <id>\n";
17 1         39 print "Example: arcraiders arc minor-storm\n";
18 1         28 return;
19             }
20              
21             # Try fetching by ID first (API supports id= query param)
22 1         40 my $result = $app->api->arcs_paginated(id => $arc_id);
23 1         274 my $arcs = $result->{data};
24              
25             # If not found by ID, search all arcs
26 1 50       7 if (!@$arcs) {
27 0         0 $arcs = $app->api->arcs_all;
28             my ($match) = grep {
29 0 0 0     0 ($_->id && lc($_->id) eq lc($arc_id)) ||
  0   0     0  
30             ($_->name && lc($_->name) eq lc($arc_id))
31             } @$arcs;
32 0 0       0 $arcs = $match ? [$match] : [];
33             }
34              
35 1 50       5 unless (@$arcs) {
36 0         0 print "Arc '$arc_id' not found.\n";
37 0         0 return;
38             }
39              
40 1         3 my $arc = $arcs->[0];
41              
42 1 50       7 if ($app->json) {
43 0         0 print JSON::MaybeXS->new(utf8 => 1, pretty => 1)->encode($arc->_raw);
44 0         0 return;
45             }
46              
47 1         3 _print_arc_details($arc);
48             }
49              
50             sub _print_arc_details {
51 1     1   3 my ($arc) = @_;
52              
53 1         77 print "=" x 60, "\n";
54 1   50     44 printf "%s\n", $arc->name // 'Unknown';
55 1         16 print "=" x 60, "\n";
56              
57 1         8 _print_field("ID", $arc->id);
58 1         7 _print_field("Type", $arc->type);
59              
60 1 50 33     8 if ($arc->maps && @{$arc->maps}) {
  1         7  
61 1         2 _print_field("Maps", join(", ", @{$arc->maps}));
  1         7  
62             }
63              
64 1 50       6 if ($arc->duration) {
65 1         7 my $mins = int($arc->duration / 60);
66 1         4 my $secs = $arc->duration % 60;
67 1 50       6 my $duration_str = $mins > 0 ? "${mins}m ${secs}s" : "${secs}s";
68 1         4 _print_field("Duration", $duration_str);
69             }
70              
71 1 50       17 if ($arc->cooldown) {
72 1         25 my $mins = int($arc->cooldown / 60);
73 1         6 _print_field("Cooldown", "${mins} minutes");
74             }
75              
76 1 50       7 if ($arc->description) {
77 1         14 print "\nDescription:\n";
78 1         5 my $desc = $arc->description;
79 1         19 $desc =~ s/(.{1,58})\s/$1\n /g; # Word wrap
80 1         18 print " $desc\n";
81             }
82              
83 1         3 my @reward_parts;
84 1 50       23 push @reward_parts, $arc->xp_reward . " XP" if $arc->xp_reward;
85 1 50       7 push @reward_parts, $arc->coin_reward . " Coins" if $arc->coin_reward;
86              
87 1 50       5 if (@reward_parts) {
88 0         0 print "\nRewards:\n";
89 0         0 print " ", join(", ", @reward_parts), "\n";
90             }
91              
92 1 50 33     8 if ($arc->loot && @{$arc->loot}) {
  1         6  
93 1         21 print "\nLoot Drops:\n";
94 1         3 for my $loot (@{$arc->loot}) {
  1         5  
95 2 50       9 if (ref $loot eq 'HASH') {
96 2   33     44 my $name = $loot->{item} // $loot->{name} // next;
      0        
97 2         8 my $chance = $loot->{chance};
98 2 50       6 if (defined $chance) {
99 2         57 printf " %-40s %d%%\n", $name, int($chance * 100);
100             } else {
101 0         0 printf " %s\n", $name;
102             }
103             }
104             }
105             }
106              
107 1 50       26 if ($arc->last_updated) {
108 0         0 print "\nLast Updated: ", $arc->last_updated, "\n";
109             }
110             }
111              
112             sub _print_field {
113 5     5   12 my ($label, $value) = @_;
114 5 50       14 return unless defined $value;
115 5         96 printf "%-15s %s\n", "$label:", $value;
116             }
117              
118             1;
119              
120             __END__
121              
122             =pod
123              
124             =encoding UTF-8
125              
126             =head1 NAME
127              
128             WWW::MetaForge::ArcRaiders::CLI::Cmd::Arc - Show details for a single arc
129              
130             =head1 VERSION
131              
132             version 0.002
133              
134             =head1 SYNOPSIS
135              
136             # Show arc details by ID
137             arcraiders arc minor-storm
138              
139             # Show arc details by name
140             arcraiders arc "Salvage Run"
141              
142             # Output as JSON
143             arcraiders --json arc minor-storm
144              
145             =head1 DESCRIPTION
146              
147             This command displays detailed information about a single ARC (mission/activity)
148             in Arc Raiders. You can search by either the arc's ID or name.
149              
150             The command first attempts to find the arc by ID. If no match is found, it
151             searches through all arcs by both ID and name (case-insensitive).
152              
153             Output includes:
154              
155             =over 4
156              
157             =item * Name and ID
158              
159             =item * Type (mission category)
160              
161             =item * Available maps
162              
163             =item * Duration (time limit)
164              
165             =item * Cooldown period
166              
167             =item * Description text
168              
169             =item * Rewards (XP and Coins)
170              
171             =item * Loot drop table with drop chances
172              
173             =item * Last updated timestamp
174              
175             =back
176              
177             If the C<--json> flag is used, outputs the raw API response as JSON instead of
178             the formatted display.
179              
180             =head1 SUPPORT
181              
182             =head2 Issues
183              
184             Please report bugs and feature requests on GitHub at
185             L<https://github.com/Getty/p5-www-metaforge/issues>.
186              
187             =head2 IRC
188              
189             You can reach Getty on C<irc.perl.org> for questions and support.
190              
191             =head1 CONTRIBUTING
192              
193             Contributions are welcome! Please fork the repository and submit a pull request.
194              
195             =head1 AUTHOR
196              
197             Torsten Raudssus <torsten@raudssus.de>
198              
199             =head1 COPYRIGHT AND LICENSE
200              
201             This software is copyright (c) 2026 by Torsten Raudssus.
202              
203             This is free software; you can redistribute it and/or modify it under
204             the same terms as the Perl 5 programming language system itself.
205              
206             =cut