- assign_teams.py: 부서 다양성 제약(같은 부서 ≤2명) 시드 고정 배정 - participants.json: 이름→팀 매핑 산출물 - app.py: 이름 선택 → 본인 팀 자동 표시 (수동 입력 부정 차단) - 어드민 참여율 메트릭 + 미투표자 목록 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
102 lines
3.1 KiB
Python
102 lines
3.1 KiB
Python
"""
|
|
참가자 35명 → 7팀 (팀당 5명) 배정.
|
|
같은 부서 2명 이하 제약. 랜덤 시드로 재현 가능.
|
|
결과: participants.json (이름→팀 매핑) + 콘솔 출력.
|
|
"""
|
|
import json
|
|
import random
|
|
from collections import Counter
|
|
from pathlib import Path
|
|
|
|
PEOPLE = [
|
|
("한지승", "MLOps Platform"),
|
|
("변수민", "MLOps Data"),
|
|
("박재호", "MLOps Data"),
|
|
("김태현", "MLOps Data"),
|
|
("강승형", "MLOps Data"),
|
|
("손현준", "MLOps Data"),
|
|
("김동국", "MLOps Data"),
|
|
("김재현", "MLOps HPC"),
|
|
("이준석", "MLOps HPC"),
|
|
("오근현", "MLOps HPC"),
|
|
("김정명", "MLOps HPC"),
|
|
("김영관", "MLOps HPC"),
|
|
("유용혁", "MLOps HPC"),
|
|
("최호진", "MLOps HPC"),
|
|
("전효준", "MLOps HPC"),
|
|
("김병훈", "MLOps System"),
|
|
("이지환", "MLOps System"),
|
|
("서희", "MLOps System"),
|
|
("정채윤", "MLOps System"),
|
|
("장혁진", "MLOps System"),
|
|
("장다현", "MLOps System"),
|
|
("박영훈", "MLOps System"),
|
|
("길주현", "MLOps System"),
|
|
("조민정", "AI Efficiency Tech"),
|
|
("김민섭", "AI Efficiency Tech"),
|
|
("김호승", "AI Efficiency Tech"),
|
|
("서한배", "AI Efficiency Tech"),
|
|
("심성환", "AI Efficiency Tech"),
|
|
("유준희", "AI Efficiency Tech"),
|
|
("이성재", "AI Efficiency Tech"),
|
|
("이재광", "AI Efficiency Tech"),
|
|
("이정태", "AI Efficiency Tech"),
|
|
("이준형", "AI Efficiency Tech"),
|
|
("정현준", "AI Efficiency Tech"),
|
|
("유지원", "AI Efficiency Tech"),
|
|
]
|
|
|
|
NUM_TEAMS = 7
|
|
TEAM_SIZE = 5
|
|
MAX_SAME_DEPT = 2
|
|
SEED = 20260428 # 행사일 시드 (재현 가능)
|
|
|
|
|
|
def assign(seed):
|
|
rng = random.Random(seed)
|
|
for attempt in range(5000):
|
|
shuffled = PEOPLE[:]
|
|
rng.shuffle(shuffled)
|
|
teams = [
|
|
shuffled[i * TEAM_SIZE : (i + 1) * TEAM_SIZE]
|
|
for i in range(NUM_TEAMS)
|
|
]
|
|
ok = all(
|
|
max(Counter(d for _, d in team).values()) <= MAX_SAME_DEPT
|
|
for team in teams
|
|
)
|
|
if ok:
|
|
return teams, attempt + 1
|
|
raise RuntimeError(f"제약 만족하는 배정 5000회 시도에도 실패")
|
|
|
|
|
|
def main():
|
|
assert len(PEOPLE) == NUM_TEAMS * TEAM_SIZE, (
|
|
f"인원수 불일치: {len(PEOPLE)}명, 기대 {NUM_TEAMS * TEAM_SIZE}명"
|
|
)
|
|
|
|
teams, attempts = assign(SEED)
|
|
print(f"# 시드 {SEED}, 시도 {attempts}회 만에 배정 완료\n")
|
|
|
|
mapping = {}
|
|
for i, team in enumerate(teams, 1):
|
|
team_name = f"팀{i}"
|
|
dept_counts = Counter(d for _, d in team)
|
|
dept_summary = ", ".join(f"{d.replace('MLOps ', '').replace('AI Efficiency Tech', 'AI Eff')} {c}" for d, c in dept_counts.items())
|
|
print(f"## {team_name} ({dept_summary})")
|
|
for name, dept in team:
|
|
print(f" - {name} ({dept})")
|
|
mapping[name] = team_name
|
|
print()
|
|
|
|
out = Path(__file__).parent / "participants.json"
|
|
out.write_text(
|
|
json.dumps(mapping, ensure_ascii=False, indent=2),
|
|
encoding="utf-8",
|
|
)
|
|
print(f"저장: {out}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|