fix: total materials across all member boards
Publish GitHub Pages output / publish (push) Successful in 32s

This commit is contained in:
2026-09-01 22:37:08 +09:00
parent c0f4060dec
commit a920d65a21
+26 -16
View File
@@ -161,8 +161,8 @@
$: filteredConnectCards = connectCards.filter((card) => { $: filteredConnectCards = connectCards.filter((card) => {
return cardMatchesSearch(card, boardCardSearch); return cardMatchesSearch(card, boardCardSearch);
}); });
$: selectedBoardMaterialTotals = boardMaterialTotals(selectedMemberId, selectedActiveBoardNodes); $: allBoardMaterialTotals = boardMaterialTotals(userData.memberBoards);
$: selectedBoardPointTotal = selectedActiveBoardNodes.reduce((total, groupId) => total + (nodeForBoardMember(selectedMemberId, groupId)?.skillTreePointCost ?? 0), 0); $: allBoardPointTotal = boardPointTotal(userData.memberBoards);
$: efficiencyLeaderOutfitOptions = efficiencyFormation.leaderCharacterId $: efficiencyLeaderOutfitOptions = efficiencyFormation.leaderCharacterId
? fiveStarCards.filter((card) => card.characterId === efficiencyFormation.leaderCharacterId && card.details.costume) ? fiveStarCards.filter((card) => card.characterId === efficiencyFormation.leaderCharacterId && card.details.costume)
.filter((card, index, cards) => cards.findIndex((candidate) => candidate.details.costume?.name === card.details.costume?.name) === index) .filter((card, index, cards) => cards.findIndex((candidate) => candidate.details.costume?.name === card.details.costume?.name) === index)
@@ -586,13 +586,15 @@
}, { points: 0, greenCubes: 0, greenCoreCubes: 0 }); }, { points: 0, greenCubes: 0, greenCoreCubes: 0 });
} }
function boardMaterialTotals(memberId: string, groupIds: readonly string[]): BoardMaterialTotal[] { function boardMaterialTotals(memberBoards: Record<string, string[]>): BoardMaterialTotal[] {
const totals = new Map<string, number>(); const totals = new Map<string, number>();
for (const groupId of groupIds) { for (const [memberId, groupIds] of Object.entries(memberBoards)) {
const node = nodeForBoardMember(memberId, groupId); for (const groupId of groupIds) {
for (const consumption of node?.consumptions ?? []) { const node = nodeForBoardMember(memberId, groupId);
const quantity = Number(consumption.quantity) || 0; for (const consumption of node?.consumptions ?? []) {
totals.set(consumption.resourceId, (totals.get(consumption.resourceId) ?? 0) + quantity); const quantity = Number(consumption.quantity) || 0;
totals.set(consumption.resourceId, (totals.get(consumption.resourceId) ?? 0) + quantity);
}
} }
} }
return [...totals.entries()] return [...totals.entries()]
@@ -600,6 +602,12 @@
.map(([resourceId, quantity]) => ({ resourceId, quantity, label: boardMaterialLabels[resourceId] ?? resourceId })); .map(([resourceId, quantity]) => ({ resourceId, quantity, label: boardMaterialLabels[resourceId] ?? resourceId }));
} }
function boardPointTotal(memberBoards: Record<string, string[]>): number {
return Object.entries(memberBoards).reduce((total, [memberId, groupIds]) =>
total + groupIds.reduce((memberTotal, groupId) =>
memberTotal + (nodeForBoardMember(memberId, groupId)?.skillTreePointCost ?? 0), 0), 0);
}
function currentFormationPower(memberBoards: Record<string, string[]>, boardCards: BoardCardPlacements = userData.boardCards): number { function currentFormationPower(memberBoards: Record<string, string[]>, boardCards: BoardCardPlacements = userData.boardCards): number {
if (!efficiencyFormationReady) return 0; if (!efficiencyFormationReady) return 0;
const members = efficiencyFormation.cardIds.map((id, index) => ({ const members = efficiencyFormation.cardIds.map((id, index) => ({
@@ -1360,13 +1368,6 @@
<p><strong>{selectedActiveBoardNodeCount}</strong> / {selectedBoardNodeCount}개 활성화</p> <p><strong>{selectedActiveBoardNodeCount}</strong> / {selectedBoardNodeCount}개 활성화</p>
<div><button type="button" on:click={activateAllBlueNodes}>모든 파란 노드 활성화</button><button type="button" on:click={() => setAllBoardNodes(true)}>모두 활성화</button><button type="button" on:click={() => setAllBoardNodes(false)}>모두 해제</button></div> <div><button type="button" on:click={activateAllBlueNodes}>모든 파란 노드 활성화</button><button type="button" on:click={() => setAllBoardNodes(true)}>모두 활성화</button><button type="button" on:click={() => setAllBoardNodes(false)}>모두 해제</button></div>
</div> </div>
<div class="board-material-summary" aria-label="활성 보드 재료 총합">
<span><small>노드 포인트</small><strong>{selectedBoardPointTotal.toLocaleString('ko-KR')}</strong></span>
{#each selectedBoardMaterialTotals as material (material.resourceId)}
<span><small>{material.label}</small><strong>{material.quantity.toLocaleString('ko-KR')}</strong></span>
{/each}
{#if selectedBoardMaterialTotals.length === 0}<p>활성 노드에 사용된 재료가 없습니다.</p>{/if}
</div>
<div <div
class="board-scroll" class="board-scroll"
class:dragging={boardDragging} class:dragging={boardDragging}
@@ -1474,6 +1475,14 @@
</div> </div>
{/if} {/if}
{/if} {/if}
<div class="board-material-summary" aria-label="전체 보드 재료 총합">
<h3>전체 보드 재료 합계</h3>
<span><small>노드 포인트</small><strong>{allBoardPointTotal.toLocaleString('ko-KR')}</strong></span>
{#each allBoardMaterialTotals as material (material.resourceId)}
<span><small>{material.label}</small><strong>{material.quantity.toLocaleString('ko-KR')}</strong></span>
{/each}
{#if allBoardMaterialTotals.length === 0}<p>활성 노드에 사용된 재료가 없습니다.</p>{/if}
</div>
</section> </section>
</div> </div>
{/if} {/if}
@@ -1593,7 +1602,8 @@
.board-toolbar p strong { color: #f0a1c2; font-size: 16px; } .board-toolbar p strong { color: #f0a1c2; font-size: 16px; }
.board-toolbar div { display: flex; gap: 6px; } .board-toolbar div { display: flex; gap: 6px; }
.board-toolbar button { padding: 6px 9px; border: 1px solid #394252; border-radius: 7px; color: #aeb7c5; background: #202630; font-size: 12px; font-weight: 750; cursor: pointer; } .board-toolbar button { padding: 6px 9px; border: 1px solid #394252; border-radius: 7px; color: #aeb7c5; background: #202630; font-size: 12px; font-weight: 750; cursor: pointer; }
.board-material-summary { display: flex; flex-wrap: wrap; gap: 7px; margin: 0 0 12px; padding: 10px; border: 1px solid #303a47; border-radius: 10px; background: #131922; } .board-material-summary { display: flex; flex-wrap: wrap; gap: 7px; margin: 18px 0 0; padding: 10px; border: 1px solid #303a47; border-radius: 10px; background: #131922; }
.board-material-summary h3 { width: 100%; margin: 0 0 3px; color: #dce3eb; font-size: 14px; }
.board-material-summary span { display: grid; gap: 2px; min-width: 108px; padding: 7px 9px; border-radius: 7px; background: #1c2430; } .board-material-summary span { display: grid; gap: 2px; min-width: 108px; padding: 7px 9px; border-radius: 7px; background: #1c2430; }
.board-material-summary small { color: #8490a0; font-size: 11px; } .board-material-summary small { color: #8490a0; font-size: 11px; }
.board-material-summary strong { color: #dce3eb; font-size: 14px; } .board-material-summary strong { color: #dce3eb; font-size: 14px; }