@@ -170,35 +170,47 @@ export const countEdges = (
170170 edgeOutcomeCounts : { [ p : string ] : { [ p : string ] : number } } ;
171171 maxEdgeCount : number ;
172172 ratioEdges : { [ p : string ] : number } ;
173- edgeCounts : { [ p : string ] : number } ;
173+ edgeCounts : { [ key : string ] : number } ;
174174 topSequences : SequenceCount [ ] ;
175175} => {
176176 const totalNodeEdges : { [ key : string ] : number } = { } ;
177177 const edgeOutcomeCounts : { [ key : string ] : { [ outcome : string ] : number } } = { } ;
178178 let maxEdgeCount = 0 ;
179179 const ratioEdges : { [ key : string ] : number } = { } ;
180180 const edgeCounts : { [ key : string ] : number } = { } ;
181+ const studentEdgeCounts : { [ key : string ] : Set < string > } = { } ; // Track unique students per edge
181182 const top5Sequences = getTopSequences ( stepSequences , 5 ) ;
182183
183- // Iterate over first-level keys (e.g., student ID, problem, etc. )
184+ // Iterate over first-level keys (student IDs )
184185 Object . keys ( stepSequences ) . forEach ( ( studentId ) => {
185- const innerStepSequences = stepSequences [ studentId ] ; // { [key: string]: string[] }
186- const innerOutcomeSequences = outcomeSequences [ studentId ] || { } ; // Handle missing outcome sequences
186+ const innerStepSequences = stepSequences [ studentId ] ;
187+ const innerOutcomeSequences = outcomeSequences [ studentId ] || { } ;
187188
188- // Iterate over second-level keys (actual step sequences )
189+ // Iterate over second-level keys (problem names )
189190 Object . keys ( innerStepSequences ) . forEach ( ( problemName ) => {
190- const steps = innerStepSequences [ problemName ] ; // string[]
191- const outcomes = innerOutcomeSequences [ problemName ] || [ ] ; // string[] (fallback to empty array)
191+ const steps = innerStepSequences [ problemName ] ;
192+ const outcomes = innerOutcomeSequences [ problemName ] || [ ] ;
192193
193- if ( steps . length < 2 ) return ; // Ignore sequences with < 2 steps
194+ if ( steps . length < 2 ) return ;
194195
195196 for ( let i = 0 ; i < steps . length - 1 ; i ++ ) {
196197 const currentStep = steps [ i ] ;
197198 const nextStep = steps [ i + 1 ] ;
198199 const outcome = outcomes [ i + 1 ] ;
199200
200201 const edgeKey = `${ currentStep } ->${ nextStep } ` ;
201- edgeCounts [ edgeKey ] = ( edgeCounts [ edgeKey ] || 0 ) + 1 ;
202+
203+ // Initialize the Set for this edge if it doesn't exist
204+ if ( ! studentEdgeCounts [ edgeKey ] ) {
205+ studentEdgeCounts [ edgeKey ] = new Set ( ) ;
206+ }
207+
208+ // Add this student to the Set for this edge
209+ studentEdgeCounts [ edgeKey ] . add ( studentId ) ;
210+
211+ // Update edge counts based on unique students
212+ edgeCounts [ edgeKey ] = studentEdgeCounts [ edgeKey ] . size ;
213+
202214 edgeOutcomeCounts [ edgeKey ] = edgeOutcomeCounts [ edgeKey ] || { } ;
203215 edgeOutcomeCounts [ edgeKey ] [ outcome ] = ( edgeOutcomeCounts [ edgeKey ] [ outcome ] || 0 ) + 1 ;
204216 totalNodeEdges [ currentStep ] = ( totalNodeEdges [ currentStep ] || 0 ) + 1 ;
@@ -213,7 +225,7 @@ export const countEdges = (
213225 // Compute ratioEdges based on totalNodeEdges
214226 Object . keys ( edgeCounts ) . forEach ( ( edge ) => {
215227 const [ start ] = edge . split ( '->' ) ;
216- ratioEdges [ edge ] = edgeCounts [ edge ] / ( totalNodeEdges [ start ] || 1 ) ; // Avoid division by zero
228+ ratioEdges [ edge ] = edgeCounts [ edge ] / ( totalNodeEdges [ start ] || 1 ) ;
217229 } ) ;
218230
219231 return {
@@ -377,8 +389,8 @@ function calculateEdgeColors(outcomes: { [outcome: string]: number }): string {
377389
378390 if ( edgeCount > min_visits ) {
379391 const tooltip = `${ currentStep } to ${ nextStep } \n`
380- + `- Edge Count : \n\t\t ${ edgeCount } \n`
381- + `- Total Count for ${ currentStep } : \n\t\t${ totalCount } \n`
392+ + `- Unique Students : \n\t\t ${ edgeCount } \n`
393+ + `- Total Students at ${ currentStep } : \n\t\t${ totalNodeEdges [ currentStep ] || 0 } \n`
382394 + `- Ratio: \n\t\t${ ( ( ratioEdges [ edgeKey ] || 0 ) * 100 ) . toFixed ( 2 ) } % of students at ${ currentStep } go to ${ nextStep } \n`
383395 + `- Outcomes: \n\t\t ${ Object . entries ( outcomes ) . map ( ( [ outcome , count ] ) => `${ outcome } : ${ count } ` ) . join ( '\n\t\t ' ) } \n`
384396 + `- Color Codes: \n\t\t Hex: ${ color } ` ;
@@ -411,8 +423,8 @@ function calculateEdgeColors(outcomes: { [outcome: string]: number }): string {
411423
412424 if ( edgeCount > min_visits ) {
413425 const tooltip = `${ currentStep } to ${ nextStep } \n`
414- + `- Edge Count : \n\t\t ${ edgeCount } \n`
415- + `- Total Count for ${ currentStep } : \n\t\t${ totalCount } \n`
426+ + `- Unique Students : \n\t\t ${ edgeCount } \n`
427+ + `- Total Students at ${ currentStep } : \n\t\t${ totalNodeEdges [ currentStep ] || 0 } \n`
416428 + `- Ratio: \n\t\t${ ( ( ratioEdges [ edge ] || 0 ) * 100 ) . toFixed ( 2 ) } % of students at ${ currentStep } go to ${ nextStep } \n`
417429 + `- Outcomes: \n\t\t ${ outcomesStr } \n`
418430 + `- Color Codes: \n\t\t Hex: ${ color } \n\t\t RGB: ${ [ parseInt ( color . substring ( 1 , 3 ) , 16 ) , parseInt ( color . substring ( 3 , 5 ) , 16 ) , parseInt ( color . substring ( 5 , 7 ) , 16 ) ] } ` ;
0 commit comments