cEDH 플레이그룹은(는) 무엇을 하나요?
이 스킬은 소규모로 직접 편집 가능한 하나의 cEDH 플레이그룹 기록을 유지하고 TopDeck.gg의 토너먼트 데이터와 결합합니다. 네 가지 주요 작업과 해당 결과를 그룹의 Discord에 게시하는 작업을 수행합니다:
- 플레이어: TopDeck 프로필 ID와 보유 덱을 기반으로 사람들을 추가합니다.
- 메타: 기본적으로 지난 30일 동안 무슨 덱이 사용되고 승리하고 있는지 보여줍니다.
- 입력: 연습 결과, 현재 덱, 메타 노트, 참석 가능 여부를 기록합니다.
- 포드: 그룹이 유용한 연습을 할 수 있도록 연습 포드를 구성합니다.
모든 계산은 scripts/ 디렉토리의 Python 스크립트(표준 라이브러리만 사용)에 있습니다.
당신의 역할은 이 스크립트를 실행하고, 출력을 읽고, 그룹이 사용할 수 있는 조언으로
변환하는 것입니다. 수동으로 통계를 다시 계산하지 마세요. 스크립트가 엣지 케이스(파트너 이름,
드로우, 작은 표본)를 처리하며, 동일한 작업을 두 번 수행하면 서로 다른 두 답변이
나올 위험이 있습니다.
설정 및 파일 위치
- 스크립트: 이 파일과 같은 디렉토리의
scripts/.python <skill-dir>/scripts/<name>.py ...로 실행합니다. - 데이터:
~/cedh-playgroup/(CEDH_PLAYGROUP_DIR환경 변수로 재정의 가능).roster.json,games.json,notes.json,availability.json, 그리고cache/tournaments.json(TopDeck 데이터 가져오기 결과) 파일이 있습니다. 일반 JSON이므로 사용자에게 보여주거나 수동으로 편집하도록 허용해도 괜찮습니다. - TopDeck API 키:
TOPDECK_API_KEY환경 변수. https://topdeck.gg/account 에서 무료로 얻을 수 있습니다. 키가 없으면 그 사실을 알리고 설정 방법을 설명하세요. 사용자에게 채팅에 API 키를 붙여넣도록 요청하지 마세요.
TopDeck API의 조건 중 하나는 출처 표시입니다. 토너먼트 데이터를 사용하는 모든 답변은 다음 문구로 끝나야 합니다: 토너먼트 데이터 출처: TopDeck.gg (https://topdeck.gg). 스크립트가 이를 출력합니다. 요약할 때 이 문구를 유지하세요.
최신성: 먼저 동기화
TopDeck에는 "플레이어 X의 결과" 엔드포인트가 없습니다. sync.py는 지정된 기간 동안 완료된 모든
EDH 토너먼트를 가져오며, 모든 플레이어 및 메타 통계는 이 캐시에서 비롯됩니다. 메타 리포트,
플레이어 통계 또는 포드 작업 전에 캐시의 최신성(cache/tournaments.json의 synced 목록)을 확인하세요.
약 하루보다 오래되었거나 필요한 기간을 포함하지 않는 경우 동기화하세요:
python scripts/sync.py # 지난 30일, 한 번에 일주일씩 가져옴
python scripts/sync.py --days 60 # 메타 "Δ 점유율" 추세 열에도 필요
python scripts/sync.py --import saved_response.json # 오프라인 / 테스트용
대량 엔드포인트는 속도 제한이 있습니다. 스크립트는 HTTP 429에 대해 자체적으로 백오프하므로, 실행되도록 두세요. 30일 동기화는 1~2분 정도 걸릴 수 있습니다.
1. 플레이어
python scripts/playgroup.py add-player "Eric" --topdeck https://topdeck.gg/profile/<id> --deck kinnan
python scripts/playgroup.py set-decks "Sam" --deck najeela --deck "tymna kraum" --primary najeela
python scripts/playgroup.py set-decks "Lee" --deck "magda" --add # 교체하지 않고 추가
python scripts/playgroup.py set-decks "Jo" --deck glarb --gauntlet-pilot yes
python scripts/playgroup.py remove-player "Max"
python scripts/analyze.py players # 모든 플레이어; 또는: players Eric Sam
--topdeck는 프로필 링크(topdeck.gg/profile/<id>또는topdeck.gg/profile/%40handle),@handle, 또는 ID 자체를 받습니다. 토너먼트 순위는 원시 플레이어 ID만 알기 때문에, 스크립트는 프로필 페이지를 열고player-id메타 태그에서 ID를 읽습니다. 찾은 TopDeck 표시 이름을 출력합니다. 그 이름이 사용자가 의도한 사람과 일치하지 않아 보이면 알리세요. 조회에 실패하면(오프라인), 제공된 대로 저장하고 경고합니다. 나중에 플레이어를 다시 추가하여 통계가 일치하도록 하세요. 사용자가 이름만 제공하면 TopDeck 프로필 링크를 요청하세요. 표시 이름으로 일치시키면 같은 이름의 다른 사람을 선택할 수 있습니다.- 지휘관 이름은 TopDeck의 철자에 퍼지 매칭됩니다("tymna kraum" → "Tymna the Weaver / Kraum, Ludevic's Opus").
스크립트는 선택한 일치 항목을 출력합니다. 대안을 나열하는 경우 사용자와 확인하세요.
playgroup.py resolve <name>은 저장하지 않고 이름을 확인합니다. - 건틀렛 파일럿은 자신의 덱 대신 그룹의 공유 덱 중 하나를 기꺼이 플레이하는 사람입니다. 아무도 소유하지 않은 최상위 메타 덱이 포드에 포함되는 방식입니다.
- 지정된 기간 동안 TopDeck 이벤트가 0인 플레이어는 오류가 아닙니다. 단지 최근에 추적된
이벤트에 참여하지 않은 것뿐입니다. 더 많은 기록을 보려면
sync.py --days 90을 제안하세요.
플레이어를 보고할 때는 연습에 유용한 정보(현재 덱, 최근 성적(전적 및 순위), 연습 로그 내용)를 먼저 제시하세요. 테이블을 단순히 다시 인쇄하지 마세요.
2. 메타 리포트
python scripts/analyze.py meta # 30일, 16명 이상 플레이어 이벤트, 상위 25개
python scripts/analyze.py meta --days 14 --min-players 32 --top 15
python scripts/analyze.py matchups "kinnan" # 이 덱이 이기고 지는 상대
python scripts/analyze.py matchups --player Eric # 동일하지만, 한 플레이어의 자체 테이블 기준
열: 참가 수, 메타 점유율, 이전 동일 기간 대비 점유율 변화(Δ), 승률, 무승부율, 상위 컷 진출율, 최고 성적.
메타에 대한 세 가지 관점. 질문의 대상에 따라 하나를 선택하거나, 사용자가 단순히 "메타가 어때?"라고 물으면 지역 메타와 큰 대회 메타를 나란히 보여주세요:
| 관점 | 명령어 | 답변 대상 |
|---|---|---|
| 지역 | meta --local | 우리 그룹이 실제로 만날 메타: 저장된 집 위치 반경 내 이벤트, 모든 규모, 지난 30일 |
| 큰 대회 | meta --big | 큰 토너먼트에서 승리하는 덱: 100명 이상 플레이어, 모든 지역, 지난 90일(드물게 발생) |
| 글로벌 | meta | TopDeck에서 16명 이상 플레이어인 모든 이벤트 |
집 위치와 "큰 대회" 기준은 playgroup.py home --zip 18201 --miles 100 --big-min 101으로
한 번 설정하거나, --zip Z --miles M으로 일회성 사용합니다. 지역 관점은 TopDeck의 이벤트
좌표를 사용합니다. 온라인 이벤트와 위치 정보가 없는 이벤트는 배치할 수 없으며, 보고서는
누락된 수를 알려줍니다. 지역 표본은 작으므로 점유율은 "누가 나타나는지"로, 승률은 힌트로
부르세요. 지역과 큰 대회가 다를 때, 그 차이가 유용한 정보입니다: 지역에서 인기 있지만
큰 대회에서는 약한 덱, 또는 큰 대회에서 우승하지만 주변에 아무도 플레이하지 않는 덱 등.
pods.py --local 또는 --big은 "최상위 메타와 대결" 관점을 해당 기준으로 사용합니다.
메타를 인쇄하는 것보다 잘 해석하는 것이 더 중요합니다:
- 승률은 4인 게임 기준입니다. 약 25%가 평균이며, 무승부를 포함하면 더 낮아집니다. 보고서는 해당 기간의 관찰된 평균을 출력합니다. 30% 승률 덱은 매우 강력한 것입니다. 승률을 50% 기준으로 해석하지 마세요.
- 작은 표본은 거짓말을 합니다. 약 20개 미만의 참가 또는
matchups에서 약 10개 미만의 공유 테이블인 경우, 수치를 발견이 아닌 힌트로 간주하세요. - 인기(점유율)와 강함(승률, 진출율)은 다른 질문입니다. 점유율보다 성과가 높은 덱과 인기가 많지만 진출율이 낮은 덱을 지적하세요.
--min-players 16은 작은 지역 이벤트를 메타 관점에서 제외합니다. 사용자가 지역 현장에 대해 묻는다면 이 기준을 낮추세요.- 그룹 자체의
notes.json을 관련성 있는 부분에서 가져오세요("LGS에 Magda가 많다고 적었는데, 글로벌 점유율도 2% 올랐습니다").
답변을 다음과 같이 구성하세요: 3~5개의 핵심 요점, 그 다음 테이블(중요한 부분으로 축소), 그 다음 이 그룹의 연습에 의미하는 바(예: "여기 아무도 Najeela를 소유하지 않았지만 #3입니다; 건틀렛 사본 하나 가치 있음").
3. 입력: 결과, 덱, 노트, 참석 가능 여부
python scripts/playgroup.py log-game --date 2026-11-08 \
--seat "Eric=Kinnan" --seat "Sam=Najeela" --seat "Lee=Tymna Kraum" --seat "Kim=Yuriko" \
--winner Sam # 또는 --winner draw; 턴 순서를 모르면 --no-order 추가
python scripts/playgroup.py note "Lots of Magda at the LGS lately" --author Eric --tag meta
python scripts/playgroup.py avail 2026-11-08 Eric Sam Lee Kim Jo # --replace로 덮어쓰기
python scripts/playgroup.py gauntlet-deck add "Najeela" --list <url>
python scripts/playgroup.py show games # roster | games | notes | avail
사람들은 결과를 대충 보고합니다("sam이 najeela로 이겼고, 나와 lee, kim은 kinnan, tymna,
yuriko로 했고, 그 다음은 무승부"). 각 게임을 하나의 log-game 호출로 변환하세요.
좌석 순서는 턴 순서이며 중요합니다: TopDeck의 4인 테이블 전체에서 좌석 1은 약 23%,
좌석 4는 약 14% 승률을 보입니다. --seat은 턴 순서대로 나열하세요(좌석 1 먼저). 보고서에
턴 순서가 명확하지 않으면 한 번 물어보세요("누가 먼저였나요?"). 모르면 --no-order로
기록하세요. 게임은 전적과 매치업에는 계수되지만 좌석 통계에는 포함되지 않습니다.
그룹에 최적의 보고 형식을 알려주세요. 모든 사람의 좌석 프로필을 제공하기 때문입니다:
G1 (턴 순서): Eric Kinnan, Sam Najeela, Lee Tymna/Kraum, Kim Yuriko. 승자 Sam.
통계를 변경하는 항목(예: 누가 이겼는지, 누가 어떤 덱을 사용했는지)이 모호하면 기록하기 전에
물어보세요. 기록 후에는 게임당 한 줄씩 읽어주어 실수를 잡을 수 있도록 하세요.
사용자가 여러 게임을 붙여넣으면 모두 기록한 다음, 그날의 요약(누가 무엇을 이겼는지, 연속 승리 등)을 제공하세요.
4. 연습 포드
이번 세션에 누가 플레이하나요?
참석은 매주 바뀌므로 포드를 구성하기 전에 누가 참석하는지 확정하세요. 선호도 순서:
- 사용자가 사람들을 지목합니다("Jeff 빼고 다", "Eric, Ryan, Saige, Alex").
- 해당 날짜에 대해 이미 저장된 목록(
playgroup.py show avail). - 물어보세요. 클라이언트에 객관식 질문 도구가 있다면 명단을 체크박스로 나열하고, 이름이 한 질문에 허용되는 것보다 많으면 여러 질문으로 나누고, 날짜도 물어보세요. 그렇지 않으면 한 줄로 물어보세요.
답변을 저장하여 포드, Discord 게시물 및 이후 보고서가 일치하도록 하세요:
python scripts/playgroup.py avail 2026-11-08 --all --remove Jeff Saige # 모두에서 제외
python scripts/playgroup.py avail 2026-11-08 Ishmael # 늦게 참석 추가
python scripts/playgroup.py avail 2026-11-08 --remove Ryan # 늦게 불참 제거
python scripts/pods.py --date 2026-11-08 # 저장된 목록으로 포드 구성
python scripts/pods.py --all --except Jeff # 일회성, 저장하지 않음
포드가 게시된 후 목록이 변경되면 다시 구성하고 누가 이동했는지 알리세요. 이미 포드를 본 사람을 조용히 재배치하지 마세요.
python scripts/pods.py --date 2026-11-08 # 그날의 참석자 사용
python scripts/pods.py --players Eric Sam Lee Kim Jo Ana Max
python scripts/pods.py --date 2026-11-08 --focus Eric # Eric의 약한 매치업 가중치 4배
python scripts/pods.py --date 2026-11-08 --deck "Sam=Tymna Kraum" --w-repeat 0
포드 빌더는 좌석 배치와 덱 선택을 검색하고 네 가지 목표에 따라 점수를 매깁니다. 모두 기본적으로 켜져 있습니다. 목표의 가중치를 0으로 설정하여 끄거나, 높여서 강조하세요:
| 목표 | 플래그 | 보상 대상 |
|---|---|---|
| 최상위 메타와 대결 | --w-meta | 각 테이블의 상위 N 메타 덱(--top-meta 15) |
| 밸런스 잡힌 포드 | --w-balance | 포드당 비슷한 평균 강함(플레이어 전적 + 덱 승률) |
| 반복 회피 | --w-repeat | 최근 기록된 게임에서 함께 앉았던 쌍 재배치 방지 |
| 약한 매치업 타겟팅 | --w-matchup | 플레이어가 지는 덱과 대결하도록 배치(아래 참조) |
누구의 나쁜 매치업인가요? "내 나쁜 매치업 연습"은 덱이 아닌 사람에 관한 것입니다. 포드 빌더는 각 플레이어의 자체 TopDeck 테이블 및 연습 게임에서 각 상대 지휘관에 대한 승률을 추정합니다. 표본이 작으므로, 동일한 매치업에서 해당 덱의 전체 승률 쪽으로 수축시킵니다. Rograkh/Thrasios에게 1/11인 파일럿은 여전히 약한 것으로 간주됩니다. Kinnan 플레이어가 전반적으로 잘하는 경우에도 마찬가지입니다. 자신의 매치업에 대해 물어본 사람을 위해 포드를 구성하기 전에 직접 증거를 살펴보세요:
python scripts/analyze.py matchups --player Eric --days 90 # Eric 자신의 테이블, 모든 이벤트 규모
python scripts/analyze.py matchups kinnan # 덱 전체 필드, 대조용
두 결과가 다를 때는 명확히 말하세요("Kinnan은 일반적으로 Najeela를 상대로 괜찮지만, 당신은 Sam의 Najeela에게 0/3입니다"). 유용한 코칭입니다: 차이는 덱이 아닌 플레이어의 라인에 있습니다.
좌석. 포드 빌더는 각 포드의 턴 순서도 설정합니다. --seat-mode practice(기본값)를
사용하면 각 플레이어는 해당 좌석이 일반적으로 승리하는 비율 에 비해 자신의 전적이 가장
약한 좌석에 앉습니다. 좌석 2에서 0/6은 나쁩니다. 좌석 4에서 2/10은 평균 수준입니다.
--seat-mode best는 예를 들어 토너먼트 전에 가장 좋은 좌석을 연습하고, random은
단순히 섞습니다. 플레이어별 좌석 및 매치업 증거:
python scripts/analyze.py profile # 모든 플레이어; 또는: profile Eric Ryan
포드 설명: 이것이 핵심입니다. 각 좌석에 대해 스크립트는 플레이어의 증거 수, 좌석 판독(가장 나쁨, 가장 좋음, 또는 아직 판독 없음, 전적 및 좌석 평균 대비 포인트), 이 테이블의 매치업("연습 필요 vs …" 및 "유리 vs …", 자신의 전적 및 필드 비율 포함), 그리고 이 테이블에 없는 약한 매치업을 출력합니다. 이를 플레이어당 짧고 데이터 기반의 "이유"로 변환하세요. 예:
좌석 1: Alex on Tayam. 좌석 1은 Alex의 가장 나쁜 좌석입니다(1/10, 좌석 1이 일반적으로 승리하는 것보다 약 7pts 낮음). 따라서 여기서 연습합니다. 또한 토너먼트에서 Sisay에게 0/7이며, Darison의 Sisay가 이 테이블에 있습니다. Ob Nixilis에게는 유리하므로, 이겨야 하는 상대입니다.
해당 설명에 대한 규칙:
- 실제 전적을 인용하세요(1/10, 0/7). 이것이 신뢰성을 줍니다.
- 약 ~6게임 미만에 기반한 경우 "얇은 표본"이라고 말하세요. 0/2를 과대평가하지 마세요.
- 플레이어에게 데이터가 없는 경우(TopDeck 링크 없음, 기록된 게임 없음), 해당 좌석은 임시이며 연습 보고서가 채울 것이라고 말하세요. 이유를 지어내지 마세요.
- 더 많은 연습 데이터가 무엇을 선명하게 할지로 끝맺으세요. 턴 순서로 기록된 모든 게임은 좌석 및 매치업 판독을 개선합니다.
포드 크기는 4인이며, 3인은 나머지를 흡수합니다. 5명인 경우 한 명이 빠지고 순환합니다. 사용자가 5인 포드를 원한다면, 그들의 선택이며 모두 좌석을 배정하세요. 출력의 "Sitting out" 줄은 순환할 사람을 지명합니다.
각 포드를 그렇게 구성된 이유와 함께 제시하세요. 평이한 언어로: 어떤 메타 덱을 만날지, 각 플레이어가 연습해야 할 약한 매치업, 피할 수 없었던 반복 매칭. 스크립트의 노트는 원재료입니다. 포드당 중요한 한두 가지를 선택하고 모두 붙여넣지 마세요. 건틀렛 덱이 할당된 경우 파일럿이 알 수 있도록 하세요.