miao-plugin/models/profile/ArtisMark.js

313 lines
7.9 KiB
JavaScript

import lodash from 'lodash'
import { Format } from '#miao'
import { attrNameMap, mainAttr, subAttr, attrMap, basicNum, attrPct } from '../../resources/meta/artifact/index.js'
let ArtisMark = {
// 根据Key获取标题
getKeyByTitle (title, dmg = false) {
if (/元素伤害加成/.test(title) || Format.isElem(title)) {
let elem = Format.matchElem(title)
return dmg ? 'dmg' : elem
} else if (title === '物理伤害加成') {
return 'phy'
}
return attrNameMap[title]
},
// 根据标题获取Key
getTitleByKey (key) {
// 检查是否是伤害字段
let dmg = Format.elemName(key, '')
if (dmg) {
return `${dmg}伤加成`
}
return attrMap[key].title
},
getKeyTitleMap () {
let ret = {}
lodash.forEach(attrMap, (ds, key) => {
ret[key] = ds.title
})
Format.eachElem((key, name) => {
ret[key] = `${name}伤加成`
})
return ret
},
formatAttr (ds) {
if (!ds) {
return {}
}
if (lodash.isArray(ds) && ds[0] && ds[1]) {
return {
key: ArtisMark.getKeyByTitle(ds[0]),
value: ds[1]
}
}
if (!ds.value) {
return {}
}
return {
key: ds.key || ArtisMark.getKeyByTitle(ds.title || ds.name || ds.key || ds.id || ''),
value: ds.value || ''
}
},
/**
* 格式化圣遗物词条
* @param ds
* @param markCfg
* @param isMain
* @returns {{title: *, value: string}|*[]}
*/
formatArti (ds, charAttrCfg = false, isMain = false, elem = '') {
// 若为attr数组
if (ds[0] && (ds[0].title || ds[0].key)) {
let ret = []
let totalUpNum = 0
let ltArr = []
let isIdAttr = false
lodash.forEach(ds, (d) => {
isIdAttr = !d.isCalcNum
let arti = ArtisMark.formatArti(d, charAttrCfg)
ret.push(arti)
if (isIdAttr) {
return true
}
totalUpNum += arti.upNum
if (arti.hasLt) {
ltArr.push(arti)
}
delete arti.hasLt
delete arti.hasGt
})
if (!isIdAttr) {
ltArr = lodash.sortBy(ltArr, 'upNum').reverse()
for (let arti of ltArr) {
if (totalUpNum > 9) {
arti.upNum = arti.upNum - 1
totalUpNum--
} else {
break
}
}
}
return ret
}
let key = ds.key
let title = ds.title || ds[0]
if (!key) {
key = ArtisMark.getKeyByTitle(title)
} else if (!title) {
title = ArtisMark.getTitleByKey(key)
}
let isDmg = Format.isElem(key)
let val = ds.value || ds[1]
let value = val
let num = ds.value || ds[1]
if (!key || key === 'undefined') {
return {}
}
let arrCfg = attrMap[isDmg ? 'dmg' : key]
val = Format[arrCfg.format](val, 1)
let ret = {
key,
value: val,
upNum: ds.upNum || 0,
eff: ds.eff || 0
}
if (!isMain && !ret.upNum) {
let incRet = ArtisMark.getIncNum(key, value)
ret.upNum = incRet.num
ret.eff = incRet.eff
ret.hasGt = incRet.hasGt
ret.hasLt = incRet.hasLt
ret.isCalcNum = true
}
if (charAttrCfg) {
let mark = charAttrCfg[key]?.mark * num || 0
if (isMain) {
mark = mark / 4 + 0.01
ret.key = key
}
ret.mark = Format.comma(mark || 0)
ret._mark = mark || 0
}
ret.eff = ret.eff ? Format.comma(ret.eff / 0.85, 1) : '-'
return ret
},
// 获取升级次数
getIncNum (key, value) {
let cfg = attrMap[key]
if (!value || !cfg || !cfg.value || !cfg.valueMin) {
return { num: 0 }
}
let maxNum = Math.min(5, Math.floor((value / cfg.valueMin).toFixed(1) * 1))
let minNum = Math.max(1, Math.ceil((value / cfg.value).toFixed(1) * 1))
// 相等时直接返回
if (maxNum === minNum) {
return { num: minNum, eff: value / cfg.value }
}
let avg = Math.round(value / (cfg.value + cfg.valueMin) * 2)
return {
num: avg,
eff: value / cfg.value,
hasGt: maxNum > avg,
hasLt: minNum < avg
}
},
// 获取评分档位
getMarkClass (mark) {
let pct = mark
let scoreMap = [['D', 7], ['C', 14], ['B', 21], ['A', 28], ['S', 35], ['SS', 42], ['SSS', 49], ['ACE', 56], ['ACE²', 66.1]]
for (let idx = 0; idx < scoreMap.length; idx++) {
if (pct < scoreMap[idx][1]) {
return scoreMap[idx][0]
}
}
},
// 获取位置分数
getMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
let ret = 0
let { attrs, posMaxMark } = charCfg
let key = mainAttr?.key
if (!key) {
return 0
}
let fixPct = 1
posIdx = posIdx * 1
if (posIdx >= 3) {
let mainKey = key
if (key !== 'recharge') {
if (posIdx === 4 && Format.isElem(key) && key === elem) {
mainKey = 'dmg'
}
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
}
ret += (attrs[mainKey]?.mark || 0) * (mainAttr.value || 0) / 4
}
lodash.forEach(subAttr, (ds) => {
ret += (attrs[ds.key]?.mark || 0) * (ds.value || 0)
})
return ret * (1 + fixPct) / 2 / posMaxMark[posIdx] * 66
},
getCritMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
let ret = 0
let { attrs, posMaxMark } = charCfg
let key = mainAttr?.key
if (!key) {
return 0
}
let fixPct = 1
posIdx = posIdx * 1
if (posIdx >= 4) {
let mainKey = key
if (posIdx === 4 && Format.isElem(key) && key === elem) {
mainKey = 'dmg'
}
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
}
if (key === 'cpct' || key === 'cdmg') {
ret += 9.41
}
lodash.forEach(subAttr, (ds) => {
if (ds.key === 'cpct' || ds.key === 'cdmg') {
let temp_s = (attrs[ds.key]?.mark || 0) * (ds.value || 0) / 85
ret += temp_s
}
})
return ret
},
getValidMark (charCfg, posIdx, mainAttr, subAttr, elem = '') {
let ret = 0
let { attrs, posMaxMark } = charCfg
let key = mainAttr?.key
if (!key) {
return 0
}
let fixPct = 1
posIdx = posIdx * 1
if (posIdx >= 4) {
let mainKey = key
if (posIdx === 4 && Format.isElem(key) && key === elem) {
mainKey = 'dmg'
}
fixPct = Math.max(0, Math.min(1, (attrs[mainKey]?.weight || 0) / (posMaxMark['m' + posIdx])))
}
lodash.forEach(subAttr, (ds) => {
let temp_s = (attrs[ds.key]?.mark || 0) * (ds.value || 0) / 85
ret += temp_s
})
return ret
},
// 获取位置最高分
getMaxMark (attrs) {
let ret = {}
for (let idx = 1; idx <= 5; idx++) {
let totalMark = 0
let mMark = 0
let mAttr = ''
if (idx === 1) {
mAttr = 'hpPlus'
} else if (idx === 2) {
mAttr = 'atkPlus'
} else if (idx >= 3) {
mAttr = ArtisMark.getMaxAttr(attrs, mainAttr[idx])[0]
mMark = attrs[mAttr].fixWeight
totalMark += attrs[mAttr].fixWeight * 2
}
let sAttr = ArtisMark.getMaxAttr(attrs, subAttr, 4, mAttr)
lodash.forEach(sAttr, (attr, aIdx) => {
totalMark += attrs[attr].fixWeight * (aIdx === 0 ? 6 : 1)
})
ret[idx] = totalMark
ret['m' + idx] = mMark
}
return ret
},
// 获取最高分的属性
getMaxAttr (attrs = {}, list2 = [], maxLen = 1, banAttr = '') {
let tmp = []
lodash.forEach(list2, (attr) => {
if (attr === banAttr) return
if (!attrs[attr]) return
tmp.push({ attr, mark: attrs[attr].fixWeight })
})
tmp = lodash.sortBy(tmp, 'mark')
tmp = tmp.reverse()
let ret = []
lodash.forEach(tmp, (ds) => ret.push(ds.attr))
return ret.slice(0, maxLen)
},
hasAttr (artis) {
for (let idx = 1; idx <= 5; idx++) {
let ds = artis[idx]
if (ds) {
if (!ds.name || !ds.main || !ds.attrs || !ds?.main?.key) {
return false
}
}
}
return true
}
}
export default ArtisMark