fix the date math
[engit/Iron-Munger.git] / lib / IronMunger / Calculate.pm
1 package IronMunger::Calculate;
2
3 use strict;
4 use warnings;
5 use List::Util qw(min);
6 use autobox;
7 use autobox::DateTime::Duration;
8 use signatures;
9
10 use Sub::Exporter -setup => {
11   exports => [
12     qw(successful_sequential_posts time_remaining_to_post)
13   ]
14 };
15
16 sub day_diff ($dt1, $dt2) {
17   $dt1 = $dt1->at if $dt1->isa('IronMunger::Post');
18   $dt2 = $dt2->at if $dt2->isa('IronMunger::Post');
19   $dt1->delta_days($dt2)->delta_days;
20 }
21
22 sub check_post_gap ($aperture, $days, @posts) {
23   return scalar @posts if @posts <= $aperture;
24   my @next_post = splice(@posts, 0, $aperture);
25   return 0 if day_diff(DateTime->now, $next_post[-1]) > $days;
26   my $success = $aperture;
27   foreach my $post (@posts) {
28     if (day_diff($next_post[0],$post) > $days) {
29       return $success;
30     }
31     $success++;
32     shift(@next_post);
33     push(@next_post, $post);
34   }
35   return $success;
36 }
37
38 sub check_time_remaining ($aperture, $days, @posts) {
39   my $cand = (@posts > $aperture ? $posts[$aperture - 1] : $posts[-1]);
40   my $days_ago = day_diff(DateTime->now, $cand);
41   return $days - $days_ago;
42 }
43
44 sub check_both ($check, @posts) {
45   return min(
46     $check->(1, 10, @posts), # 10 days between posts
47     $check->(4, 32, @posts), # 4 posts within any given 32 days
48   );
49 }
50
51 sub successful_sequential_posts (@posts) {
52   return check_both(\&check_post_gap, @posts);
53 }
54
55 sub days_remaining_to_post (@posts) {
56   return check_both(\&check_time_remaining, @posts);
57 }
58
59 1;