diff options
Diffstat (limited to 'js/baba-yaga/experimental/availability.baba')
-rw-r--r-- | js/baba-yaga/experimental/availability.baba | 108 |
1 files changed, 108 insertions, 0 deletions
diff --git a/js/baba-yaga/experimental/availability.baba b/js/baba-yaga/experimental/availability.baba new file mode 100644 index 0000000..4bc59f8 --- /dev/null +++ b/js/baba-yaga/experimental/availability.baba @@ -0,0 +1,108 @@ +// Availability via 24-block boolean mask +// WIP + +// range0: [0..n-1] +range0 : n -> + when n is + 0 then [] + _ then append (range0 (n - 1)) (n - 1); + +// overlaps: does busy interval b overlap block i? +overlaps : b i dayStart blockSize -> + (b.start < (dayStart + (i * blockSize) + blockSize)) and (b.end > (dayStart + (i * blockSize))); + +// anyBusyOnBlock: reduce OR over busy intervals for block i +anyBusyOnBlock : busyList i dayStart blockSize -> + reduce (acc b -> acc or (overlaps b i dayStart blockSize)) false busyList; + +// allFreeOnBlock: everyone free on block i? +allFreeOnBlock : busyLists i dayStart blockSize -> + reduce (acc bl -> acc and (when (anyBusyOnBlock bl i dayStart blockSize) is true then false _ then true)) true busyLists; + +// stepRuns: accumulate contiguous free runs over blocks with min-block filtering +stepRuns : busyLists dayStart blockSize minBlocks acc i -> + when acc.inRun is + true then + when (allFreeOnBlock busyLists i dayStart blockSize) is + true then { inRun: true, start: acc.start, runs: acc.runs } + _ then ( + when ((i - acc.start) >= minBlocks) is + true then { inRun: false, start: 0, runs: append acc.runs { start: acc.start, end: i } } + _ then { inRun: false, start: 0, runs: acc.runs } + ) + _ then + when (allFreeOnBlock busyLists i dayStart blockSize) is + true then { inRun: true, start: i, runs: acc.runs } + _ then acc; + +// finalizeRuns: close trailing run if needed (with min-block filtering) +finalizeRuns : acc totalBlocks minBlocks -> + when acc.inRun is + true then ( + when ((totalBlocks - acc.start) >= minBlocks) is + true then append acc.runs { start: acc.start, end: totalBlocks } + _ then acc.runs + ) + _ then acc.runs; + +// convertRunsToMinutes: map block runs to minute intervals (shape-guarded) +convertRunsToMinutes : runs dayStart blockSize -> + when (shape runs).kind is + "List" then map (r -> { start: dayStart + (r.start * blockSize), end: dayStart + (r.end * blockSize) }) runs + _ then []; + +// takeLimit: slice helper +takeLimit : limit lst -> slice lst 0 (math.min (length lst) limit); + +// findCommonAvailability using mask approach +// runnerFor: folder factory capturing inputs, returns (acc i -> ...) +runnerFor : calendars dayStart dayEnd minMinutes acc i -> + stepRuns (values calendars) dayStart ((dayEnd - dayStart) / 24) (math.ceil (minMinutes / ((dayEnd - dayStart) / 24))) acc i; + +// buildRuns: produce runs list from inputs +buildRuns : calendars dayStart dayEnd minMinutes -> + finalizeRuns ( + reduce (runnerFor calendars dayStart dayEnd minMinutes) + { inRun: false, start: 0, runs: [] } + (range0 24) + ) 24 (math.ceil (minMinutes / ((dayEnd - dayStart) / 24))); + +// slotsFor: convert runs to minute intervals +slotsFor : calendars dayStart dayEnd minMinutes -> + convertRunsToMinutes (buildRuns calendars dayStart dayEnd minMinutes) dayStart ((dayEnd - dayStart) / 24); + +// findCommonAvailability: top-level pipeline +findCommonAvailability : calendars dayStart dayEnd minMinutes limit -> + takeLimit limit (slotsFor calendars dayStart dayEnd minMinutes); + +// ---------- Example usage ---------- + +// Working window 09:00-17:00 +dayStart : 9 * 60; // 540 +dayEnd : 17 * 60; // 1020 +minSlot : 30; // minutes +limit : 5; + +// Calendars: each value is a sorted list of busy intervals { start, end } in minutes +calendars : { + alice: [ + { start: 570, end: 630 } + { start: 720, end: 780 } + { start: 960, end: 1020 } + ], + bob: [ + { start: 540, end: 555 } + { start: 660, end: 720 } + { start: 840, end: 870 } + ], + carol: [ + { start: 600, end: 660 } + { start: 750, end: 810 } + { start: 915, end: 960 } + ] +}; + +io.out "loaded"; +available : findCommonAvailability calendars dayStart dayEnd minSlot limit; +io.out "done"; +io.out available; |