dragon-item-parser: introduce item parser library
This commit is contained in:
202
dragon-item-parser/src/item.ts
Normal file
202
dragon-item-parser/src/item.ts
Normal file
@@ -0,0 +1,202 @@
|
||||
/**
|
||||
* Item stats parsed from CommunityDragon item description HTML
|
||||
*/
|
||||
export interface ItemStats {
|
||||
// Offensive stats
|
||||
attackDamage?: number
|
||||
abilityPower?: number
|
||||
attackSpeed?: number
|
||||
criticalStrikeChance?: number
|
||||
lifeSteal?: number
|
||||
omnivamp?: number
|
||||
physicalVamp?: number
|
||||
spellVamp?: number
|
||||
|
||||
// Defensive stats
|
||||
health?: number
|
||||
armor?: number
|
||||
magicResist?: number
|
||||
|
||||
// Resource stats
|
||||
mana?: number
|
||||
baseManaRegen?: number
|
||||
baseHealthRegen?: number
|
||||
|
||||
// Movement stats
|
||||
moveSpeed?: number
|
||||
|
||||
// Ability stats
|
||||
abilityHaste?: number
|
||||
|
||||
// Penetration stats (usually percentages)
|
||||
armorPenetration?: number
|
||||
magicPenetration?: number
|
||||
lethality?: number
|
||||
magicPenetrationFlat?: number
|
||||
|
||||
// Other percentage stats
|
||||
healAndShieldPower?: number
|
||||
tenacity?: number
|
||||
slowResist?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Stat name mappings from CDragon description text to stat keys
|
||||
*/
|
||||
const STAT_MAPPINGS: Record<string, keyof ItemStats> = {
|
||||
'Attack Damage': 'attackDamage',
|
||||
'Ability Power': 'abilityPower',
|
||||
'Attack Speed': 'attackSpeed',
|
||||
'Critical Strike Chance': 'criticalStrikeChance',
|
||||
'Life Steal': 'lifeSteal',
|
||||
Omnivamp: 'omnivamp',
|
||||
'Physical Vamp': 'physicalVamp',
|
||||
'Spell Vamp': 'spellVamp',
|
||||
Health: 'health',
|
||||
Armor: 'armor',
|
||||
'Magic Resist': 'magicResist',
|
||||
Mana: 'mana',
|
||||
'Base Mana Regen': 'baseManaRegen',
|
||||
'Base Health Regen': 'baseHealthRegen',
|
||||
'Move Speed': 'moveSpeed',
|
||||
'Ability Haste': 'abilityHaste',
|
||||
'Armor Penetration': 'armorPenetration',
|
||||
'Magic Penetration': 'magicPenetration',
|
||||
Lethality: 'lethality',
|
||||
'Heal and Shield Power': 'healAndShieldPower',
|
||||
Tenacity: 'tenacity',
|
||||
'Slow Resist': 'slowResist'
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a stat value string to a number
|
||||
* Handles both flat values (e.g., "25") and percentages (e.g., "25%")
|
||||
*/
|
||||
function parseStatValue(valueStr: string): { value: number; isPercentage: boolean } {
|
||||
const trimmed = valueStr.trim()
|
||||
const isPercentage = trimmed.includes('%')
|
||||
const numStr = trimmed.replace('%', '').replace(',', '').trim()
|
||||
const value = parseFloat(numStr)
|
||||
return { value, isPercentage }
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract stats section from the description HTML
|
||||
*/
|
||||
function extractStatsSection(description: string): string | null {
|
||||
const statsMatch = description.match(/<stats>(.*?)<\/stats>/s)
|
||||
return statsMatch ? statsMatch[1] : null
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse individual stat lines from the stats section
|
||||
* Format: <attention> value </attention> statName
|
||||
*/
|
||||
function parseStatLines(
|
||||
statsSection: string
|
||||
): Array<{ value: number; isPercentage: boolean; statName: string }> {
|
||||
const results: Array<{ value: number; isPercentage: boolean; statName: string }> = []
|
||||
|
||||
// Match patterns like: <attention> 25</attention> Move Speed
|
||||
// or: <attention> 25%</attention> Attack Speed
|
||||
const statRegex = /<attention>\s*([^<]+)<\/attention>\s*([^<]+)/g
|
||||
let match
|
||||
|
||||
while ((match = statRegex.exec(statsSection)) !== null) {
|
||||
const valueStr = match[1]
|
||||
const statName = match[2].trim()
|
||||
|
||||
const { value, isPercentage } = parseStatValue(valueStr)
|
||||
|
||||
if (!isNaN(value) && statName) {
|
||||
results.push({ value, isPercentage, statName })
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse item stats from CDragon description HTML
|
||||
*
|
||||
* @param description - The HTML description string from CDragon items.json
|
||||
* @returns Parsed ItemStats object with all recognized stats
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* const stats = parseItemStats(
|
||||
* '<mainText><stats><attention> 25</attention> Move Speed</stats><br><br></mainText>'
|
||||
* )
|
||||
* // Returns: { moveSpeed: 25 }
|
||||
* ```
|
||||
*/
|
||||
export function parseItemStats(description: string): ItemStats {
|
||||
const stats: ItemStats = {}
|
||||
|
||||
if (!description) {
|
||||
return stats
|
||||
}
|
||||
|
||||
const statsSection = extractStatsSection(description)
|
||||
if (!statsSection) {
|
||||
return stats
|
||||
}
|
||||
|
||||
const statLines = parseStatLines(statsSection)
|
||||
|
||||
for (const { value, statName } of statLines) {
|
||||
const statKey = STAT_MAPPINGS[statName]
|
||||
|
||||
if (statKey) {
|
||||
// For percentage stats that are stored as decimals (e.g., 25% -> 25)
|
||||
// We store the percentage value as-is for consistency with game data
|
||||
stats[statKey] = value
|
||||
}
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
/**
|
||||
* Item data structure from CDragon
|
||||
*/
|
||||
export interface CDragonItem {
|
||||
id: number
|
||||
name: string
|
||||
description: string
|
||||
active?: boolean
|
||||
inStore?: boolean
|
||||
from?: number[]
|
||||
to?: number[]
|
||||
categories?: string[]
|
||||
maxStacks?: number
|
||||
requiredChampion?: string
|
||||
requiredAlly?: string
|
||||
price?: number
|
||||
priceTotal?: number
|
||||
iconPath: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Item with parsed stats
|
||||
*/
|
||||
export interface ItemWithStats extends CDragonItem {
|
||||
stats: ItemStats
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a CDragon item and add parsed stats
|
||||
*/
|
||||
export function parseItem(item: CDragonItem): ItemWithStats {
|
||||
return {
|
||||
...item,
|
||||
stats: parseItemStats(item.description)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse an array of CDragon items and add parsed stats
|
||||
*/
|
||||
export function parseItems(items: CDragonItem[]): ItemWithStats[] {
|
||||
return items.map(parseItem)
|
||||
}
|
||||
Reference in New Issue
Block a user