sprout — 출시 전 소규모 프로젝트
가상의 방치형 수집 RPG 하나입니다. 워크북 17개 · 테이블 71개이고, 이 도구가 설계하지 않은
규칙으로 쓰인 시트를 그대로 읽습니다 — sheet-per-table 레이아웃.
dotnet run --project src/Tabbit.csproj -- --recipe samples/sprout/recipe.jsonc
값은 전부 합성입니다. 재현하는 것은 값이 아니라 규모와 형태입니다 — 테이블 수, 행 수, 컬럼 타입의 분포, 그리고 바이너리 인코더가 상대하는 통계적 성질. 왜 그것이 옮길 만한 것인지는 샘플 색인에 있습니다.
여기 있는 것
| 무엇 | 어디 |
|---|---|
| 워크북 17개 | xlsx/ — 생성물입니다. 손으로 고치지 않습니다 |
| 격자 72개 | schema/ — 정본. 시트 하나가 파일 하나입니다 |
| 생성기 | gen/ — 격자를 워크북으로 |
| 변환 설정 | recipe.jsonc |
| 산출물 | out/ — 커밋되어 있습니다 |
산출물은 이 도구가 내는 파일 산출물 전부입니다 — 지원하는 모든 언어, 바이너리, JSON 두 형태, HTML 문서, 변환 요약, 인코딩 보고서, 스키마 기준선. 그래서 이 폴더가 「변환하면 실제로 무엇이 나오는가」에 대한 답입니다. 데이터베이스 네 종과 히스토리는 쓸 서버가 필요해 커밋할 산출물이 없고, 그쪽은 회귀 스위트가 컨테이너의 실제 엔진을 상대로 봅니다.
out/에는 게이트가 없습니다. 생성기나 템플릿을 건드렸다면 위 명령으로 다시 만들어 커밋해야 하고, 빼먹어도 스위트는 통과합니다 — 아키텍처와 개발의 절차가 유일한 방어선입니다.
두 가지 규모
같은 격자에서 크기만 다른 코퍼스 둘이 나옵니다.
| 규모 | 행 | 워크북 | 어디 |
|---|---|---|---|
small | 5,008행 | 17개 · 0.3 MB | xlsx/. 커밋됩니다 |
live | 109,218행 | 17개 · 4.5 MB | xlsx-live/. 커밋하지 않습니다 |
dotnet run --project samples/sprout/gen -- --scale small # 커밋된 것을 다시 만듭니다
dotnet run --project samples/sprout/gen -- --scale live --out xlsx-live # 벤치마크 코퍼스
live의 109,218행 중 95,490행이 LevelCurveTable 하나입니다. 한 테이블이 코퍼스의
87%를 차지하는 것이 이 규모대 프로젝트의 실제 모습이고, 벤치마크가
그 테이블에서 성립합니다.
두 규모는 격자를 공유합니다. 생성 규칙의 개수 인자를 /24처럼 적으면 「시트의 24분의 1」이
되므로, 세 벌로 묶인 컬럼은 1,500행에서도 95,490행에서도 세 벌입니다.
격자의 형태
schema/<탭이름>.tsv 하나가 시트 하나입니다. 머리 4줄 중 앞의 셋이 시트에 그대로 실리고,
넷째는 생성기가 읽고 버립니다.
@desc 컬럼 설명 → 시트 1행. `#`으로 시작하면 그 컬럼은 변환에서 제외됩니다
@name 컬럼 이름 → 시트 2행. 첫 컬럼이 인덱스
@type 컬럼 타입 → 시트 3행. Int · Long · Float · String · Bool · IntArray · enum:Name
@gen 생성 규칙 → 생성기가 소비합니다
그 아래 → 시트 4행부터. 손으로 적은 행이 있으면 생성된 행 앞에 놓입니다
표기와 값이 갈라져 있는 것이 요점입니다. 레이아웃을 읽는 방식이 바뀌면 이 파일들의 diff로 드러나고, 데이터가 바뀌면 드러나지 않습니다.
생성 규칙
| 규칙 | 무엇 |
|---|---|
seq:START | 1씩 오르는 정수 인덱스 |
key:PREFIX | PREFIX_0000부터 오르는 문자열 인덱스. 유일합니다 |
int:LO..HI · int:LO..HI:zipf | 정수. zipf는 작은 값이 흔한 분포 |
float:LO..HI:N · bool | 실수와 참거짓 |
pick:N · pick:a|b|c | N개의 값 중 하나, 또는 적어 둔 것 중 하나 |
enum:Name | TableEnums에 선언된 라벨 중 하나 |
str:PREFIX:N · path:N:ROOT · text:N | 문자열 풀. 접두어를 공유합니다 |
ref:Sheet | 다른 시트의 인덱스 값 |
arr:INNER:LO..HI | 한 셀에 ;로 이은 배열 |
curve:START:STEP:PERIOD | 주기마다 다시 오르는 단조 증가 |
group:N · cycle:N | N행마다 같은 값 / N주기로 도는 값 |
const:V · - | 고정값 / 생성하지 않음 |
…@N · …@/N | pick·enum을 N행씩 묶어 냅니다 |
규칙이 적은 것은 의도입니다. 하나하나가 실제 코퍼스의 어떤 성질을 옮기기 위해 있습니다 — 값 3개가 10만 번 반복되는 컬럼, 단조 증가하는 곡선, 긴 접두어를 공유하는 경로 풀. 그럴듯해 보이게만 하는 규칙은 넣지 않았습니다.
심어 둔 것
이 레이아웃의 관용 규칙에는 실제 시트가 그런 상태이기 때문에 있는 것들이 있습니다. 그 분기에 게이트가 서도록 코퍼스에 자리를 만들어 두었습니다.
| 자리 | 무엇 | 변환이 하는 일 |
|---|---|---|
EquipOptionTable 4~7행 | 한 인덱스를 네 행이 나눠 가짐 — 복사 실수 | OnDuplicateIndex: keep-first로 첫 행만 남기고 나머지를 경고와 함께 버립니다 |
RaidTable 4행 | 인덱스는 비었는데 나머지 칸은 찬 행 | 작성 중인 행으로 보고 건너뛰며 경고합니다 |
ShopTable 4~5행 | 인덱스가 #·//로 시작 | 주석 행으로 보고 조용히 건너뜁니다 |
ConfigTable · StringTable | 첫 컬럼이 int가 아님 | 순번 Index를 앞에 만들고 원래 컬럼을 보조 인덱스로 유지합니다 |
Config.xlsx의 Table 탭 | 탭 이름이 Table 하나뿐 | Table을 떼면 이름이 남지 않으므로 그대로 둡니다 |
여러 테이블의 # 설명 컬럼 | 1행이 #으로 시작 | 그 컬럼을 변환에서 제외합니다 |
변환 로그에 나오는 경고 네 줄은 전부 이 표의 것입니다. 그 밖의 경고가 있다면 그것은 회귀입니다.