This document breaks down the project goals into actionable milestones. Each milestone is self-contained and delivers tangible value.
Status: Completed on 2026-01-06 Focus: Fix existing issues and prepare for extensibility
- Add PostgreSQL driver dependency
- Create application-postgres.properties profile
- Add MySQL driver dependency (deferred - PostgreSQL prioritized)
- Create application-mysql.properties profile (deferred)
- Add Flyway migrations for schema versioning
- Update docker-compose with database options
- Fix TODO in ChallengeController - proper HTTP error responses
- Fix TODO in OptionsController - bind all users properly
- Add input validation annotations (@Valid, @NotBlank)
- Improve error handling with custom exception handler (GlobalExceptionHandler)
- Make game timer configurable via properties (darkhold.game.timer-seconds)
- Make PIN length configurable (darkhold.game.pin-length)
- Add feature flags for upcoming features (deferred to later milestone)
src/main/resources/application-postgres.propertiessrc/main/resources/db/migration/V1__initial_schema.sqlsrc/main/resources/db/migration/V2__seed_data.sqlsrc/main/java/com/quiz/darkhold/init/GlobalExceptionHandler.javasrc/main/java/com/quiz/darkhold/init/ErrorResponse.javasrc/main/java/com/quiz/darkhold/init/GameConfig.javadocker-compose.h2.yml- Updated
docker-compose.yml(PostgreSQL)
- All 233 tests passing
- Code coverage: 71%+
Deliverable: Production-deployable application with PostgreSQL support
Status: Completed on 2026-01-07 Focus: Support more question formats beyond multiple choice
- Add
questionTypeenum to QuestionSet entity (MULTIPLE_CHOICE, TRUE_FALSE, TYPE_ANSWER, POLL) - Add
timeLimitfield to QuestionSet (per-question timer) - Add
pointsfield to QuestionSet (configurable points) - Add
acceptableAnswersfield for TYPE_ANSWER fuzzy matching - Create database migration V4 for new fields
- Update DTOs (QuestionRequest, QuestionResponse, ChallengeExportDto)
- Add Apache Commons Text dependency for Levenshtein distance
- Add question type selector to editchallenge.html
- Add time limit dropdown (5s-240s or default)
- Add points input field (default 1000)
- Conditional answer fields per question type
- True/False radio buttons for T/F questions
- Text input with acceptable answers for TYPE_ANSWER
- Hide correct checkboxes for POLL type
- Update QuestionService to handle new fields
- Update Excel parser to handle new columns (Type, TimeLimit, Points, AcceptableAnswers)
- Backward compatible - old 6-column format still works
- Update duplicateChallenge to copy new fields
- Update importFromJson to handle new fields
- Create AnswerValidationService with Levenshtein fuzzy matching
- Update GameController for different question types
- Add /validate_answer/ endpoint for TYPE_ANSWER server-side validation
- Pass question_type and question_points to game view
- Support per-question time limits
- Update game.html for different question type layouts
- Update game-scripts.js for type-specific answer handling
- Add TYPE_ANSWER text input UI with server-side validation
- TRUE_FALSE question display with True/False buttons
- POLL questions without correct/incorrect highlighting
- CSV export includes new fields (Type, TimeLimit, Points, AcceptableAnswers)
- JSON export includes new fields (via ChallengeExportDto)
- Import handles new fields
QuestionType.java- New enumV4__add_question_type_fields.sql- New migrationQuestionSet.java- Added new fieldsQuestionRequest.java,QuestionResponse.java,ChallengeExportDto.java- Updated DTOseditchallenge.html- New question type UIQuestionService.java- Handle new fieldsChallengeService.java- Updated Excel parser and import/exportAnswerValidationService.java- New service with Levenshtein fuzzy matchingGameController.java- Updated for question types, new validation endpointGameControllerTest.java- Updated for new constructor parametergame.html- Conditional layouts for different question typesgame-scripts.js- Handlers for TRUE_FALSE, TYPE_ANSWER, POLLChallengeController.java- Updated CSV export with new columnsdependencies.gradle- Added commons-text
Deliverable: Support for 4 question types with configurable settings
Status: Completed on 2026-01-06 Focus: Create/edit quizzes without Excel files
- Create "New Challenge" form (title, description)
- Create challenge edit page
- Add challenge duplicate/clone feature
- Implement challenge archive (soft delete) - deferred (hard delete sufficient)
- Create question add/edit form (modal dialog)
- Implement question type selector (deferred to Milestone 2)
- Add answer options dynamic form (2-4 answers)
- Implement correct answer selector (checkbox)
- Add question preview (in edit page)
- Implement drag-and-drop question reordering (SortableJS)
- Add question duplicate within challenge
- Add question delete with confirmation
- Implement bulk question operations
- Keep Excel import as option
- Add JSON export of challenges
- Add JSON import of challenges
- Add CSV export option
QuestionController.java- REST API for question CRUDQuestionService.java- Question business logicQuestionRequest.java,QuestionResponse.java,ReorderRequest.java- DTOsChallengeExportDto.java- Export/import DTOV3__add_question_order.sql- Database migrationcreatechallengeform.html- New challenge formeditchallenge.html- Question editor with drag-and-drop
POST /save_challenge- Create empty challengeGET/POST /edit_challenge/{id}- Edit challengePOST /duplicate_challenge/{id}- Clone challengeGET /export_challenge/{id}/json- JSON exportGET /export_challenge/{id}/csv- CSV exportPOST /import_challenge/json- JSON import/api/question/*- Full REST API for questions
Deliverable: Full in-browser quiz creation and management
Status: Completed on 2026-01-10 Focus: Add images and videos to questions
- Add image size/type validation
- Create file upload service (deferred - using direct URLs)
- Configure storage location (deferred - using external URLs)
- Implement image compression/resize (deferred)
- Add
imageUrlfield to QuestionSet - Update question editor with image URL input
- Display images in game view
- Handle image loading states
- Add image fields to answer options (deferred to future)
- Create image answer UI component (deferred)
- Update game template for image answers (deferred)
- Add
videoUrlfield to QuestionSet - Support YouTube embed URLs
- Create video player component for questions
- Support direct video file upload (deferred - using YouTube/external URLs)
- Add S3 storage adapter (deferred)
- Add configuration for cloud storage (deferred)
- Implement CDN support for media (deferred)
V6__add_media_support.sql- Added imageUrl and videoUrl columnsQuestionSet.java- Added imageUrl and videoUrl fieldsgame.html- Added media display in game vieweditchallenge.html- Added URL input fields for media
Deliverable: Rich media questions with images and videos via external URLs
Status: Completed on 2026-01-10 Focus: Improve the live game playing experience
- Implement answer streak bonus (2x, 3x, 4x multipliers)
- Show score change animation after each question
- Display rank change (+2, -1) with up/down arrows
- Display streak badges on scoreboard
- Add "Double Points" question option (deferred)
- Show live participant count (getParticipantCount in GameService)
- Add "Kick player" functionality for moderator (kickPlayer in GameService)
- Display participant avatars/colors (deferred)
- Implement nickname validation (length, characters) (deferred)
- Add basic profanity filter (deferred)
- Add "Pause Game" button for moderator
- Add "Skip Question" option
- Add "End Game Early" with confirmation
- Implement "Extend Time" mid-question (deferred)
- Show question progress (Question X of Y)
- Display time remaining prominently (FlipClock countdown)
- Add answer confirmation animation
- Show "Waiting for others" after answering
- Animate score reveals (countUp animation)
- Show podium for top 3 with gold/silver/bronze
- Display streak information on scoreboard
- Display statistics (fastest answer, most streaks) (deferred to Milestone 7: Analytics)
Challenge.java- Added totalQuestions fieldGameController.java- Pass totalQuestions to viewgame.html- Added question progress badge, waiting messagegame-scripts.js- Show waiting message after answer submissionscoreboard.html- Already had rank indicators, streak badges, score deltasfinalscore.html- Already had animated podium with gold/silver/bronzeGameService.java- Already had streak tracking, pause/resume, kick playerScoreResult.java- Already had streak multipliers, rank change calculation
Deliverable: Polished, engaging game experience with streak bonuses and visual feedback
Status: Completed on 2026-01-10 Focus: Allow multiple games to run simultaneously
- CurrentGame already PIN-scoped (repository-based)
- GameService already supports PIN parameters
- Update PreviewService.getActiveChallenge() - deprecated for concurrent games
- WebSocket messages already game-scoped via PIN
- Create "My Active Games" dashboard for moderators
- Add game status indicators (WAITING, IN_PROGRESS, PAUSED, FINISHED)
- Implement game timeout/auto-cleanup scheduler
- Ensure PIN uniqueness across active games (retry logic with 10 attempts)
- Add PIN expiration (2 hours for WAITING, 24 hours for active games)
- Add moderator tracking for game ownership queries
Game.java- Added moderator fieldGameRepository.java- Added methods for querying by moderator and statusPreviewService.java- Added PIN uniqueness check, moderator tracking, concurrent game queriesActiveGamesController.java- NEW: Controller for active games dashboardGameInfo.java- NEW: DTO for game displayactivegames.html- NEW: Dashboard templateGameCleanupScheduler.java- NEW: Scheduled cleanup of expired gamesDarkholdApplication.java- Added @EnableSchedulingnavbar.html- Added link to active games dashboardcommon-scripts.js- Added toActiveGames() functionapplication.properties- Added game expiration configurationV8__add_moderator_to_game.sql- NEW: Database migration
Deliverable: Full support for hosting multiple simultaneous quiz sessions with proper isolation and management
Status: Completed on 2026-01-10 Focus: Track and report game results
- Create GameResult entity for completed games
- Create ParticipantResult entity for individual scores
- Create QuestionResult entity for answer statistics
- Store results when game ends
- Create "Past Games" page
- Display game summary (date, participants, winner)
- View detailed results per game
- Filter games by moderator (automatic per user)
- Advanced filters by challenge/date (deferred)
- Show correct/incorrect distribution per question
- Calculate success rate percentages
- Identify "hardest" questions (difficulty levels: EASY, MEDIUM, HARD)
- Display question-level statistics in detailed view
- Display average answer time (infrastructure ready, data collection pending)
- Export game results to CSV
- Export game results to Excel (deferred)
- Generate PDF summary report (deferred)
- Email results to moderator (deferred)
GameResult.java- Entity for game sessionsParticipantResult.java- Entity for player performanceQuestionResult.java- Entity for question statisticsGameResultRepository.java- Repository with query methodsParticipantResultRepository.java- Repository for participant dataQuestionResultRepository.java- Repository for question dataResultService.java- Service for saving/retrieving resultsPastGamesController.java- Controller for past games and resultspastgames.html- Past games list viewgameresult.html- Detailed game result view with analyticsGameController.java- Modified to save results on game endnavbar.html- Added link to past gamescommon-scripts.js- Added toPastGames() functionV9__add_analytics_tables.sql- Database migrationcheckstyle/suppressions.xml- Added suppressions for analytics files
Deliverable: Comprehensive game analytics with detailed statistics and CSV export
Status: Completed on 2026-01-10 Focus: Support different ways to play
- Game mode defined in enum (SELF_PACED)
- UI preview card created ("Coming Soon" status)
- Full implementation deferred to future release
- Generate shareable link (no PIN needed) (deferred)
- Allow retakes with configurable attempts (deferred)
- Set availability window (start/end date) (deferred)
- Add game_mode field to Game and CurrentGameSession entities
- Create PracticeService for solo play
- Database migration V7 for game mode support
- Practice game initialization without PIN (UUID-based)
- Skip waiting room (direct to game)
- UI for starting practice mode from preview page
- Session-based practice game tracking
- Show correct answer immediately after each question (infrastructure ready, UI refinement deferred)
- Enhanced instant feedback UI (deferred to Milestone 10: UI/UX)
- Game mode defined in enum (CHALLENGE)
- UI preview card created ("Coming Soon" status)
- Full implementation deferred to future release
- Leaderboard across all attempts (deferred)
- Best score tracking (deferred)
- Time-based ranking (deferred)
- Enhanced preview page with mode selection cards
- Visual game mode selector with icons and descriptions
- Interactive cards with hover effects
- Support for MULTIPLAYER and PRACTICE modes (active)
- Placeholder cards for SELF_PACED and CHALLENGE modes
V7__add_game_mode.sql- Added game_mode columnPracticeService.java- Solo play service implementationGameMode.java- Expanded enum: MULTIPLAYER, PRACTICE, SELF_PACED, CHALLENGEPreviewController.java- Added startPractice endpointpreview.html- Game mode selection UI with styled cardsCurrentGameSession.java- game_mode and gameStatus fields
Deliverable: Complete game mode infrastructure with MULTIPLAYER and PRACTICE modes fully functional, modern UI for mode selection, and extensible framework for future modes (SELF_PACED and CHALLENGE)
Status: Completed on 2026-01-30 Focus: Enable team-based gameplay
- Create team before game starts
- Random team assignment option
- Custom team names/colors
- Balance teams by participant count (Balanced/Random/Manual assignment methods)
- Aggregate team scores
- Show team leaderboard
- Display individual contribution to team
- Team lobby view
- Team vs Team results screen
- Team celebration animations
src/main/java/com/quiz/darkhold/team/- Full team packageTeamController.java- Team REST APITeamService.java- Team business logicTeamConfig.java,TeamInfo.java,TeamScoreResult.java- DTOsTeamResult.java- Entity for team resultsTeamResultRepository.java- Data accessTeamAssignmentMethod.java- Enum (BALANCED, RANDOM, MANUAL)
Deliverable: Collaborative team gameplay
Status: Completed on 2026-01-17 Focus: Modern, accessible interface
- Audit mobile game experience
- Optimize touch targets for answers
- Test on various screen sizes
- Add PWA manifest for mobile install
- Implement dark/light mode toggle
- Create theme system (CSS variables)
- Allow custom quiz colors (deferred)
- Add lobby background options (deferred)
- Add ARIA labels throughout
- Ensure keyboard navigation works
- Test with screen readers
- Implement high contrast mode
- Add colorblind-friendly palettes
- Add optional sound effects
- Implement countdown sounds
- Add victory/defeat sounds
- Create smooth transitions
- Modernize login page with brand identity
- Modernize registration page to match login
- Add password reset page styling (deferred)
- Consistent error/success messaging
theme-variables.css- CSS variable system with light/dark themestheme-manager.js- Theme switching with localStorage persistenceaudio-manager.js- Sound effect manager with volume controlaccessibility.js- Keyboard navigation, ARIA live regionsanimations.css- Victory/defeat animations, confetti, focus indicatorsmanifest.json- PWA configuration with 8 icon sizesservice-worker.js- Offline caching and asset managementoffline.html- Offline fallback page- 7 sound files (correct, incorrect, tick, countdown, victory, defeat, join)
Deliverable: Polished, accessible user experience
Status: 100% Complete (All 4 target languages complete) Focus: Multi-language support Completed: 2026-02-16
- Configure Spring MessageSource (I18nConfig.java)
- Extract all UI strings to messages.properties (427 keys)
- Create language selector component (navbar dropdown with globe icon)
- Store user language preference (localStorage + session)
- All 24 Thymeleaf templates updated to use
#{key}expressions
- English (en) - 427/427 messages ✅ Complete
- Spanish (es) - 427/427 messages ✅ Complete
- French (fr) - 427/427 messages ✅ Complete
- German (de) - 427/427 messages ✅ Complete
- Community contribution guidelines added to CONTRIBUTING.md
- Add RTL CSS styles
- Test Arabic/Hebrew layouts
- Handle mixed LTR/RTL content
src/main/java/com/quiz/darkhold/init/I18nConfig.java- MessageSource, LocaleResolver, LocaleChangeInterceptorsrc/main/resources/messages.properties- English base (427 keys) ✅src/main/resources/messages_es.properties- Spanish translations (427 keys) ✅src/main/resources/messages_fr.properties- French translations (427 keys) ✅src/main/resources/messages_de.properties- German translations (427 keys) ✅src/main/resources/static/scripts/language-manager.js- Language switching logicI18N_STATUS.md- Translation progress tracking documenttranslation_helper.sh- Script to check translation progress
Deliverable: Full support for English, Spanish, French, and German languages across all UI elements
All 24 Thymeleaf templates updated to use #{key} message expressions:
- Authentication: login.html, registration.html
- Game: game.html, gamewait.html, scoreboard.html, finalscore.html
- Challenge: createchallenge.html, editchallenge.html, viewchallenges.html, preview.html, publish.html
- Admin: options.html, usermanagement.html, user_form.html, gameManagement.html
- Analytics: activegames.html, pastgames.html, gameresult.html
- Other: index.html, myprofile.html, error.html, offline.html
Deliverable: Multi-language quiz platform
Focus: Production hardening
- Implement rate limiting on PIN entry
- Add CAPTCHA for repeated failures
- Review CSRF protection
- Add Content Security Policy headers
- Implement password strength requirements
- Add account lockout policy
- Add Redis for session storage
- Implement caching for challenges
- Optimize database queries
- Add database connection pooling
- Enhance actuator endpoints
- Add Prometheus metrics
- Create Grafana dashboard templates
- Implement structured logging
- Create Kubernetes manifests
- Add Helm chart
- Document horizontal scaling
- Add health check endpoints
Deliverable: Secure, scalable, production-ready platform
Status: Pending Focus: Expose programmatic access to all platform capabilities Addresses: Limitation L1 (No REST API), L8 (No Webhooks) Enables: Milestones 14, 16, 18, 20
- Add springdoc-openapi dependency for Swagger UI and OpenAPI 3.0 spec generation
- Create
/api/v1/base path with versioning strategy - Implement JWT-based API authentication (issue tokens via
/api/v1/auth/token) - Add API rate limiting (separate from UI rate limits)
- Create API key management for service-to-service integration
- Add CORS configuration for API consumers
-
GET /api/v1/challenges- List challenges (paginated, filterable) -
POST /api/v1/challenges- Create challenge -
GET /api/v1/challenges/{id}- Get challenge details -
PUT /api/v1/challenges/{id}- Update challenge -
DELETE /api/v1/challenges/{id}- Delete challenge -
POST /api/v1/challenges/{id}/duplicate- Duplicate challenge -
GET /api/v1/challenges/{id}/questions- List questions -
POST /api/v1/challenges/{id}/questions- Add question -
PUT /api/v1/challenges/{id}/questions/{qid}- Update question -
DELETE /api/v1/challenges/{id}/questions/{qid}- Delete question -
POST /api/v1/challenges/import- Import (JSON/Excel) -
GET /api/v1/challenges/{id}/export- Export (JSON/CSV)
-
POST /api/v1/games- Create/publish game from challenge -
GET /api/v1/games/{pin}- Get game status -
POST /api/v1/games/{pin}/start- Start game -
POST /api/v1/games/{pin}/pause- Pause game -
POST /api/v1/games/{pin}/resume- Resume game -
POST /api/v1/games/{pin}/skip- Skip current question -
POST /api/v1/games/{pin}/end- End game -
GET /api/v1/games/{pin}/participants- List participants -
GET /api/v1/games/{pin}/scoreboard- Get current scoreboard
-
GET /api/v1/analytics/games- List past games (paginated) -
GET /api/v1/analytics/games/{id}- Get game result details -
GET /api/v1/analytics/games/{id}/participants- Participant results -
GET /api/v1/analytics/games/{id}/questions- Question statistics -
GET /api/v1/analytics/games/{id}/export- Export results (CSV/PDF)
-
GET /api/v1/users/me- Current user profile -
PUT /api/v1/users/me- Update profile -
GET /api/v1/admin/users- List users (admin only) -
POST /api/v1/admin/users- Create user (admin only) -
PUT /api/v1/admin/users/{id}- Update user (admin only)
- Create webhook registration entity and admin UI
-
POST /api/v1/webhooks- Register webhook URL -
GET /api/v1/webhooks- List registered webhooks -
DELETE /api/v1/webhooks/{id}- Remove webhook - Emit events:
game.created,game.started,game.ended,participant.joined,results.finalized - Implement retry logic with exponential backoff (3 attempts)
- Add webhook signature verification (HMAC-SHA256)
api/package - New API controllers, DTOs, JWT filterinit/ApiSecurityConfig.java- Separate security chain for/api/**init/JwtTokenProvider.java- JWT issue/validatewebhook/package - Webhook entity, repository, service, async dispatcher- Database migration for webhook and API key tables
application.properties- JWT secret, webhook config
Deliverable: Documented REST API (Swagger UI at /api/docs) with JWT auth and webhook event system
Status: Pending Focus: Generate quizzes from text, documents, and URLs using AI Addresses: Limitation L2 (No AI Features) Depends on: Milestone 13 (REST API for AI endpoints)
- Create
AiProviderinterface withgenerateQuestions(prompt, config)method - Implement
OpenAiProvider(GPT-4o / GPT-4o-mini) - Implement
AnthropicProvider(Claude) - Implement
OllamaProviderfor local models (Llama 3, Mistral, Gemma) - Create provider factory with configurable selection
- Add admin settings page for API keys and provider selection
- Support provider fallback chain (try primary, fall back to secondary)
- Plain text input - direct pass to LLM
- PDF upload - extract text via Apache PDFBox
- URL input - fetch and extract main content (Jsoup HTML parsing)
- Word document upload - extract via Apache POI (already in dependencies)
- Implement content chunking for documents exceeding token limits
- Add content sanitization and length validation
- Design prompt templates for each question type (MCQ, T/F, Type Answer, Poll)
- Generate configurable number of questions (5, 10, 15, 20)
- Generate difficulty levels (Easy, Medium, Hard, Mixed)
- Generate distractors (wrong answers) that are plausible
- Parse structured LLM output into QuestionRequest DTOs
- Add generation parameters: topic focus, language, target audience
- Create "AI Generate" button on challenge creation page
- Build generation wizard UI (input source -> configure -> review)
- Show generated questions in editable preview before saving
- Allow accept/reject/edit individual questions
- "Regenerate" button for individual questions
- Save accepted questions to challenge via existing QuestionService
-
POST /api/v1/ai/generate- Generate questions from text/URL/file -
POST /api/v1/ai/regenerate- Regenerate a single question -
GET /api/v1/ai/providers- List available providers and status -
POST /api/v1/ai/explain- Generate explanation for a question (future use)
- Document Ollama setup and compatible models
- Auto-detect Ollama availability on configurable host:port
- Test with Llama 3 8B, Mistral 7B, Gemma 2B (various resource profiles)
- Add model selection in admin settings
- Graceful fallback messaging when no AI provider is configured
ai/package - AiProvider interface, implementations, service, controllerai/prompt/- Prompt templates per question type and languageai/extraction/- PDF, URL, DOCX content extractors- Admin settings page for AI configuration
- AI generation wizard templates and JavaScript
- Database migration for AI configuration storage
Deliverable: AI quiz generation from text, PDF, URLs with support for cloud APIs and local models (Ollama)
Status: Pending Focus: Enterprise identity provider integration Addresses: Limitation L3 (No SSO/SAML/OIDC)
- Add spring-boot-starter-oauth2-client dependency
- Configure OAuth2 login for generic OIDC providers
- Implement auto-provisioning of users from OIDC claims (email, name, roles)
- Map OIDC groups/roles to Darkhold roles (ADMIN, GAME_MANAGER, PARTICIPANT)
- Support multiple concurrent OIDC providers
- Google Workspace (OAuth2)
- Microsoft Azure AD / Entra ID (OAuth2 + OIDC)
- Okta (OIDC)
- Keycloak (OIDC)
- Generic OIDC provider (manual configuration)
- Add spring-security-saml2-service-provider dependency
- Implement SAML 2.0 Service Provider
- Support metadata XML import for IdP configuration
- Map SAML attributes to user fields and roles
- Test with ADFS, Okta SAML, Shibboleth
- Create "Identity Providers" admin page
- Add/edit/delete OIDC provider configuration
- Add/edit/delete SAML provider configuration
- Test connection button for each provider
- Configure role mapping rules
- Enable/disable local password login per deployment
- Just-in-time (JIT) user provisioning on first SSO login
- Link existing local accounts to SSO identities by email
- Handle account deactivation when removed from IdP
- Support forced SSO (disable local login option)
- Audit log for SSO login events
- Migration: Add
identity_providertable (id, type, name, config_json, enabled) - Migration: Add
user_identitytable (user_id, provider_id, external_id, email) - Migration: Add
sso_enabledandlocal_login_enabledto app settings
sso/package - SSO configuration, provider management, user provisioninginit/SecurityConfig.java- Add OAuth2/SAML security chains- Admin pages for identity provider management
- Database migrations for SSO tables
application.properties- SSO configuration properties
Deliverable: Enterprise SSO via OAuth2/OIDC and SAML 2.0 with auto-provisioning and role mapping
Status: Pending Focus: Enable self-paced quiz completion with deadlines Addresses: Limitation L4 (No Async/Homework Mode) Depends on: Milestone 13 (REST API)
- Create
Assignmententity (challenge_id, creator_id, title, instructions) - Add deadline fields (start_datetime, end_datetime, timezone)
- Add attempt configuration (max_attempts, allow_retake, best_score_policy)
- Add access control (password, allowed_users, allowed_groups)
- Create
AssignmentAttemptentity (assignment_id, user_id, started_at, completed_at, score) - Database migration for assignment tables
- Add "Assign as Homework" option alongside "Play Live" on preview page
- Create assignment configuration form (deadline, attempts, access)
- Generate shareable link (no PIN needed, URL-based access)
- Generate QR code for assignment link
- Show assignment in "My Assignments" dashboard
- Participant opens assignment link, authenticates or enters name
- Skip waiting room - go directly to first question
- Show timer per question (or allow untimed mode)
- Show correct answer and explanation after each question
- Allow review of all answers before final submission
- Track attempt duration and per-question timing
- Aggregate results after deadline
- Show class/group performance summary
- Compare across attempts (if retakes allowed)
- Rank by best score or latest attempt (configurable)
- Integrate with existing analytics (Milestone 7 tables)
- Export assignment results (CSV, API)
- Email notification when assignment is published (if SMTP configured)
- Reminder before deadline (24h, 1h)
- Results available notification after deadline
- Webhook events for assignment lifecycle
-
POST /api/v1/assignments- Create assignment -
GET /api/v1/assignments- List assignments -
GET /api/v1/assignments/{id}- Get assignment details -
PUT /api/v1/assignments/{id}- Update assignment -
DELETE /api/v1/assignments/{id}- Delete assignment -
GET /api/v1/assignments/{id}/results- Get aggregated results -
POST /api/v1/assignments/{id}/attempt- Start attempt (participant)
assignment/package - Entity, repository, service, controller- Assignment creation and management templates
- Self-paced play templates (extend practice mode infrastructure)
- Assignment results/analytics templates
- Database migration for assignment tables
preview.html- Add "Assign as Homework" card to game mode selection
Deliverable: Full async/homework mode with deadlines, retakes, and aggregate results
Status: Pending Focus: Rich analytics dashboards with visualizations and PDF reports Addresses: Limitation L5 (No Advanced Analytics) Depends on: Milestone 7 (existing analytics tables), Milestone 13 (API)
- Add Chart.js or Apache ECharts dependency (CDN or bundled)
- Create analytics landing page with summary cards (total games, participants, questions)
- Add date range picker for filtering
- Show games-over-time line chart
- Show participants-per-game bar chart
- Show average scores trend line
- Identify questions with lowest success rates across games
- Group weak areas by topic/tag (requires question tags from Question Bank)
- Show per-participant knowledge heatmap (topics vs. mastery)
- Highlight questions where wrong answers cluster on specific distractors
- Provide "recommended review" topics based on gap analysis
- Question difficulty curve (distribution across Easy/Medium/Hard)
- Answer distribution pie charts per question
- Average time-to-answer per question
- Discrimination index (do good students get it right, weak students wrong?)
- Flag problematic questions (too easy, too hard, bad distractors)
- Track individual participant performance over multiple games
- Show improvement trends (score trajectory over time)
- Compare participants within a cohort/group
- Streak and accuracy statistics per participant
- Achievement milestones (personal bests, improvement badges)
- PDF report generation using OpenPDF library
- Game summary report (overview, participants, question stats)
- Participant report card (individual performance, strengths, weaknesses)
- Cohort comparison report (class average, distribution, outliers)
- Email report delivery (if SMTP configured)
- Scheduled report generation (weekly/monthly summaries)
-
GET /api/v1/analytics/dashboard- Dashboard summary data -
GET /api/v1/analytics/trends- Time-series data for charts -
GET /api/v1/analytics/gaps- Learning gap analysis -
GET /api/v1/analytics/participants/{id}/progress- Individual progress -
GET /api/v1/analytics/reports/{id}/pdf- Generate PDF report
analytics/dashboard/- Dashboard controller, service, aggregation queriesanalytics/report/- PDF generator, email sender- Analytics dashboard templates with Chart.js integration
- Participant progress tracking templates
- Database migration for tracking tables (if needed beyond existing schema)
Deliverable: Interactive analytics dashboards with charts, learning gap analysis, and PDF reports
Status: Pending Focus: Integrate with Learning Management Systems Addresses: Limitation L6 (No LMS Integration) Depends on: Milestone 13 (REST API), Milestone 16 (Async Mode)
- Create SCORM 1.2 content package generator
- Package challenge as SCO (Shareable Content Object)
- Implement SCORM API adapter (JavaScript runtime)
- Track: completion_status, score.raw, score.min, score.max, session_time
- Generate imsmanifest.xml with proper metadata
- ZIP package download from challenge export page
- Create SCORM 2004 (3rd/4th Edition) package generator
- Implement sequencing and navigation rules
- Track: cmi.completion_status, cmi.success_status, cmi.score.scaled
- Support multi-SCO packages (one SCO per question group)
- Add IMS Global LTI 1.3 library dependency
- Implement LTI 1.3 launch endpoint
- Handle OIDC login initiation flow
- Implement Deep Linking (Content-Item Message) for challenge selection
- Implement Assignment and Grade Services (AGS) for grade passback
- Support Names and Roles Provisioning Services (NRPS)
- Create LMS registration admin page
- Store platform credentials (client_id, deployment_id, key set URL)
- Support Moodle LTI 1.3 configuration
- Support Canvas LTI 1.3 configuration
- Support Blackboard LTI 1.3 configuration
- Support Google Classroom (via LTI or Classroom API)
- Provide Darkhold's public key set endpoint (JWKS)
- Send scores back to LMS grade book after game/assignment completion
- Map Darkhold scores to LMS grade scale (0-100%)
- Support both immediate (live game) and deferred (assignment) grading
- Handle grade update for retakes (best score, latest score, average)
- Sync completion status for compliance tracking
- Implement xAPI statement generation for game events
- Statements: attempted, completed, scored, answered, interacted
- Configure Learning Record Store (LRS) endpoint in admin settings
- Batch statement sending with retry logic
lms/package - SCORM packager, LTI provider, xAPI clientlms/scorm/- SCORM manifest builder, API adapter JSlms/lti/- LTI launch handler, OIDC flow, AGS servicelms/xapi/- Statement builder, LRS client- Admin pages for LMS platform registration
- Database migration for LMS platform credentials and grade sync records
- Challenge export page - Add SCORM download button
Deliverable: SCORM 1.2/2004 export, LTI 1.3 provider with grade passback, xAPI event reporting
Status: Pending Focus: Organization-specific branding and customization Addresses: Limitation L7 (No White-Label/Branding)
- Create
BrandConfigentity (logo_url, favicon_url, primary_color, secondary_color, accent_color, font_family, app_name) - Admin page for uploading/configuring brand assets
- Store uploaded logos and favicons on disk (configurable path)
- Preview brand changes before saving
- Database migration for brand configuration table
- Extend existing CSS custom properties to accept admin-configured values
- Inject brand colors into
theme-variables.cssdynamically via Thymeleaf - Replace hardcoded "Darkhold" text with configurable
app_namethroughout templates - Replace logo and favicon references with brand-configured assets
- Support custom CSS injection for advanced customization
- Show organization logo on game waiting screen
- Show organization logo on final score screen
- Optional "Powered by Darkhold" footer (can be hidden for full white-label)
- Custom background patterns/images for game screens
- Branded email templates (if SMTP configured)
- Branded PDF report headers and footers
- Branded CSV export with organization metadata
- Custom domain support documentation
branding/package - BrandConfig entity, repository, service, controller- Admin branding configuration page
- Update all Thymeleaf templates to use brand variables
- Update
theme-variables.cssgeneration to include brand overrides - Database migration for brand config table
Deliverable: Admin-configurable branding with custom logos, colors, fonts, and app name
Status: Pending Focus: Plugin architecture, embeddable widgets, and community marketplace Addresses: Limitation L9 (No Presentation Integration), future extensibility Depends on: Milestone 13 (REST API)
- Create lightweight embeddable game view (
/embed/game/{pin}) - Strip navigation, header, footer for clean iframe embedding
- Generate embed code snippet (
<iframe>with configurable dimensions) - Support PostMessage API for parent-frame communication
- Configurable embed options (show/hide scoreboard, branding, sound)
- Google Slides Add-on: Launch quiz from within a presentation
- PowerPoint Add-in (Office.js): Embed quiz slide in PPTX
- Generic embed URL for any presentation tool that supports web embeds
- "Presentation Mode" game view optimized for projector display
- Define plugin interface:
DarkholdPluginwith lifecycle hooks (init, destroy) - Extension points: custom question types, custom scoring algorithms, custom themes, custom export formats
- Plugin descriptor format (plugin.json with metadata, dependencies, version)
- Plugin classloader isolation (prevent conflicts)
- Plugin admin management page (install, enable, disable, remove)
- Plugin configuration storage (per-plugin settings)
- Allow users to publish challenges as "public" (opt-in)
- Create browse/search interface for public challenges
- Add tagging and categorization (subject, grade level, difficulty)
- Rating and review system (1-5 stars, text reviews)
- Fork/clone public challenges to own library
- Featured/trending challenges section
- Report inappropriate content mechanism
- Public user profiles (games hosted, challenges created, rating)
- Follow creators for notifications on new challenges
- Challenge collections/playlists (curated sets by topic)
- Contributor leaderboard (most shared, highest rated)
embed/package - Embeddable game controller and stripped-down templatesplugin/package - Plugin loader, registry, extension point interfacesmarketplace/package - Public challenge service, search, ratings- Embed templates (game-embed.html, scoreboard-embed.html)
- Marketplace browse/search templates
- Database migrations for marketplace tables (ratings, tags, visibility)
Deliverable: Embeddable quiz widget, presentation tool plugins, plugin architecture, and community challenge marketplace
Status: Pending Focus: Multi-node deployment for large-scale use Addresses: Limitation L10 (Single-Server Architecture) Depends on: Milestone 12 (Security & Scale foundation)
- Add Spring WebSocket broker relay with Redis pub-sub (or RabbitMQ STOMP)
- Replace SimpleBroker with external message broker
- Ensure game events propagate across all nodes
- Test concurrent games across multiple nodes
- Handle node failure gracefully (in-flight games continue on surviving nodes)
- Add Spring Session with Redis backend
- Migrate
CurrentGamein-memory state to Redis or database-backed store - Implement distributed locks for game state mutations (Redisson or Spring Integration)
- Configure sticky sessions as fallback (if Redis unavailable)
- Session replication across nodes
- Add Spring Cache with Redis backend
- Cache challenge data (read-heavy, write-infrequent)
- Cache user profiles and roles
- Cache i18n message bundles
- Implement cache invalidation on write operations
- Add cache hit/miss metrics
- Connection pool tuning (HikariCP) for multi-node
- Read replica support for analytics queries
- Database migration for optimistic locking on game state
- Index optimization for high-query tables (game_result, participant_result)
- Query performance monitoring and slow query logging
- Create Kubernetes manifests (Deployment, Service, Ingress, ConfigMap, Secret)
- Create Helm chart with configurable values (replicas, resources, database, Redis)
- Add horizontal pod autoscaler (HPA) based on CPU/memory/WebSocket connections
- Configure liveness and readiness probes (actuator endpoints)
- Document rolling update strategy with zero-downtime deployment
- Add PodDisruptionBudget for availability during node maintenance
- Add Micrometer metrics for Prometheus
- Expose: active games, connected WebSockets, questions served, API latency
- Create Grafana dashboard templates
- Implement distributed tracing (Micrometer Tracing + Zipkin/Jaeger)
- Structured JSON logging for log aggregation (ELK/Loki)
- Alert rules for critical metrics (game failures, high latency, node loss)
init/RedisConfig.java- Redis connection and Spring Session/Cache configinit/WebSocketConfig.java- Switch to broker relaypreview/repository/CurrentGame.java- Refactor to distributed storek8s/directory - Kubernetes manifestshelm/darkhold/directory - Helm chartgrafana/directory - Dashboard JSON templatesapplication-cluster.properties- Clustering configuration profile- Database migrations for optimistic locking columns
Deliverable: Multi-node deployment with Redis, Kubernetes manifests, Helm chart, and Grafana monitoring
Status: Pending Focus: Security-critical code with near-zero test coverage Coverage Target: 51% -> 58% instruction, raise JaCoCo minimum from 35% to 45% Details: See TEST_COVERAGE_PLAN.md
- Authentication flow tests (login success, failure, logout, remember-me)
- Authorization rule tests (admin-only endpoints, game-manager endpoints, public access)
- CSRF token validation tests (form submission, WebSocket handshake)
- Password encoding verification (BCrypt)
- Session management tests (concurrent sessions, session timeout)
- PIN entry rate limit enforcement (5 attempts per 5-minute window)
- 15-minute block after threshold exceeded
- Rate limit reset after window expiry
- Different IP addresses tracked independently
- Edge cases: exactly at threshold, rapid successive attempts
- STOMP endpoint registration verification
- WebSocket handshake with valid/invalid CSRF token
- Message broker topic configuration
- Allowed origins validation
- SockJS fallback behavior
- File type validation (allowed: xlsx, png, jpg; rejected: exe, sh)
- File size limit enforcement
- Malicious filename sanitization
- GlobalExceptionHandler: 404, 500, validation errors, access denied
- Error response structure and HTTP status codes
- Update
staticCodeAnalysis.gradle: minimum 0.35 -> 0.45 - Verify all tests pass with new threshold
- Update CI/CD pipeline if needed
Deliverable: ~53 new tests covering security infrastructure; JaCoCo minimum raised to 45%
Status: Pending Focus: Business logic services (largest gap, highest-value tests) Coverage Target: 58% -> 67% instruction, raise JaCoCo minimum to 55% Depends on: TC-1
- Save game results on game end
- Calculate participant statistics (score, accuracy, streak)
- Calculate question statistics (success rate, difficulty)
- CSV export formatting and content
- Handle games with 0 participants
- Handle questions with 0 answers
- Balanced team assignment (even distribution)
- Random team assignment (all players assigned)
- Manual team assignment
- Team score aggregation from member scores
- Team creation with custom names and colors
- Edge cases: 1 player, odd numbers, more teams than players
- Practice session creation (UUID-based, no PIN)
- Solo gameplay flow (question progression)
- Score tracking without leaderboard
- Session-based state management
- Practice mode with different question types
- Challenge CRUD operations
- Excel import (valid file, empty rows, invalid format, backward compat)
- JSON import/export round-trip
- Challenge duplication (deep copy verification)
- Question ordering and reordering
- Validation (missing title, too few questions)
- User registration (valid data, duplicate email, weak password)
- Password change (correct old password, wrong old password)
- Role management (assign, revoke)
- User lookup by email and ID
- SecurityService: auto-login after registration
- Game lifecycle: create, start, pause, resume, end
- Question advancement (next question, skip, last question)
- Player join and kick
- Streak tracking across questions
- GameCleanupScheduler: expired WAITING games, expired active games, active games untouched
- Update
staticCodeAnalysis.gradle: minimum 0.45 -> 0.55 - Verify all tests pass with new threshold
Deliverable: ~100 new tests covering all service classes; JaCoCo minimum raised to 55%
Status: Pending Focus: Undertested controllers with MockMvc integration tests Coverage Target: 67% -> 73% instruction, raise JaCoCo minimum to 62% Depends on: TC-2
- GET user management page (admin access only)
- POST create user (valid data, validation errors)
- PUT update user roles
- Access denied for non-admin users
- User list pagination and filtering
- GET view challenges page
- POST create challenge (valid, validation errors)
- GET/POST edit challenge
- POST duplicate challenge
- DELETE challenge (own, not owned, admin override)
- GET export CSV/JSON
- POST import Excel/JSON (valid, invalid, empty)
- GET options page with current settings
- POST update preferences (theme, sound, language)
- Validation of preference values
- POST publish game (creates game with PIN)
- POST join game (valid PIN, invalid PIN, expired PIN)
- Game control endpoints (pause, resume, skip, end)
- Access control (only moderator can control)
- GET profile page
- POST update profile (name, email)
- Validation errors on invalid input
- Update
staticCodeAnalysis.gradle: minimum 0.55 -> 0.62 - Verify all tests pass with new threshold
Deliverable: ~51 new tests for controller layer; JaCoCo minimum raised to 62%
Status: Pending Focus: Entities, repositories, and models with low coverage Coverage Target: 73% -> 78% instruction, raise JaCoCo minimum to 68% Depends on: TC-3
- CurrentGameSession: constructor, getters/setters, state transitions
- CurrentGameSession: JSON field serialization/deserialization
- CurrentGame: CRUD operations via repository
- CurrentGame: PIN-scoped queries (find active by PIN)
- CurrentGameSessionRepository: custom query methods
- Concurrent access patterns
- Game entity: field validation, status enum transitions
- GameRepository: find by status, find by moderator
- GameMode enum coverage
- User entity: required fields, role association
- DarkholdUserDetails: authorities mapping from roles
- Role entity: name constraints
- Options models (ChallengeInfo, ChallengeSummary): construction, fields
- Home models (GameInfo, PinValidationResponse): construction, fields
- Preview models (PreviewInfo, PublishInfo): construction, fields
- Update
staticCodeAnalysis.gradle: minimum 0.62 -> 0.68 - Verify all tests pass with new threshold
Deliverable: ~51 new tests for data layer; JaCoCo minimum raised to 68%
Status: Pending Focus: Branch coverage (34% -> 70%), error paths, full integration tests Coverage Target: 78% -> 85% instruction, 70% branch; JaCoCo minimum to 75% Depends on: TC-4
- Parameterized tests for all enum-based switches (QuestionType, GameStatus, GameMode)
- Null-path testing across service methods
- Error branch testing (try/catch paths, validation failures)
- Conditional logic in ChallengeService Excel parser (all column combinations)
- Init package branch coverage (6% -> 60%): config conditional paths
- Complete multiplayer game: create -> publish -> 3 players join -> play 5 questions -> end
- Practice mode: create -> start -> play all questions -> view results
- Team game: create -> configure teams -> play -> team results
- Game with all question types (MCQ, T/F, Type Answer, Poll)
- STOMP client connect and subscribe to game topic
- Send answer via STOMP and receive acknowledgment
- Receive scoreboard update after all players answer
- Handle disconnect and reconnect during game
- Multiple concurrent games on different topics
- Invalid PIN entry (wrong PIN, expired game, rate limited)
- Duplicate nickname in same game
- Answer after timer expires
- Concurrent answers from same player
- Game with 0 questions (validation)
- Maximum participants per game
- Update
staticCodeAnalysis.gradle: minimum 0.68 -> 0.75 - Verify all tests pass with new threshold
- Add per-package minimum rules for critical packages (init, game.service, challenge.service)
Deliverable: ~63 new tests; 85% instruction coverage, 70% branch coverage; JaCoCo minimum at 75%
| Milestone | Focus Area | Key Deliverable | Status |
|---|---|---|---|
| 1 | Foundation | Production database support | ✅ COMPLETED |
| 2 | Question Types | T/F, Poll, Type Answer | ✅ COMPLETED |
| 3 | Question Editor | In-browser quiz creation | ✅ COMPLETED |
| 4 | Media | Images & videos in questions | ✅ COMPLETED |
| 5 | Game Experience | Polished live gameplay | ✅ COMPLETED |
| 6 | Concurrency | Multiple simultaneous games | ✅ COMPLETED |
| 7 | Analytics | Reports & game history | ✅ COMPLETED |
| 8 | Game Modes | Self-paced & practice modes | ✅ COMPLETED |
| 9 | Teams | Team-based gameplay | ✅ COMPLETED |
| 10 | UI/UX | Modern, accessible interface | ✅ COMPLETED |
| 11 | i18n | Multi-language support | ✅ COMPLETED |
| Milestone | Focus Area | Key Deliverable | Addresses | Status |
|---|---|---|---|---|
| 12 | Security & Scale | Production hardening | L11 (Test Coverage) | Pending |
| 13 | REST API | Documented API + Webhooks | L1, L8 | Pending |
| 14 | AI Generation | AI quiz from text/PDF/URL | L2 | Pending |
| 15 | SSO / Identity | OAuth2, OIDC, SAML 2.0 | L3 | Pending |
| 16 | Async Mode | Homework with deadlines | L4 | Pending |
| 17 | Analytics | Dashboards, charts, PDF reports | L5 | Pending |
| 18 | LMS Integration | SCORM, LTI 1.3, xAPI | L6 | Pending |
| 19 | White-Label | Custom branding | L7 | Pending |
| 20 | Ecosystem | Plugins, embeds, marketplace | L9 | Pending |
| 21 | Scaling | Redis, Kubernetes, Helm | L10 | Pending |
| Milestone | Focus Area | Key Deliverable | Coverage Target | Status |
|---|---|---|---|---|
| TC-1 | Security & Infrastructure | Security config, rate limiting, WebSocket tests | 51% -> 58% | Pending |
| TC-2 | Core Service Layer | ResultService, TeamService, GameService, etc. | 58% -> 67% | Pending |
| TC-3 | Controller Integration | Admin, Challenge, Options, Game controllers | 67% -> 73% | Pending |
| TC-4 | Data Layer & Models | Entities, repositories, DTOs | 73% -> 78% | Pending |
| TC-5 | Branch Coverage & E2E | Error paths, lifecycle integration, WebSocket | 78% -> 85% | Pending |
See TEST_COVERAGE_PLAN.md for per-package breakdown and detailed test scenarios.
Phase 1 milestones (1-11) are completed. Phase 2 milestones (12-21) should be executed in this order based on dependencies and strategic value:
| Order | Milestone | Rationale |
|---|---|---|
| 1 | M12 | Foundation hardening; already scoped; unblocks enterprise trust |
| 2 | M13 | REST API enables M14, M16, M18, M20; transforms app into platform |
| 3 | M14 | Closes #1 competitive gap; unique with local AI for air-gapped deployments |
| 4 | M15 | Hard gate to enterprise adoption; Spring Security 6 has built-in support |
| 5 | M16 | Doubles use-case surface area; teachers and trainers need assignments |
| 6 | M17 | Premium differentiator; leverages existing analytics tables |
| 7 | M18 | Unlocks education (44.9%) and enterprise training (20.3% CAGR) procurement |
| 8 | M19 | Enterprise requirement; extends existing CSS custom properties |
| 9 | M20 | Ecosystem play; community-driven growth and content network effects |
| 10 | M21 | Large deployment support; requires stable platform from M12-M20 |
M12 (Security) ─────────────────────────────────────────── M21 (Scaling)
│
└── M13 (REST API) ──┬── M14 (AI Generation)
├── M15 (SSO)
├── M16 (Async Mode) ──── M18 (LMS Integration)
├── M17 (Analytics)
├── M19 (White-Label)
└── M20 (Ecosystem)
Pick any milestone or task and submit a PR! See the main README for contribution guidelines.