Skip to content

feat: 斗魂竞技场(CHERRY 多小队)适配 + bump 1.8.0#57

Merged
wnzzer merged 3 commits into
mainfrom
feat/arena-multiteam
May 10, 2026
Merged

feat: 斗魂竞技场(CHERRY 多小队)适配 + bump 1.8.0#57
wnzzer merged 3 commits into
mainfrom
feat/arena-multiteam

Conversation

@wnzzer
Copy link
Copy Markdown
Owner

@wnzzer wnzzer commented May 10, 2026

Summary

  • 让对局页 / 详情页 / 战绩列表 / AI 分析全套支持斗魂竞技场(CHERRY 模式,8 小队 × 2 人)
  • 数据模型从 team_one/team_two 二元字段统一到 subteams: Vec<Subteam>,5v5 是其特例(length=2)
  • 后端用 lol-end-of-game/v1/gameclient-eog-stats-block 拉权威 1~8 小队号——避开 lobby 阶段稀疏 teamParticipantId 的坑

关键改动

后端

  • StatsplayerSubteamId / subteamPlacement 字段
  • SessionData 重构成 { gameMode, isMultiTeam, mySubteamId, subteams }
  • process_session_data 走 CLASSIC / CHERRY 分支
  • 新增 eog_stats.rs 客户端,拉 16 名玩家的 puuid → subteamId 映射
  • 事件流 session-player-update-team-{one,two} 合并为 session-player-update + subteamId payload

前端

  • 新增 SubteamCard 组件 + PlayerCard density: 'normal'|'compact' 变体
  • Gaming.vue 用 grid:CLASSIC 两列,CHERRY 两列 × 自动行 + 整页可滚
  • useMatchDetailPlayers 在 CHERRY 时按 playerSubteamId 分组,标题显示"队伍 N · 第 X 名"
  • RecordCard CHERRY 局右上角显示"第 X 名"
  • AI prompt buildTeamAnalysisPromptsubteams 数组动态构造

Spec & 探针

  • spec:docs/superpowers/specs/2026-05-10-arena-multiteam-support-design.md
  • 探针:src-tauri/examples/probe_arena.rs 复用 LCU 鉴权直接落盘,schema 变化时可重跑

