ActiveRecord::Schema.define do create_table :ranges_v2 do |table| table.column :granularity, :float table.column :author, :string table.column :time_start, :date table.column :time_stop, :date end end module TimeCost class RangeV2 < ActiveRecord::Base has_many :commits_v2 GRANULARITY_DEFAULT = 0.5 def to_s show_authors = true val = "(%s)\t%s - %s\n" % [diff, fixed_start, @time_stop] if show_authors then val += "\tby %s\n" % @commits.first.author end @commits.each do |commit| lines = [] lines.concat commit.note.split(/\n/) r = lines.map{ |s| "\t %s" % s }.join "\n" r[1] = '*' val += r + "\n" end return val end end class Range attr_accessor :time_start, :time_stop, :commits, :author GRANULARITY_DEFAULT = 0.5 def initialize commit, options = {} @granularity = options[:granularity] || GRANULARITY_DEFAULT # FIXME: First approximation for users # later, we'll replace with @user = User.parse(commit.author) @author = commit.author @time_stop = DateTime.parse(commit.date) @time_start = @time_stop - (@granularity * 3 / 24.0) @commits = [commit] self end def merge range # B -----[----]---- # A --[----]------ # = ---[------]---- # minimum of both new_start = if range.time_start < @time_start then range.time_start else @time_start end new_end = if range.time_stop >= @time_stop then range.time_stop else @time_stop end @time_start = new_start @time_stop = new_end @commits.concat range.commits end def overlap? range result = false # return early result if ranges come from different authors return false if (@author != range.author) # Ref ----[----]----- # overlapping : # A -[----]-------- # B -------[----]-- # C -[----------]-- # D ------[]------- # non-overlapping : # E -[]------------ # F -----------[]-- start_before_start = (range.time_start < @time_start) start_after_start = (range.time_start >= @time_start) start_after_stop = (range.time_start >= @time_stop) start_before_stop = (range.time_start < @time_stop) stop_before_stop = (range.time_stop < @time_stop) stop_after_stop = (range.time_stop >= @time_stop) stop_before_start = (range.time_stop < @time_start) stop_after_start = (range.time_stop >= @time_start) # A case if start_before_start and start_before_stop and stop_after_start and stop_before_stop then result = true end # B case if start_after_start and start_before_stop and stop_after_start and stop_after_stop then result = true end # C case if start_before_start and start_before_stop and stop_after_start and stop_after_stop then result = true end # D case if start_after_start and start_before_stop and stop_after_start and stop_before_stop then result = true end return result end def fixed_start return @time_start + (@granularity/24.0) end def diff return ("%.2f" % ((@time_stop - fixed_start).to_f * 24)).to_f end def to_s show_authors = true val = "(%s)\t%s - %s\n" % [diff, fixed_start, @time_stop] if show_authors then val += "\tby %s\n" % @commits.first.author end @commits.each do |commit| lines = [] lines.concat commit.note.split(/\n/) r = lines.map{ |s| "\t %s" % s }.join "\n" r[1] = '*' val += r + "\n" end return val end end end