@happychef/algorithm 1.3.2 → 1.3.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.github/workflows/ci-cd.yml +80 -80
  2. package/CHANGELOG.md +8 -8
  3. package/RESERVERINGEN_GIDS.md +986 -986
  4. package/assignTables.js +444 -444
  5. package/bundle_entry.js +100 -0
  6. package/changes/2025/December/PR2___change.md +14 -14
  7. package/changes/2025/December/PR3_add__change.md +20 -20
  8. package/changes/2025/December/PR4___.md +15 -15
  9. package/changes/2025/December/PR5___.md +15 -15
  10. package/changes/2025/December/PR6__del_.md +17 -17
  11. package/changes/2025/December/PR7_add__change.md +21 -21
  12. package/changes/2026/February/PR15_add__change.md +21 -21
  13. package/changes/2026/January/PR10_add__change.md +21 -21
  14. package/changes/2026/January/PR11_add__change.md +19 -19
  15. package/changes/2026/January/PR12_add__.md +21 -21
  16. package/changes/2026/January/PR13_add__change.md +20 -20
  17. package/changes/2026/January/PR14_add__change.md +19 -19
  18. package/changes/2026/January/PR8_add__change.md +38 -38
  19. package/changes/2026/January/PR9_add__change.md +19 -19
  20. package/filters/maxArrivalsFilter.js +114 -114
  21. package/filters/maxGroupsFilter.js +221 -221
  22. package/filters/timeFilter.js +89 -89
  23. package/getAvailableTimeblocks.js +170 -158
  24. package/grouping.js +162 -162
  25. package/index.js +42 -43
  26. package/isDateAvailable.js +80 -80
  27. package/isDateAvailableWithTableCheck.js +172 -172
  28. package/isTimeAvailable.js +26 -26
  29. package/moment-timezone-shim.js +179 -0
  30. package/nul +0 -0
  31. package/package.json +27 -27
  32. package/processing/dailyGuestCounts.js +73 -73
  33. package/processing/mealTypeCount.js +133 -133
  34. package/processing/timeblocksAvailable.js +187 -182
  35. package/reservation_data/counter.js +74 -74
  36. package/restaurant_data/exceptions.js +150 -150
  37. package/restaurant_data/openinghours.js +165 -142
  38. package/simulateTableAssignment.js +727 -726
  39. package/tableHelpers.js +212 -209
  40. package/tables/time/parseTime.js +19 -19
  41. package/tables/time/shifts.js +7 -7
  42. package/tables/utils/calculateDistance.js +13 -13
  43. package/tables/utils/isTableFreeForAllSlots.js +14 -14
  44. package/tables/utils/isTemporaryTableValid.js +39 -39
  45. package/test/test_counter.js +194 -194
  46. package/test/test_dailyCount.js +81 -81
  47. package/test/test_datesAvailable.js +106 -106
  48. package/test/test_exceptions.js +172 -172
  49. package/test/test_isDateAvailable.js +330 -330
  50. package/test/test_mealTypeCount.js +54 -54
  51. package/test/test_timesAvailable.js +88 -88
  52. package/test-meal-stop-fix.js +147 -147
  53. package/test-meal-stop-simple.js +93 -93
  54. package/test.js +336 -336
  55. package/changes/2026/February/PR16_add_getDateClosingReasons.md +0 -31
  56. package/getDateClosingReasons.js +0 -193
@@ -1,93 +1,93 @@
1
- // Simple unit test for meal stop filter logic
2
-
3
- const { parseTime, getMealTypeByTime } = require('./tableHelpers');
4
-
5
- console.log('=== MEAL STOP FILTER LOGIC TEST ===\n');
6
-
7
- // Get current time in Brussels using Intl.DateTimeFormat (reliable timezone conversion)
8
- const now = new Date();
9
- const formatter = new Intl.DateTimeFormat('en-US', {
10
- timeZone: 'Europe/Brussels',
11
- hour: '2-digit',
12
- minute: '2-digit',
13
- hour12: false,
14
- });
15
- const parts = formatter.formatToParts(now);
16
- const timeParts = Object.fromEntries(parts.map(p => [p.type, p.value]));
17
- const currentTimeMinutes = parseInt(timeParts.hour, 10) * 60 + parseInt(timeParts.minute, 10);
18
- const currentTimeStr = `${timeParts.hour}:${timeParts.minute}`;
19
-
20
- console.log(`Current time in Brussels: ${currentTimeStr} (${currentTimeMinutes} minutes since midnight)`);
21
- console.log('');
22
-
23
- // Define stop times
24
- const breakfastStop = "10:00";
25
- const lunchStop = "12:00";
26
- const dinnerStop = "20:00";
27
-
28
- console.log('Configured stop times:');
29
- console.log(` - Breakfast stops at: ${breakfastStop} (${parseTime(breakfastStop)} minutes)`);
30
- console.log(` - Lunch stops at: ${lunchStop} (${parseTime(lunchStop)} minutes)`);
31
- console.log(` - Dinner stops at: ${dinnerStop} (${parseTime(dinnerStop)} minutes)`);
32
- console.log('');
33
-
34
- // Calculate which meals should be stopped
35
- const breakfastStopMinutes = parseTime(breakfastStop);
36
- const lunchStopMinutes = parseTime(lunchStop);
37
- const dinnerStopMinutes = parseTime(dinnerStop);
38
-
39
- const breakfastStopped = currentTimeMinutes >= breakfastStopMinutes;
40
- const lunchStopped = currentTimeMinutes >= lunchStopMinutes;
41
- const dinnerStopped = currentTimeMinutes >= dinnerStopMinutes;
42
-
43
- console.log('Filter decisions based on current time:');
44
- console.log(` - Breakfast: ${breakfastStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
45
- console.log(` - Lunch: ${lunchStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
46
- console.log(` - Dinner: ${dinnerStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
47
- console.log('');
48
-
49
- // Test with example time slots
50
- console.log('--- Example: How different time slots would be filtered ---');
51
- const exampleSlots = [
52
- '08:00', '08:30', '09:00', '09:30', // Breakfast
53
- '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', // Lunch
54
- '17:00', '18:00', '19:00', '20:00', '21:00' // Dinner
55
- ];
56
-
57
- exampleSlots.forEach(timeSlot => {
58
- const mealType = getMealTypeByTime(timeSlot);
59
- let willBeRemoved = false;
60
- let reason = '';
61
-
62
- if (mealType === 'breakfast' && breakfastStopped) {
63
- willBeRemoved = true;
64
- reason = 'breakfast is stopped';
65
- } else if (mealType === 'lunch' && lunchStopped) {
66
- willBeRemoved = true;
67
- reason = 'lunch is stopped';
68
- } else if (mealType === 'dinner' && dinnerStopped) {
69
- willBeRemoved = true;
70
- reason = 'dinner is stopped';
71
- } else {
72
- reason = `${mealType} is still available`;
73
- }
74
-
75
- const status = willBeRemoved ? '❌ REMOVED' : '✅ AVAILABLE';
76
- console.log(` ${timeSlot} (${mealType}): ${status} - ${reason}`);
77
- });
78
-
79
- console.log('\n--- Key Points ---');
80
- console.log('✓ The filter compares CURRENT TIME against stop time (not reservation time vs stop time)');
81
- console.log('✓ When current time >= stop time, ALL slots for that meal type are removed');
82
- console.log('✓ This ensures users in Brussels timezone see correct availability');
83
- console.log('');
84
- console.log('BEFORE the fix:');
85
- console.log(' ❌ At 10:30, trying to book lunch at 12:00 would be blocked (wrong!)');
86
- console.log(' ❌ The code compared reservation time (12:00) >= lunchStop (12:00)');
87
- console.log('');
88
- console.log('AFTER the fix:');
89
- console.log(' ✅ At 10:30, you CAN book lunch at 12:00 (correct!)');
90
- console.log(' ✅ The code compares current time (10:30) < lunchStop (12:00)');
91
- console.log(' ✅ Only when current time reaches 12:00 will lunch bookings stop');
92
-
93
- console.log('\n=== TEST COMPLETE ===');
1
+ // Simple unit test for meal stop filter logic
2
+
3
+ const { parseTime, getMealTypeByTime } = require('./tableHelpers');
4
+
5
+ console.log('=== MEAL STOP FILTER LOGIC TEST ===\n');
6
+
7
+ // Get current time in Brussels using Intl.DateTimeFormat (reliable timezone conversion)
8
+ const now = new Date();
9
+ const formatter = new Intl.DateTimeFormat('en-US', {
10
+ timeZone: 'Europe/Brussels',
11
+ hour: '2-digit',
12
+ minute: '2-digit',
13
+ hour12: false,
14
+ });
15
+ const parts = formatter.formatToParts(now);
16
+ const timeParts = Object.fromEntries(parts.map(p => [p.type, p.value]));
17
+ const currentTimeMinutes = parseInt(timeParts.hour, 10) * 60 + parseInt(timeParts.minute, 10);
18
+ const currentTimeStr = `${timeParts.hour}:${timeParts.minute}`;
19
+
20
+ console.log(`Current time in Brussels: ${currentTimeStr} (${currentTimeMinutes} minutes since midnight)`);
21
+ console.log('');
22
+
23
+ // Define stop times
24
+ const breakfastStop = "10:00";
25
+ const lunchStop = "12:00";
26
+ const dinnerStop = "20:00";
27
+
28
+ console.log('Configured stop times:');
29
+ console.log(` - Breakfast stops at: ${breakfastStop} (${parseTime(breakfastStop)} minutes)`);
30
+ console.log(` - Lunch stops at: ${lunchStop} (${parseTime(lunchStop)} minutes)`);
31
+ console.log(` - Dinner stops at: ${dinnerStop} (${parseTime(dinnerStop)} minutes)`);
32
+ console.log('');
33
+
34
+ // Calculate which meals should be stopped
35
+ const breakfastStopMinutes = parseTime(breakfastStop);
36
+ const lunchStopMinutes = parseTime(lunchStop);
37
+ const dinnerStopMinutes = parseTime(dinnerStop);
38
+
39
+ const breakfastStopped = currentTimeMinutes >= breakfastStopMinutes;
40
+ const lunchStopped = currentTimeMinutes >= lunchStopMinutes;
41
+ const dinnerStopped = currentTimeMinutes >= dinnerStopMinutes;
42
+
43
+ console.log('Filter decisions based on current time:');
44
+ console.log(` - Breakfast: ${breakfastStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
45
+ console.log(` - Lunch: ${lunchStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
46
+ console.log(` - Dinner: ${dinnerStopped ? '🔴 STOPPED (current time >= stop time)' : '🟢 AVAILABLE (current time < stop time)'}`);
47
+ console.log('');
48
+
49
+ // Test with example time slots
50
+ console.log('--- Example: How different time slots would be filtered ---');
51
+ const exampleSlots = [
52
+ '08:00', '08:30', '09:00', '09:30', // Breakfast
53
+ '11:00', '11:30', '12:00', '12:30', '13:00', '13:30', '14:00', // Lunch
54
+ '17:00', '18:00', '19:00', '20:00', '21:00' // Dinner
55
+ ];
56
+
57
+ exampleSlots.forEach(timeSlot => {
58
+ const mealType = getMealTypeByTime(timeSlot);
59
+ let willBeRemoved = false;
60
+ let reason = '';
61
+
62
+ if (mealType === 'breakfast' && breakfastStopped) {
63
+ willBeRemoved = true;
64
+ reason = 'breakfast is stopped';
65
+ } else if (mealType === 'lunch' && lunchStopped) {
66
+ willBeRemoved = true;
67
+ reason = 'lunch is stopped';
68
+ } else if (mealType === 'dinner' && dinnerStopped) {
69
+ willBeRemoved = true;
70
+ reason = 'dinner is stopped';
71
+ } else {
72
+ reason = `${mealType} is still available`;
73
+ }
74
+
75
+ const status = willBeRemoved ? '❌ REMOVED' : '✅ AVAILABLE';
76
+ console.log(` ${timeSlot} (${mealType}): ${status} - ${reason}`);
77
+ });
78
+
79
+ console.log('\n--- Key Points ---');
80
+ console.log('✓ The filter compares CURRENT TIME against stop time (not reservation time vs stop time)');
81
+ console.log('✓ When current time >= stop time, ALL slots for that meal type are removed');
82
+ console.log('✓ This ensures users in Brussels timezone see correct availability');
83
+ console.log('');
84
+ console.log('BEFORE the fix:');
85
+ console.log(' ❌ At 10:30, trying to book lunch at 12:00 would be blocked (wrong!)');
86
+ console.log(' ❌ The code compared reservation time (12:00) >= lunchStop (12:00)');
87
+ console.log('');
88
+ console.log('AFTER the fix:');
89
+ console.log(' ✅ At 10:30, you CAN book lunch at 12:00 (correct!)');
90
+ console.log(' ✅ The code compares current time (10:30) < lunchStop (12:00)');
91
+ console.log(' ✅ Only when current time reaches 12:00 will lunch bookings stop');
92
+
93
+ console.log('\n=== TEST COMPLETE ===');