Adding specializations to the public facing database page

This commit is contained in:
jb
2026-07-30 02:42:23 -04:00
parent 65a4987cad
commit 3f440dd3c9
5 changed files with 158 additions and 214 deletions
+2 -1
View File
@@ -6,7 +6,8 @@ export const databaseCategories = [
{ slug: 'os-protocols', label: 'OS Protocols', description: 'Quality, core profile, primary effect, and unique upgradeable talent.' },
{ slug: 'talents', label: 'Talents', description: 'Equipment and weapon talents with tiered descriptions and combat mechanics.' },
{ slug: 'brands', label: 'Brands', description: 'Brand Set identities and their two-, three-, and four-piece bonuses.' },
{ slug: 'skill-chips', label: 'Skill Chips', description: 'Set bonuses, primary and secondary pools, and quality-scaled unique talents.' }
{ slug: 'skill-chips', label: 'Skill Chips', description: 'Set bonuses, primary and secondary pools, and quality-scaled unique talents.' },
{ slug: 'specializations', label: 'Specializations', description: 'Specialization identities, focus paths, signature abilities, and tree node progression.' }
] as const;
export type DatabaseCategorySlug = typeof databaseCategories[number]['slug'];
+25 -8
View File
@@ -11,7 +11,8 @@ const tables = {
'os-protocols': 'os_protocols',
talents: 'talents',
brands: 'brand_sets',
'skill-chips': 'skill_chip_sets'
'skill-chips': 'skill_chip_sets',
specializations: 'specializations'
} as const;
export const load: PageServerLoad = async ({ url }) => {
@@ -89,14 +90,30 @@ export const load: PageServerLoad = async ({ url }) => {
SELECT 'skill-chips','Skill Chips',item.name,COALESCE(talent.name,'Skill Chip set')
FROM skill_chip_sets item
LEFT JOIN skill_chip_talents talent ON talent.skill_chip_set_id=item.id
WHERE item.active=1 AND (
item.name LIKE ? ESCAPE '\\' COLLATE NOCASE OR talent.name LIKE ? ESCAPE '\\' COLLATE NOCASE
OR talent.description_template LIKE ? ESCAPE '\\' COLLATE NOCASE
WHERE item.active=1 AND (
item.name LIKE ? ESCAPE '\\' COLLATE NOCASE OR talent.name LIKE ? ESCAPE '\\' COLLATE NOCASE
OR talent.description_template LIKE ? ESCAPE '\\' COLLATE NOCASE
)
UNION ALL
SELECT 'specializations','Specializations',item.name,'Specialization'
FROM specializations item
WHERE item.active=1 AND (
item.name LIKE ? ESCAPE '\\' COLLATE NOCASE OR item.description LIKE ? ESCAPE '\\' COLLATE NOCASE
OR EXISTS (
SELECT 1 FROM specialization_focuses focus
WHERE focus.specialization_id=item.id AND focus.active=1
AND focus.name LIKE ? ESCAPE '\\' COLLATE NOCASE
)
) matches
ORDER BY name COLLATE NOCASE
LIMIT 40
`)).all(...Array(23).fill(pattern))
OR EXISTS (
SELECT 1 FROM specialization_abilities ability
WHERE ability.specialization_id=item.id AND ability.active=1
AND ability.name LIKE ? ESCAPE '\\' COLLATE NOCASE
)
)
) matches
ORDER BY name COLLATE NOCASE
LIMIT 40
`)).all(...Array(27).fill(pattern))
: [];
return {
registries: counts,
+1 -1
View File
@@ -5,7 +5,7 @@
<svelte:head>
<title>The Division Resurgence database — SHD.build</title>
<meta name="description" content="Community-maintained The Division Resurgence attributes, talents, brands, gear, weapons, mods, protocols, and Skill Chip data."/>
<meta name="description" content="Community-maintained The Division Resurgence attributes, talents, brands, gear, weapons, mods, protocols, skill chips, and specializations data."/>
</svelte:head>
<main class="page community-index-page">
+48 -7
View File
@@ -340,10 +340,35 @@ export const load: PageServerLoad = async ({ params, url }) => {
LEFT JOIN specialization_abilities abilities ON abilities.id=item.specialization_ability_id
LEFT JOIN specializations ON specializations.id=abilities.specialization_id
LEFT JOIN game_data_icons icons ON icons.entity_type='skill_chip' AND icons.entity_id=item.id
WHERE item.active=1${searchClause}
ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`;
break;
}
WHERE item.active=1${searchClause}
ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`;
break;
case 'specializations':
countSql = `SELECT COUNT(*) AS total FROM specializations item WHERE item.active=1${searchClause}`;
rowsSql = `SELECT item.*,
(SELECT COUNT(*) FROM specialization_focuses focus WHERE focus.specialization_id=item.id AND focus.active=1) AS focus_count,
(SELECT COUNT(*) FROM specialization_focuses focus WHERE focus.specialization_id=item.id AND focus.builder_ready=1 AND focus.active=1) AS ready_focus_count,
(SELECT COUNT(*) FROM specialization_abilities ability WHERE ability.specialization_id=item.id AND ability.active=1) AS ability_count,
(SELECT COUNT(*) FROM specialization_tree_nodes node
JOIN specialization_focuses node_focus ON node_focus.id=node.focus_id
WHERE node_focus.specialization_id=item.id AND node_focus.active=1 AND node.active=1) AS node_count,
(SELECT GROUP_CONCAT(name, ', ') FROM (
SELECT focus.name FROM specialization_focuses focus
WHERE focus.specialization_id=item.id AND focus.active=1
ORDER BY focus.display_order,focus.name COLLATE NOCASE
)) AS focus_names,
(SELECT GROUP_CONCAT(name, ', ') FROM (
SELECT ability.name FROM specialization_abilities ability
WHERE ability.specialization_id=item.id AND ability.active=1
ORDER BY ability.name COLLATE NOCASE
)) AS ability_names,
icons.updated_at AS icon_updated_at
FROM specializations item
LEFT JOIN game_data_icons icons ON icons.entity_type='specialization' AND icons.entity_id=item.id
WHERE item.active=1${searchClause}
ORDER BY item.name COLLATE NOCASE LIMIT ? OFFSET ?`;
break;
}
const total = Number((await (await database.prepare(countSql)).get(...queryArgs))?.total ?? 0);
const pagination = getPagination(url, total);
@@ -575,9 +600,25 @@ export const load: PageServerLoad = async ({ params, url }) => {
{ label: 'PRIMARY POOL', value: `${row.primary_count} OPTIONS` },
{ label: 'SECONDARY POOL', value: `${row.secondary_count} OPTIONS` }
],
lines: [{ label: '3-PIECE TALENT', value: list(row.talent_name,'NOT CONFIGURED') }]
};
}
lines: [{ label: '3-PIECE TALENT', value: list(row.talent_name,'NOT CONFIGURED') }]
};
case 'specializations':
return {
id: String(row.id), name: String(row.name), kicker: 'SPECIALIZATION // FOCUS PATHS',
iconUrl: iconUrl('specialization',row.id,row.icon_updated_at),
badges: Number(row.ready_focus_count) ? [{ label: 'BUILDER READY' }] : [],
facts: [
{ label: 'FOCUS PATHS', value: String(row.focus_count) },
{ label: 'ABILITIES', value: String(row.ability_count) },
{ label: 'TREE NODES', value: String(row.node_count) }
],
lines: [
{ label: 'FOCUS PATHS', value: list(row.focus_names) },
{ label: 'ABILITIES', value: list(row.ability_names) }
],
description: row.description ? String(row.description) : undefined
};
}
});
return { category, items, pagination, search, filters };