131 lines
3.1 KiB
Crystal
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
|