Skip to content

ログ解析ロジック アーキテクチャドキュメント

概要

このドキュメントは、ゲームログを解析して試合情報(BAN/PICK、勝敗結果)を抽出する LogParser クラスのアーキテクチャを説明します。

ファイル構成

src/utils/logAnalyzer/          # フロント/バック共通のログ解析ライブラリ
├── LogParser.ts                # 一括解析モード(バッチ)
├── CharacterService.ts         # キャラクター名・ID変換サービス
├── StatisticsCalculator.ts    # 統計計算クラス
├── core/                       # 解析エンジン(2026-05 に 3 層分離)
│   ├── LogParserCore.ts        # 集約オーケストレータ(薄いラッパ)
│   ├── StreamLogParserV2.ts    # ストリーム解析(リアルタイム用、StreamFsm を内蔵)
│   ├── line/
│   │   └── LineParser.ts       # 純粋な行パーサ(regex / 抽出関数 / MARKER)
│   ├── fsm/
│   │   └── StreamFsm.ts        # phase 状態機械(IDLE→BP→LOADING→INGAME→RESULT)
│   └── aggregator/
│       └── Aggregator.ts       # 重複排除 / ソート / Normal 戦キャラ抽出
├── types.ts                    # 型定義
└── index.ts                    # エントリーポイント

scripts/analyze-log/            # CLIログ解析スクリプト
├── parsers/
│   └── LogParser.ts           # スクリプト用LogParser実装
├── services/
│   └── CharacterService.ts    # キャラクター変換サービス
├── statistics/
│   └── StatisticsCalculator.ts # 統計計算
├── reports/
│   └── ReportGenerator.ts     # レポート生成
└── index.ts                    # エントリーポイント

3 層分離の役割

Layerファイル責務テスト
Linecore/line/LineParser.ts1 行を受け取り構造化データを返す純粋関数(I/O・時間・Electron 依存なし)LineParser.test.ts table-driven
FSMcore/fsm/StreamFsm.tsphase の状態保持・遷移・onChange リスナーStreamFsm.test.ts 全遷移 1 ケース以上
Aggregatorcore/aggregator/Aggregator.ts解析結果の重複排除・ソート・Normal 戦キャラ抽出Aggregator.test.ts fixture ベース

LogParserCore.ts (114 行) は LineParser の関数を re-export し、Aggregator のメソッドを delegate するだけの薄いラッパ。互換のため既存 API シグネチャを維持する。

ログの構造

ゲームログには以下の重要なマーカーが含まれます:

1. BPフェーズ(BAN/PICK)関連

マーカー説明Rank/Normal
BP数据日志BAN/PICKの詳細情報(プレイヤー名、キャラID等)Rankのみ
匹配成功开始加载战斗マッチング成功・バトルロード開始(BPフェーズ終了)両方
PageBattleBanPick2V2.prefabBP画面のUI表示ログRankのみ

2. 試合進行関連

マーカー説明
ON GAME STARTゲーム開始
ON BATTLE END PUSHバトル終了
upload sdk battle player試合結果(プレイヤー名、勝敗)

3. マッチタイプ関連

マーカー説明
TYPE:Rank_2v2ランクマッチ2v2
TYPE:Rank_1v1ランクマッチ1v1
TYPE:Normal_2v2ノーマル2v2
TYPE:Normal_1v1ノーマル1v1
TYPE:Customカスタムマッチ

解析フロー

1. scanLogForMarkers()
   └── ログ全体をスキャンして重要な行番号を収集
       ├── bpEndLines[]      - BPフェーズ終了行
       ├── bpDataLines[]     - BP数据日志の行(Rank判定用)
       ├── gameStartLines[]  - ゲーム開始行
       ├── gameEndLines[]    - ゲーム終了行
       └── battleResultLines[] - 試合結果行

2. parseAllMatches()
   └── 試合ごとに解析
       ├── groupBattleResults()       - 連続した結果行をグループ化
       ├── findBpEndBeforeResult()    - 対応するBPフェーズ終了を探す
       ├── findMatchTypeBeforeResult() - TYPE:ログを探す
       ├── hasBpDataBeforeResult()    - BP数据日志の有無でRank判定
       ├── parseMatchBP()             - BAN/PICK情報を解析
       └── parseMatchResultDynamic()  - 勝敗結果を解析

