Skip to content

feat: LoL Temporal 포지션 선호도 기반 5:5 팀 매칭 알고리즘 구현 #84

@Sunja-An

Description

@Sunja-An

개요

기존 구현(#82)은 라인별 2명 고정 배정 방식이었으나,
Notion 기획서 기반으로 포지션 선호도를 반영한 완전 탐색 3단계 필터링 알고리즘으로 교체한다.

기획 핵심 (Notion 참조)

  • 핵심 목표: 10명 내 양 팀 승리 확률 50:50에 가깝게 맞추는 실력 균형
  • 보조 목표: 플레이어 포지션 선호도 존중

포지션 보정 (Model A)

포지션 선호 순위 MMR 반영 비율
1순위 100%
2순위 93.75%
3순위 87.5%
4순위 81.25%
5순위 75%

보정 공식: adjustedMMR = baseMMR × (17 - preferenceRank) (×16 스케일)

알고리즘: 3단계 필터링

10명에서 나올 수 있는 모든 팀 조합 C(10,5) = 252가지 × 포지션 배정 5! × 5! = 14,400가지 = 약 360만 경우 완전 탐색

  1. [1단계] 팀 전체 밸런스: |팀A 보정MMR 합 - 팀B 보정MMR 합| 최소
  2. [2단계] 라인별 맞대결: 각 포지션별 보정MMR 차이 합 최소
  3. [3단계] 포지션 만족도: 10명의 포지션 선호 순위 합 최소

API 변경

Request: POST /api/contests/lol/temporal

Before (기존)

{
  "members": {
    "TOP": [{"username": "A", "tag": "KR1", "rank": "GOLD I"}, ...],
    ...
  }
}

After (신규)

{
  "members": [
    {
      "username": "Player1",
      "tag": "KR1",
      "rank": "GOLD II",
      "positions": ["TOP", "MID", "JG", "ADC", "SUP"]
    },
    ... (총 10명)
  ]
}

Response

{
  "team_a": [
    {"username": "Player1", "tag": "KR1", "rank": "GOLD II", "position": "TOP", "position_preference": 1},
    ...
  ],
  "team_b": [...]
}

작업 범위

  • DTO: LolTemporalPlayerV2, LolTemporalContestRequestV2, LolTemporalAssignedPlayer, LolTemporalContestResponseV2
  • 에러 코드 추가: ErrLolTemporalInvalidPlayerCount (CT048), ErrLolTemporalInvalidPositions (CT049)
  • 알고리즘: balanceLolTeamsV2 (조합 생성, 순열 생성, 3단계 필터링)
  • 서비스: BalanceLolTemporalContestV2 메서드
  • 컨트롤러: 기존 엔드포인트 신규 메서드로 교체
  • 단위 테스트

참고

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions