Exam Training Mini Program Case
This case showcases a comprehensive exam training mini program that provides targeted preparation for various standardized tests and professional certifications through adaptive practice, mock exams, and personalized study plans.
Project Overview
Project Background
With increasing competition in education and professional development, students and professionals need effective exam preparation tools. This mini program addresses the need for accessible, comprehensive exam training that adapts to individual learning patterns and weak areas.
Core Features
- Adaptive Practice: AI-powered question selection based on performance
- Mock Exams: Full-length practice tests with realistic timing
- Performance Analytics: Detailed analysis of strengths and weaknesses
- Study Plans: Personalized preparation schedules
- Question Bank: Extensive database of practice questions
- Video Explanations: Expert explanations for difficult concepts
- Progress Tracking: Monitor improvement over time
Technical Implementation
Adaptive Question Selection
javascript
// utils/adaptive-engine.js
class AdaptiveEngine {
static async getNextQuestion(userId, examType, currentPerformance) {
try {
const res = await wx.request({
url: '/api/adaptive/next-question',
method: 'POST',
data: {
userId,
examType,
performance: currentPerformance,
weakAreas: await this.getWeakAreas(userId, examType)
}
})
return res.data.question
} catch (error) {
console.error('Failed to get next question:', error)
return null
}
}
static async updatePerformance(userId, questionId, isCorrect, timeSpent) {
try {
const res = await wx.request({
url: '/api/adaptive/performance',
method: 'POST',
data: {
userId,
questionId,
isCorrect,
timeSpent,
timestamp: Date.now()
}
})
return res.data
} catch (error) {
console.error('Failed to update performance:', error)
}
}
static async getWeakAreas(userId, examType) {
try {
const res = await wx.request({
url: `/api/adaptive/weak-areas/${userId}/${examType}`,
method: 'GET'
})
return res.data.weakAreas
} catch (error) {
console.error('Failed to get weak areas:', error)
return []
}
}
}
export default AdaptiveEngine
Mock Exam System
javascript
// pages/mock-exam/mock-exam.js
Page({
data: {
exam: null,
currentQuestion: 0,
answers: {},
timeLeft: 0,
isSubmitted: false,
showReview: false
},
onLoad(options) {
this.examId = options.examId
this.loadMockExam()
},
async loadMockExam() {
try {
const res = await wx.request({
url: `/api/mock-exams/${this.examId}`,
method: 'GET'
})
const exam = res.data
this.setData({
exam,
timeLeft: exam.duration * 60 // Convert minutes to seconds
})
this.startTimer()
} catch (error) {
console.error('Failed to load mock exam:', error)
}
},
startTimer() {
this.timer = setInterval(() => {
const timeLeft = this.data.timeLeft - 1
this.setData({ timeLeft })
if (timeLeft <= 0) {
this.autoSubmitExam()
}
// Auto-save answers every 30 seconds
if (timeLeft % 30 === 0) {
this.autoSaveAnswers()
}
}, 1000)
},
onAnswerSelect(e) {
const { questionIndex, optionIndex } = e.currentTarget.dataset
const answers = { ...this.data.answers }
answers[questionIndex] = optionIndex
this.setData({ answers })
},
async autoSaveAnswers() {
try {
await wx.request({
url: `/api/mock-exams/${this.examId}/save`,
method: 'POST',
data: {
userId: wx.getStorageSync('userId'),
answers: this.data.answers,
currentQuestion: this.data.currentQuestion,
timeLeft: this.data.timeLeft
}
})
} catch (error) {
console.error('Failed to auto-save answers:', error)
}
},
async submitExam() {
if (this.data.isSubmitted) return
try {
wx.showLoading({ title: 'Submitting...' })
const res = await wx.request({
url: `/api/mock-exams/${this.examId}/submit`,
method: 'POST',
data: {
userId: wx.getStorageSync('userId'),
answers: this.data.answers,
timeSpent: (this.data.exam.duration * 60) - this.data.timeLeft
}
})
this.setData({
isSubmitted: true,
examResult: res.data
})
this.stopTimer()
this.showExamResults(res.data)
} catch (error) {
console.error('Failed to submit exam:', error)
wx.showToast({
title: 'Submission failed',
icon: 'error'
})
} finally {
wx.hideLoading()
}
},
showExamResults(result) {
const percentage = Math.round((result.score / this.data.exam.questions.length) * 100)
wx.showModal({
title: `Exam Complete - ${percentage}%`,
content: `Score: ${result.score}/${this.data.exam.questions.length}\nTime: ${this.formatTime(result.timeSpent)}`,
confirmText: 'View Analysis',
cancelText: 'Retake',
success: (res) => {
if (res.confirm) {
this.showDetailedAnalysis(result)
} else {
this.retakeExam()
}
}
})
},
showDetailedAnalysis(result) {
wx.navigateTo({
url: `/pages/exam-analysis/exam-analysis?resultId=${result.id}`
})
},
retakeExam() {
this.setData({
currentQuestion: 0,
answers: {},
timeLeft: this.data.exam.duration * 60,
isSubmitted: false
})
this.startTimer()
},
stopTimer() {
if (this.timer) {
clearInterval(this.timer)
}
},
formatTime(seconds) {
const hours = Math.floor(seconds / 3600)
const minutes = Math.floor((seconds % 3600) / 60)
const remainingSeconds = seconds % 60
if (hours > 0) {
return `${hours}:${minutes.toString().padStart(2, '0')}:${remainingSeconds.toString().padStart(2, '0')}`
}
return `${minutes}:${remainingSeconds.toString().padStart(2, '0')}`
}
})
Performance Analytics
javascript
// utils/analytics.js
class PerformanceAnalytics {
static async generateReport(userId, examType, timeRange = '30d') {
try {
const res = await wx.request({
url: `/api/analytics/report/${userId}`,
method: 'GET',
data: {
examType,
timeRange
}
})
return res.data
} catch (error) {
console.error('Failed to generate report:', error)
return null
}
}
static async getProgressTrend(userId, examType) {
try {
const res = await wx.request({
url: `/api/analytics/progress/${userId}/${examType}`,
method: 'GET'
})
return res.data.trend
} catch (error) {
console.error('Failed to get progress trend:', error)
return []
}
}
static async getSubjectBreakdown(userId, examType) {
try {
const res = await wx.request({
url: `/api/analytics/subjects/${userId}/${examType}`,
method: 'GET'
})
return res.data.breakdown
} catch (error) {
console.error('Failed to get subject breakdown:', error)
return []
}
}
static async getPredictedScore(userId, examType) {
try {
const res = await wx.request({
url: `/api/analytics/prediction/${userId}/${examType}`,
method: 'GET'
})
return res.data.prediction
} catch (error) {
console.error('Failed to get predicted score:', error)
return null
}
}
static async getStudyRecommendations(userId, examType) {
try {
const res = await wx.request({
url: `/api/analytics/recommendations/${userId}/${examType}`,
method: 'GET'
})
return res.data.recommendations
} catch (error) {
console.error('Failed to get recommendations:', error)
return []
}
}
}
export default PerformanceAnalytics
Study Plan Generator
javascript
// utils/study-planner.js
class StudyPlanner {
static async generateStudyPlan(userId, examType, targetDate, currentLevel) {
try {
const res = await wx.request({
url: '/api/study-plan/generate',
method: 'POST',
data: {
userId,
examType,
targetDate,
currentLevel,
availableHours: await this.getAvailableStudyHours(userId)
}
})
return res.data.studyPlan
} catch (error) {
console.error('Failed to generate study plan:', error)
return null
}
}
static async getAvailableStudyHours(userId) {
try {
const res = await wx.request({
url: `/api/users/${userId}/study-schedule`,
method: 'GET'
})
return res.data.availableHours
} catch (error) {
console.error('Failed to get available study hours:', error)
return 2 // Default 2 hours per day
}
}
static async updateStudyProgress(userId, planId, taskId, completed) {
try {
const res = await wx.request({
url: `/api/study-plan/${planId}/progress`,
method: 'POST',
data: {
userId,
taskId,
completed,
timestamp: Date.now()
}
})
if (res.data.planUpdated) {
this.notifyPlanUpdate(res.data.updates)
}
return res.data
} catch (error) {
console.error('Failed to update study progress:', error)
}
}
static notifyPlanUpdate(updates) {
if (updates.length > 0) {
wx.showModal({
title: 'Study Plan Updated',
content: 'Your study plan has been adjusted based on your progress.',
showCancel: false,
confirmText: 'View Changes'
})
}
}
static async getStudyReminders(userId) {
try {
const res = await wx.request({
url: `/api/study-plan/reminders/${userId}`,
method: 'GET'
})
return res.data.reminders
} catch (error) {
console.error('Failed to get study reminders:', error)
return []
}
}
static async scheduleStudyReminder(userId, planId, reminderTime) {
try {
const res = await wx.request({
url: '/api/study-plan/reminder',
method: 'POST',
data: {
userId,
planId,
reminderTime
}
})
if (res.data.success) {
wx.showToast({
title: 'Reminder set',
icon: 'success'
})
}
return res.data
} catch (error) {
console.error('Failed to schedule reminder:', error)
}
}
}
export default StudyPlanner
Question Bank Management
javascript
// utils/question-bank.js
class QuestionBank {
static async getQuestionsByTopic(examType, topic, difficulty, limit = 20) {
try {
const res = await wx.request({
url: '/api/questions/by-topic',
method: 'GET',
data: {
examType,
topic,
difficulty,
limit
}
})
return res.data.questions
} catch (error) {
console.error('Failed to get questions by topic:', error)
return []
}
}
static async searchQuestions(examType, keyword, filters = {}) {
try {
const res = await wx.request({
url: '/api/questions/search',
method: 'GET',
data: {
examType,
keyword,
...filters
}
})
return res.data.questions
} catch (error) {
console.error('Failed to search questions:', error)
return []
}
}
static async getQuestionExplanation(questionId) {
try {
const res = await wx.request({
url: `/api/questions/${questionId}/explanation`,
method: 'GET'
})
return res.data.explanation
} catch (error) {
console.error('Failed to get question explanation:', error)
return null
}
}
static async reportQuestion(questionId, reason, description) {
try {
const res = await wx.request({
url: `/api/questions/${questionId}/report`,
method: 'POST',
data: {
reason,
description,
userId: wx.getStorageSync('userId')
}
})
if (res.data.success) {
wx.showToast({
title: 'Report submitted',
icon: 'success'
})
}
return res.data
} catch (error) {
console.error('Failed to report question:', error)
}
}
static async favoriteQuestion(questionId) {
try {
const res = await wx.request({
url: `/api/questions/${questionId}/favorite`,
method: 'POST',
data: {
userId: wx.getStorageSync('userId')
}
})
return res.data
} catch (error) {
console.error('Failed to favorite question:', error)
}
}
static async getFavoriteQuestions(userId, examType) {
try {
const res = await wx.request({
url: `/api/users/${userId}/favorite-questions`,
method: 'GET',
data: { examType }
})
return res.data.questions
} catch (error) {
console.error('Failed to get favorite questions:', error)
return []
}
}
}
export default QuestionBank
Project Results
Key Metrics
- Pass Rate Improvement: 85% of users improved their practice scores by 20+ points
- User Engagement: 78% daily active user retention
- Completion Rate: 72% study plan completion rate
- User Satisfaction: 4.8/5.0 average rating
Business Impact
- User Growth: 250% increase in registered users
- Revenue Growth: 180% increase in premium subscriptions
- Market Expansion: Covers 20+ different exam types
- Educational Impact: Over 100,000 users passed their target exams
This exam training mini program successfully demonstrates how adaptive learning and comprehensive analytics can significantly improve exam preparation effectiveness and user success rates.