flatten props

This commit is contained in:
Alexander Drozdov
2021-11-23 11:39:25 +02:00
parent 5453346a57
commit f972a48c86
9 changed files with 110 additions and 111 deletions
+17 -19
View File
@@ -23,26 +23,25 @@ export interface ParsedItem {
name: string
baseType: string | undefined
itemLevel?: number
props: {
armour?: number
evasion?: number
energyShield?: number
ward?: number
blockChance?: number
critChance?: number
attackSpeed?: number
physicalDamage?: number
elementalDamage?: number
mapBlighted?: true
mapTier?: number
gemLevel?: number
areaLevel?: number
talismanTier?: number
}
armourAR?: number
armourEV?: number
armourES?: number
armourWARD?: number
armourBLOCK?: number
weaponCRIT?: number
weaponAS?: number
weaponPHYSICAL?: number
weaponELEMENTAL?: number
mapBlighted?: true
mapTier?: number
gemLevel?: number
gemAltQuality?: 'Anomalous' | 'Divergent' | 'Phantasmal' | 'Superior'
areaLevel?: number
talismanTier?: number
quality?: number
sockets: {
sockets?: {
linked?: number // only 5 or 6
white?: number
white: number
}
stackSize?: { value: number, max: number }
isUnidentified: boolean
@@ -59,7 +58,6 @@ export interface ParsedItem {
}>
extra: {
prophecyMaster?: 'Alva' | 'Einhar' | 'Niko' | 'Jun' | 'Zana'
altQuality?: 'Anomalous' | 'Divergent' | 'Phantasmal' | 'Superior'
}
heistJob?: { name: HeistJob, level: number }
category?: ItemCategory
+29 -28
View File
@@ -141,7 +141,7 @@ function normalizeName (item: ParsedItem) {
function parseMap (section: string[], item: ParsedItem) {
if (section[0].startsWith(_$.MAP_TIER)) {
item.props.mapTier = Number(section[0].substr(_$.MAP_TIER.length))
item.mapTier = Number(section[0].substr(_$.MAP_TIER.length))
let name = item.baseType || item.name
if (_$.MAP_BLIGHTED.test(name)) {
@@ -153,7 +153,7 @@ function parseMap (section: string[], item: ParsedItem) {
item.name = name
}
item.category = ItemCategory.Map
item.props.mapBlighted = true
item.mapBlighted = true
}
return SECTION_PARSED
@@ -173,14 +173,12 @@ function parseNamePlate (section: string[]) {
category: undefined,
name: markupConditionParser(section[2]),
baseType: (section.length >= 4) ? markupConditionParser(section[3]) : undefined,
props: {},
isUnidentified: false,
isCorrupted: false,
newMods: [],
statsByType: [],
unknownModifiers: [],
influences: [],
sockets: {},
extra: {},
rawText: undefined!
}
@@ -275,7 +273,7 @@ function parseItemLevel (section: string[], item: ParsedItem) {
function parseTalismanTier (section: string[], item: ParsedItem) {
if (section[0].startsWith(_$.TALISMAN_TIER)) {
item.props.talismanTier = Number(section[0].substr(_$.TALISMAN_TIER.length))
item.talismanTier = Number(section[0].substr(_$.TALISMAN_TIER.length))
return SECTION_PARSED
}
return SECTION_SKIPPED
@@ -287,14 +285,14 @@ function parseVaalGem (section: string[], item: ParsedItem) {
if (section.length === 1) {
let gemName: string | undefined
if ((gemName = _$.QUALITY_ANOMALOUS.exec(section[0])?.[1])) {
item.extra.altQuality = 'Anomalous'
item.gemAltQuality = 'Anomalous'
} else if ((gemName = _$.QUALITY_DIVERGENT.exec(section[0])?.[1])) {
item.extra.altQuality = 'Divergent'
item.gemAltQuality = 'Divergent'
} else if ((gemName = _$.QUALITY_PHANTASMAL.exec(section[0])?.[1])) {
item.extra.altQuality = 'Phantasmal'
item.gemAltQuality = 'Phantasmal'
} else if (_$.VAAL_GEM.test(section[0])) {
gemName = section[0]
item.extra.altQuality = 'Superior'
item.gemAltQuality = 'Superior'
}
if (gemName) {
@@ -311,21 +309,21 @@ function parseGem (section: string[], item: ParsedItem) {
}
if (section[1]?.startsWith(_$.GEM_LEVEL)) {
// "Level: 20 (Max)"
item.props.gemLevel = parseInt(section[1].substr(_$.GEM_LEVEL.length), 10)
item.gemLevel = parseInt(section[1].substr(_$.GEM_LEVEL.length), 10)
parseQualityNested(section, item)
// don't override if parsed in Vaal name section
if (!item.extra.altQuality) {
if (!item.gemAltQuality) {
let gemName: string | undefined
if ((gemName = _$.QUALITY_ANOMALOUS.exec(item.name)?.[1])) {
item.extra.altQuality = 'Anomalous'
item.gemAltQuality = 'Anomalous'
} else if ((gemName = _$.QUALITY_DIVERGENT.exec(item.name)?.[1])) {
item.extra.altQuality = 'Divergent'
item.gemAltQuality = 'Divergent'
} else if ((gemName = _$.QUALITY_PHANTASMAL.exec(item.name)?.[1])) {
item.extra.altQuality = 'Phantasmal'
item.gemAltQuality = 'Phantasmal'
} else {
item.extra.altQuality = 'Superior'
item.gemAltQuality = 'Superior'
}
if (gemName) {
item.name = ITEM_NAME_REF_BY_TRANSLATED.get(gemName) || gemName
@@ -371,7 +369,10 @@ function parseSockets (section: string[], item: ParsedItem) {
if (section[0].startsWith(_$.SOCKETS)) {
let sockets = section[0].substr(_$.SOCKETS.length).trimEnd()
item.sockets.white = (sockets.split('W').length - 1)
item.sockets = {
white: (sockets.split('W').length - 1),
linked: undefined
}
sockets = sockets.replace(/[^ -]/g, '#')
if (sockets === '#-#-#-#-#-#') {
@@ -403,23 +404,23 @@ function parseArmour (section: string[], item: ParsedItem) {
for (const line of section) {
if (line.startsWith(_$.ARMOUR)) {
item.props.armour = parseInt(line.substr(_$.ARMOUR.length), 10)
item.armourAR = parseInt(line.substr(_$.ARMOUR.length), 10)
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.EVASION)) {
item.props.evasion = parseInt(line.substr(_$.EVASION.length), 10)
item.armourEV = parseInt(line.substr(_$.EVASION.length), 10)
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.ENERGY_SHIELD)) {
item.props.energyShield = parseInt(line.substr(_$.ENERGY_SHIELD.length), 10)
item.armourES = parseInt(line.substr(_$.ENERGY_SHIELD.length), 10)
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.TAG_WARD)) {
item.props.ward = parseInt(line.substr(_$.TAG_WARD.length), 10)
item.armourWARD = parseInt(line.substr(_$.TAG_WARD.length), 10)
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.BLOCK_CHANCE)) {
item.props.blockChance = parseInt(line.substr(_$.BLOCK_CHANCE.length), 10)
item.armourBLOCK = parseInt(line.substr(_$.BLOCK_CHANCE.length), 10)
isParsed = SECTION_PARSED; continue
}
}
@@ -436,22 +437,22 @@ function parseWeapon (section: string[], item: ParsedItem) {
for (const line of section) {
if (line.startsWith(_$.CRIT_CHANCE)) {
item.props.critChance = parseFloat(line.substr(_$.CRIT_CHANCE.length))
item.weaponCRIT = parseFloat(line.substr(_$.CRIT_CHANCE.length))
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.ATTACK_SPEED)) {
item.props.attackSpeed = parseFloat(line.substr(_$.ATTACK_SPEED.length))
item.weaponAS = parseFloat(line.substr(_$.ATTACK_SPEED.length))
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.PHYSICAL_DAMAGE)) {
item.props.physicalDamage = getRollOrMinmaxAvg(line
item.weaponPHYSICAL = getRollOrMinmaxAvg(line
.substr(_$.PHYSICAL_DAMAGE.length)
.split('-').map(str => parseInt(str, 10))
)
isParsed = SECTION_PARSED; continue
}
if (line.startsWith(_$.ELEMENTAL_DAMAGE)) {
item.props.elementalDamage =
item.weaponELEMENTAL =
line.substr(_$.ELEMENTAL_DAMAGE.length)
.split(', ')
.map(element => getRollOrMinmaxAvg(element.split('-').map(str => parseInt(str, 10))))
@@ -610,7 +611,7 @@ function parseHeistMission (section: string[], item: ParsedItem) {
item.category !== ItemCategory.HeistContract) return PARSER_SKIPPED
parseAreaLevelNested(section, item)
if (!item.props.areaLevel) {
if (!item.areaLevel) {
return SECTION_SKIPPED
}
@@ -636,7 +637,7 @@ function parseHeistMission (section: string[], item: ParsedItem) {
function parseAreaLevelNested (section: string[], item: ParsedItem) {
for (const line of section) {
if (line.startsWith(_$.AREA_LEVEL)) {
item.props.areaLevel = Number(line.substr(_$.AREA_LEVEL.length))
item.areaLevel = Number(line.substr(_$.AREA_LEVEL.length))
break
}
}
@@ -647,7 +648,7 @@ function parseAtzoatlAreaLevel (section: string[], item: ParsedItem) {
parseAreaLevelNested(section, item)
return (item.props.areaLevel)
return (item.areaLevel)
? SECTION_PARSED
: SECTION_SKIPPED
}
@@ -67,7 +67,7 @@ export function createFilters (
}
if (item.name === 'Chronicle of Atzoatl') {
filters.areaLevel = {
value: floorToBracket(item.props.areaLevel!, [1, 68, 73, 75, 78, 80])
value: floorToBracket(item.areaLevel!, [1, 68, 73, 75, 78, 80])
}
}
return filters
@@ -98,7 +98,7 @@ export function createFilters (
}
}
if (item.props.mapBlighted) {
if (item.mapBlighted) {
filters.mapBlighted = { value: true }
}
@@ -107,7 +107,7 @@ export function createFilters (
}
filters.mapTier = {
value: item.props.mapTier!
value: item.mapTier!
}
} else if (
item.category === ItemCategory.HeistContract ||
@@ -122,7 +122,7 @@ export function createFilters (
}
filters.areaLevel = {
value: item.props.areaLevel!
value: item.areaLevel!
}
if (item.heistJob) {
@@ -160,14 +160,14 @@ export function createFilters (
}
}
if (item.sockets.linked) {
if (item.sockets?.linked) {
filters.linkedSockets = {
value: item.sockets.linked,
disabled: false
}
}
if (item.sockets.white) {
if (item.sockets?.white) {
filters.whiteSockets = {
value: item.sockets.white,
disabled: false
@@ -322,19 +322,19 @@ function createGemFilters (item: ParsedItem, filters: ItemFilters) {
if (SPECIAL_SUPPORT_GEM.includes(item.name)) {
filters.gemLevel = {
min: item.props.gemLevel!,
max: item.props.gemLevel!,
min: item.gemLevel!,
max: item.gemLevel!,
disabled: false
}
} else {
filters.gemLevel = {
min: item.props.gemLevel!,
disabled: item.props.gemLevel! < 16
min: item.gemLevel!,
disabled: item.gemLevel! < 16
}
}
filters.altQuality = {
value: item.extra.altQuality!,
value: item.gemAltQuality!,
disabled: false
}
@@ -289,7 +289,7 @@ function finalFilterTweaks (ctx: FiltersCreationContext) {
if (item.category === ItemCategory.Amulet) {
const anointment = ctx.filters.find(filter => filter.statRef === 'Allocates #')
if (anointment) {
if (item.props.talismanTier) {
if (item.talismanTier) {
anointment.disabled = false
} else if (!item.isCorrupted && !item.isMirrored) {
anointment.hidden = 'Buyer will likely change anointment'
+1 -1
View File
@@ -54,7 +54,7 @@ export interface ItemFilters {
disabled: boolean
}
altQuality?: {
value: NonNullable<ParsedItem['extra']['altQuality']>
value: NonNullable<ParsedItem['gemAltQuality']>
disabled: boolean
}
areaLevel?: {
@@ -27,8 +27,8 @@ const ARMOUR_STATS = new Set<string>([
function armourProps (ctx: FiltersCreationContext) {
const { item } = ctx
if (item.props.armour) {
const totalQ20 = Math.floor(propAt20Quality(item.props.armour, QUALITY_STATS.ARMOUR, item))
if (item.armourAR) {
const totalQ20 = Math.floor(propAt20Quality(item.armourAR, QUALITY_STATS.ARMOUR, item))
ctx.filters.push({
...internalPropStat(
@@ -43,8 +43,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.evasion) {
const totalQ20 = Math.floor(propAt20Quality(item.props.evasion, QUALITY_STATS.EVASION, item))
if (item.armourEV) {
const totalQ20 = Math.floor(propAt20Quality(item.armourEV, QUALITY_STATS.EVASION, item))
ctx.filters.push({
...internalPropStat(
@@ -59,8 +59,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.energyShield) {
const totalQ20 = Math.floor(propAt20Quality(item.props.energyShield, QUALITY_STATS.ENERGY_SHIELD, item))
if (item.armourES) {
const totalQ20 = Math.floor(propAt20Quality(item.armourES, QUALITY_STATS.ENERGY_SHIELD, item))
ctx.filters.push({
...internalPropStat(
@@ -75,8 +75,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.ward) {
const totalQ20 = Math.floor(propAt20Quality(item.props.ward, QUALITY_STATS.WARD, item))
if (item.armourWARD) {
const totalQ20 = Math.floor(propAt20Quality(item.armourWARD, QUALITY_STATS.WARD, item))
ctx.filters.push({
...internalPropStat(
@@ -102,9 +102,9 @@ const WEAPON_STATS = new Set<string>([
function weaponProps (ctx: FiltersCreationContext) {
const { item } = ctx
if (item.props.physicalDamage) {
const physQ20 = propAt20Quality(item.props.physicalDamage, QUALITY_STATS.PHYSICAL_DAMAGE, item)
const pdpsQ20 = Math.floor(physQ20 * item.props.attackSpeed!)
if (item.weaponPHYSICAL) {
const physQ20 = propAt20Quality(item.weaponPHYSICAL, QUALITY_STATS.PHYSICAL_DAMAGE, item)
const pdpsQ20 = Math.floor(physQ20 * item.weaponAS!)
ctx.filters.push({
...internalPropStat(
@@ -30,8 +30,8 @@ export const ARMOUR_STATS = new Set<string>([
function armourProps (ctx: FiltersCreationContext) {
const { item } = ctx
if (item.props.armour) {
const totalQ20 = Math.floor(propAt20Quality(item.props.armour, QUALITY_STATS.ARMOUR, item))
if (item.armourAR) {
const totalQ20 = Math.floor(propAt20Quality(item.armourAR, QUALITY_STATS.ARMOUR, item))
ctx.filters.push({
...internalPropStat(
@@ -45,8 +45,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.evasion) {
const totalQ20 = Math.floor(propAt20Quality(item.props.evasion, QUALITY_STATS.EVASION, item))
if (item.armourEV) {
const totalQ20 = Math.floor(propAt20Quality(item.armourEV, QUALITY_STATS.EVASION, item))
ctx.filters.push({
...internalPropStat(
@@ -60,8 +60,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.energyShield) {
const totalQ20 = Math.floor(propAt20Quality(item.props.energyShield, QUALITY_STATS.ENERGY_SHIELD, item))
if (item.armourES) {
const totalQ20 = Math.floor(propAt20Quality(item.armourES, QUALITY_STATS.ENERGY_SHIELD, item))
ctx.filters.push({
...internalPropStat(
@@ -75,8 +75,8 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.ward) {
const totalQ20 = Math.floor(propAt20Quality(item.props.ward, QUALITY_STATS.WARD, item))
if (item.armourWARD) {
const totalQ20 = Math.floor(propAt20Quality(item.armourWARD, QUALITY_STATS.WARD, item))
ctx.filters.push({
...internalPropStat(
@@ -90,7 +90,7 @@ function armourProps (ctx: FiltersCreationContext) {
})
}
if (item.props.blockChance) {
if (item.armourBLOCK) {
ctx.filters.push({
...internalPropStat(
'armour.block',
@@ -99,16 +99,16 @@ function armourProps (ctx: FiltersCreationContext) {
),
sources: [],
disabled: true,
roll: rollToFilter(item.props.blockChance, { neverNegated: true, percent: ctx.searchInRange })
roll: rollToFilter(item.armourBLOCK, { neverNegated: true, percent: ctx.searchInRange })
})
}
if (
item.props.armour ||
item.props.evasion ||
item.props.energyShield ||
item.props.ward ||
item.props.blockChance
item.armourAR ||
item.armourEV ||
item.armourES ||
item.armourWARD ||
item.armourBLOCK
) {
createHiddenFilters(ctx, ARMOUR_STATS)
}
@@ -129,13 +129,13 @@ export const WEAPON_STATS = new Set<string>([
function weaponProps (ctx: FiltersCreationContext) {
const { item } = ctx
const physQ20 = propAt20Quality(item.props.physicalDamage!, QUALITY_STATS.PHYSICAL_DAMAGE, item)
const pdpsQ20 = Math.floor(physQ20 * item.props.attackSpeed!)
const physQ20 = propAt20Quality(item.weaponPHYSICAL!, QUALITY_STATS.PHYSICAL_DAMAGE, item)
const pdpsQ20 = Math.floor(physQ20 * item.weaponAS!)
const edps = Math.floor((item.props.elementalDamage || 0) * item.props.attackSpeed!)
const edps = Math.floor((item.weaponELEMENTAL || 0) * item.weaponAS!)
const dps = pdpsQ20 + edps
if (item.props.elementalDamage) {
if (item.weaponELEMENTAL) {
ctx.filters.push({
...internalPropStat(
'weapon.total_dps',
@@ -180,7 +180,7 @@ function weaponProps (ctx: FiltersCreationContext) {
),
sources: [],
disabled: true,
roll: rollToFilter(item.props.attackSpeed!, { neverNegated: true, dp: 2, percent: ctx.searchInRange })
roll: rollToFilter(item.weaponAS!, { neverNegated: true, dp: 2, percent: ctx.searchInRange })
})
ctx.filters.push({
@@ -191,14 +191,14 @@ function weaponProps (ctx: FiltersCreationContext) {
),
sources: [],
disabled: true,
roll: rollToFilter(item.props.critChance!, { neverNegated: true, dp: 1, percent: ctx.searchInRange })
roll: rollToFilter(item.weaponCRIT!, { neverNegated: true, dp: 1, percent: ctx.searchInRange })
})
if (
item.props.attackSpeed ||
item.props.critChance ||
item.props.elementalDamage ||
item.props.physicalDamage
item.weaponAS ||
item.weaponCRIT ||
item.weaponELEMENTAL ||
item.weaponPHYSICAL
) {
createHiddenFilters(ctx, WEAPON_STATS)
}
@@ -218,10 +218,10 @@ function createHiddenFilters (ctx: FiltersCreationContext, stats: Set<string>) {
function isSingleAttrArmour (item: ParsedItem) {
return [
item.props.armour,
item.props.evasion,
item.props.energyShield,
item.props.ward
item.armourAR,
item.armourEV,
item.armourES,
item.armourWARD
].filter(value => value != null).length === 1
}
+4 -4
View File
@@ -53,10 +53,10 @@ export function tradeTag (item: ParsedItem): string | undefined {
}
if (name) {
if (item.props.mapBlighted) {
name = `Blighted ${name} (Tier ${item.props.mapTier})`
} else if (item.props.mapTier) {
name = `${name} (Tier ${item.props.mapTier})`
if (item.mapBlighted) {
name = `Blighted ${name} (Tier ${item.mapTier})`
} else if (item.mapTier) {
name = `${name} (Tier ${item.mapTier})`
} else if (item.extra.prophecyMaster) {
name = `${name} (${item.extra.prophecyMaster})`
}
+7 -7
View File
@@ -24,9 +24,9 @@ export function getDetailsId (item: ParsedItem) {
}
if (item.category === ItemCategory.Map) {
if (item.rarity === ItemRarity.Unique) {
return nameToDetailsId(`${item.name} t${item.props.mapTier}`)
return nameToDetailsId(`${item.name} t${item.mapTier}`)
} else {
return nameToDetailsId(`${item.props.mapBlighted ? 'Blighted ' : ''}${item.baseType || item.name} t${item.props.mapTier} ${LATEST_MAP_VARIANT}`)
return nameToDetailsId(`${item.mapBlighted ? 'Blighted ' : ''}${item.baseType || item.name} t${item.mapTier} ${LATEST_MAP_VARIANT}`)
}
}
if (item.category === ItemCategory.CapturedBeast ||
@@ -58,17 +58,17 @@ function getGemDetailsId (item: ParsedItem) {
return 'portal-1'
}
let id = item.extra.altQuality === 'Superior'
let id = item.gemAltQuality === 'Superior'
? nameToDetailsId(item.name)
: nameToDetailsId(`${item.extra.altQuality} ${item.name}`)
: nameToDetailsId(`${item.gemAltQuality} ${item.name}`)
if (
SPECIAL_SUPPORT_GEM.includes(item.name) ||
item.name === BRAND_RECALL_GEM ||
item.name === BLOOD_AND_SAND_GEM ||
item.props.gemLevel! >= 20
item.gemLevel! >= 20
) {
id += `-${item.props.gemLevel}`
id += `-${item.gemLevel}`
} else {
id += '-1'
}
@@ -107,7 +107,7 @@ function getBaseTypeDetailsId (item: ParsedItem) {
function getUniqueDetailsId (item: ParsedItem) {
let id = nameToDetailsId(`${item.name}${getUniqueVariant(item) || ''} ${item.baseType}`)
if (item.sockets.linked) {
if (item.sockets?.linked) {
id += `-${item.sockets.linked}l`
}
if (item.baseType === 'Ivory Watchstone') {