feat: improve combination search and offline build

This commit is contained in:
dal4segno committed 2026-08-18 20:59:20 +09:00
1 parent ee3498d146
commit d0f7654998
20 files changed
+552 -99

No files matched your search

+16 -25
View File
@@ -50,7 +50,7 @@
const skillConditionOptions: SkillConditionStatus[] = ['일반', '조건부'];
const activeProbabilityOptions: ActiveProbability[] = ['높음', '중간'];
const cardVariantOptions = ['일반', ...new Set(cards.map((card) => card.versionName).filter(Boolean))];
const generationOptions = [...new Set(cards.map((card) => card.generation).filter(Boolean))];
const generationOptions = [...new Set(cards.flatMap((card) => generationMemberships(card.generation)))];
let selectedTypes = [...typeOptions];
let selectedStats = [...statOptions];
@@ -102,7 +102,7 @@
&& selectedSpecialConditions.includes(skillConditionStatus(card.details.special))
&& selectedActiveProbabilities.includes(activeProbabilityStatus(card.details.active))
&& selectedCardVariants.includes(cardVariantStatus(card))
&& selectedGenerations.includes(card.generation)
&& generationMemberships(card.generation).some((generation) => selectedGenerations.includes(generation))
);
$: allSelected = selectedTypes.length === typeOptions.length
@@ -158,7 +158,8 @@
selectedSpecialConditions = data.preferences.specialConditions.filter((value): value is SkillConditionStatus => skillConditionOptions.includes(value as SkillConditionStatus));
selectedActiveProbabilities = data.preferences.activeProbabilities.filter((value): value is ActiveProbability => activeProbabilityOptions.includes(value as ActiveProbability));
selectedCardVariants = data.preferences.cardVariants.filter((value) => cardVariantOptions.includes(value));
selectedGenerations = data.preferences.generations.filter((value) => generationOptions.includes(value));
selectedGenerations = [...new Set(data.preferences.generations.flatMap(generationMemberships))]
.filter((value) => generationOptions.includes(value));
collection = data.collection;
memberBoards = data.memberBoards;
boardCards = data.boardCards;
@@ -171,6 +172,10 @@
return card.versionName || '일반';
}
function generationMemberships(generation: string): string[] {
return generation.split(/\s*\/\s*/).filter(Boolean).map(generationLabel);
}
function generationLabel(generation: string): string {
return generation
.replace(/^hololive EN /, '')
@@ -459,7 +464,6 @@
<div class="skill-grid">
<section class="skill-card passive-card">
<header>
<span class="skill-symbol" aria-hidden="true">패</span>
<h4>패시브</h4>
</header>
{#if passive}
@@ -477,7 +481,6 @@
<section class="skill-card active-card">
<header>
<span class="skill-symbol" aria-hidden="true">액</span>
<h4>액티브</h4>
{#if active?.condition}<span class="condition-badge">조건부</span>{/if}
</header>
@@ -529,7 +532,6 @@
<section class="skill-card special-card">
<header>
<span class="skill-symbol" aria-hidden="true">스</span>
<h4>스페셜</h4>
{#if special?.condition}<span class="condition-badge">조건부</span>{/if}
</header>
@@ -624,7 +626,7 @@
main {
width: min(var(--page-max-width), calc(100% - var(--page-gutter)));
margin: 0 auto;
padding: 36px 0 80px;
padding: var(--page-content-top) 0 80px;
}
.page-header {
@@ -632,20 +634,21 @@
align-items: flex-end;
justify-content: space-between;
gap: 24px;
margin-bottom: 28px;
margin-bottom: 36px;
}
h1 {
margin: 0;
font-size: clamp(36px, 5vw, 54px);
line-height: 1.12;
font-size: var(--page-title-size);
line-height: 1.15;
letter-spacing: -0.045em;
}
.description {
margin: 12px 0 0;
margin: 10px 0 0;
color: #687185;
font-size: 16px;
font-size: var(--page-description-size);
line-height: 1.6;
}
.total {
@@ -1034,18 +1037,6 @@
font-weight: 850;
}
.passive-card .skill-symbol {
background: #8057c7;
}
.active-card .skill-symbol {
background: #4778d8;
}
.special-card .skill-symbol {
background: #e64f8f;
}
.costume-card .skill-symbol {
background: #d99a27;
}
@@ -1590,7 +1581,7 @@
@media (max-width: 680px) {
main {
width: min(100% - 24px, 1120px);
padding: 38px 0 48px;
padding: var(--page-content-top) 0 48px;
}
.page-header {