例
business_hours['monday'] = [800..1200, 1300..1700]
business_hours['tuesday'] = [900..1100, 1300..1700]
...
然后我有一大堆的活动占用一些时间间隔,例如
event = { start_at: somedatetime, end_at: somedatetime }
遍历从某个特定日期的事件某个日期,创建另一个数组
busy_hours['monday'] = [800..830, 1400..1415]
...
现在我的挑战
- 创建包含business_hours减去busy_hours的available_hours阵列
available_hours = business_hours - busy_hours
- 给予一定的持续时间说30分钟,发现其中时隙为available_hours可用。 在上面的例子中,这样的方法将返回
available_slots['monday'] = [830..900, 845..915, 900..930, and so on]
不它检查在指定的时间的时隙15分钟为增量available_hours。
谢谢您的帮助!
我认为这是对位字段的工作。 不幸的是这种解决方案将依托神奇数字,转换助手和二进制逻辑的公平一点,所以它不会是漂亮。 但它会工作,是非常有效的。
这是我会处理这个问题:
雾化你的日子到合理的时间间隔。 我会按照你的榜样和治疗的时间每次15分钟块作为考虑的一个时间块(主要是因为它使例子简单)。 然后,代表每小时的可用性作为一个十六进制数字。
例:
- 0xF = 0x1111 =>可用于整个小时。
- 位于0xC =从0x1100 =>可用于小时的前半部分。
这些串24一起,共同代表了一天。 或更少,如果你可以肯定的是没有事件的范围之外发生。 该示例假设继续24小时。
从这一点上我长期分裂的十六进制数成文字的可读性假设当天从00:00变为23:59 business_hours['monday'] = 0x0000 0000 FFFF 0FFF F000 0000
为了让您busy_hours存储在一个相似的格式事件,只是&它们放在一起。
Exmample:
event_a = 0x0000 0000 00F0 0000 0000 0000 # 10:00 - 11:00
event_b = 0x0000 0000 0000 07F8 0000 0000 # 13:15 - 15:15
busy_hours = event_a & event_b
从busy_hours和business_hours你可以得到可用时间:
available_hours = business_hours&(busy_hours ^为0xFFFF FFFF FFFF FFFF FFFF FFFF)
异或(^)essentialy转化成busy_hours not_busy_hours。 安定()与business_hours not_busy_hours给我们的可用时间为一天。
该方案还可以很方便地使用小时比较了很多人。
all_available_hours = person_a_available_hours & person_b_available_hours & person_c_available_hours
然后找到适合可用小时的时间段。 你需要做这样的事情:将您的时间长度为类似十六进制数字的一个小时,其中的那些代表小时的时间段将覆盖所有的时间块。 所以没有尾随0的下一步右移数字。
实例是比更好的解释:0x1 =在> 15分钟后,0x3 =>半小时,为0x7 => 45分钟,0xF =>充分小时,...为0xFF => 2小时,等
一旦你这样做,你这样做:
acceptable_times =[]
(0 .. 24 * 4 - (#of time chunks time slot)).each do |i|
acceptable_times.unshift(time_slot_in_hex) if available_hours & (time_slot_in_hex << i) == time_slot_in_hex << i
end
该范围的高端是有点乱的。 所以,让我们看看多一点吧。 我们不想太多次转移,不然我们就可以开始在频谱提前结束越来越误报。
24 * 4
在每天24小时,其中每个由4个比特来表示。 - (#of time chunks in time slot)
减1为您在时隙每次15分钟,我们要寻找的。 此值可以通过找到(Math.log(time_slot_in_hex)/Math.log(2)).floor + 1
其开始于一天结束时,检查每个时隙,早些时候在每次迭代时间块(在本例中15分钟)移动。 如果时隙可用它添加到可以接受的时间开始。 因此,当过程结束acceptable_times中出现的顺序进行排序。
最酷的是这个实现允许并入,使您的与会者可以在自己一天的忙碌时期,平分你休息后,他们可能会以其他方式忙着找时隙时隙。
这是给你写的辅助函数范围的阵列(即:[800..1200,1300..1700])之间进行转换和十六进制表示。 要做到这一点,最好的办法是封装行为的对象,并使用自定义的访问方法。 然后使用相同的对象来表示天,事件,繁忙时间,等等。这是没有内置此方案是如何安排的活动,使他们能够跨越天界的唯一的事情。
要回答你的问题的标题,如果发现了一系列阵列包含范围:
ary = [800..1200, 1300..1700]
test = 800..830
p ary.any? {|rng| rng.include?(test.first) and rng.include?(test.last)}
# => true
test = 1245..1330
p ary.any? {|rng| rng.include?(test.first) and rng.include?(test.last)}
# => false
这可以写成
class Range
def include_range?(r)
self.include?(r.first) and self.include?(r.last)
end
end
好吧,我没有时间写了一个完整的解决方案,但似乎问题并不太难了我。 我砍死在一起,你可以用你的构建解决方案,以帮助下面原始的方法(可能要继承范围,而不是猴子打补丁,但是这会给你的想法):
class Range
def contains(range)
first <= range.first || last >= range.last
end
def -(range)
out = []
unless range.first <= first && range.last >= last
out << Range.new(first, range.first) if range.first > first
out << Range.new(range.last, last) if range.last < last
end
out
end
end
可以遍历营业时间并查找包含像这样的事件之一:
event_range = event.start_time..event.end_time
matching_range = business_hours.find{|r| r.contains(event_range)}
您可以构建这样的新阵列(伪,未测试):
available_hours = business_hours.dup
available_hours.delete(matching_range)
available_hours += matching_range - event_range
这应该是一个漂亮的可重复使用的方法。 当然,你需要的东西,你的问题的下一部分完全不同的,但是这是我的所有时间:)