55 eq ,
66 getTableColumns ,
77 inArray ,
8+ InferSelectModel ,
89 isNull ,
910 or ,
1011 sql ,
@@ -86,8 +87,17 @@ type Params = {
8687 difficulty ?: string ;
8788} ;
8889
90+ type IGetRandomQuestionResponse = InferSelectModel < typeof QUESTIONS_TABLE > & {
91+ attemptCount : number ;
92+ } ;
93+
8994// Fetch an unattempted question or fallback to the least attempted one
90- export const getRandomQuestion = async ( { userId1, userId2, topics, difficulty } : Params ) => {
95+ export const getRandomQuestion = async ( {
96+ userId1,
97+ userId2,
98+ topics,
99+ difficulty,
100+ } : Params ) : Promise < IGetRandomQuestionResponse | null > => {
91101 // If an attempt contains either user's ID
92102 const ids = [ userId1 , userId2 ] ;
93103 const userIdClause = [
@@ -128,14 +138,15 @@ export const getRandomQuestion = async ({ userId1, userId2, topics, difficulty }
128138 }
129139
130140 for ( const filterClause of filterCombinations ) {
131- // Check if questions exist with current filters
132- const questionExists = await db
133- . select ( { count : sql < number > `count(*)` } )
141+ // Check if AT LEAST 1 question exists with current filters
142+ const questionCounts = await db
143+ . select ( { id : QUESTIONS_TABLE . id } )
134144 . from ( QUESTIONS_TABLE )
135145 . where ( and ( ...filterClause ) )
136- . then ( ( result ) => Number ( result [ 0 ] . count ) > 0 ) ;
146+ . limit ( 1 ) ;
137147
138- if ( ! questionExists ) {
148+ // No questions exist with the filter.
149+ if ( ! questionCounts || ! questionCounts . length ) {
139150 continue ;
140151 }
141152
@@ -149,28 +160,33 @@ export const getRandomQuestion = async ({ userId1, userId2, topics, difficulty }
149160 . limit ( 1 ) ;
150161
151162 if ( bothUnattempted && bothUnattempted . length > 0 ) {
152- return bothUnattempted [ 0 ] . question ;
163+ return { ... bothUnattempted [ 0 ] . question , attemptCount : 0 } ;
153164 }
154165
155166 // If no unattempted question, try least attempted
156- const attempts = db . $with ( 'at' ) . as (
157- db
158- . select ( {
159- ...getTableColumns ( QUESTIONS_TABLE ) ,
160- user1Count :
161- sql `SUM(CASE WHEN ${ QUESTION_ATTEMPTS_TABLE . userId1 } = ${ userId1 } ::uuid OR ${ QUESTION_ATTEMPTS_TABLE . userId2 } = ${ userId1 } ::uuid THEN 1 END)` . as (
162- 'user1_attempts'
163- ) ,
164- user2Count :
165- sql `SUM(CASE WHEN ${ QUESTION_ATTEMPTS_TABLE . userId1 } = ${ userId2 } ::uuid OR ${ QUESTION_ATTEMPTS_TABLE . userId2 } = ${ userId2 } ::uuid THEN 1 END)` . as (
166- 'user2_attempts'
167- ) ,
168- } )
169- . from ( QUESTIONS_TABLE )
170- . innerJoin ( QUESTION_ATTEMPTS_TABLE , and ( ...joinClause ) )
171- . where ( and ( ...filterClause ) )
172- . groupBy ( QUESTIONS_TABLE . id )
173- ) ;
167+ let nestedQuery = db
168+ . select ( {
169+ ...getTableColumns ( QUESTIONS_TABLE ) ,
170+ user1Count :
171+ sql `SUM(CASE WHEN ${ QUESTION_ATTEMPTS_TABLE . userId1 } = ${ userId1 } ::uuid OR ${ QUESTION_ATTEMPTS_TABLE . userId2 } = ${ userId1 } ::uuid THEN 1 END)` . as (
172+ 'user1_attempts'
173+ ) ,
174+ user2Count :
175+ sql `SUM(CASE WHEN ${ QUESTION_ATTEMPTS_TABLE . userId1 } = ${ userId2 } ::uuid OR ${ QUESTION_ATTEMPTS_TABLE . userId2 } = ${ userId2 } ::uuid THEN 1 END)` . as (
176+ 'user2_attempts'
177+ ) ,
178+ } )
179+ . from ( QUESTIONS_TABLE )
180+ . innerJoin ( QUESTION_ATTEMPTS_TABLE , and ( ...joinClause ) )
181+ . $dynamic ( ) ;
182+
183+ if ( filterClause . length ) {
184+ nestedQuery = nestedQuery . where ( and ( ...filterClause ) ) ;
185+ }
186+
187+ nestedQuery = nestedQuery . groupBy ( QUESTIONS_TABLE . id ) ;
188+
189+ const attempts = db . $with ( 'at' ) . as ( nestedQuery ) ;
174190
175191 const result = await db
176192 . with ( attempts )
@@ -180,7 +196,10 @@ export const getRandomQuestion = async ({ userId1, userId2, topics, difficulty }
180196 . limit ( 1 ) ;
181197
182198 if ( result && result . length > 0 ) {
183- return { ...result [ 0 ] , user1Count : undefined , user2Count : undefined } ;
199+ const { user1Count, user2Count, ...details } = result [ 0 ] ;
200+ const attemptCount =
201+ ( user1Count ? ( user1Count as number ) : 0 ) + ( user2Count ? ( user2Count as number ) : 0 ) ;
202+ return { ...details , attemptCount } ;
184203 }
185204 }
186205
0 commit comments