3 var _ = require('lodash');
4 var Backbone = require('backbone');
6 module.exports = (function() {
7 // const - 5 minutes window to merge messages into previous burst
8 var BURST_WINDOW = 5 * 60 * 1000;
11 * toCollection() converts an Array to a Backbone.Collection
12 * we do this in order to separate business logic from infrastructure workaround
14 * collection Array or Backbone.Collection - Structure in which a check is performed
15 * returns Backbone.Collection - the converted structure
17 function toCollection(collection) {
18 if (_.isArray(collection)) return new Backbone.Collection(collection);
23 * findBurstAbove() finds the first burstStart above the given index
25 * index Number - index used to find burst start
26 * @return Number - the index of burstStart found above
28 function findBurstAbove(index) {
30 if (index === 0) return index;
32 chat = this.at(index);
33 if (chat.get('burstStart')) break;
39 * findBurstBelow() finds the first burstStart below the given index
41 * index Number - index used to find burst start
42 * @return Number - the index of burstStart found below
44 function findBurstBelow(index) {
45 if (index === this.length - 1) return index;
47 while (index < this.length) {
48 chat = this.at(index);
49 if (chat.get('burstStart')) break;
56 * findSlice() triggers a parse based on a model, however it finds the correct `slice`
57 * of the chat-collection to be recalculated. To summarize: This function is responsible for calling parse
58 * with a subset of the collection.
60 * model Backbone.Model - the model that is to be added to the collection
61 * returns void - it simply calls parse(), which mutates the collection directly
63 function findSlice(model) {
64 if ('burstStart' in model.attributes) return; // already calculated bursts for this batch
65 var index = this.indexOf(model);
66 var start = findBurstAbove.call(this, index);
67 var end = findBurstBelow.call(this, index);
68 parse(this, start, end);
72 * calculateBurst() analyses what criteria a chat-item meets and modifies the current burst state accordingly
74 * chat Backbone.Model - the chat-item to be analysed
75 * state Object - the current burst state
77 * returns void - it mutates the object directly
79 function calculateBurst(chat, state) {
80 var fromUser = chat.get('fromUser');
81 var sent = chat.get('sent');
82 var user = fromUser && fromUser.username;
83 var time = (sent && new Date(sent).valueOf()) || Date.now();
85 if (chat.get('status')) {
86 state.burstStart = true;
92 var outsideBurstWindow = time - state.time > BURST_WINDOW;
94 if (state.status || user !== state.user || outsideBurstWindow) {
95 state.burstStart = true;
99 state.status = false; // resetting the status, because it might have been true
103 state.burstStart = false;
109 * parse() detects each chat-item on a Collection regarding their burst status
111 * collection Backbone.Collection - the collection to be iterated over
112 * start Number - index set as the starting point of the iteration
113 * end Number - index set as the ending point of the iteration
115 * returns Object - the mutated collection (Backbone.Collection.toJSON())
117 function parse(collection_, start, end) {
118 var collection = toCollection(collection_);
121 if (!collection) return;
122 start = typeof start !== 'undefined' ? start : 0; // start defaults at index 0
123 end = typeof end !== 'undefined' ? end : collection.length - 1; // end defaults at index n
133 collection.slice(start, end + 1).forEach(function(chat) {
134 if (chat.get('parentId')) return; // ignore thread messages for now
135 calculateBurst(chat, state);
136 chat.set('burstStart', state.burstStart);
139 return collection.toJSON();
142 /* public interface */