import '../contracts/danmaku.dart'; const defaultDuplicateDanmakuMergeWindowSeconds = 1.0; final _whitespacePattern = RegExp(r'\s+'); List mergeDuplicateDanmakuComments( Iterable comments, { double windowSeconds = defaultDuplicateDanmakuMergeWindowSeconds, }) { if (windowSeconds < 0) { throw ArgumentError.value( windowSeconds, 'windowSeconds', 'must be non-negative', ); } final sorted = comments.toList()..sort(_compareDanmakuComments); if (sorted.length < 2) return sorted; final keptByText = >{}; final passthrough = []; for (final comment in sorted) { final key = _mergeKey(comment); if (key.isEmpty) { passthrough.add(comment); continue; } final kept = keptByText.putIfAbsent(key, () => []); final windowStart = kept.isEmpty ? null : kept.last.time; if (windowStart == null || comment.time - windowStart > windowSeconds) { kept.add(comment); } } return [ ...passthrough, for (final kept in keptByText.values) ...kept, ]..sort(_compareDanmakuComments); } int _compareDanmakuComments(DanmakuComment a, DanmakuComment b) { final timeOrder = a.time.compareTo(b.time); if (timeOrder != 0) return timeOrder; return a.cid.compareTo(b.cid); } String _mergeKey(DanmakuComment comment) { return comment.text.trim().replaceAll(_whitespacePattern, ' '); }