File Coverage

blib/lib/WWW/Challonge/Tournament.pm
Criterion Covered Total %
statement 219 234 93.5
branch 72 104 69.2
condition 4 6 66.6
subroutine 23 23 100.0
pod 14 14 100.0
total 332 381 87.1


line stmt bran cond sub pod time code
1             package WWW::Challonge::Tournament;
2              
3 6     6   129 use 5.010;
  6         15  
  6         210  
4 6     6   26 use strict;
  6         5  
  6         153  
5 6     6   29 use warnings;
  6         6  
  6         142  
6 6     6   2439 use WWW::Challonge::Participant;
  6         14  
  6         227  
7 6     6   3300 use WWW::Challonge::Match;
  6         21  
  6         243  
8 6     6   42 use Carp qw/carp croak/;
  6         10  
  6         343  
9 6     6   33 use JSON qw/to_json from_json/;
  6         10  
  6         28  
10              
11             sub __is_kill;
12             sub __args_are_valid;
13              
14             =head1 NAME
15              
16             WWW::Challonge::Tournament - A class representing a single Challonge tournament.
17              
18             =head1 VERSION
19              
20             Version 1.01
21              
22             =cut
23              
24             our $VERSION = '1.01';
25              
26             =head1 SUBROUTINES/METHODS
27              
28             =head2 new
29              
30             Takes a hashref representing the tournament, the API key and the REST client
31             and turns it into an object. This is mostly used by the module itself, to
32             create a new tournament see L.
33              
34             my $t = WWW::Challonge::Tournament->new($tournament, $key, $client);
35              
36             =cut
37              
38             sub new
39             {
40 31     31 1 4829 my $class = shift;
41 31         57 my $tournament = shift;
42 31         41 my $key = shift;
43 31         42 my $client = shift;
44              
45 31         159 my $t =
46             {
47             alive => 1,
48             client => $client,
49             tournament => $tournament->{tournament},
50             key => $key,
51             };
52 31         152 bless $t, $class;
53             }
54              
55             =head2 update
56              
57             Updates specific attributes of a tournament. For a full list, see
58             L. Unlike that method, however, all of the arguments
59             are optional.
60              
61             $t->update({
62             name => "sample_tournament_2",
63             type => "swiss",
64             });
65              
66             =cut
67              
68             sub update
69             {
70 5     5 1 2805 my $self = shift;
71 5         8 my $args = shift;
72              
73             # Do not operate on a dead tournament:
74 5 100       17 return __is_kill unless($self->{alive});
75              
76             # Die on no errors:
77 4 100       85 croak "No arguments given" unless(defined $args);
78              
79             # Get the key, REST client and tournament url:
80 3         5 my $key = $self->{key};
81 3         4 my $client = $self->{client};
82 3         10 my $url = $self->{tournament}->{url};
83 3         5 my $HOST = $WWW::Challonge::HOST;
84              
85             # Check the arguments and values are valid:
86 3 50       9 return undef unless(WWW::Challonge::Tournament::__args_are_valid($args));
87              
88             # Add the API key and put everything else in a 'tournament' hash:
89 2         7 my $params = { api_key => $key, tournament => $args };
90              
91             # Make the PUT request:
92 2         17 my $response = $client->request(WWW::Challonge::__json_request(
93             "$HOST/tournaments/$url.json", "PUT", $params));
94              
95             # Check for any errors:
96 2 50       1875 WWW::Challonge::__handle_error $response if($response->is_error);
97              
98 2         24 return 1;
99             }
100              
101             =head2 destroy
102              
103             Deletes the tournament from the user's account. There is no undo, so use with
104             care!
105              
106             $t->destroy;
107              
108             # $t still contains the tournament, but any future operations will fail:
109             $t->update({ name => "sample_tournament_2" }); # ERROR!
110              
111             =cut
112              
113             sub destroy
114             {
115 2     2 1 632 my $self = shift;
116              
117             # Do not operate on a dead tournament:
118 2 100       18 return __is_kill unless($self->{alive});
119              
120             # Get the key, REST client and tournament URL:
121 1         3 my $key = $self->{key};
122 1         2 my $client = $self->{client};
123 1         3 my $url = $self->{tournament}->{url};
124 1         3 my $HOST = $WWW::Challonge::HOST;
125              
126             # Make the DELETE call:
127 1         17 my $response = $client->delete("$HOST/tournaments/$url.json?api_key=$key");
128              
129             # Check for any errors:
130 1 50       1195 WWW::Challonge::__handle_error $response if($response->is_error);
131              
132             # Set the tournament to dead:
133 1         12 $self->{alive} = 0;
134              
135 1         8 return 1;
136             }
137              
138             =head2 process_check_ins
139              
140             This should be invoked after a tournament's check-in window closes, but before
141             the tournament is started. It then does the following:
142              
143             =over 4
144              
145             =item 1
146              
147             Marks participants who have not checked in as inactive.
148              
149             =item 2
150              
151             Moves inactive participants to the bottom seeds.
152              
153             =item 3
154              
155             Transitions the tournament state from "checking_in" to "checked_in".
156              
157             =back
158              
159             $t->process_check_ins;
160              
161             =cut
162              
163             sub process_check_ins
164             {
165 4     4 1 735 my $self = shift;
166              
167             # Do not operate on a dead tournament:
168 4 100       20 return __is_kill unless($self->{alive});
169              
170             # Get the key, REST client and tournament URL:
171 3         8 my $key = $self->{key};
172 3         6 my $client = $self->{client};
173 3         11 my $url = $self->{tournament}->{url};
174 3         8 my $HOST = $WWW::Challonge::HOST;
175              
176             # Send the API key:
177 3         10 my $params = { api_key => $key };
178              
179             # Make the POST call:
180 3         24 my $response = $client->request(WWW::Challonge::__json_request(
181             "$HOST/tournaments/$url/process_check_ins.json", "POST", $params));
182              
183 3 100       3111 WWW::Challonge::__handle_error $response if($response->is_error);
184              
185 2         28 return 1;
186             }
187              
188             =head2 abort_check_in
189              
190             Aborts the check-in process if the tournament's status is currently
191             "checking_in" or "checked_in". This is useful as you cannot edit the
192             tournament's start time during this state. It does the following:
193              
194             =over 4
195              
196             =item 1
197              
198             Makes all participants active and clears their "checked_in_at" times.
199              
200             =item 2
201              
202             Sets the tournament state from "checking_in" or "checked_in" to "pending".
203              
204             =back
205              
206             $t->abort_check_in;
207              
208             =cut
209              
210             sub abort_check_in
211             {
212 2     2 1 623 my $self = shift;
213              
214             # Do not operate on a dead tournament:
215 2 100       13 return __is_kill unless($self->{alive});
216              
217             # Get the key, REST client and tournament URL:
218 1         3 my $key = $self->{key};
219 1         3 my $client = $self->{client};
220 1         4 my $url = $self->{tournament}->{url};
221 1         3 my $HOST = $WWW::Challonge::HOST;
222              
223             # Send the API key:
224 1         3 my $params = { api_key => $key };
225              
226             # Make the POST call:
227 1         10 my $response = $client->request(WWW::Challonge::__json_request(
228             "$HOST/tournaments/$url/abort_check_in.json", "POST", $params));
229              
230             # Check for any errors:
231 1 50       1124 WWW::Challonge::__handle_error $response if($response->is_error);
232              
233 1         17 return 1;
234             }
235              
236             =head2 start
237              
238             Starts a tournament, opening up matches for score reporting. The tournament
239             must have at least 2 participants. If successful, sets the state of the
240             tournament to "underway".
241              
242             $t->start;
243              
244             =cut
245              
246             sub start
247             {
248 2     2 1 689 my $self = shift;
249              
250             # Do not operate on a dead tournament:
251 2 100       11 return __is_kill unless($self->{alive});
252              
253             # Get the key, REST client and tournament URL:
254 1         4 my $key = $self->{key};
255 1         3 my $client = $self->{client};
256 1         4 my $url = $self->{tournament}->{url};
257 1         3 my $HOST = $WWW::Challonge::HOST;
258              
259             # Send the API key:
260 1         3 my $params = { api_key => $key };
261              
262             # Make the POST call:
263 1         8 my $response = $client->request(WWW::Challonge::__json_request(
264             "$HOST/tournaments/$url/start.json", "POST", $params));
265              
266             # Check for any errors:
267 1 50       1344 WWW::Challonge::__handle_error $response if($response->is_error);
268              
269 1         17 return 1;
270             }
271              
272             =head2 finalize
273              
274             Finalises a tournament that has had all match scores submitted, rendering the
275             results permenant. If successful, it sets the state to "complete".
276              
277             $t->finalize;
278              
279             =cut
280              
281             sub finalize
282             {
283 2     2 1 647 my $self = shift;
284              
285             # Do not operate on a dead tournament:
286 2 100       13 return __is_kill unless($self->{alive});
287              
288             # Get the key, REST client and tournament URL:
289 1         4 my $key = $self->{key};
290 1         2 my $client = $self->{client};
291 1         4 my $url = $self->{tournament}->{url};
292 1         3 my $HOST = $WWW::Challonge::HOST;
293              
294             # Send the API key:
295 1         4 my $params = { api_key => $key };
296              
297             # Make the POST call:
298 1         8 my $response = $client->request(WWW::Challonge::__json_request(
299             "$HOST/tournaments/$url/finalize.json", "POST", $params));
300              
301             # Check for any errors:
302 1 50       1212 WWW::Challonge::__handle_error $response if($response->is_error);
303              
304 1         18 return 1;
305             }
306              
307             =head2 reset
308              
309             Resets an "in_progress" tournament, deleting all match records. You can add,
310             remove or edit users before starting again. Sets the state to "pending".
311              
312             $t->reset;
313              
314             =cut
315              
316             sub reset
317             {
318 2     2 1 732 my $self = shift;
319              
320             # Do not operate on a dead tournament:
321 2 100       12 return __is_kill unless($self->{alive});
322              
323             # Get the key, REST client and tournament URL:
324 1         3 my $key = $self->{key};
325 1         2 my $client = $self->{client};
326 1         5 my $url = $self->{tournament}->{url};
327 1         4 my $HOST = $WWW::Challonge::HOST;
328              
329             # Send the API key:
330 1         3 my $params = { api_key => $key };
331              
332             # Make the POST call:
333 1         9 my $response = $client->request(WWW::Challonge::__json_request(
334             "$HOST/tournaments/$url/reset.json", "POST", $params));
335              
336             # Check for any errors:
337 1 50       1243 WWW::Challonge::__handle_error $response if($response->is_error);
338              
339 1         16 return 1;
340             }
341              
342             =head2 attributes
343              
344             Gets all the attributes of the tournament in a hashref. Contains the following
345             fields.
346              
347             =over 4
348              
349             =item accepting_predictions
350              
351             =item accept_attachments
352              
353             =item allow_participant_match_reporting
354              
355             =item anonymous_voting
356              
357             =item category
358              
359             =item check_in_duration
360              
361             =item completed_at
362              
363             =item created_at
364              
365             =item created_by_api
366              
367             =item credit_capped
368              
369             =item description
370              
371             =item description_source
372              
373             =item full_challonge_url
374              
375             =item game_id
376              
377             =item game_name
378              
379             =item group_stages_enabled
380              
381             =item group_stages_were_started
382              
383             =item hide_forum
384              
385             =item hide_seeds
386              
387             =item hold_third_place_match
388              
389             =item id
390              
391             =item live_image_url
392              
393             =item max_predictions_per_user
394              
395             =item name
396              
397             =item notify_users_when_match_opens
398              
399             =item notify_users_when_the_tournament_ends
400              
401             =item open_signup
402              
403             =item participants_count
404              
405             =item participants_locked
406              
407             =item participants_swappable
408              
409             =item prediction_method
410              
411             =item predictions_opened_at
412              
413             =item private
414              
415             =item progress_meter
416              
417             =item pts_for_bye
418              
419             =item pts_for_game_tie
420              
421             =item pts_for_game_win
422              
423             =item pts_for_match_tie
424              
425             =item pts_for_match_win
426              
427             =item quick_advance
428              
429             =item ranked_by
430              
431             =item review_before_finalizing
432              
433             =item require_score_agreement
434              
435             =item rr_pts_for_game_tie
436              
437             =item rr_pts_for_game_win
438              
439             =item rr_pts_for_match_tie
440              
441             =item rr_pts_for_match_win
442              
443             =item sequential pairings
444              
445             =item show_rounds
446              
447             =item signup_cap
448              
449             =item sign_up_url
450              
451             =item start_at
452              
453             =item started_at
454              
455             =item started_checking_in_at
456              
457             =item state
458              
459             =item swiss_rounds
460              
461             =item subdomain
462              
463             =item teams
464              
465             =item team_convertable
466              
467             =item tie_breaks
468              
469             =item tournament_type
470              
471             =item updated_at
472              
473             =item url
474              
475             =back
476              
477             my $attr = $t->attributes;
478             print $attr->{name}, "\n";
479              
480             =cut
481              
482             sub attributes
483             {
484 7     7 1 2260 my $self = shift;
485              
486             # Do not operate on a dead tournament:
487 7 100       34 return __is_kill unless($self->{alive});
488              
489             # Get the key, REST client and url:
490 6         10 my $key = $self->{key};
491 6         11 my $client = $self->{client};
492 6         21 my $url = $self->{tournament}->{url};
493 6         13 my $HOST = $WWW::Challonge::HOST;
494              
495             # Get the most recent version:
496 6         46 my $response = $client->get(
497             "$HOST/tournaments/$url.json?api_key=$key");
498              
499             # Check for any errors:
500 6 50       5785 WWW::Challonge::__handle_error $response if($response->is_error);
501              
502             # Save the most recent version and return it:
503 6         62 $self->{tournament} = from_json($response->decoded_content)->{tournament};
504              
505 6         1164 return $self->{tournament};
506             }
507              
508             =head2 participants
509              
510             Returns an arrayref of C objects for every
511             participant in the tourney.
512              
513             my $p = $t->participants;
514             for my $participant(@{$p})
515             {
516             ...
517              
518             =cut
519              
520             sub participants
521             {
522 2     2 1 625 my $self = shift;
523              
524             # Do not operate on a dead tournament:
525 2 100       14 return __is_kill unless($self->{alive});
526              
527             # Get the key, REST client and url:
528 1         2 my $key = $self->{key};
529 1         4 my $client = $self->{client};
530 1         4 my $url = $self->{tournament}->{url};
531 1         8 my $HOST = $WWW::Challonge::HOST;
532              
533             # Make the GET request:
534 1         10 my $response = $client->get(
535             "$HOST/tournaments/$url/participants.json?api_key=$key");
536              
537             # Check for any errors:
538 1 50       1476 WWW::Challonge::__handle_error $response if($response->is_error);
539              
540             # If not, make an object for every participant:
541 1         11 my $participants = [];
542 1         2 for my $participant(@{from_json($response->decoded_content)})
  1         5  
543             {
544 4         265 push @{$participants}, WWW::Challonge::Participant->new($participant,
  4         21  
545             $key, $client);
546             }
547 1         8 return $participants;
548             }
549              
550             =head2 participant
551              
552             Returns a single C object representing the
553             participant with the given unique ID.
554              
555             my $p = $t->participant(24279875);
556              
557             =cut
558              
559             sub participant
560             {
561 4     4 1 1615 my $self = shift;
562 4         9 my $participant = shift;
563              
564             # Do not operate on a dead tournament:
565 4 100       20 return __is_kill unless($self->{alive});
566              
567             # Die on no arguments:
568 3 100       207 croak "No arguments given" unless(defined $participant);
569              
570             # Get the key, REST client and url:
571 2         6 my $key = $self->{key};
572 2         5 my $client = $self->{client};
573 2         9 my $url = $self->{tournament}->{url};
574 2         5 my $HOST = $WWW::Challonge::HOST;
575              
576             # Make the GET request:
577 2         22 my $response = $client->get(
578             "$HOST/tournaments/$url/participants/$participant.json?api_key=$key");
579              
580             # Check for any errors:
581 2 100       3428 WWW::Challonge::__handle_error $response if($response->is_error);
582              
583             # If so, create an object and return it:
584 1         14 my $p = WWW::Challonge::Participant->new(
585             from_json($response->decoded_content), $key, $client);
586 1         6 return $p;
587             }
588              
589             =head2 new_participant
590              
591             Adds a new participant to the tournament, and if successful returns the newly
592             created C object. The possible arguments are as
593             follows.
594              
595             =over 4
596              
597             =item name
598              
599             The name of the participant. Required unless I or I
600             are provided. Must be unique within the tournament.
601              
602             =item challonge_username
603              
604             If the participant has a valid Challonge account, providing a name will send
605             them an invite to join the tournament.
606              
607             =item email
608              
609             If the email is attached to a valid Challonge account, it will invite them to
610             join the tournament. If not, the 'new-user-email' attribute will be set, and
611             an email will be sent to invite the person to join Challonge.
612              
613             =item seed
614              
615             Integer. The participant's new seed. Must be between 1 and the new number of
616             participants. Overwriting an existing seed will bump up the other participants.
617             If none is given, the participant will be given the lowest possible seed (the
618             bottom).
619              
620             =item misc
621              
622             Miscellaneous notes on a player only accessible via the API. Maximum 255
623             characters.
624              
625             =back
626              
627             my $p = $t->new_participant({
628             name => "test",
629             seed => 4
630             });
631              
632             =cut
633              
634             sub new_participant
635             {
636 16     16 1 13191 my $self = shift;
637 16         28 my $args = shift;
638              
639             # Do not operate on a dead tournament:
640 16 100       66 return __is_kill unless($self->{alive});
641              
642             # Get the key, REST client and url:
643 15         27 my $key = $self->{key};
644 15         22 my $client = $self->{client};
645 15         45 my $url = $self->{tournament}->{url};
646 15         30 my $HOST = $WWW::Challonge::HOST;
647              
648             # Fail if name or challonge_username or email is not provided:
649 15 50 66     69 unless((defined $args->{name}) || (defined $args->{challonge_username}) ||
      66        
650             (defined $args->{email}))
651             {
652 2         275 croak "Name, email or Challonge username are required to create a new ".
653             "participant.\n";
654 0         0 return undef;
655             }
656              
657             # Check the arguments and values are valid:
658 13 50       54 return undef unless(WWW::Challonge::Participant::__args_are_valid($args));
659              
660             # Add in the API key and convert to a POST request:
661 13         49 my $params = { api_key => $key, participant => $args };
662              
663             # Now we have all the arguments validated, send the POST request:
664 13         103 my $response = $client->request(WWW::Challonge::__json_request(
665             "$HOST/tournaments/$url/participants.json", "POST", $params));
666              
667             # Check for any errors:
668 13 100       14467 WWW::Challonge::__handle_error $response if($response->is_error);
669              
670             # If not, create an object and return it:
671 10         99 my $p = WWW::Challonge::Participant->new(
672             from_json($response->decoded_content), $key, $client);
673 10         78 return $p;
674             }
675              
676             =head2 matches
677              
678             Returns an arrayref of C objects for every
679             match in the tourney. The tournament must be in progress before this will
680             return anything useful.
681              
682             my $m = $t->matches;
683             for my $match(@{$m})
684             {
685             ...
686              
687             =cut
688              
689             sub matches
690             {
691 4     4 1 676 my $self = shift;
692              
693             # Do not operate on a dead tournament:
694 4 100       28 return __is_kill unless($self->{alive});
695              
696             # Get the key, REST client and url:
697 3         10 my $key = $self->{key};
698 3         10 my $client = $self->{client};
699 3         9 my $url = $self->{tournament}->{url};
700 3         8 my $HOST = $WWW::Challonge::HOST;
701              
702             # Make the GET request:
703 3         25 my $response = $client->get(
704             "$HOST/tournaments/$url/matches.json?api_key=$key");
705              
706             # Check for any errors:
707 3 50       3172 WWW::Challonge::__handle_error $response if($response->is_error);
708              
709             # If so, make an object for every participant:
710 3         30 my $matches = [];
711 3         6 for my $match(@{from_json($response->decoded_content)})
  3         23  
712             {
713 18         704 push @{$matches}, WWW::Challonge::Match->new($match, $key,
  18         63  
714             $client);
715             }
716 3         22 return $matches;
717             }
718              
719             =head2 match
720              
721             Returns a single C object representing the match with
722             the given unique ID.
723              
724             my $m = $t->match(24279875);
725              
726             =cut
727              
728             sub match
729             {
730 4     4 1 1233 my $self = shift;
731 4         6 my $match = shift;
732              
733             # Do not operate on a dead tournament:
734 4 100       20 return __is_kill unless($self->{alive});
735              
736             # Die on no arguments:
737 3 100       83 croak "No arguments given" unless(defined $match);
738              
739             # Get the key, REST client and url:
740 2         3 my $key = $self->{key};
741 2         3 my $client = $self->{client};
742 2         7 my $url = $self->{tournament}->{url};
743 2         3 my $HOST = $WWW::Challonge::HOST;
744              
745             # Make the GET request:
746 2         13 my $response = $client->get(
747             "$HOST/tournaments/$url/matches/$match.json?api_key=$key");
748              
749             # Check for any errors:
750 2 100       2238 WWW::Challonge::__handle_error $response if($response->is_error);
751              
752             # If so, create an object and return it:
753 1         10 my $m = WWW::Challonge::Match->new(from_json($response->decoded_content),
754             $key, $client);
755 1         5 return $m;
756             }
757              
758             =head2 __is_kill
759              
760             Returns an error explaining that the current tournament has been destroyed and
761             returns undef, used so a function doesn't attempt to operate on a tournament
762             that has been successfully destroyed.
763              
764             =cut
765              
766             sub __is_kill
767             {
768 13     13   1650 croak "Tournament has been destroyed";
769             }
770              
771             =head2 __args_are_valid
772              
773             Checks if the passed arguments and values are valid for creating or updating
774             a tournament.
775              
776             =cut
777              
778             sub __args_are_valid
779             {
780 20     20   3346 my $args = shift;
781              
782             # The possible parameters, grouped together by the kind of input they take.
783 20         227 my %valid_args = (
784             string => [
785             "name",
786             "tournament_type",
787             "url",
788             "subdomain",
789             "description",
790             "game_name",
791             "ranked_by",
792             ],
793             integer => [
794             "swiss_rounds",
795             "signup_cap",
796             "check_in_duration",
797             ],
798             decimal => [
799             "pts_for_match_win",
800             "pts_for_match_tie",
801             "pts_for_game_win",
802             "pts_for_game_tie",
803             "pts_for_bye",
804             "rr_pts_for_match_win",
805             "rr_pts_for_match_tie",
806             "rr_pts_for_game_win",
807             "rr_pts_for_game_tie",
808             ],
809             bool => [
810             "open_signup",
811             "hold_third_place_match",
812             "accept_attachments",
813             "hide_forum",
814             "show_rounds",
815             "private",
816             "notify_users_when_matches_open",
817             "notify_users_when_the_tournament_ends",
818             "sequential_pairings",
819             ],
820             datetime => [
821             "start_at"
822             ],
823             );
824              
825             # Validate the inputs:
826 20         36 for my $arg(@{$valid_args{string}})
  20         63  
827             {
828 140 100       304 next unless(defined $args->{$arg});
829             # Most of the string-based arguments require individual validation
830             # based on what they are:
831 23 100       131 if($arg =~ /^name$/)
    50          
    50          
    0          
832             {
833 12 50       54 if(length $args->{$arg} > 60)
834             {
835 0         0 croak "Name '" . $args->{$arg} . " is longer than 60 characters";
836             }
837             }
838             elsif($arg =~ /^tournament_type$/)
839             {
840 0 0       0 if($args->{$arg} !~ /^((single|double) elimination)|(round robin)|
841             (swiss)$/i)
842             {
843 0         0 croak "Value '" . $args->{$arg} . "' is invalid for argument '".
844             $arg . "'";
845             }
846             }
847             elsif($arg =~ /^url$/)
848             {
849 11 50       66 if($args->{$arg} !~ /^[a-zA-Z0-9_]*$/)
850             {
851 0         0 croak "Value '" . $args->{$arg} . "' is not a valid URL";
852             }
853             }
854             elsif($arg =~ /^ranked_by$/)
855             {
856 0 0       0 if($args->{$arg} !~ /^((match|game) wins)|
857             (points (scored|difference))|custom/i)
858             {
859 0         0 croak "Value '" . $args->{$arg} . "' is invalid for argument '".
860             $arg . "'";
861             }
862             }
863             }
864 20         38 for my $arg(@{$valid_args{integer}})
  20         50  
865             {
866 58 100       133 next unless(defined $args->{$arg});
867             # Make sure the argument is an integer:
868 5 100       40 if($args->{$arg} !~ /^\d*$/)
869             {
870 1         108 croak "Value '" . $args->{$arg} . "' is not a valid integer for " .
871             "argument '" . $arg . "'";
872             }
873             }
874 19         27 for my $arg(@{$valid_args{decimal}})
  19         44  
875             {
876 171 50       348 next unless(defined $args->{$arg});
877             # Make sure the argument is an integer or decimal:
878 0 0       0 if($args->{$arg} !~ /^\d*\.?\d*$/)
879             {
880 0         0 croak "Value '" . $args->{$arg} . "' is not a valid decimal for " .
881             "argument '" . $arg . "'";
882             }
883             else
884             {
885 0         0 $args->{$arg} = sprintf("%.1f", $args->{$arg});
886             }
887             }
888 19         28 for my $arg(@{$valid_args{boolean}})
  19         63  
889             {
890 0 0       0 next unless(defined $args->{$arg});
891             # Make sure the argument is true or false:
892 0 0       0 if($args->{$arg} !~ /^(true|false)$/i)
893             {
894 0         0 croak "Value '", $args->{$arg}, "' is not valid for argument '" .
895             $arg . "'. It should be 'true' or 'false'";
896             }
897             }
898 19         23 for my $arg(@{$valid_args{datetime}})
  19         43  
899             {
900 19 100       62 next unless(defined $args->{$arg});
901              
902             # Check if we have a DateTime object:
903 10         11 my $is_datetime;
904 10         14 eval { $is_datetime = $args->{$arg}->can("iso8601") };
  10         76  
905              
906             # If so, get the ISO8601 string:
907 10 50       103 if($is_datetime)
    50          
908             {
909 0         0 $args->{$arg} = $args->{$arg}->iso8601;
910             }
911             # If not make sure the argument is a valid datetime:
912             elsif($args->{$arg} !~ /
913             ^\d{4}- # The year, mandatory in all cases
914             (?:
915             (?:
916             \d{2}-\d{2} # Month and day
917             (?:
918             T\d{2}:\d{2}:\d{2} # Hours, minutes, seconds
919             (?:
920             (?:
921             \+\d{2}:\d{2} # Timezone
922             )
923             |
924             (?:
925             Z # UTC
926             )
927             )
928             )?
929             )
930             |
931             (?:
932             W\d{2} # Week
933             (?:
934             -\d # Date with week number
935             )?
936             )
937             |
938             (?:
939             \d{3} # Ordinal date
940             )
941             )
942             $
943             /x)
944             {
945 0         0 croak "Value '", $args->{$arg}, "' is not a valid datetime for " .
946             "argument '" . $arg . "'";
947             }
948             }
949              
950             # Finally, check if there are any unrecognised arguments, but just ignore
951             # them instead of erroring out:
952 19         38 my @accepted_inputs = (
953 19         34 @{$valid_args{string}},
954 19         31 @{$valid_args{integer}},
955 19         30 @{$valid_args{decimal}},
956 19         92 @{$valid_args{bool}},
957 19         31 @{$valid_args{datetime}}
958             );
959 19         32 my $is_valid = 0;
960 19         25 for my $arg(keys %{$args})
  19         62  
961             {
962 37         57 for my $valid_arg(@accepted_inputs)
963             {
964 375 100       614 if($arg eq $valid_arg)
965             {
966 37         41 $is_valid = 1;
967 37         48 last;
968             }
969             }
970 37 50       105 carp "Ignoring unknown argument '" . $arg . "'" unless($is_valid);
971 37         64 $is_valid = 0;
972             }
973 19         151 return 1;
974             }
975              
976             =head1 AUTHOR
977              
978             Alex Kerr, C<< >>
979              
980             =head1 BUGS
981              
982             Please report any bugs or feature requests to C, or through
983             the web interface at L. I will be notified, and then you'll
984             automatically be notified of progress on your bug as I make changes.
985              
986             =head1 SUPPORT
987              
988             You can find documentation for this module with the perldoc command.
989              
990             perldoc WWW::Challonge::Tournament
991              
992             You can also look for information at:
993              
994             =over 4
995              
996             =item * RT: CPAN's request tracker (report bugs here)
997              
998             L
999              
1000             =item * AnnoCPAN: Annotated CPAN documentation
1001              
1002             L
1003              
1004             =item * CPAN Ratings
1005              
1006             L
1007              
1008             =item * Search CPAN
1009              
1010             L
1011              
1012             =back
1013              
1014             =head1 SEE ALSO
1015              
1016             =over 4
1017              
1018             =item L
1019              
1020             =item L
1021              
1022             =item L
1023              
1024             =item L
1025              
1026             =back
1027              
1028             =head1 ACKNOWLEDGEMENTS
1029              
1030             Everyone on the L team for making such a great
1031             service.
1032              
1033             =head1 LICENSE AND COPYRIGHT
1034              
1035             Copyright 2015 Alex Kerr.
1036              
1037             This program is free software; you can redistribute it and/or modify it
1038             under the terms of the the Artistic License (2.0). You may obtain a
1039             copy of the full license at:
1040              
1041             L
1042              
1043             Any use, modification, and distribution of the Standard or Modified
1044             Versions is governed by this Artistic License. By using, modifying or
1045             distributing the Package, you accept this license. Do not use, modify,
1046             or distribute the Package, if you do not accept this license.
1047              
1048             If your Modified Version has been derived from a Modified Version made
1049             by someone other than you, you are nevertheless required to ensure that
1050             your Modified Version complies with the requirements of this license.
1051              
1052             This license does not grant you the right to use any trademark, service
1053             mark, tradename, or logo of the Copyright Holder.
1054              
1055             This license includes the non-exclusive, worldwide, free-of-charge
1056             patent license to make, have made, use, offer to sell, sell, import and
1057             otherwise transfer the Package with respect to any patent claims
1058             licensable by the Copyright Holder that are necessarily infringed by the
1059             Package. If you institute patent litigation (including a cross-claim or
1060             counterclaim) against any party alleging that the Package constitutes
1061             direct or contributory patent infringement, then this Artistic License
1062             to you shall terminate on the date that such litigation is filed.
1063              
1064             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
1065             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
1066             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1067             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
1068             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
1069             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
1070             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
1071             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1072              
1073             =cut
1074              
1075             1; # End of WWW::Challonge::Tournament