본문으로 건너뛰기

샘플

Tabbit이 실제로 무엇을 하는지 보려면 여기서 시작합니다. 넷 다 가상 프로젝트이고 값은 전부 합성이지만, 규모와 시트의 형태는 실제 프로젝트에서 가져온 것입니다.

샘플무엇을 증명하나레이아웃규모
sprout변환하면 무엇이 나오는가sheet-per-table워크북 17개 · 테이블 71개 · 109,218행
canopy규모에서 무엇이 일어나는가named-range워크북 42개 · 테이블 549개 · 셀 873만
wildling우리 표기로 적고, 그것으로 게임을 돌린다tabbit워크북 9개 · 테이블 40개 · 플레이되는 유니티 게임
clover같은 데이터셋이 두 런타임에서 같은 게임이 되는가tabbit워크북 9개 · 테이블 40개 · 웹과 유니티

넷으로 나눈 것은 넷이 서로 다른 질문에 답하기 때문입니다. 하나로 합치면 어느 답도 선명하지 않게 됩니다.


sprout — 출시 전 소규모 프로젝트

가상의 방치형 수집 RPG. 이 도구가 설계하지 않은 규칙으로 쓰인 시트를 그대로 읽습니다 — 마커가 없고, 시트 탭 하나가 테이블 하나이며, 머리 세 줄이 헤더입니다.

dotnet run --project src/Tabbit.csproj -- --recipe samples/sprout/recipe.jsonc

여기가 「변환하면 실제로 무엇이 나오는가」의 답입니다. sprout/out/에 이 도구가 내는 파일 산출물이 전부 들어 있습니다 — 지원하는 모든 언어, 바이너리, JSON 두 형태, HTML 문서, 변환 요약, 인코딩 보고서, 스키마 기준선.

레이아웃의 관용 규칙 여섯 개가 코퍼스 안에 자리를 갖고 있습니다. 인덱스 중복, 미완성 행, 주석 행, 문자열 키, Table 하나뿐인 탭, # 설명 컬럼 — 실제 시트가 그런 상태이기 때문에 있는 규칙들이고, 심어 두지 않으면 그 분기에 게이트가 없습니다.

벤치마크의 데이터셋이기도 합니다. --scale live가 109,218행을 만들고, 그중 95,490행이 성장 곡선 테이블 하나입니다.

canopy — 라이브 대규모 프로젝트

가상의 라이브 서비스 MMO. 테이블의 경계가 워크북의 정의된 이름인 레이아웃이고, 시트 안에 제약을 선언해 둡니다 — :required · :min · :max · :enum · :links · :asset.

dotnet run --project src/Tabbit.csproj -- --recipe samples/canopy/recipe.jsonc

여기가 규모의 답입니다. 정의된 이름 549개 중 515개가 변환되고, 나머지는 이 레이아웃이 읽지 않는 정수 격자여서 recipe가 이름으로 제외합니다. 컬럼의 10분의 1이 중첩이고, 219 × 482 매트릭스 표와 지역 변종 95개와 정의된 이름이 없는 작업용 시트 12개가 들어 있습니다.

같은 워크북이 xlsx/xlsb/ 양쪽에 있습니다. 임포터가 둘을 완전히 다른 경로로 읽으므로 두 변환의 결과가 같아야 하고, 다르면 리더의 결함입니다.

wildling — 기능 전수

가상 게임 하나를 기획하고, 그 기획이 요구하는 데이터를 이 도구의 표기로 적었습니다. 앞의 둘이 「남의 규칙으로 쓰인 시트를 읽어낸다」의 증거라면, 이쪽은 「우리 규칙으로 쓰면 무엇을 적을 수 있나」의 증거입니다.

그리고 그 데이터로 도는 게임이 함께 있습니다. 생성된 C#과 .bytes를 읽어 탐사 · 육성 · 각성 · 자동 전투 · 지역 해금이 실제로 돌아가고, Windows standalone 으로 빌드됩니다. asset 검사가 자리표가 아니라 게임이 화면에 띄우는 파일을 봅니다.

그렇게 만든 것이 값입니다. 변환이 끝까지 돌고 값이 시트대로여도 게임은 돌지 않을 수 있습니다 — 실제로 지역 2가 열리지 않아 첫 지역에서 끝나는 상태였고, 그 결함은 변환의 어느 검사에도 걸리지 않았습니다.


clover — 같은 데이터셋으로 두 플랫폼

포커 로그라이크 한 편을 규칙과 수치까지 재현하고, 그것을 웹과 유니티에 각각 만듭니다. 그리고 같은 리플레이를 양쪽에 먹여 결과가 같은지를 봅니다.

dotnet run --project src/Tabbit.csproj -- --recipe samples/clover/design-data/recipe.jsonc

여기가 「데이터셋이 한 구현에 기대지 않는가」의 답입니다. 조커 150종의 효과가 전부 시트에 있고, 웹의 TypeScript 엔진과 유니티의 C# 엔진은 그 시트를 읽는 서로 독립된 두 구현입니다. 효과가 데이터에 없으면 두 구현이 갈라지고, 갈라지지 않는 것이 이 샘플의 판정 기준입니다.

원작은 상용 게임이고, 규칙과 수치만 가지고 오며 이름과 설명문과 그림은 자작합니다. 그 경계는 clover/readme.md에 있습니다.


데이터가 만들어지는 방식

sproutcanopy의 워크북은 생성물입니다. 손으로 고치지 않습니다.

무엇어디
정본schema/*.tsv — 시트 하나가 파일 하나. 표기가 여기 있습니다
생성기gen/ — 격자를 워크북으로
워크북xlsx/ — 생성물

표기와 값이 갈라져 있는 것이 요점입니다. 레이아웃을 읽는 방식이 바뀌면 격자 파일의 diff로 드러나고, 데이터가 바뀌면 드러나지 않습니다.

두 가지 규모가 한 격자에서 나옵니다.

dotnet run --project samples/<샘플>/gen -- --scale small # 커밋된 것
dotnet run --project samples/<샘플>/gen -- --scale live --out xlsx-live # 전량

small만 커밋됩니다. live는 벤치마크와 규모 확인에 쓰고, 같은 격자에서 언제든 다시 나옵니다.

합성인 이유

이 도구는 한동안 실제 상용 프로젝트의 워크북으로 검증했습니다. 그 데이터는 회사 자산이므로 공개할 수 없고, 이름만 바꾸는 것으로는 부족합니다 — 컬럼 구성과 밸런스 곡선 자체가 노하우일 수 있기 때문입니다.

도구가 증명해야 하는 것은 규모와 레이아웃의 다양성이지 실제 값이 아닙니다. 그래서 생성기가 값이 아니라 분포를 재현합니다 — 값 3개가 10만 번 반복되는 컬럼, 단조 증가하는 곡선, 긴 접두어를 공유하는 경로 풀. 그것이 바이너리 인코더가 상대하는 성질이고, 그래서 벤치마크의 근거가 저장소 안에 있게 됩니다.

어떤 성질을 어떻게 옮겼는지는 각 샘플의 readme에 있습니다 — sprout의 생성 규칙 표와 canopy의 표기 표가 그것입니다.

산출물과 게이트

out/은 커밋되어 있지만 테스트가 보지 않습니다. 생성기나 템플릿을 건드렸다면 다시 만들어 커밋해야 하고, 빼먹어도 스위트는 통과합니다 — 아키텍처와 개발의 절차가 유일한 방어선입니다.