我假設我們給出了'計劃','可用'和'覆蓋率'的小時範圍,其中'覆蓋率'是'備用'範圍之前和之後的'可用'範圍。此外,「覆蓋範圍」包含「計劃」,其「備用」範圍中的一個或兩個可以是零持續時間。
代碼
def categories(avail, plan)
adj_avail = adj_avail(avail)
adj_plan = adj_plan(avail, plan)
arr = []
finish = [adj_avail[:available][:start], adj_plan[:start]].min
add_block(arr, :standby, adj_avail[:coverage][:start], finish)
start = finish
finish = [adj_avail[:available][:finish], adj_plan[:start]].min
add_block(arr, :available, start, finish)
start = finish
add_block(arr, :standby, finish, adj_plan[:start])
arr << [:plan, adj_plan]
finish = [adj_plan[:finish], adj_avail[:available][:finish]].max
add_block(arr, :available, adj_plan[:finish], finish)
add_block(arr, :standby, finish, adj_avail[:coverage][:finish])
restore_times(arr)
end
def adj_avail(avail)
avail.each_with_object({}) do |(k,g),h|
start, finish = g[:start], g[:finish]
h[k] = case k
when :coverage
{ start: start, finish: finish + (finish < start ? 24 : 0) }
else # when :available
{ start: start + (start < h[:coverage][:start] ? 24 : 0),
finish: finish + (finish < start ? 24 : 0) }
end
end
end
def adj_plan(avail, plan)
{ start: plan[:start] + (plan[:start] < avail[:coverage][:start] ? 24 : 0),
finish: plan[:finish] + (plan[:finish] < plan[:start] ? 24 : 0) }
end
def add_block(arr, value, curr_epoch, nxt_epoch)
arr << [value, { start: curr_epoch, finish: nxt_epoch }] if nxt_epoch > curr_epoch
end
def restore_times(arr)
arr.map! do |k,g|
start, finish = g.values_at(:start, :finish)
start -= 24 if start > 24
finish -= 24 if finish > 24
[k, { start: start, finish: finish }]
end
end
實例
avail = { coverage: { start: 3, finish: 18 },
available: { start: 3, finish: 12 } }
plan = { start: 6, finish: 15 }
categories(avail, plan)
#=> [[:available, {:start=>3, :finish=>6} ],
# [:plan, {:start=>6, :finish=>15} ],
# [:standby, {:start=>15, :finish=>18}]]
avail = { coverage: { start: 22, finish: 11 },
available: { start: 23, finish: 10 } }
plan = { start: 24, finish: 9 }
categories(avail, plan)
#=> [[:standby, {:start=>22, :finish=>23}],
# [:available, {:start=>23, :finish=>24}],
# [:plan, {:start=>24, :finish=>9 }],
# [:available, {:start=>9, :finish=>10}],
# [:standby, {:start=>10, :finish=>11}]]
avail = { coverage: { start: 1, finish: 13 },
available: { start: 2, finish: 3 } }
plan = { start: 4, finish: 12 }
categories(avail, plan)
#=> [[:standby, {:start=>1, :finish=>2 }],
# [:available, {:start=>2, :finish=>3 }],
# [:standby, {:start=>3, :finish=>4 }],
# [:plan, {:start=>4, :finish=>12}],
# [:standby, {:start=>12, :finish=>13}]]
說明
這裏的主要問題是'覆蓋率'的結束小時小於開始時間,這意味着'覆蓋範圍'範圍包含午夜。發生這種情況時,「可用」和「計劃」範圍也可能包含午夜。我已經處理了這個問題,在計算範圍之前,在午夜之後增加24小時到幾小時,然後在計算範圍之後,從所有小時值中減去24小時以上的值。
考慮上面的第二個例子。
avail = { coverage: { start: 22, finish: 11 },
available: { start: 23, finish: 10 } }
adj_avail(avail)
#=> {:coverage=> {:start=>22, :finish=>35},
# :available=>{:start=>23, :finish=>34}}
plan = { start: 24, finish: 9 }
adj_plan(avail, plan)
#=> {:start=>24, :finish=>33}
如果我執行categories
爲avail
和這些值,與註釋掉最後一行,我獲得
a = categories(avail, plan)
#=> [[:standby, {:start=>22, :finish=>23}],
# [:available, {:start=>23, :finish=>24}],
# [:plan, {:start=>24, :finish=>33}],
# [:available, {:start=>33, :finish=>34}],
# [:standby, {:start=>34, :finish=>35}]]
和
restore_times(a)
#=> the return value shown above
請閱讀 「[問]」 包括鏈接頁面,「[mcve]」和「[Stack Overflow用戶需要多少研究工作?](http://meta.stackoverflow.com/questions/261592)」。我們希望看到你的努力的證據。你嘗試了什麼?你搜索並沒有找到任何東西?你有沒有找到東西,但它沒有幫助?你有沒有嘗試寫代碼?如果不是,爲什麼?如果是這樣,那麼最小的代碼示例顯示了您嘗試的內容以及它爲什麼不起作用?沒有它,看起來你沒有嘗試並希望我們爲你寫信。 –