mirror of
https://github.com/Kvan7/Exiled-Exchange-2.git
synced 2026-09-28 15:45:58 +00:00
update mod parser impl
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-for="modifier in item.modifiers" :key="`${modifier.mod.text}${modifier.type}`"
|
||||
<div v-for="modifier in item.modifiers" :key="`${modifier.modInfo.text}${modifier.type}`"
|
||||
class="py-2 border-b border-gray-700">
|
||||
<div class="pb-1 flex items-baseline">
|
||||
<i class="fas fa-check-square w-5"></i>
|
||||
<span class="">{{ modifier.mod.text }}</span>
|
||||
<span class="">{{ modifier.modInfo.text }}</span>
|
||||
</div>
|
||||
<div class="flex">
|
||||
<div class="w-5"></div>
|
||||
|
||||
+23
-60
@@ -14,9 +14,10 @@ import {
|
||||
PREFIX_SUPERIOR,
|
||||
SUFFIX_INFLUENCE
|
||||
} from './parser-constants'
|
||||
import { Prophecies, ItemisedMonsters, Mods, Mod } from '../data'
|
||||
import { Prophecies, ItemisedMonsters } from '../data'
|
||||
import { getDetailsId, nameToDetailsId } from './trends/getDetailsId'
|
||||
import { ItemInfo, Prices } from './Prices'
|
||||
import { ItemModifier, ModifierType, sectionToStatStrings, tryFindModifier } from './parser/modifiers'
|
||||
|
||||
export {
|
||||
ItemRarity,
|
||||
@@ -37,11 +38,7 @@ export interface ParsedItem {
|
||||
gemLevel?: number
|
||||
influences: ItemInfluence[]
|
||||
rawText: string
|
||||
modifiers: Array<{
|
||||
mod: Mod
|
||||
values?: number[]
|
||||
type: ModifierType
|
||||
}>
|
||||
modifiers: ItemModifier[]
|
||||
computed: {
|
||||
category?: ItemCategory
|
||||
mapName?: string
|
||||
@@ -56,14 +53,6 @@ export enum ItemCategory {
|
||||
ItemisedMonster = 'Itemised Monster'
|
||||
}
|
||||
|
||||
export enum ModifierType {
|
||||
Pseudo = 'pseudo',
|
||||
Explicit = 'explicit',
|
||||
Implicit = 'implicit',
|
||||
Crafted = 'crafted',
|
||||
Enchant = 'enchant'
|
||||
}
|
||||
|
||||
const SECTION_PARSED = 1
|
||||
const SECTION_SKIPPED = 0
|
||||
const PARSER_SKIPPED = -1
|
||||
@@ -332,56 +321,27 @@ function parseModifiers (section: string[], item: ParsedItem) {
|
||||
|
||||
const countBefore = item.modifiers.length
|
||||
|
||||
for (let line of section) {
|
||||
const statIterator = sectionToStatStrings(section)
|
||||
let stat = statIterator.next()
|
||||
while (!stat.done) {
|
||||
let modType: ModifierType | undefined
|
||||
let mod: Mod | undefined
|
||||
const values: number[] = []
|
||||
let mod: ItemModifier | undefined
|
||||
|
||||
// cleanup suffix
|
||||
if (line.endsWith(IMPLICIT_SUFFIX)) {
|
||||
line = line.slice(0, -IMPLICIT_SUFFIX.length)
|
||||
if (stat.value.endsWith(IMPLICIT_SUFFIX)) {
|
||||
stat.value = stat.value.slice(0, -IMPLICIT_SUFFIX.length)
|
||||
modType = ModifierType.Implicit
|
||||
} else if (line.endsWith(CRAFTED_SUFFIX)) {
|
||||
line = line.slice(0, -CRAFTED_SUFFIX.length)
|
||||
} else if (stat.value.endsWith(CRAFTED_SUFFIX)) {
|
||||
stat.value = stat.value.slice(0, -CRAFTED_SUFFIX.length)
|
||||
modType = ModifierType.Crafted
|
||||
}
|
||||
|
||||
// 1. try to find "as is"
|
||||
mod = Mods.get(line)
|
||||
if (!mod) {
|
||||
// 2. replace
|
||||
// example: +#%, #%, #, +#, # to #, #-#
|
||||
line = line.replace(/(?<![\d])[+-]?[\d.]+/g, (value) => {
|
||||
values.push(Number(value))
|
||||
return '#'
|
||||
})
|
||||
if (values.length !== 1 && values.length !== 2) {
|
||||
continue
|
||||
}
|
||||
// 3. match variants
|
||||
// @TODO: IMPORTANT! distinguish between local and global mods
|
||||
const variants = [
|
||||
{ invertSign: false, text: line },
|
||||
{ invertSign: false, text: line + ' (Local)' },
|
||||
{ invertSign: false, text: line.replace('#', '+#') },
|
||||
{ invertSign: false, text: line.replace('#', '+#') + ' (Local)' },
|
||||
{ invertSign: true, text: line.replace('#% reduced', '#% increased') },
|
||||
{ invertSign: true, text: line.replace('#% reduced', '#% increased') + ' (Local)' }
|
||||
]
|
||||
for (const variant of variants) {
|
||||
mod = Mods.get(variant.text)
|
||||
if (mod) {
|
||||
if (variant.invertSign) {
|
||||
values[0] *= -1
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod = tryFindModifier(stat.value)
|
||||
if (mod) {
|
||||
// @TODO: IMPORTANT! distinguish between local and global mods
|
||||
|
||||
if (modType == null) {
|
||||
for (const type of mod.types) {
|
||||
for (const type of mod.modInfo.types) {
|
||||
if (
|
||||
type.name !== ModifierType.Pseudo &&
|
||||
type.name !== ModifierType.Implicit &&
|
||||
@@ -393,11 +353,14 @@ function parseModifiers (section: string[], item: ParsedItem) {
|
||||
}
|
||||
}
|
||||
|
||||
item.modifiers.push({
|
||||
mod,
|
||||
type: modType!,
|
||||
values: values.length ? values : undefined
|
||||
})
|
||||
mod.type = modType!
|
||||
if (mod.modInfo.types.find(type => type.name === mod!.type)!.tradeId) {
|
||||
item.modifiers.push(mod)
|
||||
}
|
||||
|
||||
stat = statIterator.next(true)
|
||||
} else {
|
||||
stat = statIterator.next(false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
import { Mods, Mod, StatMatcher } from '../../data'
|
||||
|
||||
export enum ModifierType {
|
||||
Pseudo = 'pseudo',
|
||||
Explicit = 'explicit',
|
||||
Implicit = 'implicit',
|
||||
Crafted = 'crafted',
|
||||
Enchant = 'enchant'
|
||||
}
|
||||
|
||||
export interface ItemModifier {
|
||||
modInfo: Mod
|
||||
values?: number[]
|
||||
option?: StatMatcher['option']
|
||||
condition?: StatMatcher['condition']
|
||||
type: ModifierType
|
||||
}
|
||||
|
||||
export function * sectionToStatStrings (section: string[]) {
|
||||
let idx = 0
|
||||
let multi = (idx + 1) < section.length
|
||||
|
||||
while (idx < section.length) {
|
||||
const str = multi ? `${section[idx]}\n${section[idx + 1]}` : section[idx]
|
||||
|
||||
const isParsed: boolean = yield str
|
||||
|
||||
if (isParsed) {
|
||||
idx += multi ? 2 : 1
|
||||
multi = (idx + 1) < section.length
|
||||
} else {
|
||||
if (multi) {
|
||||
multi = false
|
||||
} else {
|
||||
idx += 1
|
||||
multi = (idx + 1) < section.length
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
const PLACEHOLDER_MAP = [
|
||||
// 0 #
|
||||
[[]],
|
||||
// 1 #
|
||||
[[0], []],
|
||||
// 2 #
|
||||
[[0, 1], [0], [1], []],
|
||||
// 3 #
|
||||
[[0, 1, 2], [1, 2], [0, 2], [0, 1], [2], [1], [0]],
|
||||
// 4 #
|
||||
[[0, 1, 2, 3], [1, 2, 3], [0, 2, 3], [0, 1, 3], [0, 1, 2], [2, 3], [1, 3], [1, 2], [0, 3], [0, 2], [0, 1]]
|
||||
]
|
||||
|
||||
export function tryFindModifier (stat: string): ItemModifier | undefined {
|
||||
const matches = [] as string[]
|
||||
|
||||
const withPlaceholders = stat
|
||||
.replace(/[ ]{2,}/gm, ' ') // required to align with how "mods.json" was generated
|
||||
.replace(/(?<![\d#])[+-]?[\d.]+/gm, (value) => {
|
||||
matches.push(value)
|
||||
return '#'
|
||||
})
|
||||
|
||||
if (matches.length > PLACEHOLDER_MAP.length) return
|
||||
|
||||
const comboVariants = PLACEHOLDER_MAP[matches.length]
|
||||
for (const combo of comboVariants) {
|
||||
let pIdx = -1
|
||||
const possibleStat = withPlaceholders.replace(/#/gm, () => {
|
||||
pIdx += 1
|
||||
if (combo.includes(pIdx)) {
|
||||
return matches[pIdx]
|
||||
} else {
|
||||
return '#'
|
||||
}
|
||||
})
|
||||
|
||||
const found = Mods.get(possibleStat)
|
||||
if (found) {
|
||||
const values = matches
|
||||
.filter((_, idx) => !combo.includes(idx))
|
||||
.map(str => Number(str) * (found.condition.negate ? -1 : 1))
|
||||
|
||||
return {
|
||||
modInfo: found.mod,
|
||||
values: values.length ? values : undefined,
|
||||
option: found.condition.option,
|
||||
condition: found.condition.condition,
|
||||
type: undefined!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+12
-1
@@ -25,4 +25,15 @@ export interface Mod {
|
||||
|
||||
export const Prophecies = new Set(prophecies as string[])
|
||||
export const ItemisedMonsters = new Set(monsters as string[])
|
||||
export const Mods = new Map<string, Mod>(mods)
|
||||
|
||||
// Mods
|
||||
export const Mods = new Map<string, { condition: StatMatcher, mod: Mod }>()
|
||||
|
||||
for (const entry of (mods as Array<{ conditions: StatMatcher[], mod: Mod }>)) {
|
||||
for (const condition of entry.conditions) {
|
||||
Mods.set(condition.string, {
|
||||
condition,
|
||||
mod: entry.mod
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user