ruby-on-rails - 如果允许有效重叠,如何计算预订
问题描述
我在这里查看了一些 SO 讨论,至少我还没有看到这个观点。我正在尝试编写代码来计算给定资源的预订,我想在其中找到完成所有预订所需的最小资源数量。
让我们以酒店房间为例。鉴于我有以下预订
- 克里斯:7 月 4 日至 7 月 17 日
- 拍拍:7 月 15 日至 7 月 19 日
- 泰勒:7 月 10 日至 7 月 11 日
克里斯打来电话,想在他们为朋友预订的房间中添加一些房间,并想知道我有多少房间可用。
Rooms_available = Rooms_in_hotel - Rooms_booked
这Rooms_booked
就是我遇到麻烦的地方。似乎大多数问题(实际上是我的代码)只是关注重叠的日期。所以它会做这样的事情:
Booking.where("booking_end >= :start_check AND booking_start <= :end_check", { start_check: "July 4, 2021".to_date, end_check: "July 7, 2021".to_date})
此代码将返回 3。这意味着如果酒店理论上有 5 个房间,我会告诉 Chris 还有 2 个房间可用。
然而,虽然这种计数方法在技术上是准确的,但它错过了有效重叠的可能性。也就是说,由于泰勒在帕特前 4 天退房,他们都可以被“分配”到同一个房间。所以从技术上讲,我可以为克里斯再提供 3 个房间。
所以我的问题是如何更准确地计算Rooms_booked
允许有效重叠(即有效的资源分配)?是否有使用 ActiveRecord 的查询或我在现有查询之上施加什么计算?
解决方案
我不认为只有一个查询可以解决您的问题(或非常非常复杂的查询)。
我的想法是按(booking_start, booking_end)
顺序分组(和计数)booking_start asc
然后重新分配,例如,如果有 2 个预订July 15-July 19
和 3 个预订,July 10-July 11
那么我们只能重新分配 2 对,我们需要 3 个房间(2 个房间July 15-July 19-July 10-July 11
和 1个房间July 10-July 11
。
并在代码中重新分配而不是查询(我们可以通过选择一个狭窄的时间范围来优化)
# when Chris calls and would like to add some room(s) to their reservation for friends,
# and wonders how many available rooms.
# pick (start_time, end_time) so that the range time long enough that
# including those booking {n} month ago
# but no need too long or all the time
scope :booking_available_count, -> (start_time, end_time) {
group_by_time = \
Booking.where("booking_start >= ? AND booking_end <= ?", start_time, end_time)
.group(:booking_start, :booking_end).order(:booking_start).count
# result: {[booking_start, booking_end] => 1, [booking_start, booking_end] => 2, ... }
# in order booking_start ASC
# then we could re-assign from left to right as below
booked = 0
group_by_time.each do |(start_time, end_time), count|
group_by_time.each do |(assign_start_time, assign_end_time), assign_count|
next if end_time > assign_start_time
count -= assign_count # re-assign
break if count <= 0
end
booked += count if count > 0
end
# return number of available rooms
# allow negative number
Room.count - booked
}
推荐阅读
- c# - 在asp net framework 4.5中使用多种身份验证方法
- javascript - 在带有功能组件的for循环中生成时,无法将新创建的对象附加到数组useState
- java - 两个线程独立处理连接和读取事件
- javascript - eclipse 2021-09 / 如何关闭 javascript 自动完成选项?
- javascript - Atom IDE 中的 Javascript 调试器
- python - 为什么第一行不显示 10 个数字?
- github - 以编程方式将 GitHub 存储库连接到 Google Cloud 项目
- eloquent - Laravel 8模型属性值在模型关系函数中为空
- swift - 正则表达式匹配一个字符串和适当括号之间的所有字符
- python - 基于Python中的索引合并两个嵌套列表