| 7 | const sumStatus = (status) => ({ $sum: { $cond: [{ $eq: ['$status', status] }, 1, 0] } }); |
| 8 | |
| 9 | export async function udoc(report) { |
| 10 | const userStats = new Map<string, { nLiked?: number, nAccept?: number, nSubmit?: number }>(); |
| 11 | |
| 12 | report({ message: 'Udoc nLiked' }); |
| 13 | const likedPipeline = [ |
| 14 | { |
| 15 | $match: { |
| 16 | docType: document.TYPE_PROBLEM_SOLUTION, |
| 17 | vote: { $gt: 0 }, |
| 18 | }, |
| 19 | }, |
| 20 | { |
| 21 | $group: { |
| 22 | _id: { domainId: '$domainId', uid: '$owner' }, |
| 23 | nLiked: { $sum: '$vote' }, |
| 24 | }, |
| 25 | }, |
| 26 | ]; |
| 27 | for await (const adoc of document.coll.aggregate<any>(likedPipeline, { allowDiskUse: true })) { |
| 28 | userStats.set(`${adoc._id.domainId}/${adoc._id.uid}`, { nLiked: adoc.nLiked }); |
| 29 | } |
| 30 | |
| 31 | report({ message: 'Udoc' }); |
| 32 | const pipeline = [ |
| 33 | { |
| 34 | $match: { |
| 35 | contest: { $nin: [RecordModel.RECORD_PRETEST, RecordModel.RECORD_GENERATE] }, |
| 36 | status: { $ne: STATUS.STATUS_CANCELED }, |
| 37 | uid: { $gte: 0 }, |
| 38 | }, |
| 39 | }, |
| 40 | { |
| 41 | $group: { |
| 42 | _id: { domainId: '$domainId', pid: '$pid', uid: '$uid' }, |
| 43 | nSubmit: { $sum: 1 }, |
| 44 | nAccept: sumStatus(STATUS.STATUS_ACCEPTED), |
| 45 | }, |
| 46 | }, |
| 47 | { |
| 48 | $group: { |
| 49 | _id: { domainId: '$_id.domainId', uid: '$_id.uid' }, |
| 50 | nSubmit: { $sum: { $min: ['$nSubmit', 1] } }, |
| 51 | nAccept: { $sum: { $min: ['$nAccept', 1] } }, |
| 52 | }, |
| 53 | }, |
| 54 | ]; |
| 55 | for await (const adoc of db.collection('record').aggregate<any>(pipeline, { allowDiskUse: true })) { |
| 56 | const key = `${adoc._id.domainId}/${adoc._id.uid}`; |
| 57 | const stat = userStats.get(key) || {}; |
| 58 | stat.nSubmit = adoc.nSubmit; |
| 59 | stat.nAccept = adoc.nAccept; |
| 60 | userStats.set(key, stat); |
| 61 | } |
| 62 | |
| 63 | let bulk = db.collection('domain.user').initializeUnorderedBulkOp(); |
| 64 | for (const [key, stat] of userStats) { |
| 65 | const [domainId, uid] = key.split('/'); |
| 66 | bulk.find({ domainId, uid: +uid }).updateOne({ |