Skip to content

Commit

Permalink
fix(booking_collection): address occupiedDuration edge cases (#209)
Browse files Browse the repository at this point in the history
* fix(booking_collection): address `occupiedDuration` edge cases

* docs(booking_collection): document tested methods
  • Loading branch information
albertms10 committed Feb 26, 2023
1 parent 69c337e commit 59e9736
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 24 deletions.
57 changes: 51 additions & 6 deletions lib/src/model/booking_collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -114,18 +114,63 @@ class BookingCollection with ChangeNotifier implements Serializable {
null;
}

Duration occupiedDuration([DateRanger? dateRanger]) {
final bookingsList =
dateRanger != null ? allBookingsBetween(dateRanger) : allBookings;

/// Returns the occupied [Duration] in a [dateRanger].
///
/// Example:
/// ```dart
/// final bookingCollection = BookingCollection(
/// bookings: {
/// SingleBooking(
/// startDate: DateTime.utc(2022, 12, 4, 9),
/// endDate: DateTime.utc(2022, 12, 4, 9, 30),
/// ),
/// },
/// recurringBookings: {
/// RecurringBooking(
/// startDate: DateTime.utc(2022, 12, 4, 9, 30),
/// endDate: DateTime.utc(2022, 12, 4, 10, 30),
/// recurringEndDate: DateTime.utc(2023, 2, 4),
/// ),
/// },
/// );
/// final occupiedDuration = bookingCollection.occupiedDuration(
/// DateRange.fromDate(DateTime.utc(2022, 12, 4)),
/// );
/// assert(occupiedDuration == const Duration(hours: 1, minutes: 30));
/// ```
Duration occupiedDuration([DateRanger dateRanger = DateRange.infinite]) {
var runDuration = Duration.zero;
for (final booking in bookingsList) {
runDuration += booking.duration;
for (final booking in allBookings) {
runDuration += booking.overlappingDurationWith(dateRanger);
}

return runDuration;
}

/// Returns the occupancy percent in a [dateRanger].
///
/// Example:
/// ```dart
/// final bookingCollection = BookingCollection(
/// bookings: {
/// SingleBooking(
/// startDate: DateTime.utc(2022, 12, 4, 9),
/// endDate: DateTime.utc(2022, 12, 4, 9, 30),
/// ),
/// },
/// recurringBookings: {
/// RecurringBooking(
/// startDate: DateTime.utc(2022, 12, 4, 9, 30),
/// endDate: DateTime.utc(2022, 12, 4, 10),
/// recurringEndDate: DateTime.utc(2023, 2, 4),
/// ),
/// },
/// );
/// final occupancyPercent = bookingCollection.occupancyPercentOn(
/// DateRange.fromDate(DateTime.utc(2022, 12, 4)),
/// );
/// assert(occupancyPercent == 0.0625); // 6.25%
/// ```
double occupancyPercentOn([DateRanger? dateRanger]) {
dateRanger ??= DateRange.today();

Expand Down
3 changes: 2 additions & 1 deletion lib/src/model/cabin_collection.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import 'booking/single_booking.dart';
import 'booking_collection.dart';
import 'cabin/cabin.dart';
import 'cabin/tokenized_cabin.dart';
import 'date/date_range.dart';
import 'date/date_ranger.dart';
import 'file/file_manager.dart';
import 'file/writable_manager.dart';
Expand Down Expand Up @@ -125,7 +126,7 @@ class CabinCollection extends WritableManager<Set<Cabin>>
return count;
}

Duration totalOccupiedDuration([DateRanger? dateRanger]) {
Duration totalOccupiedDuration([DateRanger dateRanger = DateRange.infinite]) {
var duration = Duration.zero;
for (final cabin in cabins) {
duration += cabin.bookingCollection.occupiedDuration(dateRanger);
Expand Down
28 changes: 11 additions & 17 deletions test/model/booking_collection_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ void main() {
final emptyBookingCollection = BookingCollection();
expect(emptyBookingCollection.occupiedDuration(), Duration.zero);
expect(
emptyBookingCollection.occupiedDuration(DateRange.infinite),
emptyBookingCollection.occupiedDuration(),
Duration.zero,
);
expect(
Expand All @@ -152,7 +152,7 @@ void main() {
SingleBooking(
id: 'booking-1-id',
startDate: DateTime.utc(2022, 12, 4, 9),
endDate: DateTime.utc(2022, 12, 4, 10, 30),
endDate: DateTime.utc(2022, 12, 4, 9, 30),
description: 'Student 1',
isLocked: true,
),
Expand All @@ -166,19 +166,15 @@ void main() {
recurringBookings: SplayTreeSet.of({
RecurringBooking(
id: 'recurring-booking-id',
startDate: DateTime.utc(2022, 12, 6, 9),
endDate: DateTime.utc(2022, 12, 6, 10, 30),
startDate: DateTime.utc(2022, 12, 4, 9, 30),
endDate: DateTime.utc(2022, 12, 4, 10, 30),
description: 'Student 3',
recurringEndDate: DateTime.utc(2023, 2, 4),
),
}),
);
const totalDuration = Duration(hours: 16);
const totalDuration = Duration(hours: 10, minutes: 30);
expect(bookingCollection.occupiedDuration(), totalDuration);
expect(
bookingCollection.occupiedDuration(DateRange.infinite),
totalDuration,
);
expect(
bookingCollection.occupiedDuration(
DateRange.fromDate(DateTime.utc(2022, 12, 4)),
Expand All @@ -192,8 +188,7 @@ void main() {
endDate: DateTime.utc(2022, 12, 5, 21),
),
),
// TODO(albertms10): should be 30 minutes.
const Duration(hours: 1),
const Duration(minutes: 30),
);
});
});
Expand Down Expand Up @@ -221,7 +216,7 @@ void main() {
SingleBooking(
id: 'booking-1-id',
startDate: DateTime.utc(2022, 12, 4, 9),
endDate: DateTime.utc(2022, 12, 4, 10, 30),
endDate: DateTime.utc(2022, 12, 4, 9, 30),
description: 'Student 1',
isLocked: true,
),
Expand All @@ -235,8 +230,8 @@ void main() {
recurringBookings: SplayTreeSet.of({
RecurringBooking(
id: 'recurring-booking-id',
startDate: DateTime.utc(2022, 12, 6, 9),
endDate: DateTime.utc(2022, 12, 6, 10, 30),
startDate: DateTime.utc(2022, 12, 4, 9, 30),
endDate: DateTime.utc(2022, 12, 4, 10, 30),
description: 'Student 3',
recurringEndDate: DateTime.utc(2023, 2, 4),
),
Expand All @@ -246,7 +241,7 @@ void main() {
bookingCollection.occupancyPercentOn(
DateRange.fromDate(DateTime.utc(2022, 12, 4)),
),
closeTo(0.063, 0.001),
0.0625,
);
expect(
bookingCollection.occupancyPercentOn(
Expand All @@ -255,8 +250,7 @@ void main() {
endDate: DateTime.utc(2022, 12, 5, 21),
),
),
// TODO(albertms10): fix out of bounds ratio.
2,
1,
);
},
);
Expand Down

0 comments on commit 59e9736

Please sign in to comment.