switch day diff calculation to epoch based so that "N hours short of M days" becomes...
[engit/Iron-Munger.git] / lib / IronMunger / Calculate.pm
CommitLineData
ac04ccd9 1package IronMunger::Calculate;
2
3use strict;
4use warnings;
66bdbe82 5use List::Util qw(min);
38827ef4 6use autobox;
38efa3f1 7use autobox::DateTime::Duration;
f79d4b5c 8use signatures;
67e9aef2 9
a7b549f9 10use Sub::Exporter -setup => {
11 exports => [
69941ee3 12 qw(successful_sequential_posts days_remaining_to_post level_for_post_count)
a7b549f9 13 ]
14};
15
66bdbe82 16sub day_diff ($dt1, $dt2) {
17 $dt1 = $dt1->at if $dt1->isa('IronMunger::Post');
18 $dt2 = $dt2->at if $dt2->isa('IronMunger::Post');
dd4e50cb 19 my $seconds = $dt2->epoch - $dt1->epoch;
20 $seconds = -$seconds if $seconds < 0;
21 int($seconds / 86400);
22 #$dt1->delta_days($dt2)->delta_days;
66bdbe82 23}
24
38efa3f1 25sub check_post_gap ($aperture, $days, @posts) {
66bdbe82 26 return scalar @posts if @posts <= $aperture;
38efa3f1 27 my @next_post = splice(@posts, 0, $aperture);
e1738c74 28 if (day_diff(DateTime->now, $next_post[-1]) > $days) {
29 while (@next_post && day_diff(DateTime->now, $next_post[-1]) > $days) {
30 pop @next_post;
31 }
32 return scalar(@next_post);
33 }
38efa3f1 34 my $success = $aperture;
67e9aef2 35 foreach my $post (@posts) {
66bdbe82 36 if (day_diff($next_post[0],$post) > $days) {
37 return $success;
38 }
67e9aef2 39 $success++;
40 shift(@next_post);
41 push(@next_post, $post);
42 }
43 return $success;
44}
38efa3f1 45
a51e36e5 46sub check_time_remaining ($aperture, $days, @posts) {
e1738c74 47 my @consider = @posts > $aperture ? @posts[0 .. $aperture - 1] : @posts;
48 foreach my $cand (reverse @consider) {
49 my $days_ago = day_diff(DateTime->now, $cand);
50 return $days - $days_ago if $days > $days_ago;
51 }
52 return $days;
a51e36e5 53}
54
a7b549f9 55sub check_both ($check, @posts) {
66bdbe82 56 return min(
a7b549f9 57 $check->(1, 10, @posts), # 10 days between posts
58 $check->(4, 32, @posts), # 4 posts within any given 32 days
38efa3f1 59 );
60}
ac04ccd9 61
a7b549f9 62sub successful_sequential_posts (@posts) {
63 return check_both(\&check_post_gap, @posts);
64}
65
38827ef4 66sub days_remaining_to_post (@posts) {
a7b549f9 67 return check_both(\&check_time_remaining, @posts);
68}
69
69941ee3 70sub level_for_post_count($count) {
71 return 'paper' if $count < 4;
72 return 'stone' if $count < 12;
73 return 'bronze' if $count < 36;
74 return 'iron';
75}
76
ac04ccd9 771;