An intelligent quiz platform with adaptive difficulty, real-time leaderboards, and comprehensive performance tracking.
- Adaptive Difficulty Algorithm: Questions dynamically adjust based on user performance
- Real-time Score Updates: Instant feedback and score calculation after each answer
- Streak System: Track consecutive correct answers with streak decay after 24 hours
- Dual Leaderboards: Compete on both total score and maximum streak
- Performance Analytics: Detailed metrics including accuracy, difficulty distribution, and recent performance
- Idempotent Answer Submission: Prevents duplicate score updates
- Redis Caching: Fast access to user state, question pools, and leaderboards
- Rate Limiting: Protection against abuse
- JWT Authentication: Secure user sessions
- Responsive Design: Works seamlessly on desktop and mobile
- Dark Mode: Full light/dark theme support
- Design System: Reusable component library with design tokens
- Node.js + Express.js: RESTful API server
- MongoDB: Primary database for users, questions, and game state
- Redis: Caching layer for performance optimization
- JWT: Authentication and authorization
- bcryptjs: Password hashing
- React 18: UI framework
- Vite: Build tool and dev server
- React Router: Client-side routing
- Axios: HTTP client
- Tailwind CSS: Utility-first styling
- Lucide React: Icon library
- Docker + Docker Compose: Containerization
- ESLint + Prettier: Code quality
- Docker Desktop (includes Docker Compose)
- Node.js 18+ (for local development)
docker-compose up --buildThis command will:
- Build and start MongoDB
- Build and start Redis
- Build and start the backend API (port 5000)
- Build and start the frontend app (port 3000)
- Frontend: http://localhost:3000
- Backend API: http://localhost:5000
- Health Check: http://localhost:5000/health
docker-compose exec backend npm run seedThis will populate the database with 30 questions across difficulty levels 1-10.
.
├── backend/
│ ├── config/ # Database and Redis configuration
│ ├── controllers/ # Request handlers
│ ├── middleware/ # Auth, rate limiting
│ ├── models/ # MongoDB schemas
│ ├── routes/ # API routes
│ ├── services/ # Business logic (adaptive, cache)
│ ├── scripts/ # Seed data script
│ └── server.js # Entry point
├── frontend/
│ ├── src/
│ │ ├── components/ # Reusable UI components
│ │ │ ├── ui/ # Design system components
│ │ │ ├── layout/ # Layout components
│ │ │ └── auth/ # Auth components
│ │ ├── contexts/ # React contexts (Auth, Theme)
│ │ ├── pages/ # Route pages
│ │ ├── App.jsx # App component
│ │ └── main.jsx # Entry point
│ └── index.html
└── docker-compose.yml # Container orchestration
- Create a new account or login with existing credentials
- JWT token is stored in localStorage for session management
- View your current stats: difficulty level, streak, score, accuracy
- See performance trends and difficulty distribution
- Quick access to start a quiz
- Answer questions that adapt to your skill level
- Get instant feedback on correctness
- See real-time updates to score, streak, and difficulty
- Questions get harder as you answer correctly, easier if you struggle
- View top players by score or streak
- See your current rank
- Real-time updates after each answer
- View detailed statistics
- Track achievements and badges
- Monitor accuracy and progress over time
- Correct Answer:
- Streak ≥ 3: +2 difficulty
- Streak ≥ 1: +1 difficulty
- Wrong Answer:
- -1 to -2 difficulty based on recent performance
- Range: 1-10 (clamped)
baseScore = difficulty × 10
streakMultiplier = 1 + (streak × 0.1)
difficultyBonus = difficulty × 5
finalScore = (baseScore + difficultyBonus) × streakMultiplier- Increments on correct answers
- Resets to 0 on wrong answers
- Decays after 24 hours of inactivity
- Max streak tracked separately
POST /api/v1/auth/register- Register new userPOST /api/v1/auth/login- Login userGET /api/v1/auth/profile- Get user profile (protected)
GET /api/v1/quiz/next- Get next question (protected)POST /api/v1/quiz/answer- Submit answer (protected, idempotent)GET /api/v1/quiz/metrics- Get user metrics (protected)
GET /api/v1/leaderboard/score- Get score leaderboard (protected)GET /api/v1/leaderboard/streak- Get streak leaderboard (protected)
- Primary: Blue shades (main actions, links)
- Secondary: Purple shades (accents)
- Success: Green shades (correct answers, positive feedback)
- Error: Red shades (wrong answers, errors)
- Warning: Yellow/Orange shades (streaks, alerts)
- Button: Multiple variants (primary, secondary, outline, ghost)
- Card: Composable with Header, Body, Footer
- Input: Form inputs with labels and error states
- Badge: Status indicators
- Progress: Progress bars with labels
- sm: 640px
- md: 768px
- lg: 1024px
- xl: 1280px
- Password hashing with bcrypt
- JWT token authentication
- Rate limiting on all API endpoints
- Stricter limits on auth endpoints
- CORS enabled
- Environment variable configuration
{
username: String (unique),
email: String (unique),
password: String (hashed),
createdAt: Date
}{
difficulty: Number (1-10),
prompt: String,
choices: [String],
correctAnswerHash: String (SHA-256),
tags: [String]
}{
userId: ObjectId,
currentDifficulty: Number (1-10),
streak: Number,
maxStreak: Number,
totalScore: Number,
lastQuestionId: ObjectId,
lastAnswerAt: Date,
stateVersion: Number,
totalAnswered: Number,
correctAnswers: Number
}{
userId: ObjectId,
questionId: ObjectId,
difficulty: Number,
answer: String,
correct: Boolean,
scoreDelta: Number,
streakAtAnswer: Number,
answeredAt: Date,
answerIdempotencyKey: String (unique)
}- Idempotency: Duplicate answer submissions return cached results
- Streak Decay: Automatic reset after 24 hours of inactivity
- State Version Mismatch: Prevents race conditions in concurrent requests
- Question Pool Exhaustion: Falls back to any available question
- Difficulty Boundaries: Clamped between 1-10
- Negative Scores: Prevented (minimum 0)
- Cache Invalidation: Automatic on state changes
- Register multiple users
- Answer questions correctly/incorrectly
- Verify difficulty adjustments
- Check leaderboard updates
- Test streak decay (modify lastAnswerAt)
- Verify idempotency with duplicate requests
cd backend
npm install
npm run devcd frontend
npm install
npm run devBackend .env:
PORT=5000
MONGODB_URI=mongodb://localhost:27017/adaptive-quiz
REDIS_HOST=localhost
REDIS_PORT=6379
JWT_SECRET=your-secret-key
JWT_EXPIRES_IN=7d
NODE_ENV=development
- Calculate score deltas based on difficulty and streak
- Adjust difficulty based on performance
- Handle streak decay logic
- Provide performance metrics
- Manage Redis operations
- Cache user state, question pools, leaderboards
- Handle cache invalidation strategies
- Define TTL policies
- Handle HTTP requests/responses
- Validate input
- Call services
- Format responses
Keys:
user_state:{userId}- TTL: 300squestion_pool:{difficulty}- TTL: 3600sleaderboard:{type}- TTL: 60s
Invalidation:
- User state: On answer submission
- Leaderboards: On score/streak changes
- Question pools: Manual/time-based
UserState: userId, totalScore (desc), maxStreak (desc)Question: difficultyAnswerLog: userId + answeredAt (desc), answerIdempotencyKey
✅ Frontend (25%)
- Modern React SPA with Vite
- Reusable component library
- Design system with tokens
- Responsive + dark mode
- Lazy loading ready
- Clean architecture
✅ LLD Rigour (25%)
- Clear module responsibilities
- API schemas documented
- DB schema with indexes
- Cache strategy defined
- Pseudocode in services
✅ Functional Requirements (25%)
- Adaptive difficulty ✓
- Real-time updates ✓
- Leaderboards ✓
- Score/streak tracking ✓
- Metrics dashboard ✓
✅ Edge Cases (15%)
- Idempotency ✓
- Streak decay ✓
- State versioning ✓
- Boundary conditions ✓
✅ Operational Concerns (10%)
- Strong consistency ✓
- Rate limiting ✓
- Caching ✓
- Stateless servers ✓
- Docker deployment ✓
The application is fully containerized and can be deployed to:
- Docker Swarm
- Kubernetes
- AWS ECS
- Any Docker-compatible platform
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Open a Pull Request
MIT License
Built as part of the Scalar assignment.
- React team for the amazing framework
- Tailwind CSS for the utility-first approach
- MongoDB and Redis teams for robust databases