如果允许有效重叠,如何计算预订

时间:2021-06-22 21:54:59

标签: ruby-on-rails ruby activerecord

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

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

  • 克里斯:7 月 4 日至 7 月 17 日
  • 帕特:7 月 15 日至 7 月 19 日
  • 泰勒:7 月 10 日至 7 月 11 日

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

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 天退房,他们都可以被“分配”到同一个房间。所以从技术上讲,我可以再给 Chris 提供 3 个房间。

所以我的问题是如何更准确地计算 Rooms_booked 以实现有效重叠(即有效的资源分配)?是否有使用 ActiveRecord 的查询,或者我在现有查询之上施加了什么计算?

1 个答案:

答案 0 :(得分:0)

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

我的想法是按 (booking_start, booking_end)booking_start asc 进行分组(和计数),然后重新分配,例如如果有 2 个预订 July 15-July 19 和 3 个预订 July 10-July 11 那么我们只能重新分配 2 对,我们需要 3 个房间(July 15-July 19-July 10-July 11 有 2 个房间,July 10-July 11 有 1 个房间}}。

并在代码中重新分配而不是查询(我们可以通过选择一个狭窄的时间范围来优化)

# 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
}
相关问题