@@ -5,6 +5,7 @@ import MwApi from '../MwApi';
5
5
import ContributionSurveyRowParser , {
6
6
RawContributionSurveyRow
7
7
} from './ContributionSurveyRowParser' ;
8
+ import { ContributionSurveyRowSort } from './ContributionSurveyRowSort' ;
8
9
9
10
export enum ContributionSurveyRowStatus {
10
11
// The row has not been processed yet.
@@ -68,6 +69,122 @@ export default class ContributionSurveyRow {
68
69
return ContributionSurveyRowStatus . Unknown ;
69
70
}
70
71
72
+ /**
73
+ * Guesses the sort order for a given set of revisions.
74
+ *
75
+ * @param diffs The diffs to guess from.
76
+ * @return The sort order
77
+ */
78
+ static guessSortOrder (
79
+ diffs : Iterable < ContributionSurveyRevision >
80
+ ) : ContributionSurveyRowSort {
81
+ let last : ContributionSurveyRevision = null ;
82
+ let dateScore = 1 ;
83
+ let dateReverseScore = 1 ;
84
+ let byteScore = 1 ;
85
+ for ( const diff of diffs ) {
86
+ if ( last == null ) {
87
+ last = diff ;
88
+ } else {
89
+ const diffTimestamp = new Date ( diff . timestamp ) . getTime ( ) ;
90
+ const lastTimestamp = new Date ( last . timestamp ) . getTime ( ) ;
91
+ dateScore = ( dateScore + (
92
+ diffTimestamp > lastTimestamp ? 1 : 0
93
+ ) ) / 2 ;
94
+ dateReverseScore = ( dateReverseScore + (
95
+ diffTimestamp < lastTimestamp ? 1 : 0
96
+ ) ) / 2 ;
97
+ byteScore = ( byteScore + (
98
+ diff . diffsize < last . diffsize ? 1 : 0
99
+ ) ) / 2 ;
100
+ last = diff ;
101
+ }
102
+ }
103
+
104
+ // Multiply by weights to remove ties
105
+ dateScore *= 1.1 ;
106
+ dateReverseScore *= 1.05 ;
107
+
108
+ switch ( Math . max ( dateScore , dateReverseScore , byteScore ) ) {
109
+ case byteScore :
110
+ return ContributionSurveyRowSort . Bytes ;
111
+ case dateScore :
112
+ return ContributionSurveyRowSort . Date ;
113
+ case dateReverseScore :
114
+ return ContributionSurveyRowSort . DateReverse ;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Gets the sorter function which will sort a set of diffs based on a given
120
+ * sort order. This sorts any array containing revisions.
121
+ *
122
+ * @param sort
123
+ * @param mode The sort mode to use.
124
+ */
125
+ static getSorterFunction ( sort : ContributionSurveyRowSort , mode ?: 'array' ) :
126
+ ( a : ContributionSurveyRevision , b : ContributionSurveyRevision ) => number ;
127
+ /**
128
+ * Gets the sorter function which will sort a set of diffs based on a given
129
+ * sort order. This sorts any entry array using the first element (the key).
130
+ *
131
+ * @param sort
132
+ * @param mode The sort mode to use.
133
+ */
134
+ static getSorterFunction ( sort : ContributionSurveyRowSort , mode ?: 'key' ) :
135
+ ( a : [ ContributionSurveyRevision , any ] , b : [ ContributionSurveyRevision , any ] ) => number ;
136
+ /**
137
+ * Gets the sorter function which will sort a set of diffs based on a given
138
+ * sort order. This sorts any entry array using the second element (the value).
139
+ *
140
+ * @param sort
141
+ * @param mode The sort mode to use.
142
+ */
143
+ static getSorterFunction ( sort : ContributionSurveyRowSort , mode ?: 'value' ) :
144
+ ( a : [ any , ContributionSurveyRevision ] , b : [ any , ContributionSurveyRevision ] ) => number ;
145
+ /**
146
+ * Gets the sorter function which will sort a set of diffs based on a given
147
+ * sort order.
148
+ *
149
+ * @param sort
150
+ * @param mode The sort mode to use. If `array`, the returned function sorts an
151
+ * array of revisions. If `key`, the returned function sorts entries with the first
152
+ * entry element (`entry[0]`) being a revision. If `value`, the returned function
153
+ * sorts values with the second entry element (`entry[1]`) being a revision.
154
+ * @return The sorted array
155
+ */
156
+ static getSorterFunction (
157
+ sort : ContributionSurveyRowSort ,
158
+ mode : 'array' | 'key' | 'value' = 'array'
159
+ ) {
160
+ return ( _a : any , _b : any ) => {
161
+ let a : ContributionSurveyRevision , b : ContributionSurveyRevision ;
162
+ switch ( mode ) {
163
+ case 'array' :
164
+ a = _a ;
165
+ b = _b ;
166
+ break ;
167
+ case 'key' :
168
+ a = _a [ 0 ] ;
169
+ b = _b [ 0 ] ;
170
+ break ;
171
+ case 'value' :
172
+ a = _a [ 1 ] ;
173
+ b = _b [ 1 ] ;
174
+ break ;
175
+ }
176
+
177
+ switch ( sort ) {
178
+ case ContributionSurveyRowSort . Date :
179
+ return new Date ( a . timestamp ) . getTime ( ) - new Date ( b . timestamp ) . getTime ( ) ;
180
+ case ContributionSurveyRowSort . DateReverse :
181
+ return new Date ( b . timestamp ) . getTime ( ) - new Date ( a . timestamp ) . getTime ( ) ;
182
+ case ContributionSurveyRowSort . Bytes :
183
+ return b . diffsize - a . diffsize ;
184
+ }
185
+ } ;
186
+ }
187
+
71
188
/**
72
189
* The case page of this row.
73
190
*/
@@ -121,7 +238,7 @@ export default class ContributionSurveyRow {
121
238
}
122
239
123
240
/**
124
- * The diffs included in this row.
241
+ * The diffs included in this row. Mapped by revision IDs.
125
242
*/
126
243
private diffs ?: Map < number , ContributionSurveyRevision > ;
127
244
@@ -226,9 +343,10 @@ export default class ContributionSurveyRow {
226
343
}
227
344
) ;
228
345
346
+ const sortOrder = ContributionSurveyRow . guessSortOrder ( revisionData . values ( ) ) ;
229
347
// Sort from most bytes to least.
230
348
return this . diffs = new Map ( [ ...revisionData . entries ( ) ] . sort (
231
- ( a , b ) => b [ 1 ] . diffsize - a [ 1 ] . diffsize
349
+ ContributionSurveyRow . getSorterFunction ( sortOrder , 'value' )
232
350
) ) ;
233
351
}
234
352
0 commit comments