Canonicalise certain transition pairs, handle arbitrary consecutive transitions
Transition pairs joined,left and left,joined are now transformed into single meta-transitions "joined_and_left" and "left_and_joined" respectively. These are described as "joined and left", "left and rejoined". Treat consecutive sequences of transitions as repetitions, and handle any arbitrary repetitions of transitions: ...,joined,left,joined,left,joined,left,... is canonicalised into ...,joined_and_left, joined_and_left, joined_and_left,... which is truncated and described as ... , joined and left 3 times, ... This also works if there are multiple consecutive sequences separated by other transitions: ..., banned, banned, banned, joined, unbanned, unbanned, unbanned,... becomes ... was banned 3 times, joined, was unbanned 3 times ...pull/21833/head
parent
fb68fff536
commit
82d6805a71
|
@ -88,62 +88,105 @@ module.exports = React.createClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
_getDescriptionForTransition(t, plural) {
|
_getDescriptionForTransition(t, plural, repeats) {
|
||||||
let beConjugated = plural ? "were" : "was";
|
let beConjugated = plural ? "were" : "was";
|
||||||
let invitation = plural ? "invitations" : "an invitation";
|
let invitation = plural ? "invitations" : "an invitation";
|
||||||
|
|
||||||
switch (t) {
|
let res = null;
|
||||||
case 'joined': return "joined";
|
let map = {
|
||||||
case 'left': return "left";
|
"joined": "joined",
|
||||||
case 'invite_reject': return "rejected " + invitation;
|
"left": "left",
|
||||||
case 'invite_withdrawal': return "withdrew " + invitation;
|
"joined_and_left": "joined and left",
|
||||||
case 'invited': return beConjugated + " invited";
|
"left_and_joined": "left and rejoined",
|
||||||
case 'banned': return beConjugated + " banned";
|
"invite_reject": "rejected " + invitation,
|
||||||
case 'unbanned': return beConjugated + " unbanned";
|
"invite_withdrawal": "withdrew " + invitation,
|
||||||
case 'kicked': return beConjugated + " kicked";
|
"invited": beConjugated + " invited",
|
||||||
|
"banned": beConjugated + " banned",
|
||||||
|
"unbanned": beConjugated + " unbanned",
|
||||||
|
"kicked": beConjugated + " kicked",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Object.keys(map).includes(t)) {
|
||||||
|
res = map[t] + (repeats > 1 ? " " + repeats + " times" : "" );
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getCanonicalTransitions: function(transitions) {
|
||||||
|
let modMap = {
|
||||||
|
'joined' : {
|
||||||
|
'after' : 'left',
|
||||||
|
'newTransition' : 'joined_and_left',
|
||||||
|
},
|
||||||
|
'left' : {
|
||||||
|
'after' : 'joined',
|
||||||
|
'newTransition' : 'left_and_joined',
|
||||||
|
},
|
||||||
|
// $currentTransition : {
|
||||||
|
// 'after' : $nextTransition,
|
||||||
|
// 'newTransition' : 'new_transition_type',
|
||||||
|
// },
|
||||||
|
};
|
||||||
|
const res = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < transitions.length; i++) {
|
||||||
|
let t = transitions[i];
|
||||||
|
let t2 = transitions[i + 1];
|
||||||
|
|
||||||
|
let transition = t;
|
||||||
|
|
||||||
|
if (i < transitions.length - 1 && modMap[t] && modMap[t].after === t2) {
|
||||||
|
transition = modMap[t].newTransition;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push(transition);
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
},
|
||||||
|
|
||||||
|
_getTruncatedTransitions: function(transitions) {
|
||||||
|
let res = [];
|
||||||
|
for (let i = 0; i < transitions.length; i++) {
|
||||||
|
if (res.length > 0 && res[res.length - 1].transitionType === transitions[i]) {
|
||||||
|
res[res.length - 1].repeats += 1;
|
||||||
|
} else {
|
||||||
|
res.push({
|
||||||
|
transitionType: transitions[i],
|
||||||
|
repeats: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// returns [{
|
||||||
|
// transitionType: "joined_and_left"
|
||||||
|
// repeats: 123
|
||||||
|
// }, ... ]
|
||||||
|
return res;
|
||||||
},
|
},
|
||||||
|
|
||||||
_renderSummary: function(eventAggregates) {
|
_renderSummary: function(eventAggregates) {
|
||||||
let summaries = Object.keys(eventAggregates).map((transitions) => {
|
let summaries = Object.keys(eventAggregates).map((transitions) => {
|
||||||
let nameList = this._renderNameList(eventAggregates[transitions]);
|
let nameList = this._renderNameList(eventAggregates[transitions]);
|
||||||
|
let plural = eventAggregates[transitions].length > 1;
|
||||||
|
|
||||||
let repeats = 1;
|
let repeats = 1;
|
||||||
let repeatExtra = 0;
|
let repeatExtra = 0;
|
||||||
|
|
||||||
let splitTransitions = transitions.split(',');
|
let splitTransitions = transitions.split(',');
|
||||||
let describedTransitions = splitTransitions;
|
|
||||||
let plural = eventAggregates[transitions].length > 1;
|
|
||||||
|
|
||||||
for (let modulus = 1; modulus <= 2; modulus++) {
|
// Some pairs of transitions are common and are repeated a lot, so canonicalise them into "pair" transitions
|
||||||
// Sequences that are repeating through modulus transitions will be truncated
|
let canonicalTransitions = this._getCanonicalTransitions(splitTransitions);
|
||||||
if (this._isRepeatedSequence(describedTransitions, modulus)) {
|
// Remove consecutive repetitions of the same transition (like 5 consecutive 'join_and_leave's)
|
||||||
// Extra repeating sequence on the end that should be treated separately
|
let truncatedTransitions = this._getTruncatedTransitions(canonicalTransitions);
|
||||||
// so as to avoid j,l,j,l,j => "... joined and left 2.5 times"
|
|
||||||
repeatExtra = describedTransitions.length % modulus;
|
|
||||||
|
|
||||||
repeats = (describedTransitions.length - repeatExtra) / modulus;
|
let descs = truncatedTransitions.map((t) => {
|
||||||
describedTransitions = describedTransitions.slice(0, modulus);
|
return this._getDescriptionForTransition(t.transitionType, plural, t.repeats);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let numberOfTimes = repeats > 1 ? " " + repeats + " times" : "";
|
|
||||||
|
|
||||||
let descs = describedTransitions.map((t) => {
|
|
||||||
return this._getDescriptionForTransition(t, plural);
|
|
||||||
});
|
|
||||||
|
|
||||||
let afterRepeatDescs = splitTransitions.slice(splitTransitions.length - repeatExtra).map((t) => {
|
|
||||||
return this._getDescriptionForTransition(t, plural);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let desc = this._renderCommaSeparatedList(descs);
|
let desc = this._renderCommaSeparatedList(descs);
|
||||||
let afterRepeatDesc = this._renderCommaSeparatedList(afterRepeatDescs);
|
|
||||||
|
|
||||||
return nameList + " " + desc + numberOfTimes + (afterRepeatDesc ? " and then " + afterRepeatDesc : "");
|
return nameList + " " + desc;
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!summaries) {
|
if (!summaries) {
|
||||||
|
|
Loading…
Reference in New Issue