feat: balance lab P0 (Datra.Lab, [Knob], <DatraLab />) - #17
Merged
Merged
Conversation
Datra.Lab lets a game tune its numbers by their outcome instead of by reading tables: mark fields as knobs, write one simulator class, and a batch of seeded bots plays the game on a forked copy of the data. - Datra/Attributes: [Knob] (label, group, unit, range, Row / EachRow, Set / Scale / Offset, Economy / Physics layer). It sits next to [TableData] so a data assembly needs nothing but Datra. - Knob schema by reflection over a data context, plus knobs declared in code for values that span several fields. - ContextForker / OverlayRawDataProvider: a fork is an ordinary TContext on an overlay provider. Reads fall through to a cached baseline, writes stay in the overlay, so nothing reaches the saved data. - ISimulator<TContext> and SimRun: stages, ticks, progress, purchases, marks, explanations, stored physics outcomes, policy parameters. - BotRunner: N bots in parallel, one derived seed each, records returned in bot order so the result does not depend on scheduling. - ResultAggregator and LabResult: the JSON document the views draw from. - IOutcomeReader (read side only), InMemoryOutcomes, JsonlOutcomeReader. - Scenario (baseline + changed knobs), snapshots, FileSnapshotStore. Datra.Lab.Sample is a toy incremental game (floors with a fare, a fare box that is also the wallet, everything left behind on the way down) with its simulator; the tests and the web sample share it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Datra.WebEditor.Server: AddDatraLab<TContext, TSimulator>() and MapDatraLab() (/api/datra/lab/schema, /run, /snapshots). The lab reads the baseline through the container's IRawDataProvider and refreshes it when the table editor saves or reloads. - Datra.WebEditor: <DatraLab />, a host for framework-free JavaScript view modules (SVG): a knob panel built from the schema, time per stage, progression, purchase timeline, each with the comparison (saved data or a snapshot) drawn behind the scenario. The modules take a source object, so a standalone export can feed them later. - Datra.WebEditor.Sample: /lab runs the toy game end to end. - Endpoint round-trip tests on an in-memory server. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docs/LAB.md: what Datra provides and what a game writes, the consumer code, knob semantics, the simulator contract, endpoints, and what P0 leaves out. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
게임 수치를 표로 읽지 않고 결과로 보며 맞추는 "밸런스 실험실"의 첫 조각(P0)입니다. 게임이 필드에
[Knob]을 붙이고 시뮬레이터 클래스 하나를 쓰면, Datra 가 손잡이 판을 만들고 봇 수십 명을 같은 시드로 돌려 단계별 시간·진행·구매 순서를 그립니다. 끄는 동안 데이터 파일에는 아무것도 쓰지 않습니다.Unity 와 무관한 일반 부분만 들어 있습니다. 머지는 하지 않았습니다.
들어 있는 것
Datra(코어)Datra/Attributes/KnobAttribute.cs:[Knob],KnobLayer,KnobApply. 데이터 어셈블리가 Datra 만 참조해도 붙일 수 있게[TableData]옆에 두었습니다(.meta포함). 코어의 다른 파일은 건드리지 않았습니다.Datra.Lab(새 프로젝트, netstandard2.1, UI 없음)[Knob]을 모읍니다.Row(한 행),EachRow(행마다 하나),Set / Scale / Offset, 코드로 선언하는 묶음 손잡이(IKnobSet,KnobBuilder).ContextForker가OverlayRawDataProvider위에 같은 타입의 컨텍스트를 새로 올립니다. 읽기는 캐시된 기준 파일로, 쓰기는 오버레이에만 갑니다. 시뮬레이터는 평소처럼data.Floor를 읽습니다.ISimulator<TContext>,SimRun(Stage,Tick,Progress,Purchase,Mark,Explain,Outcome<T>,Policy,Param),SimRandom(SplitMix64).ResultAggregator→LabResult(단계별 중앙값·p10·p90·목표, 진행 곡선, 대표 봇의 구매, 체크, 표시, 이유 문장, 문제 목록).IOutcomeReader,InMemoryOutcomes,JsonlOutcomeReader. 읽기만 있습니다.FileSnapshotStore,{이름}.json).호스팅
Datra.WebEditor.Server:AddDatraLab<TContext, TSimulator>(),MapDatraLab()→/api/datra/lab/schema,/run,/snapshots. 표 편집기가 저장·리로드하면 기준을 다시 읽습니다.Datra.WebEditor:<DatraLab />. 안쪽 그림은 프레임워크 없는 JS 모듈(SVG)입니다(wwwroot/lab/). 스키마로 만든 손잡이 판, 단계별 시간 막대, 진행, 구매 타임라인. 손잡이를 움직이면 저장된 데이터의 결과가 회색으로 뒤에 겹칩니다. 비교 대상을 스냅샷으로 바꿀 수 있습니다. 모듈은source객체(schema(),run()…)만 보므로 나중에 HTML 한 장으로 내보낼 때 같은 코드를 씁니다. 화면 글자는Locale="ko"로 한국어가 됩니다.샘플과 테스트
Datra.Lab.Sample: 장난감 인크리멘탈 게임. 층마다 운임, 요금함이 곧 지갑(사면 진행이 내려감), 내려갈 때 돈은 전부 두고 감, 계정 업그레이드와 층 장치. 물리 배치를 흉내 낸 결과 풀에서 뽑아 씁니다.Datra.WebEditor.Sample:/lab에서 Unity 없이 끝까지 돕니다.Datra.Lab.Tests(49): 스키마 추출, 갈래 격리(파일 바이트 동일, 저장된 컨텍스트 불변, 갈래끼리 객체 공유 없음, 갈래를 저장해도 오버레이에만), 시드별 결정성(같은 시드 같은 결과, 스레드 1개와 8개가 같은 결과, 봇 하나만 다시 돌려도 같은 기록), 기록·집계, 스냅샷.Datra.WebEditor.Tests(+13): 인메모리 서버로 엔드포인트 왕복.docs/LAB.md: Datra 가 주는 것과 게임이 쓰는 것, 소비자 코드.게임이 쓰는 코드
<DatraLab />설계 스케치와 다르게 한 곳
SimRun.Progress(fraction)을 더했습니다. 요금함이 지갑이면 "운임을 얼마나 채웠나"가 번 돈의 합으로 나오지 않아 시뮬레이터가 직접 알려야 합니다.Stage(id, targetSeconds:)). 화면만 분으로 보입니다.[Knob(EachRow = true)]를 더했습니다. 층마다 운임처럼 행마다 손잡이가 필요할 때 속성을 행 수만큼 반복하지 않습니다.AddDatraLab은Datra.WebEditor.Server에 두었습니다. 컴포넌트는 엔드포인트만 부르므로 RCL 은Datra.Lab을 참조하지 않습니다.이번에 없는 것
Datra.Lab은 Unity 패키지가 아닙니다(asmdef·meta 없음). 호스트 쪽에서만 씁니다확인
dotnet build Datra.sln -c Release: 오류 0. 새 경고 없음.dotnet test Datra.sln -c Release: Datra.Tests 772, Datra.Editor.Tests 158, Datra.WebEditor.Tests 50, Datra.Lab.Tests 49, Datra.Analyzers.Tests 7 모두 통과./lab을 브라우저로 확인했습니다: 콘솔 오류 없음, 손잡이를 움직이면 막대·진행·타임라인이 바뀌고 저장값이 겹쳐 보임, 스냅샷 저장과 비교,?lang=ko, 기존 편집기 화면(/) 그대로.dotnet pack으로Datra.Lab,Datra.WebEditor패키지에 JS·CSS 가 들어가는 것을 확인했습니다.🤖 Generated with Claude Code