crowny-gametools 서버·화면 통합 — 티옴타·퀴즈배틀 (T199+T200+T202)
개요
/Users/ef/crowny-gametools 서버.한선과 web/ 화면에 검증완료 엔진 2본(티옴타.한선, 퀴즈배틀.한선)을 배선.
SSOT=SPEC.md 바카라/시험운영 선례를 그대로 확장(룸 게임모드 필드, deal 분기, /api/quiz/* 라우트).무엇을 했는지
- 서버.한선:
_방게임모드("none"|"tiomta"|"quiz") +_방티옴타(직렬화) + 퀴즈 room 필드 3종
_방퀴즈문제idx/_방퀴즈답안/_방퀴즈점수, 전부 문자열/정수) 추가. /api/room/new?game=,
/tiomta/{room} /quiz/{room} HTML 라우트, /api/deal 분기(tiomta→티옴타배분 결과를 tio 필드에,
quiz→카드 배분 없이 phase만 dealt), /api/quiz/next(이전 라운드 채점 + 무작위 출제 + 초기화),
/api/quiz/answer?room&seat&pick(답안 누적 기록). 퀴즈뱅크(data/퀴즈뱅크.psv, 기존 20문항)는
부팅 1회 퀴즈배틀부팅()으로 로드.
- web/티옴타.html: 참가자(
?seat=N) 4장 카드 inline SVG(▲○▽●) + 합산·점수, 딜러뷰 좌석 그리드. - web/퀴즈.html: 딜러 출제 버튼·문제/점수판, 참가자 4지선다 대형버튼(터치=answer API, 250ms 폴링).
- web/랜딩.html: 게임 선택 세그먼트(레디/티옴타/퀴즈배틀) 추가, 선택된 게임에 맞는 라우트로 이동.
- 한선씨 동반:
티옴타화면.한선·퀴즈화면.한선(화면시험.한선 패턴 최소판, 순수계산 자체검증
공통.한선에 카드기호/손패합산_클라/점수판정_클라/티옴타파싱 추가
(web/공통.js 신규 클라 함수의 한선씨 동반본).★실사고로 잡은 VM함정 (신규, 미문서화였던 것)
request-scope 메모리마커()/메모리복원()이 영속 전역 배열을 되감아 오염시킨다.
서버.한선 accept 루프는 요청마다 배열마크=메모리마커() → 처리 → 메모리복원(배열마크)로
"이번 요청이 만든 임시 배열"만 회수하려 하지만, 퀴즈배틀.한선의 좌석배열/선택배열처럼
요청 중 추가()로 키워지는 영속 전역 배열까지 같은 배열힙에서 되감긴다. 다음 요청이 같은
번지를 재사용하면 이전 요청에서 저장한 값이 소급 오염된다(실측: /api/quiz/answer 2회째 호출
직후 1회째 항목의 seat 필드가 통째로 2회째 요청의 원시 HTTP 텍스트로 뒤바뀜 — 파라미터명 리네임
으로는 재현 불변, 순수 배열힙 재사용 문제로 확인).
우회(적용됨): 여러 요청에 걸쳐 사는 room 상태는 (기존 _방좌석 비트문자열 패턴과 동일하게)
문자열/정수 필드로만 관리하고, 퀴즈배틀.한선의 배열기반 라운드 헬퍼(라운드초기화/좌석답안기록/
답안직렬화/점수문자열화/라운드채점/선착순정답판정)는 request-scope 서버에서 호출하지 않음
(엔진의 순수 조회 함수 출제/현재문제텍스트/현재보기/현재정답번호만 안전 재사용). 서버.한선에
_퀴즈답안개수/_퀴즈채점 헬퍼로 동등 로직을 문자열 파싱으로 재구현.
이 함정은 ~/.claude/templates/한선씨-가드레일.md에도 반영 필요(다음 세션 몫).
검증 (격리 사본, 라이브 9625 무접촉)
/tmp/gt_iso에 사본 배포, 포트 9629(9625/9626/9627/9628 충돌 확인 후 free 포트 선택)로 기동.
./hanseonc_high 서버.한선STRICT 경고 0건 (9236 토큰, 20272 큐브)- tiomta: room new → seat×3 ready → deal → state의
tio필드에 4장씩 3좌석 직렬화 확인 - quiz: room new →
/api/quiz/next(출제) → seat1/seat2 answer → stateqans정상 누적
"1,1,1|2,2,2") → 다음 /api/quiz/next 호출 시 이전 라운드 채점되어 qscore":"1:10" 확인
- 기존
game=none(트라이얼) 룸도 회귀 없이 바카라 배분 정상 동작 확인 - 격리 서버 종료,
/tmp/gt_iso삭제. 라이브 9625는 무접촉.
관련 파일
/Users/ef/crowny-gametools/서버.한선(게임모드/퀴즈 라우트 추가)/Users/ef/crowny-gametools/공통.한선(클라 대응 계산 함수 추가)/Users/ef/crowny-gametools/티옴타화면.한선/Users/ef/crowny-gametools/퀴즈화면.한선(신규, 화면시험 패턴)/Users/ef/crowny-gametools/web/티옴타.html/Users/ef/crowny-gametools/web/퀴즈.html(신규)/Users/ef/crowny-gametools/web/랜딩.html/Users/ef/crowny-gametools/web/공통.js(수정)/Users/ef/crowny-gametools/티옴타.한선/Users/ef/crowny-gametools/퀴즈배틀.한선(기존 엔진, 미수정)
잔여 이슈 (다음 티켓 T203 몫)
- 라이브 9625 재기동 필요(이번 작업은 라이브 무접촉 지시로 배선만, 재기동은 별도 티켓).
- 퀴즈 라운드 상태가 room-scope지만 문제뱅크 출제 함수(
출제())는 여전히 엔진 전역
현재문제인덱스 하나를 공유 — 동시에 여러 quiz room이 /api/state 폴링을 인터리브해도
_퀴즈JSON조각이 매번 출제(qidx)로 재설정 후 즉시 읽으므로 단일 요청 내에서는 안전하지만,
극단적 동시성(멀티스레드) 환경이면 레이스 가능 — 현재 accept 루프는 단일스레드 순차처리라
실사용 무해. 참고만.
- 디자인이식 훅이 기존 파일(딜러.html/랜딩.html 등)에 이미 있던 치수까지 묶어 "타" 판정을