Skip to content

Main#89

Merged
Sunja-An merged 5 commits intodevelopfrom
main
Apr 6, 2026
Merged

Main#89
Sunja-An merged 5 commits intodevelopfrom
main

Conversation

@Sunja-An
Copy link
Copy Markdown
Contributor

@Sunja-An Sunja-An commented Apr 6, 2026

No description provided.

Sunja-An and others added 5 commits April 2, 2026 20:21
- 기존 라인별 2명 고정 방식 → 10명 자유 입력 + 포지션 선호도 기반으로 교체
- C(10,5)=252 × 5!×5!=14,400 조합 완전 탐색 (약 360만 케이스)
- 3단계 필터링: 팀 MMR 밸런스 → 라인별 맞대결 편차 → 포지션 만족도
- 포지션 보정(Model A): 1순위 100% ~ 5순위 75% (6.25%씩 선형 감소)
- 새 에러코드: ErrLolTemporalInvalidPlayerCount(CT048), ErrLolTemporalInvalidPositions(CT049)
- 단위 테스트 13개 추가 (서비스 9개, 컨트롤러 8개)
- Swagger 문서 갱신

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- AcceptApplication에 application 조회 에러/nil/상태 검증 추가
- UploadThumbnail goroutine에서 context race condition 수정 (oldKey 캡처)
- balanceLolTeamsV2 조합/순열 테이블 패키지 레벨 precompute로 성능 최적화

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: LoL Temporal 포지션 선호도 기반 5:5 팀 매칭 알고리즘 구현 (#84)
- contest 도메인에서 lol 도메인으로 LoL 관련 로직 분리
- LoL 세션 관리 (WebSocket Hub, Redis adapter) 추가
- LoL 커스텀 매치 도메인 및 DB 마이그레이션 추가
- notification 도메인 제거 (SSE → WebSocket으로 대체)
- 팀 밸런싱 서비스 및 벤치마크 테스트 추가

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: LoL 도메인 분리 및 세션/팀밸런싱 기능 구현 (#84)
@Sunja-An Sunja-An merged commit d63924f into develop Apr 6, 2026
1 check passed
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a new LoL module, including custom match session management via WebSockets and a team balancing algorithm based on position preferences. It also cleans up the notification system by removing unused SSE-related code and refactors the contest application service. I have provided feedback regarding context usage in goroutines, the removal of dead code, and suggestions for improving code reusability across controllers.

if contest.BannerKey != nil && *contest.BannerKey != "" {
oldKey := *contest.BannerKey
go func() {
if delErr := c.storagePort.Delete(context.Background(), *contest.BannerKey); delErr != nil {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using context.Background() in a goroutine that's part of a request lifecycle can be problematic as it detaches the operation from the request's context, making it impossible to cancel if the request is cancelled. While you've added a timeout which is a good improvement, it's better to pass the request's context ctx to the goroutine to ensure proper lifecycle management.

Suggested change
if delErr := c.storagePort.Delete(context.Background(), *contest.BannerKey); delErr != nil {
if delErr := c.storagePort.Delete(ctx, *contest.BannerKey); delErr != nil {

// rank 2 → 15/16 = 93.75%
// rank 5 → 12/16 = 75%
func adjustedMMRScore(baseMMR, preferenceRank int) int {
return baseMMR * (17 - preferenceRank)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The magic number 17 in this calculation makes the logic obscure. It's better to define it as a named constant with a comment explaining its purpose to improve code clarity and maintainability.

	// The multiplier is derived from (MaxMultiplier + 1 - preferenceRank), where MaxMultiplier is 16.
	const preferenceMultiplierBase = 17
	return baseMMR * (preferenceMultiplierBase - preferenceRank)

Comment on lines +51 to +59
func isBetterLolCandidate(a, b lolTeamCandidate) bool {
if a.teamBalance != b.teamBalance {
return a.teamBalance < b.teamBalance
}
if a.laneDeviation != b.laneDeviation {
return a.laneDeviation < b.laneDeviation
}
return a.posSatisfaction < b.posSatisfaction
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

This function isBetterLolCandidate is unused. Its logic is already implemented inside the main balancing loop. Please remove this dead code to improve maintainability.

Comment on lines +227 to +230
session, _ := c.sessionService.GetSession(sessionID)
if session != nil {
c.broadcastToSession(sessionID, dto.WsEventPlayerJoined, gin.H{"players": session.Players})
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The error returned by c.sessionService.GetSession(sessionID) is ignored. While an error might be unlikely after a successful JoinSession, it's safer to handle it. If an error occurs, session will be nil, leading to a broadcast with incomplete data. Please consider logging the error for better diagnostics. A similar issue exists in the handleLeave function.

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