File Coverage

blib/lib/WWW/Challonge/Match.pm
Criterion Covered Total %
statement 127 141 90.0
branch 34 50 68.0
condition 7 9 77.7
subroutine 14 14 100.0
pod 6 6 100.0
total 188 220 85.4


line stmt bran cond sub pod time code
1             package WWW::Challonge::Match;
2              
3 6     6   103 use 5.010;
  6         15  
  6         189  
4 6     6   25 use strict;
  6         6  
  6         152  
5 6     6   20 use warnings;
  6         8  
  6         145  
6 6     6   23 use WWW::Challonge;
  6         7  
  6         85  
7 6     6   2167 use WWW::Challonge::Match::Attachment;
  6         59  
  6         205  
8 6     6   33 use Carp qw/carp croak/;
  6         8  
  6         282  
9 6     6   24 use JSON qw/to_json from_json/;
  6         8  
  6         23  
10              
11             sub __args_are_valid;
12              
13             =head1 NAME
14              
15             WWW::Challonge::Match - A class representing a single match within
16             a Challonge tournament.
17              
18             =head1 VERSION
19              
20             Version 1.00
21              
22             =cut
23              
24             our $VERSION = '1.00';
25              
26             =head1 SUBROUTINES/METHODS
27              
28             =head2 new
29              
30             Takes a hashref representing the match, the API key and the REST client and
31             turns it into an object. This is mostly used by the module itself.
32              
33             my $m = WWW::Challonge::Match->new($match, $key, $client);
34              
35             =cut
36              
37             sub new
38             {
39 19     19 1 136 my $class = shift;
40 19         18 my $match = shift;
41 19         20 my $key = shift;
42 19         17 my $client = shift;
43              
44 19         38 my $m =
45             {
46             client => $client,
47             match => $match->{match},
48             key => $key,
49             };
50 19         58 bless $m, $class;
51             }
52              
53             =head2 update
54              
55             Updates the match with the results. Requires an arrayref of comma-seperated
56             values and optional arguments for votes. The 'winner_id' is not required as the
57             module calculates it. Returns the updated C object:
58              
59             =over 4
60              
61             =item scores_csv
62              
63             Required. An arrayref containing the match results with the following format -
64             "x-y", where x and y are both integers, x being player 1's score and y being
65             player 2's.
66              
67             =item player1_votes
68              
69             Integer. Overwrites the number of votes for player 1.
70              
71             =item player2_votes
72              
73             Integer. Overwrites the number of votes for player 2.
74              
75             =back
76              
77             # If votes are not given, the argument can simply be an arrayref:
78             $m->update(["1-3", "3-2", "3-0"]);
79              
80             # Otherwise, a hashref is required:
81             $m->update({
82             scores_csv => ["1-3", "3-2", "3-0"],
83             player1_votes => 2,
84             player2_votes => 1,
85             });
86              
87             =cut
88              
89             sub update
90             {
91 7     7 1 3640 my $self = shift;
92 7         10 my $args = shift;
93              
94             # Get the key, REST client and match id:
95 7         12 my $key = $self->{key};
96 7         10 my $client = $self->{client};
97 7         14 my $url = $self->{match}->{tournament_id};
98 7         13 my $id = $self->{match}->{id};
99 7         10 my $HOST = $WWW::Challonge::HOST;
100              
101 7         17 my $params = { api_key => $key, match => { } };
102              
103             # Check what kind of arguments we are dealing with:
104 7 100 100     36 if((ref $args eq "ARRAY") || (ref $args eq "HASH"))
105             {
106             # Check we have the mandatory scores:
107 5 100 66     26 if((ref $args eq "HASH") && ((! defined $args->{scores_csv}) ||
      66        
108             (ref $args->{scores_csv} ne "ARRAY")))
109             {
110 1         81 croak "Required argument 'scores_csv' as an array reference";
111 0         0 return undef;
112             }
113              
114             # Check the arguments are valid:
115 4 50       9 return undef unless(__args_are_valid($args));
116              
117             # Once everything is good, work out the winner based on the results:
118 1         3 my $results = $args;
119 1 50       4 if(ref $args eq "HASH") { $results = $args->{scores_csv}; }
  0         0  
120 1         5 my %results = ( p1 => 0, p2 => 0 );
121 1         2 for my $result(@{$results})
  1         2  
122             {
123             # Increment the score of whoever has the highest result:
124 1         3 my ($p1, $p2) = split '-', $result;
125 1 50       6 ($p1 > $p2) ? $results{p1}++ : $results{p2}++;
126             }
127              
128             # Save the id of whichever player got the most wins:
129 1 50       4 if($results{p1} > $results{p2})
    0          
130             {
131 1         5 $params->{match}->{winner_id} = $self->{match}->{player1_id};
132             }
133             elsif($results{p1} < $results{p2})
134             {
135 0         0 $params->{match}->{winner_id} = $self->{match}->{player2_id};
136             }
137             else
138             {
139 0         0 $params->{match}->{winner_id} = "tie";
140             }
141              
142             # Save the scores as a comma-seperated list:
143 1         28 $params->{match}->{scores_csv} = join ",", @{$results};
  1         5  
144              
145             # Go through and add the prediction arguments if they exist:
146 1 50       4 if(ref $args eq "HASH")
147             {
148 0         0 for my $key(keys %{$args})
  0         0  
149             {
150 0 0       0 next unless($key =~ /^player[12]_votes$/);
151 0         0 $params->{match}->{$key} = $args->{$key};
152             }
153             }
154              
155             # Make the PUT call:
156 1         11 my $response = $client->request(WWW::Challonge::__json_request(
157             "$HOST/tournaments/$url/matches/$id.json", "PUT", $params));
158              
159             # Check for any errors:
160 1 50       692 WWW::Challonge::__handle_error $response if($response->is_error);
161              
162 1         15 return 1;
163             }
164             else
165             {
166             # Otherwise, give an error and exit:
167 2         180 croak "Expected an arrayref or hashref";
168 0         0 return undef;
169             }
170             }
171              
172             =head2 attributes
173              
174             Returns a hashref of all the attributes of the match. Contains the following
175             fields.
176              
177             =over 4
178              
179             =item attachment_count
180              
181             =item created_at
182              
183             =item group_id
184              
185             =item has_attachment
186              
187             =item id
188              
189             =item identifier
190              
191             =item location
192              
193             =item loser_id
194              
195             =item player1_id
196              
197             =item player1_is_prereq_match_loser
198              
199             =item player1_prereq_match_id
200              
201             =item player1_votes
202              
203             =item player2_id
204              
205             =item player2_is_prereq_match_loser
206              
207             =item player2_prereq_match_id
208              
209             =item player2_votes
210              
211             =item prerequisite_match_ids_csv
212              
213             =item round
214              
215             =item scheduled_time
216              
217             =item scores_csv
218              
219             =item started_at
220              
221             =item state
222              
223             =item tournament_id
224              
225             =item underway_at
226              
227             =item updated_at
228              
229             =item winner_id
230              
231             =back
232              
233             my $attr = $m->attributes;
234             print $attr->{identifier}, "\n";
235              
236             =cut
237              
238             sub attributes
239             {
240 4     4 1 4589 my $self = shift;
241              
242             # Get the key, REST client, tournament url and id:
243 4         11 my $key = $self->{key};
244 4         8 my $client = $self->{client};
245 4         10 my $url = $self->{match}->{tournament_id};
246 4         9 my $id = $self->{match}->{id};
247 4         7 my $HOST = $WWW::Challonge::HOST;
248              
249             # Get the most recent version:
250 4         29 my $response = $client->get(
251             "$HOST/tournaments/$url/matches/$id.json?api_key=$key");
252              
253             # Check for any errors:
254 4 50       3995 WWW::Challonge::__handle_error $response if($response->is_error);
255              
256             # If not, save it and then return it:
257 4         37 $self->{match} = from_json($response->decoded_content)->{match};
258 4         503 return $self->{match};
259             }
260              
261             =head2 attachments
262              
263             Returns an arrayref of C objects for every
264             attachment the match has.
265              
266             my $attachments = $m->attachments;
267              
268             =cut
269              
270             sub attachments
271             {
272 1     1 1 1143 my $self = shift;
273              
274             # Get the key, REST client, tournament url and id:
275 1         3 my $key = $self->{key};
276 1         2 my $client = $self->{client};
277 1         3 my $url = $self->{match}->{tournament_id};
278 1         3 my $id = $self->{match}->{id};
279 1         1 my $HOST = $WWW::Challonge::HOST;
280              
281             # Get the match attachments:
282 1         9 my $response = $client->get(
283             "$HOST/tournaments/$url/matches/$id/attachments.json?api_key=$key");
284              
285             # Check for any errors:
286 1 50       808 WWW::Challonge::__handle_error $response if($response->is_error);
287              
288             # If it was successful, create the objects and return them:
289 1         8 my $attachments = [];
290 1         2 for my $att(@{from_json($response->decoded_content)})
  1         3  
291             {
292 3         122 push @{$attachments},
  3         13  
293             WWW::Challonge::Match::Attachment->new($att, $url, $key, $client);
294             }
295 1         5 return $attachments;
296             }
297              
298             =head2 attachment
299              
300             Returns a single C object for the
301             attachment with the given ID:
302              
303             my $ma = $m->attachment(124858);
304              
305             =cut
306              
307             sub attachment
308             {
309 4     4 1 1743 my $self = shift;
310 4         8 my $atth = shift;
311              
312             # Die on no arguments:
313 4 100       89 croak "No arguments given" unless(defined $atth);
314              
315             # Get the key, REST client, tournament url and id:
316 3         9 my $key = $self->{key};
317 3         5 my $client = $self->{client};
318 3         8 my $url = $self->{match}->{tournament_id};
319 3         8 my $id = $self->{match}->{id};
320 3         5 my $HOST = $WWW::Challonge::HOST;
321              
322             # Get the match attachments:
323 3         23 my $response = $client->get(
324             "$HOST/tournaments/$url/matches/$id/attachments/$atth.json?api_key=$key");
325              
326             # Check for any errors:
327 3 100       2410 WWW::Challonge::__handle_error $response if($response->is_error);
328              
329             # If it was successful, create the object and return it:
330 2         20 my $attachment = WWW::Challonge::Match::Attachment->new(
331             from_json($response->decoded_content),
332             $url,
333             $key,
334             $client
335             );
336 2         9 return $attachment;
337             }
338              
339             =head2 new_attachment
340              
341             Creates a new match attachment and returns the resulting
342             C object. Takes the following arguments, at
343             least one of them is required. The tournament's "accept_attachments" attribute
344             must be true for this to succeed.
345              
346             =over 4
347              
348             =item asset
349              
350             A file upload (max 250KB). If provided, the 'url' parameter will be ignored.
351              
352             =item url
353              
354             A web URL. Must include http://, https:// or ftp://.
355              
356             =item description
357              
358             Text to the describte the file or URL, or it can simply be standalone text.
359              
360             =back
361              
362             # A simple URL:
363             my $ma = $m->new_attachment({
364             url => http://www.example.com/image.png",
365             description => "An example URL",
366             });
367              
368             # File uploads require a filename:
369             my $ma = $m->new_attachment({
370             asset => "example.png",
371             description => "An example file",
372             });
373              
374             =cut
375              
376             sub new_attachment
377             {
378 13     13 1 7257 my $self = shift;
379 13         17 my $args = shift;
380              
381             # Die on no arguments:
382 13 100       108 croak "No arguments given" unless(defined $args);
383              
384             # Get the key, REST client, tournament url and id:
385 12         17 my $key = $self->{key};
386 12         17 my $client = $self->{client};
387 12         27 my $url = $self->{match}->{tournament_id};
388 12         23 my $id = $self->{match}->{id};
389 12         18 my $HOST = $WWW::Challonge::HOST;
390              
391             # Check the arguments are valid:
392             return undef
393 12 50       32 unless(WWW::Challonge::Match::Attachment::__args_are_valid($args));
394              
395             # Wrap the filename in an arrayref for HTTP::Request::Common:
396 9 100       29 $args->{asset} = [ $args->{asset} ] if(defined $args->{asset});
397              
398             # Make the POST call:
399 9         87 my @params = map { "match_attachment[" . $_ . "]" => $args->{$_} }
  9         19  
400 9         12 keys %{$args};
401 9         83 my $response = $client->post(
402             "$HOST/tournaments/$url/matches/$id/attachments.json",
403             "Content-Type" => 'form-data',
404             "Content" => [ "api_key" => $key, @params ],
405             );
406              
407             # Check for any errors:
408 9 100       30796 WWW::Challonge::__handle_error $response if($response->is_error);
409              
410             # If so, make an object and return it:
411 7         64 return WWW::Challonge::Match::Attachment->new(
412             from_json($response->decoded_content),
413             $url,
414             $key,
415             $client
416             );
417             }
418              
419             =head2 __args_are_valid
420              
421             Checks if the passed arguments and values are valid for updating a match.
422              
423             =cut
424              
425             sub __args_are_valid
426             {
427 4     4   5 my $args = shift;
428 4         4 my $results = $args;
429 4 100       9 if(ref $args eq "HASH") { $results = $args->{scores_csv}; }
  2         3  
430              
431             # Check the arrayref contains the correct values:
432 4         4 for my $result(@{$results})
  4         9  
433             {
434 4 100       26 if($result !~ /^\d*-\d*$/)
435             {
436 1         205 croak "Results must be given in the format \"x-y\", where x and y ".
437             "are integers";
438 0         0 return undef;
439             }
440             }
441              
442             # Check the remaining arguments are also integers:
443 3 100       9 if(ref $args eq "HASH")
444             {
445 2         4 for my $arg(qw/player1_votes player2_votes/)
446             {
447 3 100       9 next unless(defined $args->{$arg});
448 1 50       4 if($args->{$arg} !~ /^\d*$/)
449             {
450 1         87 croak "Argument '", $arg, "' must be an integer";
451 0         0 return undef;
452             }
453             }
454              
455             # Finally, check if there are any unrecognised arguments, but just ignore
456             # them instead of erroring out:
457 1         2 my $is_valid = 0;
458 1         2 for my $arg(keys %{$args})
  1         5  
459             {
460 1         3 for my $valid_arg(qw/player1_votes player2_votes scores_csv/)
461             {
462 3 50       8 if($arg eq $valid_arg)
463             {
464 0         0 $is_valid = 1;
465 0         0 last;
466             }
467             }
468 1 50       89 carp "Ignoring unknown argument '$arg'" unless($is_valid);
469 0         0 $is_valid = 0;
470             }
471             }
472 1         3 return 1;
473             }
474              
475             =head1 AUTHOR
476              
477             Alex Kerr, C<< >>
478              
479             =head1 BUGS
480              
481             Please report any bugs or feature requests to C, or through
482             the web interface at L. I will be notified, and then you'll
483             automatically be notified of progress on your bug as I make changes.
484              
485             =head1 SUPPORT
486              
487             You can find documentation for this module with the perldoc command.
488              
489             perldoc WWW::Challonge::Match
490              
491             You can also look for information at:
492              
493             =over 4
494              
495             =item * RT: CPAN's request tracker (report bugs here)
496              
497             L
498              
499             =item * AnnoCPAN: Annotated CPAN documentation
500              
501             L
502              
503             =item * CPAN Ratings
504              
505             L
506              
507             =item * Search CPAN
508              
509             L
510              
511             =back
512              
513             =head1 SEE ALSO
514              
515             =over 4
516              
517             =item L
518              
519             =item L
520              
521             =item L
522              
523             =item L
524              
525             =back
526              
527             =head1 ACKNOWLEDGEMENTS
528              
529             Everyone on the L team for making such a great
530             service.
531              
532             =head1 LICENSE AND COPYRIGHT
533              
534             Copyright 2015 Alex Kerr.
535              
536             This program is free software; you can redistribute it and/or modify it
537             under the terms of the the Artistic License (2.0). You may obtain a
538             copy of the full license at:
539              
540             L
541              
542             Any use, modification, and distribution of the Standard or Modified
543             Versions is governed by this Artistic License. By using, modifying or
544             distributing the Package, you accept this license. Do not use, modify,
545             or distribute the Package, if you do not accept this license.
546              
547             If your Modified Version has been derived from a Modified Version made
548             by someone other than you, you are nevertheless required to ensure that
549             your Modified Version complies with the requirements of this license.
550              
551             This license does not grant you the right to use any trademark, service
552             mark, tradename, or logo of the Copyright Holder.
553              
554             This license includes the non-exclusive, worldwide, free-of-charge
555             patent license to make, have made, use, offer to sell, sell, import and
556             otherwise transfer the Package with respect to any patent claims
557             licensable by the Copyright Holder that are necessarily infringed by the
558             Package. If you institute patent litigation (including a cross-claim or
559             counterclaim) against any party alleging that the Package constitutes
560             direct or contributory patent infringement, then this Artistic License
561             to you shall terminate on the date that such litigation is filed.
562              
563             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
564             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
565             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
566             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
567             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
568             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
569             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
570             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
571              
572             =cut
573              
574             1; # End of WWW::Challonge::Match