Rank判定ロジック(2025-12-06修正済み)

マッチタイプ判定の優先順位

LogParserは以下の3段階でマッチタイプを判定します:

1. TYPE:ログによる明示的判定(最優先)

試合結果の前500行以内でTYPE:マーカーを検索:

typescript
const typeMatch = this.lines[i].match(/TYPE:(Rank_2v2|Rank_1v1|Normal_2v2|Normal_1v1|Custom|[\w_]+)/);

2. BP数据日志によるRank判定(フォールバック)

TYPE:が見つからない場合、BP数据日志の有無でRank判定:

typescript
if (!matchType && this.hasBpDataBeforeResult(resultStartLine, bpEndLine)) {
  matchType = playerCount === 2 ? 'Rank_1v1' : 'Rank_2v2';
}

BP数据日志の特性:

  • ランクマッチでのみ出力される
  • BAN/PICK情報(プレイヤー名、キャラID、チーム)を含む
  • ログ例:
    [Info]:00:00:30:547  BP数据日志---玩家:もーり(1046101022) P1 Team:TeamA TeamSort:0

3. プレイヤー数による推定(最終手段)

上記2つで判定できない場合、プレイヤー数から推定:

typescript
const is1v1 = matchType?.includes('1v1') || playerCount === 2;

hasBpDataBeforeResult()の実装

typescript
private hasBpDataBeforeResult(resultLine: number, bpEndLine: number | null): boolean {
  if (bpEndLine === null) return false;

  // 前のBPフェーズ終了行を探す(この試合のBPフェーズ開始点として使う)
  const prevBpEndIdx = this.bpEndLines.indexOf(bpEndLine) - 1;
  const bpStartLine = prevBpEndIdx >= 0 ? this.bpEndLines[prevBpEndIdx] + 1 : 0;

  // bpStartLine から resultLine の間に BP数据日志 があるか確認
  for (const bpDataLine of this.bpDataLines) {
    if (bpDataLine >= bpStartLine && bpDataLine < resultLine) {
      return true;
    }
  }
  return false;
}

ログの行番号関係(試合1の例)

行134〜    : BP数据日志(BAN/PICK情報)
行749     : 匹配成功开始加载战斗(BPフェーズ終了)
行953〜956: upload sdk battle player(試合結果)

この例では:

  1. bpStartLine = 0(最初の試合)
  2. bpEndLine = 749
  3. resultLine = 953
  4. bpDataLines内に134が含まれる
  5. 134 >= 0 && 134 < 953 → true → Rank判定成功

テスト用コマンド

bash
# ログ解析実行
cd c:/Users/mouri/Documents/devkit/broadcast-Overlay
npx tsx scripts/analyze-log/index.ts "scripts/testData/mouri/Log_2025_12_06.txt"

# BP数据日志の存在確認
grep -n "BP数据日志" scripts/testData/mouri/Log_2025_12_06.txt | head -10

# TYPE:ログの確認
grep -n "TYPE:" scripts/testData/mouri/Log_2025_12_06.txt | head -30

関連ファイル

ログ解析コア

CLIスクリプト

テストデータ

解析結果の出力内容

LogParserは以下の情報を抽出します:

1. 試合基本情報

  • 試合番号
  • タイムスタンプ
  • マッチタイプ(Rank_2v2, Normal_2v2, etc.)
  • ゲーム開始・終了時刻
  • 試合時間

2. プレイヤー情報

  • プレイヤー名
  • プレイヤーID(UID)
  • 勝敗結果
  • チーム(TeamA/TeamB)

3. BAN/PICK情報(ランクマッチのみ)

  • BANされたキャラクター
  • BANしたプレイヤー
  • ピックされたキャラクター
  • ピックしたプレイヤー

4. 統計情報

  • プレイヤー別勝敗数・勝率
  • キャラクター別BAN回数
  • キャラクター別ピック回数
  • 総試合数・ランクマッチ数