@neo-reckoning/core 0.1.0-alpha.1
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.
- package/dist/displayType.d.ts +9 -0
- package/dist/displayType.d.ts.map +1 -0
- package/dist/displayType.js +23 -0
- package/dist/displayType.js.map +1 -0
- package/dist/evaluator.d.ts +86 -0
- package/dist/evaluator.d.ts.map +1 -0
- package/dist/evaluator.js +608 -0
- package/dist/evaluator.js.map +1 -0
- package/dist/events.d.ts +10 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +28 -0
- package/dist/events.js.map +1 -0
- package/dist/grid.d.ts +36 -0
- package/dist/grid.d.ts.map +1 -0
- package/dist/grid.js +177 -0
- package/dist/grid.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/scoring.d.ts +14 -0
- package/dist/scoring.d.ts.map +1 -0
- package/dist/scoring.js +152 -0
- package/dist/scoring.js.map +1 -0
- package/dist/time.d.ts +58 -0
- package/dist/time.d.ts.map +1 -0
- package/dist/time.js +169 -0
- package/dist/time.js.map +1 -0
- package/dist/timeline.d.ts +24 -0
- package/dist/timeline.d.ts.map +1 -0
- package/dist/timeline.js +158 -0
- package/dist/timeline.js.map +1 -0
- package/dist/types.d.ts +349 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/yearGrid.d.ts +16 -0
- package/dist/yearGrid.d.ts.map +1 -0
- package/dist/yearGrid.js +61 -0
- package/dist/yearGrid.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
import { parseDate, getDayOfWeek, daysInMonth, compareDates, dateRange, parseTime, formatTime, timeToMinutes, minutesToTime, addMinutes, convertTime, formatDate, } from './time.js';
|
|
2
|
+
/**
|
|
3
|
+
* RangeEvaluator — the core computation engine of neo-reckoning.
|
|
4
|
+
*
|
|
5
|
+
* Determines whether dates/times fall within a DateRange and expands
|
|
6
|
+
* ranges into concrete occurrences within a given window.
|
|
7
|
+
*/
|
|
8
|
+
export class RangeEvaluator {
|
|
9
|
+
userTimezone;
|
|
10
|
+
constructor(userTimezone) {
|
|
11
|
+
this.userTimezone = userTimezone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Check if a date (YYYY-MM-DD) falls within a range's day-level criteria.
|
|
15
|
+
*/
|
|
16
|
+
isDateInRange(dateStr, range) {
|
|
17
|
+
// Check fixedBetween / fromDate / toDate bounds first
|
|
18
|
+
if (!this.isDateInBounds(dateStr, range)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// Explicit dates list
|
|
22
|
+
if (range.dates && range.dates.length > 0) {
|
|
23
|
+
return range.dates.includes(dateStr);
|
|
24
|
+
}
|
|
25
|
+
// Recurrence patterns — if any are set, ALL set patterns must match (AND)
|
|
26
|
+
const hasRecurrence = range.everyWeekday || range.everyDate || range.everyMonth;
|
|
27
|
+
if (!hasRecurrence) {
|
|
28
|
+
// No day-level recurrence and no explicit dates — range applies to all days in bounds
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
const { year, month, day } = parseDate(dateStr);
|
|
32
|
+
const weekday = getDayOfWeek(dateStr);
|
|
33
|
+
if (range.everyWeekday && !range.everyWeekday.includes(weekday)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (range.everyDate && !range.everyDate.includes(day)) {
|
|
37
|
+
return false;
|
|
38
|
+
}
|
|
39
|
+
if (range.everyMonth && !range.everyMonth.includes(month + 1)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
return true;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get all time occurrences for a range on a specific day.
|
|
46
|
+
* Returns empty array for all-day ranges (check isDateInRange instead).
|
|
47
|
+
*/
|
|
48
|
+
getTimeSlots(dateStr, range) {
|
|
49
|
+
if (!this.hasTimeFields(range)) {
|
|
50
|
+
return [];
|
|
51
|
+
}
|
|
52
|
+
const slots = [];
|
|
53
|
+
if (range.everyHour) {
|
|
54
|
+
for (const hour of range.everyHour) {
|
|
55
|
+
const startTime = formatTime(hour, 0);
|
|
56
|
+
const resolved = this.resolveTime(dateStr, startTime, range.timezone);
|
|
57
|
+
if (resolved === null)
|
|
58
|
+
continue; // DST gap
|
|
59
|
+
let endTime = null;
|
|
60
|
+
let duration = range.duration ?? null;
|
|
61
|
+
if (duration) {
|
|
62
|
+
endTime = addMinutes(resolved, duration);
|
|
63
|
+
}
|
|
64
|
+
slots.push({
|
|
65
|
+
startTime: resolved,
|
|
66
|
+
endTime,
|
|
67
|
+
duration,
|
|
68
|
+
rangeId: range.id,
|
|
69
|
+
label: range.label,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
else if (range.startTime) {
|
|
74
|
+
const resolvedStart = this.resolveTime(dateStr, range.startTime, range.timezone);
|
|
75
|
+
if (resolvedStart === null)
|
|
76
|
+
return slots; // DST gap
|
|
77
|
+
if (range.repeatEvery) {
|
|
78
|
+
const endBoundary = range.endTime
|
|
79
|
+
? this.resolveTime(dateStr, range.endTime, range.timezone) ?? '24:00'
|
|
80
|
+
: '24:00';
|
|
81
|
+
const endMinutes = timeToMinutes(endBoundary);
|
|
82
|
+
let currentMinutes = timeToMinutes(resolvedStart);
|
|
83
|
+
while (currentMinutes < endMinutes) {
|
|
84
|
+
const startTime = formatTime(Math.floor(currentMinutes / 60), currentMinutes % 60);
|
|
85
|
+
let endTime = null;
|
|
86
|
+
let duration = range.duration ?? null;
|
|
87
|
+
if (duration) {
|
|
88
|
+
endTime = addMinutes(startTime, duration);
|
|
89
|
+
}
|
|
90
|
+
slots.push({
|
|
91
|
+
startTime,
|
|
92
|
+
endTime,
|
|
93
|
+
duration,
|
|
94
|
+
rangeId: range.id,
|
|
95
|
+
label: range.label,
|
|
96
|
+
});
|
|
97
|
+
currentMinutes += range.repeatEvery;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
// Single time block
|
|
102
|
+
let endTime = null;
|
|
103
|
+
if (range.endTime) {
|
|
104
|
+
endTime = this.resolveTime(dateStr, range.endTime, range.timezone);
|
|
105
|
+
}
|
|
106
|
+
let duration = range.duration ?? null;
|
|
107
|
+
if (!duration && endTime) {
|
|
108
|
+
duration = timeToMinutes(endTime) - timeToMinutes(resolvedStart);
|
|
109
|
+
}
|
|
110
|
+
if (!endTime && duration) {
|
|
111
|
+
endTime = addMinutes(resolvedStart, duration);
|
|
112
|
+
}
|
|
113
|
+
slots.push({
|
|
114
|
+
startTime: resolvedStart,
|
|
115
|
+
endTime,
|
|
116
|
+
duration,
|
|
117
|
+
rangeId: range.id,
|
|
118
|
+
label: range.label,
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Sort by start time
|
|
123
|
+
slots.sort((a, b) => timeToMinutes(a.startTime) - timeToMinutes(b.startTime));
|
|
124
|
+
return slots;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Check if a specific datetime falls within a range (both day and time criteria).
|
|
128
|
+
*/
|
|
129
|
+
isInRange(datetime, range) {
|
|
130
|
+
const dateStr = formatDate(datetime);
|
|
131
|
+
if (!this.isDateInRange(dateStr, range)) {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
if (!this.hasTimeFields(range)) {
|
|
135
|
+
return true; // All-day range, day match is sufficient
|
|
136
|
+
}
|
|
137
|
+
const hour = datetime.getHours();
|
|
138
|
+
const minute = datetime.getMinutes();
|
|
139
|
+
const timeStr = formatTime(hour, minute);
|
|
140
|
+
const currentMinutes = timeToMinutes(timeStr);
|
|
141
|
+
const slots = this.getTimeSlots(dateStr, range);
|
|
142
|
+
for (const slot of slots) {
|
|
143
|
+
const slotStart = timeToMinutes(slot.startTime);
|
|
144
|
+
const slotEnd = slot.endTime ? timeToMinutes(slot.endTime) : slotStart + (slot.duration ?? 0);
|
|
145
|
+
if (currentMinutes >= slotStart && currentMinutes < slotEnd) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
// Point-in-time occurrence (no duration/end) — exact match
|
|
149
|
+
if (!slot.endTime && !slot.duration && currentMinutes === slotStart) {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return false;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Expand a DateRange into all concrete occurrences within a date window.
|
|
157
|
+
* This is the core computation described in the plan's Addendum C.
|
|
158
|
+
*/
|
|
159
|
+
expand(range, from, to) {
|
|
160
|
+
const fromStr = formatDate(from);
|
|
161
|
+
const toStr = formatDate(to);
|
|
162
|
+
// Step 1: Generate candidate days
|
|
163
|
+
const candidateDays = this.getCandidateDays(range, fromStr, toStr);
|
|
164
|
+
// Step 2: Generate occurrences for each day
|
|
165
|
+
const occurrences = [];
|
|
166
|
+
for (const day of candidateDays) {
|
|
167
|
+
if (this.hasTimeFields(range)) {
|
|
168
|
+
const slots = this.getTimeSlots(day, range);
|
|
169
|
+
for (const slot of slots) {
|
|
170
|
+
occurrences.push({
|
|
171
|
+
date: day,
|
|
172
|
+
startTime: slot.startTime,
|
|
173
|
+
endTime: slot.endTime,
|
|
174
|
+
rangeId: range.id,
|
|
175
|
+
label: range.label,
|
|
176
|
+
allDay: false,
|
|
177
|
+
...(range.displayType !== undefined ? { displayType: range.displayType } : {}),
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
occurrences.push({
|
|
183
|
+
date: day,
|
|
184
|
+
startTime: null,
|
|
185
|
+
endTime: null,
|
|
186
|
+
rangeId: range.id,
|
|
187
|
+
label: range.label,
|
|
188
|
+
allDay: true,
|
|
189
|
+
...(range.displayType !== undefined ? { displayType: range.displayType } : {}),
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return occurrences;
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Expand a DateRange for a single day — convenience for day/week views.
|
|
197
|
+
*/
|
|
198
|
+
expandDay(range, dateStr) {
|
|
199
|
+
if (!this.isDateInRange(dateStr, range)) {
|
|
200
|
+
return [];
|
|
201
|
+
}
|
|
202
|
+
return this.getTimeSlots(dateStr, range);
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Compute contiguous spans for multiple ranges within a date window.
|
|
206
|
+
* Groups consecutive matching days into SpanInfo objects, assigns lanes
|
|
207
|
+
* using greedy interval scheduling, and computes overlap metrics.
|
|
208
|
+
*/
|
|
209
|
+
computeSpans(ranges, from, to) {
|
|
210
|
+
const fromStr = formatDate(from);
|
|
211
|
+
const toStr = formatDate(to);
|
|
212
|
+
const allSpans = [];
|
|
213
|
+
for (const range of ranges) {
|
|
214
|
+
const candidateDays = this.getCandidateDays(range, fromStr, toStr);
|
|
215
|
+
if (candidateDays.length === 0)
|
|
216
|
+
continue;
|
|
217
|
+
// Group consecutive days into contiguous spans
|
|
218
|
+
let spanStart = candidateDays[0];
|
|
219
|
+
let prevDate = candidateDays[0];
|
|
220
|
+
let spanDays = [candidateDays[0]];
|
|
221
|
+
for (let i = 1; i < candidateDays.length; i++) {
|
|
222
|
+
const day = candidateDays[i];
|
|
223
|
+
if (this.isNextDay(prevDate, day)) {
|
|
224
|
+
spanDays.push(day);
|
|
225
|
+
prevDate = day;
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
// End previous span, start new one
|
|
229
|
+
allSpans.push({
|
|
230
|
+
rangeId: range.id,
|
|
231
|
+
label: range.label,
|
|
232
|
+
displayType: range.displayType,
|
|
233
|
+
startDate: spanStart,
|
|
234
|
+
endDate: prevDate,
|
|
235
|
+
days: spanDays,
|
|
236
|
+
});
|
|
237
|
+
spanStart = day;
|
|
238
|
+
prevDate = day;
|
|
239
|
+
spanDays = [day];
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
// Push final span
|
|
243
|
+
allSpans.push({
|
|
244
|
+
rangeId: range.id,
|
|
245
|
+
label: range.label,
|
|
246
|
+
displayType: range.displayType,
|
|
247
|
+
startDate: spanStart,
|
|
248
|
+
endDate: prevDate,
|
|
249
|
+
days: spanDays,
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
if (allSpans.length === 0)
|
|
253
|
+
return [];
|
|
254
|
+
// Step 2: Build day-indexed overlap map (day -> list of span indices)
|
|
255
|
+
const dayToSpans = new Map();
|
|
256
|
+
for (let i = 0; i < allSpans.length; i++) {
|
|
257
|
+
for (const day of allSpans[i].days) {
|
|
258
|
+
const list = dayToSpans.get(day);
|
|
259
|
+
if (list) {
|
|
260
|
+
list.push(i);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
dayToSpans.set(day, [i]);
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
// Step 3: Assign lanes using greedy interval scheduling
|
|
268
|
+
const sortedIndices = allSpans
|
|
269
|
+
.map((_, i) => i)
|
|
270
|
+
.sort((a, b) => {
|
|
271
|
+
const cmp = compareDates(allSpans[a].startDate, allSpans[b].startDate);
|
|
272
|
+
if (cmp !== 0)
|
|
273
|
+
return cmp;
|
|
274
|
+
return compareDates(allSpans[a].endDate, allSpans[b].endDate);
|
|
275
|
+
});
|
|
276
|
+
const lanes = new Array(allSpans.length).fill(-1);
|
|
277
|
+
const laneEndDates = [];
|
|
278
|
+
for (const idx of sortedIndices) {
|
|
279
|
+
const span = allSpans[idx];
|
|
280
|
+
let assigned = -1;
|
|
281
|
+
for (let lane = 0; lane < laneEndDates.length; lane++) {
|
|
282
|
+
if (compareDates(laneEndDates[lane], span.startDate) < 0) {
|
|
283
|
+
assigned = lane;
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
if (assigned === -1) {
|
|
288
|
+
assigned = laneEndDates.length;
|
|
289
|
+
laneEndDates.push(span.endDate);
|
|
290
|
+
}
|
|
291
|
+
else {
|
|
292
|
+
laneEndDates[assigned] = span.endDate;
|
|
293
|
+
}
|
|
294
|
+
lanes[idx] = assigned;
|
|
295
|
+
}
|
|
296
|
+
// Step 4: Compute maxOverlap per span and totalLanes for overlap groups
|
|
297
|
+
const maxOverlaps = new Array(allSpans.length).fill(1);
|
|
298
|
+
for (let i = 0; i < allSpans.length; i++) {
|
|
299
|
+
for (const day of allSpans[i].days) {
|
|
300
|
+
const overlapping = dayToSpans.get(day);
|
|
301
|
+
if (overlapping.length > maxOverlaps[i]) {
|
|
302
|
+
maxOverlaps[i] = overlapping.length;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Build overlap groups via BFS on shared-day adjacency
|
|
307
|
+
const spanNeighbors = new Map();
|
|
308
|
+
for (const spanIndices of dayToSpans.values()) {
|
|
309
|
+
if (spanIndices.length > 1) {
|
|
310
|
+
for (const a of spanIndices) {
|
|
311
|
+
if (!spanNeighbors.has(a))
|
|
312
|
+
spanNeighbors.set(a, new Set());
|
|
313
|
+
for (const b of spanIndices) {
|
|
314
|
+
if (a !== b)
|
|
315
|
+
spanNeighbors.get(a).add(b);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
const visited = new Set();
|
|
321
|
+
const componentOf = new Array(allSpans.length).fill(-1);
|
|
322
|
+
const components = [];
|
|
323
|
+
for (let i = 0; i < allSpans.length; i++) {
|
|
324
|
+
if (visited.has(i))
|
|
325
|
+
continue;
|
|
326
|
+
const component = [];
|
|
327
|
+
const queue = [i];
|
|
328
|
+
visited.add(i);
|
|
329
|
+
while (queue.length > 0) {
|
|
330
|
+
const node = queue.shift();
|
|
331
|
+
component.push(node);
|
|
332
|
+
const neighbors = spanNeighbors.get(node);
|
|
333
|
+
if (neighbors) {
|
|
334
|
+
for (const n of neighbors) {
|
|
335
|
+
if (!visited.has(n)) {
|
|
336
|
+
visited.add(n);
|
|
337
|
+
queue.push(n);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
const compIdx = components.length;
|
|
343
|
+
components.push(component);
|
|
344
|
+
for (const idx of component) {
|
|
345
|
+
componentOf[idx] = compIdx;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
const componentTotalLanes = components.map(comp => {
|
|
349
|
+
const usedLanes = new Set(comp.map(idx => lanes[idx]));
|
|
350
|
+
return usedLanes.size;
|
|
351
|
+
});
|
|
352
|
+
// Step 5: Build SpanInfo results, sorted by startDate then lane
|
|
353
|
+
const results = [];
|
|
354
|
+
for (let i = 0; i < allSpans.length; i++) {
|
|
355
|
+
const span = allSpans[i];
|
|
356
|
+
results.push({
|
|
357
|
+
rangeId: span.rangeId,
|
|
358
|
+
label: span.label,
|
|
359
|
+
...(span.displayType !== undefined ? { displayType: span.displayType } : {}),
|
|
360
|
+
startDate: span.startDate,
|
|
361
|
+
endDate: span.endDate,
|
|
362
|
+
length: span.days.length,
|
|
363
|
+
maxOverlap: maxOverlaps[i],
|
|
364
|
+
lane: lanes[i],
|
|
365
|
+
totalLanes: componentTotalLanes[componentOf[i]],
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
results.sort((a, b) => {
|
|
369
|
+
const cmp = compareDates(a.startDate, b.startDate);
|
|
370
|
+
if (cmp !== 0)
|
|
371
|
+
return cmp;
|
|
372
|
+
return a.lane - b.lane;
|
|
373
|
+
});
|
|
374
|
+
return results;
|
|
375
|
+
}
|
|
376
|
+
/**
|
|
377
|
+
* Find time-level conflicts among ranges on a single date.
|
|
378
|
+
* Two timed ranges that overlap in time are a conflict.
|
|
379
|
+
* Two all-day ranges, or an all-day + timed range, are NOT conflicts.
|
|
380
|
+
*/
|
|
381
|
+
findConflicts(ranges, date) {
|
|
382
|
+
const slots = [];
|
|
383
|
+
for (const range of ranges) {
|
|
384
|
+
if (!this.isDateInRange(date, range))
|
|
385
|
+
continue;
|
|
386
|
+
if (!this.hasTimeFields(range))
|
|
387
|
+
continue; // all-day — skip
|
|
388
|
+
const timeSlots = this.getTimeSlots(date, range);
|
|
389
|
+
for (const slot of timeSlots) {
|
|
390
|
+
if (slot.endTime === null)
|
|
391
|
+
continue; // point-in-time, no overlap possible
|
|
392
|
+
slots.push({
|
|
393
|
+
rangeId: range.id,
|
|
394
|
+
label: range.label,
|
|
395
|
+
startMinutes: timeToMinutes(slot.startTime),
|
|
396
|
+
endMinutes: timeToMinutes(slot.endTime),
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Sort by start time for sweep-line
|
|
401
|
+
slots.sort((a, b) => a.startMinutes - b.startMinutes || a.endMinutes - b.endMinutes);
|
|
402
|
+
// Sweep-line: find overlapping pairs from different ranges
|
|
403
|
+
const conflicts = [];
|
|
404
|
+
const seen = new Set();
|
|
405
|
+
for (let i = 0; i < slots.length; i++) {
|
|
406
|
+
for (let j = i + 1; j < slots.length; j++) {
|
|
407
|
+
// Since sorted by start, slots[j].startMinutes >= slots[i].startMinutes
|
|
408
|
+
if (slots[j].startMinutes >= slots[i].endMinutes)
|
|
409
|
+
break; // no more overlaps with i
|
|
410
|
+
// Same range — not a conflict
|
|
411
|
+
if (slots[i].rangeId === slots[j].rangeId)
|
|
412
|
+
continue;
|
|
413
|
+
// Deduplicate: use sorted pair key
|
|
414
|
+
const pairKey = slots[i].rangeId < slots[j].rangeId
|
|
415
|
+
? `${slots[i].rangeId}|${slots[j].rangeId}`
|
|
416
|
+
: `${slots[j].rangeId}|${slots[i].rangeId}`;
|
|
417
|
+
if (seen.has(pairKey))
|
|
418
|
+
continue;
|
|
419
|
+
seen.add(pairKey);
|
|
420
|
+
const overlapStart = Math.max(slots[i].startMinutes, slots[j].startMinutes);
|
|
421
|
+
const overlapEnd = Math.min(slots[i].endMinutes, slots[j].endMinutes);
|
|
422
|
+
conflicts.push({
|
|
423
|
+
rangeA: { id: slots[i].rangeId, label: slots[i].label },
|
|
424
|
+
rangeB: { id: slots[j].rangeId, label: slots[j].label },
|
|
425
|
+
date,
|
|
426
|
+
overlapStart: formatTime(Math.floor(overlapStart / 60), overlapStart % 60),
|
|
427
|
+
overlapEnd: formatTime(Math.floor(overlapEnd / 60), overlapEnd % 60),
|
|
428
|
+
});
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
return conflicts;
|
|
432
|
+
}
|
|
433
|
+
/**
|
|
434
|
+
* Find time-level conflicts across a date window.
|
|
435
|
+
*/
|
|
436
|
+
findConflictsInWindow(ranges, from, to) {
|
|
437
|
+
const fromStr = formatDate(from);
|
|
438
|
+
const toStr = formatDate(to);
|
|
439
|
+
const days = dateRange(fromStr, toStr);
|
|
440
|
+
const allConflicts = [];
|
|
441
|
+
for (const day of days) {
|
|
442
|
+
const dayConflicts = this.findConflicts(ranges, day);
|
|
443
|
+
for (const c of dayConflicts) {
|
|
444
|
+
allConflicts.push(c);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return allConflicts;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Find free (unoccupied) time slots on a given date by analysing all ranges.
|
|
451
|
+
*
|
|
452
|
+
* Algorithm:
|
|
453
|
+
* 1. Expand all ranges for the date into time slots (using getTimeSlots)
|
|
454
|
+
* 2. Collect occupied intervals as [startMinutes, endMinutes] pairs
|
|
455
|
+
* 3. Merge overlapping intervals
|
|
456
|
+
* 4. Walk from dayStart to dayEnd — gaps between merged intervals are free slots
|
|
457
|
+
* 5. Filter by minDuration
|
|
458
|
+
*/
|
|
459
|
+
findFreeSlots(ranges, date, options) {
|
|
460
|
+
const minDuration = options?.minDuration ?? 15;
|
|
461
|
+
const dayStartMin = timeToMinutes(options?.dayStart ?? '00:00');
|
|
462
|
+
const dayEndMin = timeToMinutes(options?.dayEnd ?? '24:00');
|
|
463
|
+
// Step 1-2: Collect all occupied intervals for this date
|
|
464
|
+
const occupied = [];
|
|
465
|
+
for (const range of ranges) {
|
|
466
|
+
if (!this.isDateInRange(date, range))
|
|
467
|
+
continue;
|
|
468
|
+
// All-day ranges have no time slots — they don't block time
|
|
469
|
+
const slots = this.getTimeSlots(date, range);
|
|
470
|
+
for (const slot of slots) {
|
|
471
|
+
const start = timeToMinutes(slot.startTime);
|
|
472
|
+
const end = slot.endTime
|
|
473
|
+
? timeToMinutes(slot.endTime)
|
|
474
|
+
: start + (slot.duration ?? 0);
|
|
475
|
+
if (end > start) {
|
|
476
|
+
occupied.push([start, end]);
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
// Step 3: Sort and merge overlapping intervals
|
|
481
|
+
occupied.sort((a, b) => a[0] - b[0] || a[1] - b[1]);
|
|
482
|
+
const merged = [];
|
|
483
|
+
for (const interval of occupied) {
|
|
484
|
+
if (merged.length > 0 && interval[0] <= merged[merged.length - 1][1]) {
|
|
485
|
+
merged[merged.length - 1][1] = Math.max(merged[merged.length - 1][1], interval[1]);
|
|
486
|
+
}
|
|
487
|
+
else {
|
|
488
|
+
merged.push([interval[0], interval[1]]);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
// Step 4: Walk from dayStart to dayEnd, gaps are free slots
|
|
492
|
+
const freeSlots = [];
|
|
493
|
+
let cursor = dayStartMin;
|
|
494
|
+
for (const [start, end] of merged) {
|
|
495
|
+
// Clamp interval to the search window
|
|
496
|
+
const clampedStart = Math.max(start, dayStartMin);
|
|
497
|
+
const clampedEnd = Math.min(end, dayEndMin);
|
|
498
|
+
if (clampedStart > cursor) {
|
|
499
|
+
const gapEnd = Math.min(clampedStart, dayEndMin);
|
|
500
|
+
const duration = gapEnd - cursor;
|
|
501
|
+
if (duration >= minDuration) {
|
|
502
|
+
freeSlots.push({
|
|
503
|
+
date,
|
|
504
|
+
startTime: minutesToTime(cursor),
|
|
505
|
+
endTime: minutesToTime(gapEnd),
|
|
506
|
+
duration,
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
cursor = Math.max(cursor, clampedEnd);
|
|
511
|
+
}
|
|
512
|
+
// Trailing gap after last occupied interval
|
|
513
|
+
if (cursor < dayEndMin) {
|
|
514
|
+
const duration = dayEndMin - cursor;
|
|
515
|
+
if (duration >= minDuration) {
|
|
516
|
+
freeSlots.push({
|
|
517
|
+
date,
|
|
518
|
+
startTime: minutesToTime(cursor),
|
|
519
|
+
endTime: minutesToTime(dayEndMin),
|
|
520
|
+
duration,
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
return freeSlots;
|
|
525
|
+
}
|
|
526
|
+
/**
|
|
527
|
+
* Find the next free slot of at least `duration` minutes, searching day by day
|
|
528
|
+
* from `from` to `to`.
|
|
529
|
+
*/
|
|
530
|
+
findNextFreeSlot(ranges, from, to, duration, options) {
|
|
531
|
+
const fromStr = formatDate(from);
|
|
532
|
+
const toStr = formatDate(to);
|
|
533
|
+
const days = dateRange(fromStr, toStr);
|
|
534
|
+
for (const day of days) {
|
|
535
|
+
const slots = this.findFreeSlots(ranges, day, {
|
|
536
|
+
minDuration: duration,
|
|
537
|
+
dayStart: options?.dayStart,
|
|
538
|
+
dayEnd: options?.dayEnd,
|
|
539
|
+
});
|
|
540
|
+
for (const slot of slots) {
|
|
541
|
+
if (slot.duration >= duration) {
|
|
542
|
+
return slot;
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return null;
|
|
547
|
+
}
|
|
548
|
+
// === Private helpers ===
|
|
549
|
+
/**
|
|
550
|
+
* Check if dateB is exactly the day after dateA.
|
|
551
|
+
*/
|
|
552
|
+
isNextDay(dateA, dateB) {
|
|
553
|
+
const { year, month, day } = parseDate(dateA);
|
|
554
|
+
const d = new Date(year, month, day + 1);
|
|
555
|
+
return formatDate(d) === dateB;
|
|
556
|
+
}
|
|
557
|
+
isDateInBounds(dateStr, range) {
|
|
558
|
+
if (range.fixedBetween) {
|
|
559
|
+
if (range.fromDate && compareDates(dateStr, range.fromDate) < 0)
|
|
560
|
+
return false;
|
|
561
|
+
if (range.toDate && compareDates(dateStr, range.toDate) > 0)
|
|
562
|
+
return false;
|
|
563
|
+
}
|
|
564
|
+
else {
|
|
565
|
+
if (range.fromDate && compareDates(dateStr, range.fromDate) < 0)
|
|
566
|
+
return false;
|
|
567
|
+
if (range.toDate && compareDates(dateStr, range.toDate) > 0)
|
|
568
|
+
return false;
|
|
569
|
+
}
|
|
570
|
+
return true;
|
|
571
|
+
}
|
|
572
|
+
getCandidateDays(range, fromStr, toStr) {
|
|
573
|
+
// Determine the effective window
|
|
574
|
+
let effectiveFrom = fromStr;
|
|
575
|
+
let effectiveTo = toStr;
|
|
576
|
+
if (range.fromDate && compareDates(range.fromDate, effectiveFrom) > 0) {
|
|
577
|
+
effectiveFrom = range.fromDate;
|
|
578
|
+
}
|
|
579
|
+
if (range.toDate && compareDates(range.toDate, effectiveTo) < 0) {
|
|
580
|
+
effectiveTo = range.toDate;
|
|
581
|
+
}
|
|
582
|
+
if (compareDates(effectiveFrom, effectiveTo) > 0) {
|
|
583
|
+
return []; // No overlap between range bounds and query window
|
|
584
|
+
}
|
|
585
|
+
// Explicit dates — just filter to the window
|
|
586
|
+
if (range.dates && range.dates.length > 0) {
|
|
587
|
+
return range.dates.filter(d => compareDates(d, effectiveFrom) >= 0 && compareDates(d, effectiveTo) <= 0);
|
|
588
|
+
}
|
|
589
|
+
// Generate all days in the window and filter by recurrence
|
|
590
|
+
const allDays = dateRange(effectiveFrom, effectiveTo);
|
|
591
|
+
return allDays.filter(day => this.isDateInRange(day, range));
|
|
592
|
+
}
|
|
593
|
+
hasTimeFields(range) {
|
|
594
|
+
return !!(range.everyHour || range.startTime);
|
|
595
|
+
}
|
|
596
|
+
/**
|
|
597
|
+
* Resolve a time in the range's timezone to the user's timezone.
|
|
598
|
+
* Returns null if the time doesn't exist (DST spring-forward gap).
|
|
599
|
+
* Returns the time unchanged if the range has no timezone (floating).
|
|
600
|
+
*/
|
|
601
|
+
resolveTime(dateStr, time, timezone) {
|
|
602
|
+
if (!timezone) {
|
|
603
|
+
return time; // Floating — no conversion
|
|
604
|
+
}
|
|
605
|
+
return convertTime(dateStr, time, timezone, this.userTimezone);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
//# sourceMappingURL=evaluator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evaluator.js","sourceRoot":"","sources":["../src/evaluator.ts"],"names":[],"mappings":"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"}
|
package/dist/events.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DateRange, Occurrence, CalendarEvent } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Convert a native DateRange + one of its expanded Occurrences into a CalendarEvent.
|
|
4
|
+
*/
|
|
5
|
+
export declare function fromDateRange(range: DateRange, occurrence: Occurrence): CalendarEvent;
|
|
6
|
+
/**
|
|
7
|
+
* Batch-convert: expand a DateRange within a window and return CalendarEvents.
|
|
8
|
+
*/
|
|
9
|
+
export declare function expandToEvents(range: DateRange, occurrences: Occurrence[]): CalendarEvent[];
|
|
10
|
+
//# sourceMappingURL=events.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAGvE;;GAEG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAG,aAAa,CAkBrF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,KAAK,EAAE,SAAS,EAChB,WAAW,EAAE,UAAU,EAAE,GACxB,aAAa,EAAE,CAEjB"}
|