Test plan

  • npm run check 全绿(prettier + eslint + vue-tsc + cargo fmt + clippy -Dwarnings)
  • npm run test 217 前端测试通过(含新增 useMatchDetailPlayers.spec.ts
  • cargo test --lib 95 后端测试通过(含 5 个 session 单测:CLASSIC swap、CHERRY 分组、稀疏 tpid 保留)
  • 真实斗魂局:8 小队 × 2 人正确配对(EOG 端点担保)
  • 真实斗魂局:详情页按名次升序,标题"队伍 N · 第 X 名"
  • 真实斗魂局:战绩列表"第 X 名"
  • 5v5 排位 / 海克斯乱斗:行为零回归(左右两栏)
  • 选英雄阶段(EOG 不可用时)回退到 tpid 分组——下次进选英雄时回归测试

已知限制

  • CHERRY 选英雄阶段 EOG 端点尚不可用,会回退到稀疏 tpid 分组(可能 >8 小队)。InProgress 后立刻切换为权威 1~8 配对。

Copilot AI review requested due to automatic review settings May 10, 2026 11:41
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

该 PR 将对局会话模型从传统的 teamOne/teamTwo 二元结构升级为统一的 subteams 多小队结构,以支持斗魂竞技场(CHERRY,8 队 × 2 人)在对局页、详情页、战绩列表和 AI 分析中的完整展示,并同步版本号至 1.8.0。

Changes:

  • 会话数据契约重构:前后端统一为 subteams(CLASSIC 退化为 2 个 subteam;CHERRY 为多 subteam)。
  • CHERRY 分组能力接入:详情页/战绩列表按 playerSubteamId/subteamPlacement 展示小队与名次;对局页新增 SubteamCard 网格展示。
  • 后端新增 EOG stats 客户端并调整事件流:session-player-update-team-{one,two} 合并为 session-player-update(带 subteamId)。

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
lol-record-analysis-tauri/src/views/Gaming.vue 对局页改为按 subteams 渲染网格,并根据是否多小队切换紧凑布局
lol-record-analysis-tauri/src/types/domain/match.ts ParticipantStats 增加 CHERRY 小队/名次字段
lol-record-analysis-tauri/src/types/domain/gaming.ts SessionData 重构为 subteams 统一模型
lol-record-analysis-tauri/src/services/ai/prompts/team.ts AI team prompt 改为按 subteams 动态构造;player prompt 拆分
lol-record-analysis-tauri/src/services/ai/prompts/team-player.ts 新增单玩家分析 prompt 文件
lol-record-analysis-tauri/src/composables/useSessionTiers.ts 段位展示改为 subteamId -> TierDisplay[]
lol-record-analysis-tauri/src/composables/useSessionSync.ts 前端 session 同步逻辑适配 subteams + 合并后的 player-update 事件
lol-record-analysis-tauri/src/composables/useMatchDetailPlayers.ts CHERRY 模式下按 playerSubteamId 分组并按名次排序展示
lol-record-analysis-tauri/src/composables/useMatchDetailPlayers.spec.ts 新增 CHERRY 分组测试用例
lol-record-analysis-tauri/src/components/record/RecordCard.vue CHERRY 战绩卡片右上角展示“第 X 名”
lol-record-analysis-tauri/src/components/record/MatchDetailModal.vue 详情页布局微调(防止 shrink)
lol-record-analysis-tauri/src/components/gaming/SubteamCard.vue 新增小队卡片组件,内部渲染 PlayerCard + 占位
lol-record-analysis-tauri/src/components/gaming/PlayerHistoryGrid.vue 样式微调避免换行/压缩
lol-record-analysis-tauri/src/components/gaming/PlayerCard.vue 增加 density 变体与 mine/enemy 边框样式
lol-record-analysis-tauri/src-tauri/tauri.conf.json 版本号 bump 到 1.8.0
lol-record-analysis-tauri/src-tauri/src/lcu/api/session.rs Queue/OnePlayer 补充 gameMode/teamParticipantId 字段
lol-record-analysis-tauri/src-tauri/src/lcu/api/model.rs Stats 补充 CHERRY subteam 字段并添加反序列化测试
lol-record-analysis-tauri/src-tauri/src/lcu/api/eog_stats.rs 新增 EOG stats block 客户端用于 CHERRY 权威分组
lol-record-analysis-tauri/src-tauri/src/lcu/api.rs 导出 eog_stats 模块
lol-record-analysis-tauri/src-tauri/src/command/session.rs 后端 session 主流程重构为 CLASSIC/CHERRY 分支 + 新事件流
lol-record-analysis-tauri/src-tauri/examples/probe_arena.rs 新增探针示例用于落盘斗魂相关 schema
docs/superpowers/specs/2026-05-10-arena-multiteam-support-design.md 新增设计文档说明多小队适配方案

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +495 to +520
// 我方组优先;其它按 key 升序
let mut groups: Vec<Vec<crate::lcu::api::session::OnePlayer>> = grouped.into_values().collect();
groups.sort_by_key(|g| !g.iter().any(|p| p.puuid == *my_puuid));

// 删除 Tag 标记(减少数据量)
delete_meet_gamers_record(&mut session_data);
let to_summoner = |p: &crate::lcu::api::session::OnePlayer| SessionSummoner {
champion_id: p.champion_id,
champion_key: format!("champion_{}", p.champion_id),
summoner: Summoner {
puuid: p.puuid.clone(),
..Default::default()
},
..Default::default()
};

// 发送完成事件
app_handle
.emit("session-complete", &session_data)
.map_err(|e| e.to_string())?;
let mut subteams: Vec<Subteam> = Vec::with_capacity(groups.len());
let mut my_subteam_id = 0;
for (i, group) in groups.iter().enumerate() {
let subteam_id = (i as i32) + 1;
if group.iter().any(|p| p.puuid == *my_puuid) {
my_subteam_id = subteam_id;
}
subteams.push(Subteam {
subteam_id,
players: group.iter().map(to_summoner).collect(),
});
}
Comment on lines 236 to 250
if phase == "ChampSelect" {
match get_champion_select_session().await {
Ok(select_session) => {
// 转换类型:从 champion_select::OnePlayer 到 session::OnePlayer
session.game_data.team_one = select_session
.my_team
.into_iter()
.map(|p| crate::lcu::api::session::OnePlayer {
champion_id: p.champion_id,
puuid: p.puuid,
selected_position: String::new(),
team_participant_id: 0,
})
.collect();
session.game_data.team_two.clear(); // 选英雄阶段看不到对手
session.game_data.team_two.clear();
}
Comment on lines +27 to +32
<script setup lang="ts">
import { computed } from 'vue'
import { NTag } from 'naive-ui'
import PlayerCard from './PlayerCard.vue'
import type { Subteam } from '@renderer/types/domain/gaming'
import type { TierDisplay } from '@renderer/composables/useSessionTiers'
* 对局会话领域模型:当前 session / 我方与敌方
* 对局会话领域模型:subteams 统一模型
* - CLASSIC 模式:subteams.length === 2,[0] 是我方,[1] 是敌方
* - CHERRY 模式:subteams.length 为 1~8(按 teamParticipantId 临时分组)
@wnzzer wnzzer force-pushed the feat/arena-multiteam branch 3 times, most recently from 34234dc to ae2b7c1 Compare May 10, 2026 12:29
wnzzer added 3 commits May 10, 2026 20:29
The spec documents the data contract changes and design for斗魂竞技场
(CHERRY mode) support. The probe binary at src-tauri/examples/probe_arena.rs
reuses existing LCU auth to dump session/match-detail/champ-select JSON to
.claude/plans/arena-probe/, useful for re-verifying schema when LCU
contract changes.
让对局页 / 详情页 / 战绩列表 / AI 分析全套支持斗魂竞技场(CHERRY 模式,
8 小队 × 2 人)。数据模型从 team_one / team_two 二元字段统一到
subteams: Vec<Subteam>,5v5 是其特例(length=2)。

后端
- Stats 加 playerSubteamId / subteamPlacement 字段
- SessionData 重构成 { gameMode, isMultiTeam, mySubteamId, subteams }
- process_session_data 走 CLASSIC / CHERRY 分支
- 新增 lol-end-of-game/v1/gameclient-eog-stats-block 客户端,InProgress
  阶段拉 16 人 puuid → subteamId(1-8) 权威映射;champ-select 等 EOG 不
  可用时回退到 lobby 的 teamParticipantId 分组
- 事件流 session-player-update-team-{one,two} 合并为 session-player-update
  + subteamId payload
- add_pre_group_markers / insert_meet_gamers_record 等改成遍历 subteams

前端
- 新增 SubteamCard 组件 + PlayerCard density: 'normal'|'compact' 变体
- Gaming.vue 用 grid:CLASSIC 两列、CHERRY 两列 × 自动行 + 整页可滚
- useMatchDetailPlayers 在 CHERRY 时按 playerSubteamId 分组,标题显示
  '队伍 N · 第 X 名';非 CHERRY 走原 teamId 分组
- RecordCard CHERRY 局右上角显示 '第 X 名'
- AI prompt buildTeamAnalysisPrompt 按 subteams 数组动态构造,CHERRY
  和 CLASSIC 两种模板分支;buildPlayerAnalysisPrompt 拆到 team-player.ts

测试
- Rust:5 个 session 单测覆盖 CLASSIC swap / CHERRY 8 小队 / 残局 / 稀疏
  tpid 不强行配对
- TS:useMatchDetailPlayers.spec.ts 验证 CHERRY 按 subteamId 分组、按
  placement 升序,CLASSIC 仍按 win/loss 排序
@wnzzer wnzzer merged commit 54665a1 into main May 10, 2026
3 checks passed
@wnzzer wnzzer deleted the feat/arena-multiteam branch May 10, 2026 12:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants