class Workpattern::Day
Attributes
first_working_minute[RW]
hours_per_day[RW]
last_working_minute[RW]
pattern[RW]
Public Class Methods
new(hours_per_day = HOURS_IN_DAY, type = WORK_TYPE)
click to toggle source
# File lib/workpattern/day.rb, line 7 def initialize(hours_per_day = HOURS_IN_DAY, type = WORK_TYPE) @hours_per_day = hours_per_day @pattern = initial_day(type) set_first_and_last_minutes end
Public Instance Methods
calc(a_date, a_duration)
click to toggle source
# File lib/workpattern/day.rb, line 39 def calc(a_date, a_duration) if a_duration == 0 return a_date, a_duration, SAME_DAY else return a_duration > 0 ? add(a_date, a_duration) : subtract(a_date, a_duration) end end
resting?(hour, minute)
click to toggle source
# File lib/workpattern/day.rb, line 35 def resting?(hour, minute) !working?(hour,minute) end
set_resting(start_time, finish_time)
click to toggle source
# File lib/workpattern/day.rb, line 13 def set_resting(start_time, finish_time) mask = resting_mask(start_time, finish_time) @pattern = @pattern & mask set_first_and_last_minutes end
set_working(from_time, to_time)
click to toggle source
# File lib/workpattern/day.rb, line 19 def set_working(from_time, to_time) @pattern = @pattern | working_mask(from_time, to_time) set_first_and_last_minutes end
working?(hour, minute)
click to toggle source
# File lib/workpattern/day.rb, line 29 def working?(hour, minute) mask = (2**((hour * 60) + minute)) result = mask & @pattern mask == result end
working_minutes(from_time = FIRST_TIME_IN_DAY, to_time = LAST_TIME_IN_DAY)
click to toggle source
# File lib/workpattern/day.rb, line 24 def working_minutes(from_time = FIRST_TIME_IN_DAY, to_time = LAST_TIME_IN_DAY) section = @pattern & working_mask(from_time, to_time) section.to_s(2).count('1') end
Private Instance Methods
add(a_date, a_duration)
click to toggle source
# File lib/workpattern/day.rb, line 49 def add(a_date, a_duration) minutes_left = working_minutes(a_date) if a_duration > minutes_left return [a_date, a_duration - minutes_left, NEXT_DAY] elsif a_duration < minutes_left return add_minutes(a_date, a_duration) else if working?(LAST_TIME_IN_DAY.hour, LAST_TIME_IN_DAY.min) return [a_date, 0, NEXT_DAY] else return_date = Time.gm(a_date.year, a_date.month, a_date.day, @last_working_minute.hour, @last_working_minute.min) + 60 return [ return_date, 0, SAME_DAY] end end end
add_minutes(a_date, a_duration)
click to toggle source
# File lib/workpattern/day.rb, line 65 def add_minutes(a_date, a_duration) elapsed_date = a_date + (a_duration * 60) - 60 if working_minutes(a_date, elapsed_date) == a_duration return [elapsed_date += 60, 0, SAME_DAY] else begin elapsed_date += 60 end while working_minutes(a_date, elapsed_date) != a_duration return [elapsed_date += 60, 0, SAME_DAY] end end
first_minute()
click to toggle source
# File lib/workpattern/day.rb, line 189 def first_minute if working?(FIRST_TIME_IN_DAY.hour, FIRST_TIME_IN_DAY.min) return FIRST_TIME_IN_DAY end top = minutes_in_time(LAST_TIME_IN_DAY) bottom = minutes_in_time(FIRST_TIME_IN_DAY) mark = top / 2 not_done = true while not_done minutes = working_minutes(minutes_to_time(bottom), minutes_to_time(mark)) if minutes > 1 top = mark mark = mark - ((top - bottom) / 2) elsif minutes == 0 bottom = mark mark = mark + (( top - bottom) / 2) elsif minutes == 1 && is_resting(mark) top = mark mark = mark - ((top - bottom) / 2) else not_done = false end if mark == 1 && top == 1 mark = 0 end end minutes_to_time(mark) end
initial_day(type = WORK_TYPE)
click to toggle source
# File lib/workpattern/day.rb, line 107 def initial_day(type = WORK_TYPE) pattern = 2**((60 * @hours_per_day) + 1) if type == WORK_TYPE pattern = pattern - 1 end pattern end
is_resting(minutes)
click to toggle source
# File lib/workpattern/day.rb, line 227 def is_resting(minutes) a_time =(minutes_to_time(minutes)) resting?(a_time.hour, a_time.min) end
last_minute()
click to toggle source
# File lib/workpattern/day.rb, line 145 def last_minute if working?(LAST_TIME_IN_DAY.hour, LAST_TIME_IN_DAY.min) return LAST_TIME_IN_DAY end top = minutes_in_time(LAST_TIME_IN_DAY) bottom = minutes_in_time(FIRST_TIME_IN_DAY) mark = top / 2 not_done = true while not_done minutes = working_minutes(minutes_to_time(mark), minutes_to_time(top)) if minutes > 1 bottom = mark mark = mark + ((top - bottom) / 2) elsif minutes == 0 top = mark mark = mark - (( top - bottom) / 2) elsif minutes == 1 && is_resting(mark) bottom = mark mark = mark + ((top - bottom) / 2) else not_done = false end if mark == bottom #& last_mark != mark mark = mark + 1 end if mark == 1 && top == 1 mark = 0 end end minutes_to_time(mark) end
minutes_in_time(a_time)
click to toggle source
# File lib/workpattern/day.rb, line 141 def minutes_in_time(a_time) (a_time.hour * 60) + a_time.min end
minutes_to_time(minutes)
click to toggle source
# File lib/workpattern/day.rb, line 223 def minutes_to_time(minutes) Time.gm(1963,6,10,minutes / 60, minutes - (minutes / 60 * 60)) end
resting_mask(start_time, finish_time)
click to toggle source
# File lib/workpattern/day.rb, line 129 def resting_mask(start_time, finish_time) start = minutes_in_time(start_time) finish_clock = Clock.new(finish_time.hour, finish_time.min + 1) mask = initial_day(REST_TYPE) if minutes_in_time(finish_time) != LAST_TIME_IN_DAY.minutes mask = mask | working_mask(finish_clock,LAST_TIME_IN_DAY) end mask | ((2**start) - 1) end
set_first_and_last_minutes()
click to toggle source
# File lib/workpattern/day.rb, line 232 def set_first_and_last_minutes if working_minutes == 0 @first_working_minute = nil @last_working_minute = nil else @first_working_minute = first_minute @last_working_minute = last_minute end end
subtract(a_date, a_duration)
click to toggle source
# File lib/workpattern/day.rb, line 78 def subtract(a_date, a_duration) minutes_left = working_minutes(FIRST_TIME_IN_DAY,a_date - 60) abs_duration = a_duration.abs if abs_duration > minutes_left return [a_date, a_duration + minutes_left, PREVIOUS_DAY] elsif abs_duration < minutes_left return subtract_minutes(a_date, abs_duration) else return [Time.gm(a_date.year,a_date.month,a_date.day,@first_working_minute.hour,@first_working_minute.min), 0, SAME_DAY] end end
subtract_minutes(a_date, abs_duration)
click to toggle source
# File lib/workpattern/day.rb, line 90 def subtract_minutes(a_date, abs_duration) elapsed_date = a_date - (abs_duration * 60) if working_minutes(elapsed_date, a_date - 60) == abs_duration return [elapsed_date, 0, SAME_DAY] else a_date -= 60 begin elapsed_date -= 60 end while working_minutes(elapsed_date, a_date) != abs_duration return [elapsed_date, 0, SAME_DAY] end end
working_day()
click to toggle source
# File lib/workpattern/day.rb, line 103 def working_day 2**((60 * @hours_per_day) +1) - 1 end
working_mask(start_time, finish_time)
click to toggle source
# File lib/workpattern/day.rb, line 118 def working_mask(start_time, finish_time) start = minutes_in_time(start_time) finish = minutes_in_time(finish_time) mask = initial_day mask = mask - ((2**start) - 1) mask & ((2**(finish + 1)) -1) end