git-timecost/src/timecost/range.cr

131 lines
3.1 KiB
Crystal

require "./commit"
module TimeCost
class Range
property time_start
property time_stop
property commits : Array(Commit)
property author
EPSILON_DEFAULT = 0.5
def initialize(commit : Commit, @epsilon = EPSILON_DEFAULT)
# FIXME: First approximation for users
# later, we'll replace with @user = User.parse(commit.author)
@author = commit.author
@time_stop = commit.datetime
@time_start = commit.datetime - epsilon.hours
@commits = [commit]
self
end
def author : Author?
@commits.first.try &.author
end
def merge(range)
# B -----[----]----
# A --[----]------
# = ---[------]----
# minimum of both
new_start = (
if range.time_start < @time_start
range.time_start
else
@time_start
end
)
new_end = (
if range.time_stop >= @time_stop
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)
result = true
end
# B case
if (start_after_start and start_before_stop and
stop_after_start and stop_after_stop)
result = true
end
# C case
if (start_before_start and start_before_stop and
stop_after_start and stop_after_stop)
result = true
end
# D case
if (start_after_start and start_before_stop and
stop_after_start and stop_before_stop)
result = true
end
return result
end
def fixed_start
return @time_start + (@epsilon/24.0)
end
def diff : Float
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
val += "\tby %s\n" % @commits.first.author
end
@commits.each do |commit|
lines = [] of String
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