The Reading Comprehension module implements a modular three-layer architecture supporting 10 distinct question types aligned with HKDSE English Paper 2 standards. Built on Next.js + React + TypeScript with Redux state management and Ant Design UI components.
QuestionPanel manages mode switching (Guide/Exam), Part navigation with locking mechanisms, checkpoint scoring via selectCurrentPartGainedScore, and forced submission logic for exam timeouts.
QuestionContainer implements factory pattern dynamically rendering components based on question.type. Normalizes answer data across formats via mapPointsToCorrectResult.
10 specialized components: Classification, DragAndDrop, MCQ, TextInput, TrueOrFalse, FillInTheBlanks, DragTheWords, InteractiveWordBuilder, ReferentMatching, TimelineMatching, TableCompletion.
{ practiceId, points, userAnswers }EXAM_DURATION_MINUTES = 90)selectCurrentPartTotalScore, selectCurrentPartGainedScore, selectContentTranslationLocaleDynamic form rendering based on levelForm.json. Multi-select with multiSelectableMaximum enforcement. Redux state persistence via appStudentPlatformActions.setState.
The assessment is embedded via iframe: {origin}/english-assessment/form/{selectedLevel}/{selectedFormId}.html. Authentication tokens are passed as URL parameters using btoa(token) for Base64 encoding. Cross-origin communication uses window.postMessage API. The payload structure: { selectedLevelId, selectedFormId, formData }. Strict origin checking prevents XSS injection attacks.
useBreakpoints hook for device detection. Background image swapping: imgBubble for desktop, imgBubbleMobile for mobile. Mascot height adjusts from 220px to 200px on mobile. Text scales from 20px to 16px. Touch targets minimum 44px for young learners on tablets.
availableAnswers preventing duplicates#3695E5 selected, #26A347 correct, #F26E6E incorrectisCorrect calculationForm.useWatch real-time validationallowMultipleItemsPerStage for grouping.inputId field mapping for sparse tables.Record<string, { answer: any; isCorrect: boolean }>practiceMode === practiceModes.exam.valueEXAM_DURATION_MS = 90 * 60 * 1000)forceSubmit effect on timeoutdisableArticleHints = truepracticeMode === practiceModes.guide.valueallowPartGroupSwitch = truereportActivityLog calls on every interaction: modeSelectionExam, modeSelectionGuide, modeSelectionExittotalTimeOptions aggregates timeSec across passage structuregetPartsForInstructions(passageData) traverses passage structure to identify parts and partGroups. Time aggregation sums timeSec across parts. QuestionTypeClassifier maps types to instructional text: MCQ โ "Select the best answer", TextInput โ "Write your answer", TFNG โ "Indicate TRUE, FALSE, or NOT GIVEN". Collapsible via examInstructionsCollapsed Redux state.
id="p{n}"), hint buttonssplitIntoSentences() for hover-enabled analysissplitIntoTokens() for clickable wordsReact.memo, useMemo, event delegationfontSizeOptions constants with immediate visual feedbackparagraphsPerPage dynamic calculationaria-label attributes, keyboard navigationAutomatic calculation of which paragraphs each question references. Display format: "Refer to paragraphs 2-4". parseParagraphId(element: HTMLElement): number extracts paragraph number from element IDs. Checkpoint branding displays question numbers as gamified checkpoints. getActualPart(passageData, partId) retrieves current part data. getQuestionsForPart(part) counts questions within each part.
aria-label on interactive elementsonKeyDown handlers for Enter/Space keysoutline: 3px solid var(--acc)@media (prefers-reduced-motion) supportparseParagraphId(element) extracts paragraph number from element or closest parent with ID pattern p{n}. splitIntoSentences(text) uses regex for sentence boundary detection. splitIntoTokens(text) returns { type: 'word' | 'punct' | 'space', value: string }[]. All parsing is memoized to prevent unnecessary recalculation.
Multi-modal hint system providing just-in-time scaffolding. Opens on word/paragraph click via setPassageDeconstructionDialog Redux action.
getI18nValue(content: MapObject, locale: string) handles multilingual AI responses. Fallback chain: contentTranslationLocale โ zh-HK โ zh-CN โ en. API via useCallGetArticleHint() hook with { hintType, paragraphId, selectedText, locale } parameters. Loading state uses Spin component with size="large". Error handling shows retry button.
PROFICIENT (green) vs EMERGING (red)SCORE_RATIO_EXCELLENT = 0.7, SCORE_RATIO_POOR = 0.4areAllTopLevelPartsCompleted()fontSizeChange โ struggling with text densitypageSelect โ reading speed patternsparagraphsPerPage โ comprehension confidencequestionSubmit โ submission frequencyquestionFooterNext โ progression flowquestionFooterSkip โ AI Coach avoidancehintButton โ engagement signalsreportActivityLog({ module: 'readingComprehension.practice', entity: { paperId, partId, questionId, hintType }, action: 'click', element: 'modeSelectionExam' })
Enriched with timestamp, sessionId, userId. Sent to /api/activity-log endpoint via POST. Supports adaptive recommendations based on hint usage frequency, time per paragraph, and feedback expansion patterns.
Each log includes paperId, partId, userPartId, and questionId. This enables contextual error analysis: which specific question types, paragraphs, or difficulty levels trigger the most help-seeking behavior. Privacy: anonymized before storage, opt-out available, aggregated for teacher dashboards.
scoreRatio = correctCount / totalItems
Returns ApiAnswerResult.PartialCorrect when 0 < correctCount < totalItems.
Example: 5-item T/F question, 3 correct โ 60% โ PartialCorrect
getArticleForPartuseCallGetQuestionFeedback API hookMapObject feedback data for i18n localization via contentTranslationLocaleAll question types normalize to Record<string, { answer: any; isCorrect: boolean }>. This enables: AI evaluation pipeline for semantic correctness, cross-question analytics identifying struggling types, Vocabulary Trainer interventions based on specific weaknesses, and Dashboard progress tracking with granular metrics.
IconResultMastery
Gold trophy icon. Applied when scoreRatio โฅ SCORE_RATIO_EXCELLENT. Shows in PartResultDialog success theme.
IconResultProgress
Blue rocket icon. Applied when SCORE_RATIO_POOR โค scoreRatio < SCORE_RATIO_EXCELLENT. Progress theme.
IconResultFoundation
Orange target icon. Applied when scoreRatio < SCORE_RATIO_POOR. Encouraging message, not failure.
#1296db โ #81e8ff โ #58d2adactivePaperSessionId enables session resumption on browser closeAnswerStatus enum: NotStarted, InProgress, CompletedAssessment results propagate to all modules: Vocabulary System determines word list difficulty, Course Adventure routing uses recommendedLevel for entry points, Conversation Role Play calibrates scenario difficulty, Reading Comprehension determines Guided vs Exam mode. Pre-authentication personalization reads localStorage for session continuity โ blue detective theme from previous sessions.
Listen/Read: PassageContent with pagination, typography controls, paragraph referencing
Capture: 10 question types โ Classification, MCQ, TextInput, TrueOrFalse, FillInTheBlanks, DragTheWords, InteractiveWordBuilder, ReferentMatching, TimelineMatching, TableCompletion
Review: Immediate feedback with color-coded answers, PartResultDialog analytics, MentorFeedback AI analysis
Master: Activity logging โ Dashboard โ Vocabulary Builder โ Course Adventure progression
@apply directives, responsive via useBreakpointszh-HK / zh-CN / en locale supportReact.memo, useMemo, event delegation, code-splittingreportActivityLog capturing reading behavior, attempt patterns, help-seekingpostMessage validationSame Codebase โ Dual Pedagogical Experiences โ Maximum Platform Value
From onboarding through assessment through practice to mastery โ one integrated system.