BurningTimesAi/프로젝트/수상한잡화점/시뮬레이터/03_결과_JSON_포맷_v1.md

6.8 KiB
Raw Blame History

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 로그 항상 포함 → 토큰·디스크 낭비. 플래그 제어가 효율