feedback1 WB: bounty-half evidence stated as a trend with its counter-evidence; queued free offers counted on the pill and header

- tools/build-data.mjs bountyDraftHalf: exact faction-series counts (12 of 18 two-battle cards bring first-half
  enemies, 5 outside the wave tables, enemyeffect_12_4 a second-half attachment), base-HP gradient, the user's
  two-battle recall; counter-evidence (假想敌 named enemyInitial_*, the unread NGA R3 guide); the split marked
  [ASSUMED] with its flip; data unchanged
- server/match/choices.js, docs/META.md, docs/DATA.md: the split marked [ASSUMED]
- m.private shop.rewardOffer.queued: offers waiting behind the shown one; the header says 之后还有 N 项 and the
  reminder pill +N (a 定向投放 behind a promotion reward put off)
- tests: corrected headers, the stale bountyTiers fixture dropped, queued checks (unit + opt-in e2e on desktop
  and 756x366)
This commit is contained in:
sganggs committed 2026-10-03 02:38:42 +08:00
1 parent 49c0ebcf4d
commit 6e0c26af9e
14 files changed
+158 -37

No files matched your search

+7 -3
View File
@@ -543,18 +543,22 @@ export function completesMerge(priv, slot, { getChess = () => null, getItem = ()
* reads 晋升奖励 / PROMOTION; any other offer — a strategy's special refresh (凯瑟琳 定向投放, 娜仁图亚 见者有份), an item
* (寻呼模块, 信标) or a 特质 (松果) — reads its `label` with the refresh icon (player report #6 after 0.1.0: 凯瑟琳's three
* items showed up as nameless operator cards under 晋升奖励). `items` = the offer holds items (cards drawn as item cards).
* `queued` = offers waiting behind this one (shop.rewardOffer.queued, e.g. a 定向投放 behind a promotion reward put
* off): `more` (header) and the pill's "+N" say so, null / no suffix when none.
* @param {any} offer
* @returns {{ title: string, micro: string, sub: string, icon: string, items: boolean, pill: string }}
* @returns {{ title: string, micro: string, sub: string, icon: string, items: boolean, pill: string, queued: number, more: string|null }}
*/
export function offerHeader(offer) {
const slots = isObj(offer) && Array.isArray(offer.slots) ? offer.slots : [];
const items = slots.some((s) => isObj(s) && s.kind === 'item');
const label = isObj(offer) && typeof offer.label === 'string' && offer.label ? offer.label : null;
const queued = isObj(offer) && Number.isInteger(offer.queued) && offer.queued > 0 ? offer.queued : 0;
const tail = { queued, more: queued ? `之后还有 ${queued} 项` : null };
if (!items && (!isObj(offer) || offer.source === 'merge' || offer.source == null) && !label) {
return { title: '晋升奖励', micro: 'PROMOTION', sub: '免费选择 1 名', icon: 'crown', items: false, pill: '晋升奖励待选择' };
return { title: '晋升奖励', micro: 'PROMOTION', sub: '免费选择 1 名', icon: 'crown', items: false, pill: '晋升奖励待选择', ...tail };
}
const title = label || (items ? '装备补给' : '特殊招募');
return { title, micro: 'SPECIAL', sub: items ? '免费选择 1 件' : '免费选择 1 名', icon: 'refresh', items, pill: `${title}待选择` };
return { title, micro: 'SPECIAL', sub: items ? '免费选择 1 件' : '免费选择 1 名', icon: 'refresh', items, pill: `${title}待选择`, ...tail };
}
/**