Skip to content

Vk/86ff gsd discuss phas - #25

Merged
DavidHLP merged 62 commits into
mainfrom
vk/86ff-gsd-discuss-phas
Apr 19, 2026
Merged

Vk/86ff gsd discuss phas#25
DavidHLP merged 62 commits into
mainfrom
vk/86ff-gsd-discuss-phas

Conversation

@DavidHLP

Copy link
Copy Markdown
Owner

No description provided.

DavidHLP added 30 commits April 18, 2026 20:10
All phases complete: Foundation+CI, CD Pipeline, Hardening (8 plans).
259 files changed across the milestone. Roadmap collapsed, PROJECT.md evolved.
Archived to milestones/v1.2-REQUIREMENTS.md. Fresh requirements will be created for next milestone.
…uages

- Trimmed SUPPORTED_LANGUAGES from 13 to 5 entries (javascript, python, java, c, cpp)
- Matches CodeExecutionService whitelist to prevent submissions in unsupported languages
…parsing

- All 5 batch wrappers (JS, Python, C, C++, Java) read /sys/fs/cgroup/memory.current
- parseBatchResults extracts memory bytes and converts to MB
- buildCaseResult accepts double memoryMb parameter, formats as "X.XMB"
- Execute method computes maxMemory from case results instead of hardcoded "0KB"
- emptyResult uses "0.0MB" instead of "0KB"
- 10 test methods covering: pollAndProcess, processJob, determineVerdict,
  shouldRetry, onFailure, parseMemoryMb, parseRuntimeMs
- Tests verify verdict priority ordering (RE > MLE > TLE > WA > PE > Accepted)
- Tests verify retry logic skips compile errors and unsupported languages
- Tests verify System Error handling for null/empty test cases
…, and WebSocket push

- JudgeWorkerProcessor implements JobProcessor<JudgeJob>, polls Redis judge_queue via @scheduled
- Verdict priority: RE > MLE > TLE > WA > PE > Accepted
- Retry with exponential backoff (2s, 4s, 8s), max 3 retries; compile errors not retried
- System Error verdict after exhausting retries
- WebSocket push via RealtimeService.emitSubmissionResult after verdict
- AtomicInteger activeJobs guard prevents unbounded concurrency
- QueueConfig adds judgeEnabled field for conditional activation
- 27 unit tests pass covering all behaviors
- SUMMARY.md with 2 tasks, 3 files, 11min duration
- STATE.md advanced to plan 2/2 (100%), ready for verification
- ROADMAP.md phase 12 marked Complete
- REQUIREMENTS.md JUDGE-01 marked complete
Two plans covering contest entity creation, admin CRUD, announcement
management, and contest submission recording.

- 13-01: Entities + mappers + admin contest lifecycle (Wave 1)
- 13-02: Contest submission recording + announcement CRUD (Wave 2)

Covers: CONTEST-01, CONTEST-02, CONTEST-05, CONTEST-07
…es and mappers

- Rename PARTICIPATING->STARTED, COMPLETED->FINISHED in enum to match DB schema
- Update all references in ContestServiceImpl (8 occurrences) and ContestParticipantMapper SQL
- Create ContestProblem entity (Long problemId matching bigint column)
- Create ContestSubmission entity (no updatedAt per V3 DDL)
- Create ContestAnnouncement entity (no updatedAt per V3 DDL)
- Create ContestProblemMapper with findByContestId, countByContestId, deleteByContestId, findByProblemId
- Create ContestSubmissionMapper with findByContestIdAndParticipantId, countByContestId
- Create ContestAnnouncementMapper with findByContestIdOrderByCreatedAtDesc (pinned first)
- Add createContest with problem bulk-insert (Q1/Q2/Q3 labels, UPCOMING status)
- Add updateContest with status validation (UPCOMING only) and problem replacement
- Add deleteContest with soft-delete (UPCOMING or FINISHED only)
- Add startContest (UPCOMING->RUNNING, validates at least one problem assigned)
- Add endContest (RUNNING->FINISHED)
- Extend toAdminVO to set problemCount from contestProblemMapper.countByContestId
- Add 5 REST endpoints: POST /, PATCH /{id}, DELETE /{id}, POST /{id}/start, POST /{id}/end
- All endpoints require ADMIN or SUPER_ADMIN role via @PreAuthorize
…ervice

