refactor: 收口 BangDream 玩家卡牌列表规格
This commit is contained in:
parent
68b55764c2
commit
322938ae6f
@ -385,6 +385,7 @@ export interface TsuguHook {
|
||||
- 已新增 `render-blocks/event-stage-spec.ts`,收口试炼列表最大列高、歌曲单元格/封面/ID/难度条尺寸、试炼类型顶部文字规格和换列判断;`event-stage.ts` 与 `list-event-stage.ts` 改为消费 spec,活动/歌曲选择和输出结构保持不变。
|
||||
- 线上 smoke 暴露 `/查试炼 310 -m` 将所有列横向拼成一张巨大 canvas 会触发 Pod `OOMKilled exit=137`;已改为按小批次绘制 stage、边分列边输出多张 CQ 图片,不再创建最终横向巨图,普通版和 meta 版均拆成 5 张输出,同时避免完全串行导致冷缓存首条命令耗时过长。
|
||||
- 已新增 `event-stage-spec.spec.ts`,覆盖试炼歌曲行尺寸、类型顶部文字规格、换列判断和按列高拆分算法;本地生成 `event-stage-split-310*.jpg`、`event-stage-split-310-meta*.jpg`,验证 `/查试炼 310` 与 `/查试炼 310 -m` 图片输出正常。
|
||||
- 已新增 `render-blocks/list-player-card-icon-spec.ts`,收口玩家详情主卡组展示顺序、默认行高、文本字号比例、卡牌间距比例和卡牌图标可见性标记;`list-player-card-icon-list.ts` 改为消费 spec,主卡组渲染顺序和输出结构保持不变;`list-player-card-icon-spec.spec.ts` 覆盖历史卡牌顺序、缺失条目跳过和字号/间距计算,本地 `/查玩家 26591455 jp` 图片 smoke 输出非空。
|
||||
- smoke/Jenkins/远程调试卡点继续按已固化规则处理:同一卡点第二次尝试前必须改变可验证变量;Jenkins 查询 URL 含方括号时用 `curl -g` 或改查 Jenkins home;线上图片 smoke 必须查询 `commandId`、拉回图片、展示图片、查日志并清理本轮临时目录;PowerShell 双引号 here-string 中不要写 JS `${...}` 模板字面量,避免被 PowerShell 提前插值;smoke 没有真实图片落盘时必须失败。
|
||||
|
||||
### Phase 6:策略 policy 和时间/档线规则
|
||||
|
||||
@ -3,6 +3,12 @@ import { Player } from '@/qqbot/plugins/bangDream/tsugu/models/player';
|
||||
import { Canvas } from 'skia-canvas';
|
||||
import { drawCardIcon } from '@/qqbot/plugins/bangDream/tsugu/render-blocks/card-art';
|
||||
import { drawList } from './list-frame';
|
||||
import {
|
||||
BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC,
|
||||
getPlayerCardIconListSpacing,
|
||||
getPlayerCardIconListTextSize,
|
||||
sortPlayerMainDeckEntries,
|
||||
} from './list-player-card-icon-spec';
|
||||
|
||||
/**
|
||||
* 在图片布局层中绘制玩家卡牌In列表。
|
||||
@ -17,19 +23,14 @@ export async function drawPlayerCardInList(
|
||||
player: Player,
|
||||
key?: string,
|
||||
cardIdVisible = false,
|
||||
lineHeight = 184,
|
||||
lineHeight = BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.list.defaultLineHeight,
|
||||
): Promise<Canvas> {
|
||||
const textSize = (lineHeight / 200) * 180;
|
||||
const spacing = (lineHeight / 200) * 13;
|
||||
const textSize = getPlayerCardIconListTextSize(lineHeight);
|
||||
const spacing = getPlayerCardIconListSpacing(lineHeight);
|
||||
const promiseList: Promise<Canvas>[] = [];
|
||||
const tempCardDataList = player.profile.mainDeckUserSituations.entries;
|
||||
//将tempCardDataList调整顺序,为3,1,0,2,4
|
||||
const defaultCardSort = [3, 1, 0, 2, 4];
|
||||
const cardDataList = [];
|
||||
for (let i = 0; i < defaultCardSort.length; i++) {
|
||||
const tempCardData = tempCardDataList[defaultCardSort[i]];
|
||||
cardDataList.push(tempCardData);
|
||||
}
|
||||
const cardDataList = sortPlayerMainDeckEntries(
|
||||
player.profile.mainDeckUserSituations.entries,
|
||||
);
|
||||
const cardIconList: Array<Canvas> = [];
|
||||
for (const i in cardDataList) {
|
||||
const tempCardData = cardDataList[i];
|
||||
@ -40,8 +41,9 @@ export async function drawPlayerCardInList(
|
||||
illustrationTrainingStatus: tempCardData.illust == 'after_training',
|
||||
limitBreakRank: tempCardData.limitBreakRank,
|
||||
cardIdVisible: cardIdVisible,
|
||||
skillTypeVisible: true,
|
||||
cardTypeVisible: false,
|
||||
skillTypeVisible:
|
||||
BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.card.showSkillType,
|
||||
cardTypeVisible: BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.card.showCardType,
|
||||
skillLevel: tempCardData.skillLevel,
|
||||
}),
|
||||
);
|
||||
|
||||
@ -0,0 +1,41 @@
|
||||
export const BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC = {
|
||||
card: {
|
||||
defaultOrder: [3, 1, 0, 2, 4],
|
||||
showCardType: false,
|
||||
showSkillType: true,
|
||||
},
|
||||
list: {
|
||||
defaultLineHeight: 184,
|
||||
spacingRatio: 13 / 200,
|
||||
textSizeRatio: 180 / 200,
|
||||
},
|
||||
} as const;
|
||||
|
||||
/**
|
||||
* 计算玩家卡牌列表文本字号。
|
||||
*
|
||||
* @param lineHeight - 列表行高。
|
||||
*/
|
||||
export function getPlayerCardIconListTextSize(lineHeight: number) {
|
||||
return lineHeight * BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.list.textSizeRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* 计算玩家卡牌列表卡牌间距。
|
||||
*
|
||||
* @param lineHeight - 列表行高。
|
||||
*/
|
||||
export function getPlayerCardIconListSpacing(lineHeight: number) {
|
||||
return lineHeight * BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.list.spacingRatio;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按历史展示顺序排列玩家主卡组。
|
||||
*
|
||||
* @param entries - 玩家主卡组条目。
|
||||
*/
|
||||
export function sortPlayerMainDeckEntries<T>(entries: T[]): T[] {
|
||||
return BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.card.defaultOrder
|
||||
.map((index) => entries[index])
|
||||
.filter((entry): entry is T => entry !== undefined);
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
import {
|
||||
BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC,
|
||||
getPlayerCardIconListSpacing,
|
||||
getPlayerCardIconListTextSize,
|
||||
sortPlayerMainDeckEntries,
|
||||
} from '@/qqbot/plugins/bangDream/tsugu/render-blocks/list-player-card-icon-spec';
|
||||
|
||||
describe('BangDream player card icon list spec', () => {
|
||||
it('keeps player card list text and spacing ratios stable', () => {
|
||||
const lineHeight =
|
||||
BANGDREAM_PLAYER_CARD_ICON_LIST_SPEC.list.defaultLineHeight;
|
||||
|
||||
expect(lineHeight).toBe(184);
|
||||
expect(getPlayerCardIconListTextSize(lineHeight)).toBe(165.6);
|
||||
expect(getPlayerCardIconListSpacing(lineHeight)).toBe(11.96);
|
||||
});
|
||||
|
||||
it('keeps historical player deck display order', () => {
|
||||
expect(sortPlayerMainDeckEntries(['0', '1', '2', '3', '4'])).toEqual([
|
||||
'3',
|
||||
'1',
|
||||
'0',
|
||||
'2',
|
||||
'4',
|
||||
]);
|
||||
});
|
||||
|
||||
it('skips missing deck entries without changing the remaining order', () => {
|
||||
expect(sortPlayerMainDeckEntries(['0', '1', '2'])).toEqual([
|
||||
'1',
|
||||
'0',
|
||||
'2',
|
||||
]);
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user