@@ -69,6 +69,7 @@ const RATING_SOURCE_DEVELOPMENT = 'DEVELOPMENT_CHALLENGE'
6969const RATING_SOURCE_DATA_SCIENCE_CHALLENGE = 'DATA_SCIENCE_CHALLENGE'
7070const RATING_SOURCE_MARATHON_MATCH = 'MARATHON_MATCH'
7171const RERATE_MARATHON_ACTOR = 'rerate-mm-stats'
72+ const CHALLENGE_TRACK_QUALITY_ASSURANCE = 'QUALITY_ASSURANCE'
7273const CHALLENGE_WINNER_PLACEMENT_TYPE = 'PLACEMENT'
7374const CHALLENGE_WINNER_PASSED_REVIEW_TYPE = 'PASSED_REVIEW'
7475const CHALLENGE_WINNER_HISTORY_TYPES = [ CHALLENGE_WINNER_PLACEMENT_TYPE , CHALLENGE_WINNER_PASSED_REVIEW_TYPE ]
@@ -364,6 +365,38 @@ function isChallengeRatingEnabled (challenge) {
364365 return isChallengeRated ( challenge )
365366}
366367
368+ /**
369+ * Normalize challenge track labels for source-routing checks.
370+ * @param {* } value raw challenge track label, enum value, or abbreviation
371+ * @returns {string } uppercase source track key
372+ */
373+ function normalizeChallengeSourceTrack ( value ) {
374+ return String ( value || '' )
375+ . trim ( )
376+ . toUpperCase ( )
377+ . replace ( / [ \s - ] + / g, '_' )
378+ }
379+
380+ /**
381+ * Check whether a challenge source track is Quality Assurance.
382+ * QA Challenge results are rated in the public Data Science Challenge bucket.
383+ * @param {* } value raw challenge track label, enum value, or abbreviation
384+ * @returns {boolean } true when the source track is QA
385+ */
386+ function isQualityAssuranceChallengeSourceTrack ( value ) {
387+ const normalizedTrack = normalizeChallengeSourceTrack ( value )
388+ return normalizedTrack === CHALLENGE_TRACK_QUALITY_ASSURANCE || normalizedTrack === 'QA'
389+ }
390+
391+ /**
392+ * Build the source tracks replayed for Data Science Challenge ratings.
393+ * QA Challenges share the public Data Science Challenge rating bucket.
394+ * @returns {Array<string> } challenge source track labels
395+ */
396+ function getDataScienceChallengeSourceTrackNames ( ) {
397+ return [ TRACK_NAMES . DATA_SCIENCE , CHALLENGE_TRACK_QUALITY_ASSURANCE ]
398+ }
399+
367400/**
368401 * Load challenge metadata needed to decide which ratings apply.
369402 * @param {Object } challengeClient prisma challenge client
@@ -405,7 +438,8 @@ async function fetchChallengeForRatingUpdate (challengeClient, challengeId) {
405438 typeId : true ,
406439 track : {
407440 select : {
408- name : true
441+ name : true ,
442+ track : true
409443 }
410444 } ,
411445 type : {
@@ -432,14 +466,16 @@ async function fetchChallengeForRatingUpdate (challengeClient, challengeId) {
432466 * @returns {string|null } source identifier or null when unsupported
433467 */
434468function resolveChallengeRatingSource ( challenge ) {
435- const trackName = getCanonicalTrackName ( _ . get ( challenge , 'track.name' ) || _ . get ( challenge , 'trackId' ) )
469+ const rawTrackName = _ . get ( challenge , 'track.track' ) || _ . get ( challenge , 'track.name' ) || _ . get ( challenge , 'trackId' )
470+ const trackName = getCanonicalTrackName ( rawTrackName )
436471 const typeName = getCanonicalTypeName ( _ . get ( challenge , 'type.name' ) || _ . get ( challenge , 'typeId' ) )
437472
438473 if ( trackName === TRACK_NAMES . DEVELOP && typeName === TYPE_NAMES . CHALLENGE ) {
439474 return RATING_SOURCE_DEVELOPMENT
440475 }
441476
442- if ( trackName === TRACK_NAMES . DATA_SCIENCE && typeName === TYPE_NAMES . CHALLENGE ) {
477+ if ( ( trackName === TRACK_NAMES . DATA_SCIENCE || isQualityAssuranceChallengeSourceTrack ( rawTrackName ) ) &&
478+ typeName === TYPE_NAMES . CHALLENGE ) {
443479 return RATING_SOURCE_DATA_SCIENCE_CHALLENGE
444480 }
445481
@@ -554,7 +590,7 @@ async function fetchChallengeResultParticipantIds (reviewDbClient, challengeId)
554590
555591/**
556592 * Fetch placement winner participants from challenge-api for completed
557- * Development rating rerates. This covers QA-created challenges where winners
593+ * Development/Data Science rating rerates. This covers challenges where winners
558594 * can be assigned without a review-api challengeResult row for the same member.
559595 * @param {Object } challengeClient challenge Prisma client
560596 * @param {string|number } challengeId challenge identifier
@@ -695,7 +731,7 @@ async function rerateChallengeRatingJobForMember (challengeClient, reviewDbClien
695731 ? {
696732 targetTrackName : TRACK_NAMES . DATA_SCIENCE ,
697733 targetTypeName : TYPE_NAMES . CHALLENGE ,
698- challengeTrackNames : [ TRACK_NAMES . DATA_SCIENCE ] ,
734+ challengeTrackNames : getDataScienceChallengeSourceTrackNames ( ) ,
699735 challengeTypeNames : [ TYPE_NAMES . CHALLENGE ]
700736 }
701737 : undefined
@@ -4270,7 +4306,8 @@ refreshMemberStats.schema = {
42704306 * Re-rate every existing submitter on a completed challenge for all applicable
42714307 * rating dimensions. This includes the native challenge track/type rating when
42724308 * supported and any configured named rating paths whose tags/skills match the
4273- * challenge, such as the default AI path.
4309+ * challenge, such as the default AI path. Quality Assurance Challenge rows are
4310+ * replayed into the public DATA_SCIENCE / Challenge rating bucket.
42744311 * @param {Object } currentUser the user who performs operation
42754312 * @param {Object } data rerate payload containing the completed challenge id
42764313 * @returns {Object } summary of participants, rating jobs, updates, and per-member failures
@@ -4433,6 +4470,8 @@ rerateChallengeSubmitterRatings.schema = {
44334470 * Trigger a DEVELOPMENT / Challenge, DATA_SCIENCE / Challenge,
44344471 * DATA_SCIENCE / MARATHON_MATCH, or configured tag- or skill-based rating path
44354472 * re-rating pass beginning with the supplied challenge.
4473+ * DATA_SCIENCE / Challenge rerates also replay Quality Assurance Challenge
4474+ * source rows because QA history is surfaced in that public rating bucket.
44364475 * The relevant review-api results are reprocessed in chronological order and
44374476 * persisted into the existing unified rating tables for the member.
44384477 * @param {Object } currentUser the user who performs operation
@@ -4485,7 +4524,7 @@ async function rerateMemberStats (currentUser, handle, data) {
44854524 {
44864525 targetTrackName : TRACK_NAMES . DATA_SCIENCE ,
44874526 targetTypeName : TYPE_NAMES . CHALLENGE ,
4488- challengeTrackNames : [ TRACK_NAMES . DATA_SCIENCE ] ,
4527+ challengeTrackNames : getDataScienceChallengeSourceTrackNames ( ) ,
44894528 challengeTypeNames : [ TYPE_NAMES . CHALLENGE ]
44904529 }
44914530 )
0 commit comments