6.8 KiB
6.8 KiB
| type | project | subject | version | date | status | author |
|---|---|---|---|---|---|---|
| 설계문서 | 수상한잡화점 | 시뮬레이션 결과 출력 JSON 포맷 | v1 | 2026-04-17 | 초판 | 개발팀장 |
결과 JSON 포맷 v1
1. 목적
SimulationRunner 실행 결과의 출력 포맷. 기획팀이 후처리·비교·차트화할 때 구조화된 형태로 활용. 단일 실행·스윕·배치 모두 동일 스키마의 확장.
2. 단일 실행 결과
{
"schema_version": "1.0",
"scenario_id": "anchor_stage1_no_card_4mob_touch",
"run_id": "run_20260417_142301_0001",
"timestamp": "2026-04-17T14:23:01Z",
"seed": 42,
"result": {
"pc_survived": true,
"pc_remaining_hp": 23,
"pc_remaining_hp_ratio": 0.23,
"total_turns": 142,
"duration_sec": 14.2,
"monsters_killed": 4,
"monsters_killed_ids": ["m1", "m2", "m3", "m4"],
"pc_damage_taken_total": 77,
"pc_damage_blocked_total": 33,
"pc_damage_dealt_total": 60,
"defence_activations": 14,
"defence_active_ratio": 0.42,
"attacks_by_pc": 8,
"attacks_by_pc_blocked_ratio": 0.0
},
"breakdown": {
"damage_taken_by_monster": {"m1": 16, "m2": 20, "m3": 22, "m4": 19},
"damage_blocked_by_monster": {"m1": 7, "m2": 9, "m3": 10, "m4": 7},
"defence_duration_sec": 5.96
},
"detail_log_path": null,
"errors": []
}
3. 필드 정의
3-1. 메타
| 필드 | 설명 |
|---|---|
schema_version |
결과 스키마 버전 |
scenario_id |
입력 시나리오 ID echo |
run_id |
실행별 고유 ID (스윕·배치에서 중복 방지) |
timestamp |
ISO 8601 UTC |
seed |
사용된 난수 시드 |
3-2. result (결과 요약 — 밸런싱 판단 핵심 축)
| 필드 | 타입 | 설명 |
|---|---|---|
pc_survived |
bool | PC 생존 여부 |
pc_remaining_hp |
float | 종료 시점 PC HP |
pc_remaining_hp_ratio |
float | remaining_hp / max_hp |
total_turns |
int | 실행된 tick 수 |
duration_sec |
float | 시뮬 내부 경과 시간 (tick × interval) |
monsters_killed |
int | 처치된 몬스터 수 |
monsters_killed_ids |
string[] | 처치된 몬스터 ID 목록 |
pc_damage_taken_total |
float | PC가 받은 총 피해 (감소 후) |
pc_damage_blocked_total |
float | 방어로 감소된 총 피해량 (= 원본피해 - 실피해) |
pc_damage_dealt_total |
float | PC가 입힌 총 피해 |
defence_activations |
int | 방어 상태 진입 횟수 |
defence_active_ratio |
float | 방어 상태 유지 시간 / 전체 시뮬 시간 |
attacks_by_pc |
int | PC 공격 발동 횟수 |
attacks_by_pc_blocked_ratio |
float | PC 공격이 방어로 인해 취소된 비율 (기획팀 분석용) |
3-3. breakdown (세부 분해)
| 필드 | 타입 | 설명 |
|---|---|---|
damage_taken_by_monster |
map<id, float> | 몬스터별 가한 피해 (감소 후) |
damage_blocked_by_monster |
map<id, float> | 몬스터별 감소시킨 피해량 |
defence_duration_sec |
float | 누적 방어 유지 시간 |
3-4. detail_log_path (선택)
- 입력의
simulation.record_detail == true이면 tick별 상세 로그 파일 경로 - false면
null
3-5. errors (진단)
- 시뮬 중 발생한 경고·비치명 에러 목록 (string[])
- 치명 에러는 예외 throw로 종료되므로 본 필드에 오지 않음
4. 스윕 결과
{
"schema_version": "1.0",
"sweep_id": "Defence_Mul_Grid",
"sweep_axes": [
{"path": "global_value.PCDefence_Mul", "values": [0.2, 0.3, 0.4, 0.5]},
{"path": "monsters[0].attack_dmg", "values": [3, 5, 7]}
],
"runs_per_cell": 10,
"cells": [
{
"coords": {"PCDefence_Mul": 0.2, "monster_attack_dmg": 3},
"runs": [ /* 결과 10개 */ ],
"stats": {
"pc_survived_ratio": 1.0,
"pc_remaining_hp_mean": 62.3,
"pc_remaining_hp_std": 8.1,
"total_turns_mean": 98,
"total_turns_std": 12
}
}
/* N × M cells */
]
}
스윕 cell별 자동 집계 통계:
pc_survived_ratio: 생존률pc_remaining_hp_mean/std: 종료 HP 평균·표준편차total_turns_mean/std: tick 수 평균·표준편차
5. 배치 결과
{
"schema_version": "1.0",
"batch_id": "Anchor_Strategies_Compare",
"results": [
{"scenario_id": "strategy_never", /* 단일 결과 §2 */},
{"scenario_id": "strategy_always", /* ... */},
{"scenario_id": "strategy_touch_hold", /* ... */}
],
"comparison": {
"best_by": "pc_remaining_hp_ratio",
"ranking": ["strategy_touch_hold", "strategy_always", "strategy_never"],
"deltas": {
"strategy_touch_hold_vs_never": {"pc_remaining_hp_ratio": 0.42, "total_turns": 34}
}
}
}
6. 출력 위치 선택지
기획팀 결정 영역 (1차 응답서 §3-2 참조). 현 설계는 3가지 지원:
| 모드 | 출력 방식 | 용도 |
|---|---|---|
stdout |
표준 출력 스트림 | MCP execute_code 응답으로 즉시 수신 |
file |
Assets/Sim/Output/{scenario_id}_{timestamp}.json |
Editor 내 기록 보존 |
path |
사용자 지정 경로 (프로젝트 외부 가능) | 기획팀/.cache/ 등으로 직접 저장 |
ResultEmitter.Emit(result, mode, pathOptional) 시그니처.
7. 세부 로그 포맷 (record_detail=true 시)
별도 파일 detail_log_path가 가리키는 JSON (tick별 상태):
{
"scenario_id": "...",
"ticks": [
{
"t": 0.0,
"pc": {"hp": 100, "is_defencing": false, "attack_acc": 0.0},
"monsters": [{"id": "m1", "hp": 15, "attack_acc": 0.0}]
},
{
"t": 0.1,
"pc": {"hp": 100, "is_defencing": true},
"events": ["monster_m1_projectile_spawned", "pc_defence_activated"]
}
]
}
주의: 상세 로그 파일은 tick당 수 KB이므로 max_turns: 500 시나리오에서 수 MB까지 가능. 평소 off 권장, 밸런스 디버깅 시점만 on.
8. 후처리 가이드 (기획팀)
8-1. 단일 실행 분석
pc_remaining_hp_ratio를 "체감 난이도" 지표로 활용 (0.5 이상 = 여유, 0.2 이하 = 타이트)defence_active_ratio가 과도히 높으면 (>0.6) 방어가 의도보다 강력함 신호
8-2. 스윕 분석
pc_survived_ratio == 1.0이지만pc_remaining_hp_ratio편차가 큰 cell = 불안정 밸런스stats.total_turns_std / mean > 0.3= 난수 편차 과다 (시나리오 취약)
8-3. 배치 분석
comparison.ranking로 전략 우위 확인deltas로 구체 수치 차이 측정
9. 변경 이력
- v1 (2026-04-17): 초판.
10. 기각안
- 기각안 A: Markdown 결과 출력 → 후처리 자동화 곤란. JSON 구조화가 밸런싱 툴 호환성 최고
- 기각안 B: Excel/CSV 결과 → 중첩 구조(breakdown/sweep cells) 표현 제한. JSON + 필요 시 CSV 변환이 유연
- 기각안 C: tick 로그 항상 포함 → 토큰·디스크 낭비. 플래그 제어가 효율