- Record ContestSubmission atomically alongside regular Submission for active contest participants
- Guard contest recording with try-catch to never break main submission flow
- Check for RUNNING contest status and STARTED participant status before recording
- Add announcement CRUD methods (create, update, delete, list) to AdminContestService
- Emit WebSocket push via RealtimeService.emitAnnouncement() on announcement creation
…ContestController

- Create CreateAnnouncementDTO with @notblank on title/content and @SiZe(max=200) on title
- Create UpdateAnnouncementDTO with optional fields for PATCH semantics
- Add GET/POST/PATCH/DELETE announcement endpoints to AdminContestController
- All endpoints require ADMIN/SUPER_ADMIN role and use typed DTOs (no Map usage)
DavidHLP and others added 26 commits April 19, 2026 08:49
…tle infrastructure

- Add RankingService dependency via constructor injection
- Add markDirty(String) method to mark contests with pending ranking updates
- Add @scheduled(fixedRate=1000) flushPendingRankings() to emit at most
  one ranking update per second per contest
- Map ContestRankingVO fields (score, penalty, problemsSolved) to RankingItem
- Add Set and Collectors imports for throttle logic

Per D-12 (throttled to max once per second per contest),
D-13 (ranking recalculated on every submission),
D-14 (payload: userId, username, rank, score, penalty, solved count)
…cking and fix contestId in WebSocket payload

SubmissionServiceImpl:
- Inject RealtimeService via constructor
- Call realtimeService.markDirty(contestId) after ContestSubmission insert

JudgeWorkerProcessor:
- Inject ContestSubmissionMapper via constructor
- Add findContestIdBySubmissionId() helper using MyBatis-Plus query wrapper
- Update pushResult() signature to accept contestId parameter
- Pass contestId (not null) to SubmissionResultPayload.of() at all call sites
- All three pushResult call sites updated: processJob (success),
  processJob (System Error fallback), and onFailure (retry exhausted)

Per D-15 (JudgeWorkerProcessor has WebSocket push),
D-16 (pushed to /user/{userId}/submission),
D-17 (payload: submissionId, status, score, timeUsed, memoryUsed, judgedAt)
…lementation

- RatingCalculationService interface with calculateAndUpdate(contestId)
- CF Elo formula: expected=1/(1+10^((opp-my)/400)), K=32/24/16 by rating
- Rating clamped to 0-3500 range
- fromRating() maps rating to correct RatingTitle per D-08 thresholds (10 levels)
- Assigns final_rank 1-based from sorted participants (score DESC, penalty ASC)
- Only rates participants with existing global_ranking records (D-11)
- Updates global_rankings and recalculates global ranks after batch update

Refs: D-06, D-07, D-08, D-09, D-10, D-11, T-14-05, T-14-06
ContestStatusEvent.ContestStatus enum uses ENDED, not FINISHED.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
CR-01 fix: actual score now uses rank-based binary outcome
(actual=1 if me.rank < opp.rank, else 0), not always 1.
Also rename oderId -> userId per IN-01.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 14: 2/2 plans complete
- 14-01: throttle infrastructure (markDirty + flushPendingRankings + contestId fix)
- 14-02: ContestScheduler + RatingCalculationService + ContestScheduler ENDED fix + CF Elo formula fix

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Phase 15: Problem + User Enhancements
- PROB-01: GET /problems/random endpoint
- PROB-02: acceptance rate calculation from submissions
- PROB-03: admin bulk operations API
- PROB-04: extend CreateProblemDTO with full fields
- USER-01: globalRank in UserStatsDTO
- USER-02: acceptanceRate in UserStatsDTO
- USER-03: public user profile routing
- USER-04: achievement path aliases
- USER-05: submissionCount in UserStatsDTO

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Wave 1 (15-01): PROB-01/02 random problem + acceptance rate, USER-01/02/05 stats enrichment
Wave 2 (15-02): PROB-03/04 admin bulk ops + extended DTO, USER-03/04 public profile + achievement aliases

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add findRandomPublished() method to ProblemService interface for
PROB-01: GET /problems/random endpoint implementation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PROB-01: Implement findRandomPublished() in ProblemServiceImpl using
ORDER BY RAND() LIMIT 1 to select a random published problem.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PROB-01: Add GET /problems/random public endpoint to ProblemController.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
PROB-02: Add static factory methods from(Problem) and
from(Problem, BigDecimal) to ProblemVO to support acceptance rate
calculation from SQL aggregation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
USER-01/USER-02/USER-05: Add three new SQL queries to SubmissionMapper:
- findGlobalRankByUserId: get global rank from global_rankings table
- calculateAcceptanceRateByUserId: compute acceptance rate percentage
- countTotalSubmissionsByUserId: count total submissions per user

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…atsDTO

