@@ -60,60 +60,174 @@ const findQuestionInLearnCollections = async (problemId) => {
6060 return null ;
6161} ;
6262
63+ // Helper: Search for question in caseLog collection
64+ const findQuestionInCaseLog = async ( problemId ) => {
65+ try {
66+ console . log ( ` ↳ Searching in caseLog collection for problemId: "${ problemId } "` ) ;
67+
68+ // Search by problemId first (in case caseLog documents have this field)
69+ let question = await mongoose . connection . db
70+ . collection ( 'caseLog' )
71+ . findOne ( { problemId } ) ;
72+
73+ if ( question ) {
74+ console . log ( ` ✅ Found in caseLog collection by problemId` ) ;
75+ return question ;
76+ }
77+
78+ // Try searching by _id if it's a valid MongoDB ObjectId
79+ if ( problemId . match ( / ^ [ 0 - 9 a - f ] { 24 } $ / i) ) {
80+ try {
81+ console . log ( ` ↳ CaseLog: Trying to find by _id (ObjectId): "${ problemId } "` ) ;
82+ const objId = new mongoose . Types . ObjectId ( problemId ) ;
83+ question = await mongoose . connection . db
84+ . collection ( 'caseLog' )
85+ . findOne ( { _id : objId } ) ;
86+
87+ if ( question ) {
88+ console . log ( ` ✅ Found in caseLog collection by _id (ObjectId)` ) ;
89+ return question ;
90+ }
91+ } catch ( objIdErr ) {
92+ console . log ( ` ⚠️ CaseLog ObjectId conversion failed: ${ objIdErr . message } ` ) ;
93+ }
94+
95+ // Fallback: try searching with string _id
96+ try {
97+ console . log ( ` ↳ CaseLog: Trying to find by _id (string): "${ problemId } "` ) ;
98+ question = await mongoose . connection . db
99+ . collection ( 'caseLog' )
100+ . findOne ( { _id : problemId } ) ;
101+
102+ if ( question ) {
103+ console . log ( ` ✅ Found in caseLog collection by _id (string)` ) ;
104+ return question ;
105+ }
106+ } catch ( strIdErr ) {
107+ console . log ( ` ⚠️ CaseLog string _id search failed: ${ strIdErr . message } ` ) ;
108+ }
109+ }
110+
111+ console . log ( ` ❌ CaseLog: Document not found with problemId: "${ problemId } "` ) ;
112+ } catch ( err ) {
113+ console . log ( ` ⚠️ CaseLog collection search failed:` , err . message ) ;
114+ }
115+ return null ;
116+ } ;
117+
63118// Submit solution and award rewards only on first-time completion
64119export const submitSolutionService = async ( {
65120 userId,
66121 questionId,
67122 code,
68- languageId
123+ languageId,
124+ sourceArea = 'learn_page' ,
125+ collectionName = null ,
126+ preloadedTestCases = [ ]
69127} ) => {
70128 try {
71129 // Debug: Log received identifiers
72- console . log ( "📝 Submit received - userId:" , userId , "questionId:" , questionId ) ;
130+ console . log ( "📝 Submit received - userId:" , userId , "questionId:" , questionId , "sourceArea:" , sourceArea , "collectionName:" , collectionName , "preloadedTestCases:" , preloadedTestCases . length ) ;
73131
74132 // Step 1: Validate user exists
75133 const user = await User . findById ( userId ) ;
76134 if ( ! user ) {
77135 throw new Error ( "User not found" ) ;
78136 }
79137
80- // Step 2: Validate question exists search learn collections first, then main Question collection
81- console . log ( `🔍 Searching for question with problemId: "${ questionId } "` ) ;
82-
83- // Try learn collections first (where most questions live)
84- let question = await findQuestionInLearnCollections ( questionId ) ;
85-
86- // If not found in learn collections, try main Question collection
138+ let testCases = [ ] ;
139+ let question = null ;
140+
141+ console . log ( `📊 TEST CASES ANALYSIS:` ) ;
142+ console . log ( ` - preloadedTestCases.length: ${ preloadedTestCases ?. length || 0 } ` ) ;
143+ console . log ( ` - preloadedTestCases: ${ JSON . stringify ( preloadedTestCases ?. slice ( 0 , 1 ) ) } ` ) ;
144+ console . log ( ` - collectionName provided: ${ collectionName ? 'YES - ' + collectionName : 'NO' } ` ) ;
145+ console . log ( ` - sourceArea: ${ sourceArea } ` ) ;
146+
147+ console . log ( `🔍 Searching for question with questionId: "${ questionId } "` ) ;
148+
149+ if ( collectionName ) {
150+ console . log ( ` → Direct lookup in collection: "${ collectionName } "` ) ;
151+ console . log ( ` → Searching for problemId: ${ questionId } ` ) ;
152+ question = await mongoose . connection . db
153+ . collection ( collectionName )
154+ . findOne ( { problemId : questionId } ) ;
155+
156+ console . log ( ` → Result from problemId search: ${ question ? 'FOUND' : 'NOT FOUND' } ` ) ;
157+
158+ if ( ! question && questionId . match ( / ^ [ 0 - 9 a - f ] { 24 } $ / i) ) {
159+ try {
160+ const objId = new mongoose . Types . ObjectId ( questionId ) ;
161+ console . log ( ` → Trying ObjectId search for: ${ objId } ` ) ;
162+ question = await mongoose . connection . db
163+ . collection ( collectionName )
164+ . findOne ( { _id : objId } ) ;
165+ console . log ( ` → Result from ObjectId search: ${ question ? 'FOUND' : 'NOT FOUND' } ` ) ;
166+ } catch ( err ) {
167+ console . log ( ` → ObjectId conversion failed: ${ err . message } ` ) ;
168+ console . log ( ` → Trying string _id search for: ${ questionId } ` ) ;
169+ question = await mongoose . connection . db
170+ . collection ( collectionName )
171+ . findOne ( { _id : questionId } ) ;
172+ console . log ( ` → Result from string _id search: ${ question ? 'FOUND' : 'NOT FOUND' } ` ) ;
173+ }
174+ }
175+
176+ if ( question ) {
177+ console . log ( ` ✅ Found in collection: ${ collectionName } , has test_cases: ${ question . test_cases ? question . test_cases . length : 0 } ` ) ;
178+ } else {
179+ console . log ( ` ❌ Not found in collection: ${ collectionName } , attempting fallback...` ) ;
180+ }
181+ } else {
182+ console . log ( `⚠️ WARNING: collectionName is NULL! This means frontend didn't pass it.` ) ;
183+ }
184+
185+ if ( ! question && sourceArea === 'case_log' ) {
186+ console . log ( ` → Fallback: Searching caseLog collection` ) ;
187+ question = await findQuestionInCaseLog ( questionId ) ;
188+ }
189+
87190 if ( ! question ) {
88- console . log ( ` ↳ Not found in learn collections, trying main Question collection` ) ;
191+ console . log ( ` → Fallback: Searching learn collections` ) ;
192+ question = await findQuestionInLearnCollections ( questionId ) ;
193+ }
194+
195+ if ( ! question ) {
196+ console . log ( ` ↳ Fallback: Trying main Question collection` ) ;
89197 question = await Question . findOne ( { problemId : questionId } ) ;
90198 if ( question ) {
91199 console . log ( ` ✅ Found in main Question collection` ) ;
92200 }
93201 }
94-
95- // Last resort: try finding by _id (MongoDB ID)
202+
96203 if ( ! question && questionId . match ( / ^ [ 0 - 9 a - f ] { 24 } $ / i) ) {
97- console . log ( ` ↳ Not found by problemId, trying _id: " ${ questionId } " ` ) ;
204+ console . log ( ` ↳ Fallback: Trying by MongoDB _id` ) ;
98205 question = await Question . findById ( questionId ) ;
99206 if ( question ) {
100207 console . log ( ` ✅ Found by MongoDB _id` ) ;
101208 }
102209 }
103-
104- console . log ( `✅ Question found:` , question ? `${ question . problemId } (${ question . original ?. title } )` : "NOT FOUND" ) ;
105- if ( ! question ) {
106- throw new Error ( "Question not found" ) ;
210+
211+ if ( preloadedTestCases && preloadedTestCases . length > 0 ) {
212+ console . log ( `✅ Using preloaded test cases from frontend (${ preloadedTestCases . length } cases)` ) ;
213+ testCases = preloadedTestCases ;
214+ } else {
215+ console . log ( `⚠️ WARNING: preloadedTestCases is EMPTY or NULL. Will use question document test cases.` ) ;
107216 }
108217
109- // Step 3: Get test cases from question
110- let testCases = question . test_cases || [ ] ;
111218 if ( testCases . length === 0 ) {
112- throw new Error ( "No test cases found for this question" ) ;
219+ testCases = question ?. test_cases || question ?. testCases || [ ] ;
113220 }
114221
222+ const questionDifficulty = question ?. difficulty || null ;
223+
224+ console . log ( `📦 Test cases found: ${ testCases . length } ` ) ;
115225 console . log ( `📦 Raw test cases from DB:` , JSON . stringify ( testCases . slice ( 0 , 1 ) , null , 2 ) ) ;
116226
227+ if ( testCases . length === 0 ) {
228+ throw new Error ( "No test cases found for this question" ) ;
229+ }
230+
117231 // Normalize test cases: ensure they have the right field names
118232 testCases = testCases . map ( tc => ( {
119233 input : tc . input || tc . input_data || "" ,
@@ -137,7 +251,7 @@ export const submitSolutionService = async ({
137251 console . log ( ` Test cases:` , JSON . stringify ( visibleTestCases , null , 2 ) ) ;
138252 // Record this attempt (creates progress entry if first time)
139253 try {
140- await incrementAttempt ( userId , questionId , 'coding' , question . difficulty || null , languageName ) ;
254+ await incrementAttempt ( userId , questionId , 'coding' , questionDifficulty , languageName ) ;
141255 } catch ( err ) {
142256 console . warn ( 'Could not increment attempt in progress service:' , err . message ) ;
143257 }
@@ -180,7 +294,7 @@ export const submitSolutionService = async ({
180294 console . log ( `ℹ️ Question already completed by user ${ userId } ` ) ;
181295 // Ensure progress record marks solved=true and has metadata
182296 try {
183- await markQuestionSolved ( userId , questionId , 'coding' , 'code_editor' , passedCount , visibleTestCases . length , question . difficulty || null , languageName ) ;
297+ await markQuestionSolved ( userId , questionId , 'coding' , 'code_editor' , passedCount , visibleTestCases . length , questionDifficulty , languageName ) ;
184298 } catch ( err ) {
185299 console . warn ( 'Could not mark question solved on alreadyCompleted path:' , err . message ) ;
186300 }
@@ -192,7 +306,7 @@ export const submitSolutionService = async ({
192306 }
193307
194308 // Step 7: First-time completion - award rewards
195- const rewardConfig = getRewardConfig ( "coding" , question . difficulty ) ;
309+ const rewardConfig = getRewardConfig ( "coding" , questionDifficulty ) ;
196310 const earnedXP = rewardConfig . xp || 25 ;
197311 const earnedTokens = rewardConfig . tokens || 10 ;
198312
0 commit comments