-
Notifications
You must be signed in to change notification settings - Fork 15
/
sprint_boundary_iterator.rb
65 lines (50 loc) · 1.56 KB
/
sprint_boundary_iterator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
require "active_support"
require "active_support/core_ext/numeric/time"
require "pathname"
require "yaml"
class SprintBoundaryIterator
include Enumerable
def initialize(last_day = Date.today)
@last_day = last_day
exceptions_yml = Pathname.new(__dir__).join("sprint_boundary_exceptions.yml")
@exceptions = exceptions_yml.exist? ? YAML.unsafe_load(exceptions_yml.read) : {}
@exceptions.transform_values! { |range_start, range_end| (range_start..range_end) }
end
def each
init_iterator
loop do
number, range = next_boundary
yield number, range
break if range.end >= @last_day
end
end
def self.start_range
new.first.last
end
private
INITIAL_SPRINT = 8
def init_iterator
@last_number = INITIAL_SPRINT - 1
@last_range = nil
end
def next_boundary
next_number = @last_number + 1
next_range = @exceptions[next_number] || compute_next_range(@last_range, sprint_length(next_number))
@last_number, @last_range = next_number, next_range
end
def compute_next_range(current, sprint_length)
date = current.end + sprint_length
date += 1.weeks while winter_break?(date) || july_4_break?(date)
(current.end + 1.day)..date
end
# With sprint 52 (first sprint of 2017) we switched to 2 week sprints
def sprint_length(number)
number >= 52 ? 2.weeks : 3.weeks
end
def winter_break?(date)
(date.month == 12 && (21..31).cover?(date.day)) || (date.month == 1 && (1..3).cover?(date.day))
end
def july_4_break?(date)
date.month == 7 && (3..4).cover?(date.day)
end
end