USER-01/USER-02/USER-05: Add globalRank, acceptanceRate, and
submissionCount fields to UserStatsDTO and populate them in
getUserStatsById() via SubmissionMapper queries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add BulkProblemRequestDTO and BulkProblemResultDTO for batch
operations on problems (publish, unpublish, delete, edit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Implement bulkAction method to perform batch operations
(publish, unpublish, delete, edit) on multiple problems.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add bulk action endpoint for batch operations on problems.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add summary, content, examples, constraints, hints, languages, and
tags fields to support full problem creation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add /achievements/my and /achievements/points as aliases for
frontend routes /achievements/user/me and /achievements/user/me/points.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add user profile route to console router.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Create user profile page that displays username, join date, global rank,
acceptance rate, submission count, and solved problems breakdown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…shed

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@DavidHLP
DavidHLP merged commit bebe042 into main Apr 19, 2026
1 check passed

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ba0053d1eb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +81 to +82
if (newRating > gr.getMaxRating()) {
globalRankingMapper.updateMaxRatingTitle(newTitle.name(), userId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Pass mapper arguments in correct order

The updateMaxRatingTitle call swaps userId and maxRatingTitle: the mapper signature is (userId, maxRatingTitle), but this code sends (newTitle.name(), userId). When a user reaches a new max rating, the SQL WHERE user_id = ... clause is evaluated against a title string (e.g., EXPERT), so the row is not updated (and may violate enum expectations for max_rating_title).

Useful? React with 👍 / 👎.

Comment on lines +260 to +261
contest.setStatus(ContestStatus.FINISHED.name());
contestMapper.updateById(contest);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Invoke contest finalization side effects on manual end

This admin path sets contest status to FINISHED and returns, but it does not trigger rating computation. In this commit, rating updates are only executed from ContestScheduler.transitionToFinished, which runs only when transitioning a RUNNING contest itself; once admin sets FINISHED here, that scheduler path is skipped, leaving final ranks/ratings stale for manually ended contests.

Useful? React with 👍 / 👎.

Comment on lines +85 to +88
.memory(results.stream()
.map(RunResultDTO.RunCaseResult::getMemory)
.max(String::compareTo)
.orElse("0.0MB"))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Aggregate memory usage numerically, not lexicographically

The overall memory field is computed via max(String::compareTo) on values like "4.0MB", which performs lexicographic comparison rather than numeric comparison. This can report the wrong peak memory (for example, "9.5MB" can be treated as larger than "12.0MB"), causing inaccurate submission metrics.

Useful? React with 👍 / 👎.

@DavidHLP
DavidHLP deleted the vk/86ff-gsd-discuss-phas branch May 16, 2026 12:25
DavidHLP added a commit that referenced this pull request Jul 3, 2026
* chore: archive v1.2 CI/CD Pipeline milestone

All phases complete: Foundation+CI, CD Pipeline, Hardening (8 plans).
259 files changed across the milestone. Roadmap collapsed, PROJECT.md evolved.

* chore: remove REQUIREMENTS.md for v1.2 milestone

Archived to milestones/v1.2-REQUIREMENTS.md. Fresh requirements will be created for next milestone.

* docs: start milestone v1.3 Core Features

* docs: define milestone v1.3 requirements (20 requirements, 4 categories)

* docs: create milestone v1.3 roadmap (4 phases, 20 requirements)

* docs(12): capture phase context

* docs(state): record phase 12 context session

* docs(12): research judge worker phase domain

* docs(12-judge-worker): create phase plan

* docs(12): phase plans created (2 plans, 2 waves)

* feat(12-01): restrict SUPPORTED_LANGUAGES to 5 sandbox-supported languages

- Trimmed SUPPORTED_LANGUAGES from 13 to 5 entries (javascript, python, java, c, cpp)
- Matches CodeExecutionService whitelist to prevent submissions in unsupported languages

* feat(12-01): add cgroup v2 memory measurement to wrapper scripts and parsing

- All 5 batch wrappers (JS, Python, C, C++, Java) read /sys/fs/cgroup/memory.current
- parseBatchResults extracts memory bytes and converts to MB
- buildCaseResult accepts double memoryMb parameter, formats as "X.XMB"
- Execute method computes maxMemory from case results instead of hardcoded "0KB"
- emptyResult uses "0.0MB" instead of "0KB"

* docs(12-01): complete language-validation-and-memory plan

* test(12-02): add failing tests for JudgeWorkerProcessor

- 10 test methods covering: pollAndProcess, processJob, determineVerdict,
  shouldRetry, onFailure, parseMemoryMb, parseRuntimeMs
- Tests verify verdict priority ordering (RE > MLE > TLE > WA > PE > Accepted)
- Tests verify retry logic skips compile errors and unsupported languages
- Tests verify System Error handling for null/empty test cases

* feat(12-02): implement JudgeWorkerProcessor with verdict logic, retry, and WebSocket push

- JudgeWorkerProcessor implements JobProcessor<JudgeJob>, polls Redis judge_queue via @scheduled
- Verdict priority: RE > MLE > TLE > WA > PE > Accepted
- Retry with exponential backoff (2s, 4s, 8s), max 3 retries; compile errors not retried
- System Error verdict after exhausting retries
- WebSocket push via RealtimeService.emitSubmissionResult after verdict
- AtomicInteger activeJobs guard prevents unbounded concurrency
- QueueConfig adds judgeEnabled field for conditional activation
- 27 unit tests pass covering all behaviors

* docs(12-02): complete Judge Worker plan

- SUMMARY.md with 2 tasks, 3 files, 11min duration
- STATE.md advanced to plan 2/2 (100%), ready for verification
- ROADMAP.md phase 12 marked Complete
- REQUIREMENTS.md JUDGE-01 marked complete

* docs(phase-12): complete phase execution

* docs(13): capture phase context

* docs(state): record phase 13 context session

* docs(13): research contest data layer phase

* docs(13): create phase plan for contest data layer

Two plans covering contest entity creation, admin CRUD, announcement
management, and contest submission recording.

- 13-01: Entities + mappers + admin contest lifecycle (Wave 1)
- 13-02: Contest submission recording + announcement CRUD (Wave 2)

Covers: CONTEST-01, CONTEST-02, CONTEST-05, CONTEST-07

* docs(13): revise plans to fix enum mismatch, typed DTOs, and resolved research questions

* docs(state): record phase 13 planning complete

* feat(13-01): fix ContestParticipantStatus enum, create contest entities and mappers

- Rename PARTICIPATING->STARTED, COMPLETED->FINISHED in enum to match DB schema
- Update all references in ContestServiceImpl (8 occurrences) and ContestParticipantMapper SQL
- Create ContestProblem entity (Long problemId matching bigint column)
- Create ContestSubmission entity (no updatedAt per V3 DDL)
- Create ContestAnnouncement entity (no updatedAt per V3 DDL)
- Create ContestProblemMapper with findByContestId, countByContestId, deleteByContestId, findByProblemId
- Create ContestSubmissionMapper with findByContestIdAndParticipantId, countByContestId
- Create ContestAnnouncementMapper with findByContestIdOrderByCreatedAtDesc (pinned first)

* feat(13-01): implement admin contest CRUD and lifecycle endpoints

- Add createContest with problem bulk-insert (Q1/Q2/Q3 labels, UPCOMING status)
- Add updateContest with status validation (UPCOMING only) and problem replacement
- Add deleteContest with soft-delete (UPCOMING or FINISHED only)
- Add startContest (UPCOMING->RUNNING, validates at least one problem assigned)
- Add endContest (RUNNING->FINISHED)
- Extend toAdminVO to set problemCount from contestProblemMapper.countByContestId
- Add 5 REST endpoints: POST /, PATCH /{id}, DELETE /{id}, POST /{id}/start, POST /{id}/end
- All endpoints require ADMIN or SUPER_ADMIN role via @PreAuthorize

* docs(13-01): complete contest-entities-and-admin-crud plan

* docs(phase-13): update tracking after wave 1

* feat(13-02): add contest submission recording and announcement CRUD service

- Record ContestSubmission atomically alongside regular Submission for active contest participants
- Guard contest recording with try-catch to never break main submission flow
- Check for RUNNING contest status and STARTED participant status before recording
- Add announcement CRUD methods (create, update, delete, list) to AdminContestService
- Emit WebSocket push via RealtimeService.emitAnnouncement() on announcement creation

* feat(13-02): create announcement DTOs and add REST endpoints to AdminContestController

- Create CreateAnnouncementDTO with @notblank on title/content and @SiZe(max=200) on title
- Create UpdateAnnouncementDTO with optional fields for PATCH semantics
- Add GET/POST/PATCH/DELETE announcement endpoints to AdminContestController
- All endpoints require ADMIN/SUPER_ADMIN role and use typed DTOs (no Map usage)

* docs(13-02): complete announcement CRUD and contest submission recording plan

* docs(phase-13): update tracking after wave 2

* docs(phase-13): complete phase execution

* docs(14): capture phase context

* docs(state): record phase 14 context session

* docs(14): research contest engine domain

- Spring @scheduled patterns from BackupScheduler
- CF Elo rating formula with K-factor thresholds
- RealtimeService throttle/flush infrastructure
- JUDGE-04 WebSocket verdict push gap (missing contestId)
- Null end_time risk for RUNNING→FINISHED transition
- Rating title enum vs threshold mismatch risk

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(14): create contest engine plans -- throttle, scheduler, rating

feat(14-01): Add RealtimeService markDirty/flushPendingRankings throttle
- Wire SubmissionServiceImpl.markDirty() after contest submission
- Fix SubmissionResultPayload to include contestId
- Fix JUDGE-04 (verdict push) and CONTEST-04 (real-time ranking)

feat(14-02): Create ContestScheduler and RatingCalculationService
- ContestScheduler polls every 10s for UPCOMING->RUNNING->FINISHED
- RatingCalculationService uses CF Elo with K=32/24/16, 10 title levels
- Addresses CONTEST-03 (lifecycle) and CONTEST-06 (rating calc)

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(14-contest-engine): add markDirty and flushPendingRankings throttle infrastructure

- Add RankingService dependency via constructor injection
- Add markDirty(String) method to mark contests with pending ranking updates
- Add @scheduled(fixedRate=1000) flushPendingRankings() to emit at most
  one ranking update per second per contest
- Map ContestRankingVO fields (score, penalty, problemsSolved) to RankingItem
- Add Set and Collectors imports for throttle logic

Per D-12 (throttled to max once per second per contest),
D-13 (ranking recalculated on every submission),
D-14 (payload: userId, username, rank, score, penalty, solved count)

* feat(14-contest-engine): wire contest submission verdict to dirty tracking and fix contestId in WebSocket payload

SubmissionServiceImpl:
- Inject RealtimeService via constructor
- Call realtimeService.markDirty(contestId) after ContestSubmission insert

JudgeWorkerProcessor:
- Inject ContestSubmissionMapper via constructor
- Add findContestIdBySubmissionId() helper using MyBatis-Plus query wrapper
- Update pushResult() signature to accept contestId parameter
- Pass contestId (not null) to SubmissionResultPayload.of() at all call sites
- All three pushResult call sites updated: processJob (success),
  processJob (System Error fallback), and onFailure (retry exhausted)

Per D-15 (JudgeWorkerProcessor has WebSocket push),
D-16 (pushed to /user/{userId}/submission),
D-17 (payload: submissionId, status, score, timeUsed, memoryUsed, judgedAt)

* docs(14): complete plan 14-01 summary

* feat(14-contest-engine): add RatingCalculationService with CF Elo implementation

- RatingCalculationService interface with calculateAndUpdate(contestId)
- CF Elo formula: expected=1/(1+10^((opp-my)/400)), K=32/24/16 by rating
- Rating clamped to 0-3500 range
- fromRating() maps rating to correct RatingTitle per D-08 thresholds (10 levels)
- Assigns final_rank 1-based from sorted participants (score DESC, penalty ASC)
- Only rates participants with existing global_ranking records (D-11)
- Updates global_rankings and recalculates global ranks after batch update

Refs: D-06, D-07, D-08, D-09, D-10, D-11, T-14-05, T-14-06

* docs(14): complete plan 14-02 summary

* fix(14): use ContestStatus.ENDED instead of FINISHED in ContestScheduler

ContestStatusEvent.ContestStatus enum uses ENDED, not FINISHED.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* fix(14): correct CF Elo formula and rename oderId to userId

CR-01 fix: actual score now uses rank-based binary outcome
(actual=1 if me.rank < opp.rank, else 0), not always 1.
Also rename oderId -> userId per IN-01.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(14): mark phase complete, update ROADMAP and STATE tracking

Phase 14: 2/2 plans complete
- 14-01: throttle infrastructure (markDirty + flushPendingRankings + contestId fix)
- 14-02: ContestScheduler + RatingCalculationService + ContestScheduler ENDED fix + CF Elo formula fix

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(15): capture phase 15 context

Phase 15: Problem + User Enhancements
- PROB-01: GET /problems/random endpoint
- PROB-02: acceptance rate calculation from submissions
- PROB-03: admin bulk operations API
- PROB-04: extend CreateProblemDTO with full fields
- USER-01: globalRank in UserStatsDTO
- USER-02: acceptanceRate in UserStatsDTO
- USER-03: public user profile routing
- USER-04: achievement path aliases
- USER-05: submissionCount in UserStatsDTO

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(state): record phase 15 context session

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(15): add plan files for Phase 15 Problem + User Enhancements

Wave 1 (15-01): PROB-01/02 random problem + acceptance rate, USER-01/02/05 stats enrichment
Wave 2 (15-02): PROB-03/04 admin bulk ops + extended DTO, USER-03/04 public profile + achievement aliases

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(state): update Phase 15 status to plans ready

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(problem): add findRandomPublished() to ProblemService

Add findRandomPublished() method to ProblemService interface for
PROB-01: GET /problems/random endpoint implementation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(problem): implement findRandomPublished() with RAND() query

PROB-01: Implement findRandomPublished() in ProblemServiceImpl using
ORDER BY RAND() LIMIT 1 to select a random published problem.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(problem): add GET /problems/random endpoint

PROB-01: Add GET /problems/random public endpoint to ProblemController.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(problem): add from() factory methods to ProblemVO

PROB-02: Add static factory methods from(Problem) and
from(Problem, BigDecimal) to ProblemVO to support acceptance rate
calculation from SQL aggregation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(user): add globalRank, acceptanceRate, submissionCount queries

USER-01/USER-02/USER-05: Add three new SQL queries to SubmissionMapper:
- findGlobalRankByUserId: get global rank from global_rankings table
- calculateAcceptanceRateByUserId: compute acceptance rate percentage
- countTotalSubmissionsByUserId: count total submissions per user

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(user): add globalRank, acceptanceRate, submissionCount to UserStatsDTO

USER-01/USER-02/USER-05: Add globalRank, acceptanceRate, and
submissionCount fields to UserStatsDTO and populate them in
getUserStatsById() via SubmissionMapper queries.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(admin): add bulk problem operation DTOs

Add BulkProblemRequestDTO and BulkProblemResultDTO for batch
operations on problems (publish, unpublish, delete, edit).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(admin): implement bulkAction in AdminProblemService

Implement bulkAction method to perform batch operations
(publish, unpublish, delete, edit) on multiple problems.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(admin): add POST /admin/problems/bulk endpoint

Add bulk action endpoint for batch operations on problems.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(problem): extend CreateProblemDTO with content fields

Add summary, content, examples, constraints, hints, languages, and
tags fields to support full problem creation.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(achievement): add /my and /points path aliases

Add /achievements/my and /achievements/points as aliases for
frontend routes /achievements/user/me and /achievements/user/me/points.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(console): add /users/:id route for public user profiles

Add user profile route to console router.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* feat(console): add UserProfileView for public user profiles

Create user profile page that displays username, join date, global rank,
acceptance rate, submission count, and solved problems breakdown.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

* docs(state): milestone v1.3 complete — Phase 15 done, all phases finished

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant