Commit | Line | Data |
ac04ccd9 |
1 | package IronMunger::Calculate; |
2 | |
3 | use strict; |
4 | use warnings; |
66bdbe82 |
5 | use List::Util qw(min); |
38827ef4 |
6 | use autobox; |
38efa3f1 |
7 | use autobox::DateTime::Duration; |
f79d4b5c |
8 | use signatures; |
67e9aef2 |
9 | |
a7b549f9 |
10 | use Sub::Exporter -setup => { |
11 | exports => [ |
69941ee3 |
12 | qw(successful_sequential_posts days_remaining_to_post level_for_post_count) |
a7b549f9 |
13 | ] |
14 | }; |
15 | |
66bdbe82 |
16 | sub 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 |
25 | sub 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 |
46 | sub 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 |
55 | sub 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 |
62 | sub successful_sequential_posts (@posts) { |
63 | return check_both(\&check_post_gap, @posts); |
64 | } |
65 | |
38827ef4 |
66 | sub days_remaining_to_post (@posts) { |
a7b549f9 |
67 | return check_both(\&check_time_remaining, @posts); |
68 | } |
69 | |
69941ee3 |
70 | sub 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 |
77 | 1; |