BattleSessionQuery.kt

package io.github.lishangbu.avalon.game.battle.engine.core.session

import io.github.lishangbu.avalon.game.battle.engine.core.runtime.flow.BattleRuntimeSnapshot

/**
 * BattleSession 对外查询结果。
 *
 * 设计意图:
 * - 把 session 当前对外可见的状态收拢成稳定 DTO。
 * - 避免调用方直接分别拉取 snapshot、pending actions、replacement requests、logs。
 *
 * @property snapshot 当前 battle 快照。
 * @property pendingActions 当前待执行行动列表。
 * @property choiceStatuses 当前回合各 side 的输入状态。
 * @property replacementRequests 当前待处理替补请求。
 * @property resourceLedger 当前全部资源账本条目。
 * @property battleLogs 人类可读 battle log。
 * @property eventLogs 结构化事件日志。
 */
data class BattleSessionQuery(
    val snapshot: BattleRuntimeSnapshot,
    val pendingActions: List<BattleSessionAction>,
    val choiceStatuses: List<BattleSessionChoiceStatus>,
    val replacementRequests: List<BattleSessionReplacementRequest>,
    val resourceLedger: List<BattleSessionResourceUsage>,
    val battleLogs: List<String>,
    val eventLogs: List<BattleSessionEvent>,
) {
    /**
     * 当前运行中回合的派生状态。
     *
     * 说明:
     * - 这是 session 级的运行时视图,不落到 `BattleState`。
     * - 只有 battle 进入 `RUNNING` 之后,这个值才有意义。
     */
    val turnStatus: BattleSessionTurnStatus?
        get() =
            BattleSessionTurnStatus.from(
                lifecycle = snapshot.battle.lifecycle,
                hasPendingReplacement = replacementRequests.isNotEmpty(),
                readyToResolve = choiceStatuses.isNotEmpty() && choiceStatuses.all(BattleSessionChoiceStatus::ready),
            )

    /**
     * 结构化事件的强类型 payload 视图。
     *
     * 设计意图:
     * - 让调用方直接消费强类型 payload,而不是再从松散 attributes 反推事件语义。
     * - 保持 `eventLogs` 作为完整事件壳的同时,提供更贴近业务的 typed 访问入口。
     */
    val eventPayloads: List<BattleSessionEventPayload>
        get() = eventLogs.map(BattleSessionEvent::payload)

    /**
     * 已入队动作事件的强类型视图。
     */
    val queuedActionEvents: List<BattleSessionQueuedActionPayload>
        get() = eventPayloads.filterIsInstance<BattleSessionQueuedActionPayload>()

    /**
     * 已执行动作事件的强类型视图。
     */
    val executedActionEvents: List<BattleSessionExecutedActionPayload>
        get() = eventPayloads.filterIsInstance<BattleSessionExecutedActionPayload>()

    /**
     * 捕捉资源账本的强类型视图。
     *
     * 设计意图:
     * - 让结算与投影逻辑可以直接消费捕捉账本,而不是再从泛型账本列表中手动筛选。
     */
    val captureResourceLedger: List<BattleSessionCaptureResourceUsage>
        get() = resourceLedger.filterIsInstance<BattleSessionCaptureResourceUsage>()
}