@@ -12,7 +12,10 @@ const logger = require('../../util/logger')
12
12
const challengeService = require ( '../../services/challengeService' )
13
13
const { getV4ESClient, getM2MToken } = require ( '../../util/helper' )
14
14
const translationService = require ( '../../services/translationService' )
15
- // const resourceService = require('../../services/resourceService')
15
+ // const csv = require('csv-parser')
16
+ const fs = require ( 'fs' )
17
+ const resourceService = require ( '../../services/resourceService' )
18
+ const { v5 } = require ( 'uuid' )
16
19
17
20
const memberHandleCache = new HashMap ( )
18
21
@@ -23,6 +26,8 @@ const migrationFunction = {
23
26
let page = 0
24
27
let batch = 1
25
28
29
+ const challengeJson = { challenges : [ ] }
30
+
26
31
while ( ! finish ) {
27
32
logger . info ( `Batch-${ batch } - Loading challenges` )
28
33
const challenges = await getMatchesFromES ( page , perPage )
@@ -31,8 +36,23 @@ const migrationFunction = {
31
36
// // logger.info(`Updating ${challenges}`)
32
37
for ( const challenge of challenges ) {
33
38
logger . debug ( `Loading challenge ${ challenge . id } ` )
34
- // get challenge from v4 api
35
39
const c = await challengeService . getMMatchFromV4API ( challenge . id )
40
+ if ( ! c ) {
41
+ logger . error ( `Challenge Not Found - ID: ${ challenge . id } , RoundID: ${ challenge . roundId } ` )
42
+ continue
43
+ }
44
+
45
+ const v5ChallengeLookup = await challengeService . getChallengeIDsFromV5 ( { legacyId : challenge . id } , 10 )
46
+ // logger.debug(JSON.stringify(v5ChallengeLookup))
47
+ if ( v5ChallengeLookup && v5ChallengeLookup . v5Ids && v5ChallengeLookup . v5Ids [ 0 ] ) {
48
+ logger . debug ( 'Skipping!' )
49
+ continue
50
+
51
+ // for (const id of v5ChallengeLookup.v5Ids) {
52
+ // logger.warn(`Deleting Entry for ${id}`)
53
+ // await challengeService.deleteChallenge(id)
54
+ // }
55
+ }
36
56
37
57
const v5TrackProperties = translationService . convertV4TrackToV5 (
38
58
'DATA_SCIENCE' ,
@@ -90,48 +110,88 @@ const migrationFunction = {
90
110
newChallenge . updated = challengeEndDate
91
111
92
112
let handlesToLookup = [ ]
93
- for ( const registrant of c . registrants ) {
94
- // build cache
95
- if ( ! getMemberIdFromCache ( registrant . handle ) ) {
96
- handlesToLookup . push ( registrant . handle )
113
+ if ( c . registrants && c . registrants . length > 0 ) {
114
+ for ( const registrant of c . registrants ) {
115
+ // build cache
116
+ if ( ! getMemberIdFromCache ( registrant . handle ) ) {
117
+ handlesToLookup . push ( registrant . handle )
118
+ } else {
119
+ // logger.debug(`Handle Found in Cache ${registrant.handle}`)
120
+ }
121
+ if ( handlesToLookup . length >= 15 ) {
122
+ await cacheHandles ( handlesToLookup )
123
+ handlesToLookup = [ ]
124
+ }
97
125
}
98
- if ( handlesToLookup . length >= 25 ) {
99
- await cacheHandles ( handlesToLookup )
100
- handlesToLookup = [ ]
126
+ await cacheHandles ( handlesToLookup )
127
+
128
+ // csv
129
+ // challenge id, member id, member handle, submission id, score
130
+ const winners = _ . map ( c . winners , w => {
131
+ return {
132
+ handle : w . submitter ,
133
+ userId : getMemberIdFromCache ( w . submitter ) ,
134
+ points : w . points ,
135
+ submissionId : w . submissionId
136
+ }
137
+ } )
138
+
139
+ const sortedWinners = _ . orderBy ( winners , [ 'points' ] , [ 'desc' ] )
140
+
141
+ // console.log('Sorted Winners', JSON.stringify(sortedWinners))
142
+ let placement = 1
143
+ let counter = 1
144
+ let lastPointsValue = null
145
+ const calculatedWinners = [ ]
146
+ for ( const winner of sortedWinners ) {
147
+ // calculate rank
148
+ if ( lastPointsValue && lastPointsValue > winner . points ) {
149
+ placement = counter
150
+ }
151
+ const calculatedWinner = { }
152
+ calculatedWinner . handle = _ . toString ( winner . handle )
153
+ calculatedWinner . userId = _ . toString ( winner . userId )
154
+ calculatedWinner . placement = placement
155
+ lastPointsValue = winner . points
156
+ counter += 1
157
+
158
+ calculatedWinners . push ( calculatedWinner )
101
159
}
102
- }
103
- await cacheHandles ( handlesToLookup )
160
+ // console.log('Calculated Winners', JSON.stringify(calculatedWinners))
161
+
162
+ newChallenge . winners = calculatedWinners
163
+
164
+ const savedChallengeId = await challengeService . save ( newChallenge )
165
+ // const savedChallengeId = uuid() // FOR TESTING
166
+ // logger.debug(`Challenge: ${JSON.stringify(c.submissions)}`)
104
167
105
- const winners = _ . map ( c . winners , w => {
106
- return {
107
- handle : w . submitter
108
- // placement: w.rank // TODO :: missing placement?
109
- // TODO :: missing points as an object property
168
+ const thisChallenge = {
169
+ challengeId : challenge . id ,
170
+ submissions : c . submissions
110
171
}
111
- } )
112
- newChallenge . winners = winners
113
-
114
- // const savedChallenge = await challengeService.save(newChallenge)
115
- const savedChallenge = { id : uuid ( ) }
116
- logger . debug ( `Challenge: ${ JSON . stringify ( newChallenge ) } ` )
117
-
118
- for ( const registrant of c . registrants ) {
119
- const memberId = await getMemberIdFromCache ( registrant . handle )
120
- const newResource = {
121
- // legacyId: resource.id,
122
- created : moment ( registrant . registrationDate ) . utc ( ) . format ( ) ,
123
- createdBy : registrant . handle ,
124
- updated : moment ( registrant . registrationDate ) . utc ( ) . format ( ) ,
125
- updatedBy : registrant . handle ,
126
- memberId : _ . toString ( memberId ) ,
127
- memberHandle : registrant . handle ,
128
- challengeId : savedChallenge . id ,
129
- roleId : config . SUBMITTER_ROLE_ID
172
+ challengeJson . challenges . push ( thisChallenge )
173
+ fs . writeFileSync ( 'src/scripts/files/challenges.json' , JSON . stringify ( challengeJson ) )
174
+
175
+ for ( const registrant of c . registrants ) {
176
+ const memberId = await getMemberIdFromCache ( registrant . handle )
177
+ const newResource = {
178
+ // legacyId: resource.id,
179
+ created : moment ( registrant . registrationDate ) . utc ( ) . format ( ) ,
180
+ createdBy : registrant . handle ,
181
+ updated : moment ( registrant . registrationDate ) . utc ( ) . format ( ) ,
182
+ updatedBy : registrant . handle ,
183
+ memberId : _ . toString ( memberId ) ,
184
+ memberHandle : registrant . handle ,
185
+ challengeId : savedChallengeId ,
186
+ roleId : config . SUBMITTER_ROLE_ID
187
+ }
188
+ await resourceService . saveResource ( newResource )
189
+ // logger.debug(`Resource: ${JSON.stringify(newResource)}`)
130
190
}
131
- // await resourceService.save(newResource)
132
- // logger.debug(`Resource: ${JSON.stringify(newResource) }`)
191
+ } else {
192
+ logger . warn ( `No Registrants for Challenge ${ challenge . id } `)
133
193
}
134
- return
194
+ // return
135
195
}
136
196
} else {
137
197
logger . info ( 'Finished' )
@@ -159,16 +219,29 @@ async function cacheHandles (handles) {
159
219
logger . debug ( `Caching ${ handles . length } handles` )
160
220
// curl --location --request GET 'https://api.topcoder-dev.com/v3/members/_search/?fields=userId%2Chandle%2CfirstName%2Cemail%2ClastName&query=handleLower:upbeat%20OR%20handleLower:tonyj'
161
221
const ids = _ . map ( handles , h => `handleLower:${ h } ` )
162
- const query = ids . join ( '%20OR%20' )
222
+ const query = encodeURIComponent ( escapeChars ( ids . join ( '%20OR%20' ) ) )
163
223
const token = await getM2MToken ( )
164
- const url = `https://api.topcoder-dev.com/v3/members/ _search?fields=userId%2Chandle&query=${ query } ` // TODO COnfig
224
+ const url = `${ config . V3_MEMBER_API_URL } / _search?fields=userId%2Chandle&query=${ query } `
165
225
const res = await request . get ( url ) . set ( { Authorization : `Bearer ${ token } ` } )
166
226
const handleArray = _ . get ( res . body , 'result.content' )
167
227
for ( const h of handleArray ) {
168
228
cacheMemberIdForHandle ( h . handle , h . userId )
169
229
}
170
230
}
171
231
232
+ // + - && || ! ( ) { } [ ] ^ " ~ * ? : \
233
+ function escapeChars ( str ) {
234
+ str = str . replace ( / ] / g, '\\]' )
235
+ str = str . replace ( / \[ / g, '\\[' )
236
+ str = str . replace ( / - / g, '\\-' )
237
+ str = str . replace ( / { / g, '\\{' )
238
+ str = str . replace ( / } / g, '\\}' )
239
+ str = str . replace ( / \) / g, '\\)' )
240
+ str = str . replace ( / \( / g, '\\(' )
241
+ str = str . replace ( / \/ / g, '\\/' )
242
+ return str
243
+ }
244
+
172
245
function convertPhases ( v4PhasesArray ) {
173
246
let challengeEndDate = moment ( )
174
247
let challengeStartDate = null
@@ -210,11 +283,12 @@ async function getMatchesFromES (page = 0, perPage = 10) {
210
283
from : page * perPage ,
211
284
body : {
212
285
query : {
213
- match_all : { }
286
+ // match_phrase: { id: 16492 }
287
+ match_all : { }
214
288
}
215
289
}
216
290
}
217
- logger . debug ( `ES Query ${ JSON . stringify ( esQuery ) } ` )
291
+ // logger.debug(`ES Query ${JSON.stringify(esQuery)}`)
218
292
// Search with constructed query
219
293
let docs
220
294
try {
0 commit comments