fix: 토너먼트 참가 즉시 조편성과 화면 여백을 수정
수동 참가자를 비포화 예선 조에 즉시 배치하고 자동 참가 설정을 건드리던 잘못된 부작용을 제거한다. 자동 참가 장수와 NPC의 8x8 조 편입을 회귀 테스트로 고정한다. 장수 아이콘 아래 배당이 잘리지 않도록 대진 높이를 늘리고 갱신·참가·닫기 버튼의 클릭 영역을 확대한다.
This commit is contained in:
@@ -155,6 +155,60 @@ export const assignGroupSlots = (
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Ref assigns a manual applicant to one uniformly selected non-full preliminary
|
||||
* group as part of the join request. Keeping that assignment in the persisted
|
||||
* participant projection lets the applicant see the group immediately while
|
||||
* the later participant-fill pass can still balance automatic applicants.
|
||||
*/
|
||||
export const assignManualApplicantGroup = (options: {
|
||||
state: TournamentState;
|
||||
baseSeed: string;
|
||||
current: TournamentParticipantEntry[];
|
||||
applicant: TournamentParticipantEntry;
|
||||
groupCount?: number;
|
||||
groupSize?: number;
|
||||
}): TournamentParticipantEntry => {
|
||||
const groupCount = options.groupCount ?? 8;
|
||||
const groupSize = options.groupSize ?? 8;
|
||||
const groupCounts = Array.from({ length: groupCount }, () => 0);
|
||||
|
||||
for (const participant of options.current) {
|
||||
const groupId = participant.groupId;
|
||||
if (groupId !== undefined && groupId >= 0 && groupId < groupCount) {
|
||||
groupCounts[groupId] = (groupCounts[groupId] ?? 0) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
const openGroupIds = groupCounts.flatMap((count, groupId) => (count < groupSize ? [groupId] : []));
|
||||
if (openGroupIds.length === 0) {
|
||||
throw new Error('참가 인원이 가득 찼습니다.');
|
||||
}
|
||||
|
||||
const rng = createTournamentRng(options.baseSeed, {
|
||||
openYear: options.state.openYear,
|
||||
openMonth: options.state.openMonth,
|
||||
stage: 1,
|
||||
phase: options.state.phase,
|
||||
matchIndex: options.applicant.id,
|
||||
participantIndex: options.current.length,
|
||||
extraSeed: `manual-group:${options.current.map((entry) => entry.id).join('-')}:${openGroupIds.join('-')}`,
|
||||
});
|
||||
const groupId = rng.choice(openGroupIds);
|
||||
|
||||
return {
|
||||
...options.applicant,
|
||||
groupId,
|
||||
groupNo: groupCounts[groupId] ?? 0,
|
||||
win: 0,
|
||||
draw: 0,
|
||||
lose: 0,
|
||||
gl: 0,
|
||||
seedRank: 0,
|
||||
finalRank: 0,
|
||||
};
|
||||
};
|
||||
|
||||
const selectWeighted = <T>(rng: ReturnType<typeof createTournamentRng>, pool: Array<{ item: T; weight: number }>): T =>
|
||||
rng.choiceUsingWeightPair(pool.map((entry) => [entry.item, entry.weight]));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user