@happychef/algorithm 1.2.10 → 1.2.12

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 (46) hide show
  1. package/.github/workflows/ci-cd.yml +133 -2
  2. package/BRANCH_PROTECTION_SETUP.md +167 -0
  3. package/CHANGELOG.md +8 -8
  4. package/RESERVERINGEN_GIDS.md +986 -986
  5. package/assignTables.js +424 -398
  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 +16 -0
  9. package/changes/2025/December/PR5___.md +16 -0
  10. package/changes/2025/December/PR6__del_.md +18 -0
  11. package/changes/2025/December/PR7_add__change.md +22 -0
  12. package/changes/2026/January/PR8_add__change.md +39 -0
  13. package/changes/2026/January/PR9_add__change.md +20 -0
  14. package/filters/maxArrivalsFilter.js +114 -114
  15. package/filters/maxGroupsFilter.js +221 -221
  16. package/filters/timeFilter.js +89 -89
  17. package/getAvailableTimeblocks.js +158 -158
  18. package/grouping.js +162 -162
  19. package/index.js +42 -42
  20. package/isDateAvailable.js +80 -80
  21. package/isDateAvailableWithTableCheck.js +171 -171
  22. package/isTimeAvailable.js +25 -25
  23. package/package.json +27 -27
  24. package/processing/dailyGuestCounts.js +73 -73
  25. package/processing/mealTypeCount.js +133 -133
  26. package/processing/timeblocksAvailable.js +167 -167
  27. package/reservation_data/counter.js +64 -64
  28. package/restaurant_data/exceptions.js +149 -149
  29. package/restaurant_data/openinghours.js +123 -123
  30. package/simulateTableAssignment.js +709 -699
  31. package/tableHelpers.js +178 -178
  32. package/tables/time/parseTime.js +19 -19
  33. package/tables/time/shifts.js +7 -7
  34. package/tables/utils/calculateDistance.js +13 -13
  35. package/tables/utils/isTableFreeForAllSlots.js +14 -14
  36. package/tables/utils/isTemporaryTableValid.js +39 -39
  37. package/test/test_counter.js +194 -194
  38. package/test/test_dailyCount.js +81 -81
  39. package/test/test_datesAvailable.js +106 -106
  40. package/test/test_exceptions.js +172 -172
  41. package/test/test_isDateAvailable.js +330 -330
  42. package/test/test_mealTypeCount.js +54 -54
  43. package/test/test_timesAvailable.js +88 -88
  44. package/test-meal-stop-fix.js +147 -147
  45. package/test-meal-stop-simple.js +93 -93
  46. package/test.js +336 -336
@@ -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 ===');