feat: support four-star leader outfits
Publish GitHub Pages output / publish (push) Successful in 48s
Publish GitHub Pages output / publish (push) Successful in 48s
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { leaderOutfitCards } from './leader-outfits.ts';
|
||||
import { calculateUnitPower, type UnitPowerCard } from './unit-power.ts';
|
||||
|
||||
function outfitCard(id: string, rarity: number, name: string, characterId = 'leader') {
|
||||
return { id, rarity, characterId, details: { costume: { name, description: '전원의 전체 파라미터가 35% UP' } } };
|
||||
}
|
||||
|
||||
test('리더의 4·5성 의상만 선택하고 기존 5성 순서와 이름 중복 제거를 유지한다', () => {
|
||||
const cards = [outfitCard('four', 4, '드리미 드롭'), outfitCard('five', 5, '기본 의상'),
|
||||
outfitCard('duplicate', 5, '기본 의상'), outfitCard('other', 4, '다른 멤버', 'other'),
|
||||
outfitCard('three', 3, '제외'), { ...outfitCard('none', 4, ''), details: { costume: null } }];
|
||||
assert.deepEqual(leaderOutfitCards(cards, 'leader').map((card) => card.id), ['five', 'four']);
|
||||
assert.deepEqual(leaderOutfitCards(cards, 'unknown'), []);
|
||||
assert.equal(cards[0].id, 'four');
|
||||
});
|
||||
|
||||
test('4성 의상만 있는 멤버도 선택할 수 있다', () => {
|
||||
assert.equal(leaderOutfitCards([outfitCard('four', 4, '드리미 드롭')], 'leader')[0].id, 'four');
|
||||
});
|
||||
|
||||
test('실제 4성 의상을 선택해 파라미터와 스코어 서포트에 반영한다', () => {
|
||||
type DataCard = ReturnType<typeof outfitCard>;
|
||||
const { cards }: { cards: DataCard[] } = JSON.parse(readFileSync(new URL('../data/cards-summary.json', import.meta.url), 'utf8'));
|
||||
const outfits = cards.filter((card) => card.rarity === 4 && card.details.costume);
|
||||
assert.ok(outfits.length > 0);
|
||||
for (const card of outfits) {
|
||||
assert.ok(leaderOutfitCards(cards, card.characterId).some((option) => option.id === card.id));
|
||||
}
|
||||
const members = ['a', 'b', 'c', 'd', 'e'].map((id) => ({
|
||||
card: { id, characterId: id, name: id, type: '큐트', generation: '0기생',
|
||||
power: { maxLevel: 80, statsAtMaxLevel: { performance: 100, technique: 100, sense: 100 } },
|
||||
details: { passive: [] } } satisfies UnitPowerCard,
|
||||
awakening: 0
|
||||
}));
|
||||
const parameter = outfits.find((card) => card.details.costume.description.trim() === '전원의 전체 파라미터가 35% UP');
|
||||
assert.ok(parameter);
|
||||
assert.equal(calculateUnitPower(members, parameter.details.costume).outfitTotal, 525);
|
||||
const support = outfits.find((card) => card.details.costume.description.trim() === '전원의 스코어 서포트 효과 50%');
|
||||
assert.ok(support);
|
||||
assert.equal(calculateUnitPower(members, support.details.costume).outfitScoreSupportPercent, 50);
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
type OutfitCard = {
|
||||
characterId: string;
|
||||
rarity: number;
|
||||
details: { costume: { name: string; description: string } | null };
|
||||
};
|
||||
|
||||
export function leaderOutfitCards<T extends OutfitCard>(cards: readonly T[], characterId: string): T[] {
|
||||
const seen = new Set<string>();
|
||||
return cards
|
||||
.filter((card) => card.characterId === characterId && (card.rarity === 4 || card.rarity === 5) && card.details.costume)
|
||||
.sort((left, right) => right.rarity - left.rarity)
|
||||
.filter((card) => {
|
||||
const name = card.details.costume!.name;
|
||||
if (seen.has(name)) return false;
|
||||
seen.add(name);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user