首页 > 解决方案 > 如果允许有效重叠,如何计算预订

问题描述

我在这里查看了一些 SO 讨论,至少我还没有看到这个观点。我正在尝试编写代码来计算给定资源的预订,我想在其中找到完成所有预订所需的最小资源数量。

让我们以酒店房间为例。鉴于我有以下预订

克里斯打来电话,想在他们为朋友预订的房间中添加一些房间,并想知道我有多少房间可用。

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 的查询或我在现有查询之上施加什么计算?

标签: ruby-on-railsrubyactiverecord

解决方案


我不认为只有一个查询可以解决您的问题(或非常非常复杂的查询)。

我的想法是按(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
}

推荐阅读