detectMultiClauding function
Detect multi-session (using multiple Neomage sessions concurrently).
Uses a sliding window to find the pattern: session1 -> session2 -> session1 within a 30-minute window.
Implementation
({int overlapEvents, int sessionsInvolved, int userMessagesDuring})
detectMultiClauding(
List<({String sessionId, List<String> timestamps})> sessions,
) {
const overlapWindowMs = 30 * 60000;
final allMessages = <({int ts, String sessionId})>[];
for (final session in sessions) {
for (final timestamp in session.timestamps) {
try {
final ts = DateTime.parse(timestamp).millisecondsSinceEpoch;
allMessages.add((ts: ts, sessionId: session.sessionId));
} catch (_) {
// Skip invalid timestamps.
}
}
}
allMessages.sort((a, b) => a.ts.compareTo(b.ts));
final multiNeomageSessionPairs = <String>{};
final messagesDuringMultiNeomage = <String>{};
int windowStart = 0;
final sessionLastIndex = <String, int>{};
for (int i = 0; i < allMessages.length; i++) {
final msg = allMessages[i];
// Shrink window from the left.
while (windowStart < i &&
msg.ts - allMessages[windowStart].ts > overlapWindowMs) {
final expiring = allMessages[windowStart];
if (sessionLastIndex[expiring.sessionId] == windowStart) {
sessionLastIndex.remove(expiring.sessionId);
}
windowStart++;
}
// Check if this session appeared earlier in the window.
final prevIndex = sessionLastIndex[msg.sessionId];
if (prevIndex != null) {
for (int j = prevIndex + 1; j < i; j++) {
final between = allMessages[j];
if (between.sessionId != msg.sessionId) {
final pair = [msg.sessionId, between.sessionId]..sort();
multiNeomageSessionPairs.add(pair.join(':'));
messagesDuringMultiNeomage.add(
'${allMessages[prevIndex].ts}:${msg.sessionId}',
);
messagesDuringMultiNeomage.add('${between.ts}:${between.sessionId}');
messagesDuringMultiNeomage.add('${msg.ts}:${msg.sessionId}');
break;
}
}
}
sessionLastIndex[msg.sessionId] = i;
}
final sessionsWithOverlaps = <String>{};
for (final pair in multiNeomageSessionPairs) {
final parts = pair.split(':');
if (parts.length == 2) {
sessionsWithOverlaps.add(parts[0]);
sessionsWithOverlaps.add(parts[1]);
}
}
return (
overlapEvents: multiNeomageSessionPairs.length,
sessionsInvolved: sessionsWithOverlaps.length,
userMessagesDuring: messagesDuringMultiNeomage.length,
);
}