git-timecost/lib/timecost/range.rb

147 lines
3.4 KiB
Ruby

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