class Linesmen::Timeline
This class deals with timeline operations. We understand timelines here as a sequence of non-contiguous events. The methods here are mostly boolean operations. This article may help you to understand them: www.wikiwand.com/en/Boolean_operations_on_polygons
Attributes
time_ranges[R]
Public Class Methods
new(*time_ranges)
click to toggle source
# File lib/linesmen/timeline.rb, line 11 def initialize(*time_ranges) @time_ranges = time_ranges ensure_no_overlapping! end
Public Instance Methods
gross_duration()
click to toggle source
# File lib/linesmen/timeline.rb, line 54 def gross_duration time_ranges.last.end - time_ranges.first.begin end
hours()
click to toggle source
# File lib/linesmen/timeline.rb, line 70 def hours minutes / 60 end
intersect(other)
click to toggle source
# File lib/linesmen/timeline.rb, line 34 def intersect(other) case other when Range then intersect_time_ranges(other) when Timeline then intersect_time_ranges(*other.time_ranges) end end
Also aliased as: &
invert()
click to toggle source
# File lib/linesmen/timeline.rb, line 43 def invert Timeline.new( *time_ranges.map.with_index do |range, index| next if index.zero? time_ranges[index - 1].end..range.begin end.compact ) end
Also aliased as: !@
minutes()
click to toggle source
# File lib/linesmen/timeline.rb, line 66 def minutes seconds / 60 end
net_duration()
click to toggle source
# File lib/linesmen/timeline.rb, line 58 def net_duration time_ranges.sum(0) do |time_range| time_range.end - time_range.begin end end
Also aliased as: seconds
subtract(other)
click to toggle source
# File lib/linesmen/timeline.rb, line 25 def subtract(other) case other when Range then subtract_time_ranges(other) when Timeline then subtract_time_ranges(*other.time_ranges) end end
Also aliased as: -
union(other)
click to toggle source
# File lib/linesmen/timeline.rb, line 16 def union(other) case other when Range then Timeline.new(*(time_ranges + [other])) when Timeline then Timeline.new(*(time_ranges + other.time_ranges)) end end
Also aliased as: +
Private Instance Methods
ensure_no_overlapping!()
click to toggle source
# File lib/linesmen/timeline.rb, line 76 def ensure_no_overlapping! @time_ranges.sort_by!(&:begin) time_ranges.each_with_index do |time_range, index| next if index.zero? prev_range = time_ranges[index - 1] next unless prev_range.overlaps?(time_range) @time_ranges[index - 1] = union_two_ranges(prev_range, time_range) @time_ranges.delete_at(index) return ensure_no_overlapping! end end
intersect_time_ranges(*other_ranges)
click to toggle source
# File lib/linesmen/timeline.rb, line 108 def intersect_time_ranges(*other_ranges) Timeline.new( *time_ranges.reduce([]) do |memo, r| memo + other_ranges .select { |o| r.overlaps?(o) } .map { |o| [intersect_two_ranges(r, o)].compact } .flatten end ) end
intersect_timelines(*other_timelines)
click to toggle source
# File lib/linesmen/timeline.rb, line 126 def intersect_timelines(*other_timelines) intersect_time_ranges(*other_timelines.map(&:time_ranges).flatten) end
intersect_two_ranges(range_a, range_b)
click to toggle source
# File lib/linesmen/timeline.rb, line 120 def intersect_two_ranges(range_a, range_b) s = [range_a.begin, range_b.begin].max e = [range_a.end, range_b.end].min (s..e) if s < e end
subtract_time_ranges(*other_ranges)
click to toggle source
# File lib/linesmen/timeline.rb, line 92 def subtract_time_ranges(*other_ranges) return self if other_ranges.empty? o = other_ranges.first r = time_ranges.detect { |range| range.overlaps?(o) } return subtract_time_ranges(*other_ranges[1..-1]) unless r new_time_ranges = time_ranges - [r] + subtract_two_ranges(r, o) Timeline.new(*new_time_ranges).send(:subtract_time_ranges, *other_ranges) end
subtract_two_ranges(range_a, range_b)
click to toggle source
# File lib/linesmen/timeline.rb, line 101 def subtract_two_ranges(range_a, range_b) [ ((range_a.begin..(range_b.begin - 1)) if range_a.begin < range_b.begin), (((range_b.end + 1)..range_a.end) if range_b.end < range_a.end) ].compact end
union_two_ranges(range_a, range_b)
click to toggle source
# File lib/linesmen/timeline.rb, line 88 def union_two_ranges(range_a, range_b) [range_a.begin, range_a.end].min..[range_b.begin, range_b.end].max end