初步增加群伤害排名统计功能

This commit is contained in:
Kokomi 2022-11-09 06:04:08 +08:00
parent 7fcbe22c3d
commit 78d0c0b856
28 changed files with 188 additions and 32 deletions

View File

@ -0,0 +1,25 @@
import { Character, ProfileRank } from '../../models/index.js'
import { renderProfile } from './ProfileDetail.js'
export async function groupMaxProfile (e) {
let groupId = e.group_id
if (!groupId) {
return false
}
let msg = e.original_msg || e.msg
if (!/(最强|最高|最高分|最牛|第一)/.test(msg)) {
return false
}
let mode = /(分|圣遗物|评分|ACE)/.test(msg) ? 'mark' : 'dmg'
let name = msg.replace(/(#|最强|最高分|第一|最高|最牛|圣遗物|评分|群|面板|面版|详情)/g, '')
let char = Character.get(name)
if (!char) {
return false
}
let uid = await ProfileRank.getGroupMaxUid(groupId, char.id, mode)
if (uid) {
e.uid = uid
return await renderProfile(e, char)
}
}

View File

@ -6,6 +6,7 @@ import { renderProfile } from './character/ProfileDetail.js'
import { profileStat } from './character/ProfileStat.js'
import { profileList } from './character/ProfileList.js'
import { enemyLv } from './character/ProfileUtils.js'
import { groupMaxProfile } from './character/ProfileRank.js'
let app = App.init({
id: 'profile',
@ -16,6 +17,11 @@ app.reg('profile-detail', profileDetail, {
name: '角色面板'
})
app.reg('group-profile', groupMaxProfile, {
rule: /^#?(群|群内)?(最强|最高|最高分|最牛|第一)+.+/,
name: '群内最强'
})
app.reg('artis-list', profileArtisList, {
rule: /^#圣遗物列表\s*(\d{9})?$/,
name: '面板圣遗物列表'
@ -66,6 +72,10 @@ export async function profileDetail (e) {
msg = msg.replace('面版', '面板')
let dmgRet = /伤害(\d?)$/.exec(name)
let dmgIdx = 0
if (/(最强|最高|最高分|最牛|第一)/.test(msg)) {
mode = /(分|圣遗物|评分|ACE)/.test(msg) ? 'rank-mark' : 'rank-dmg'
name = name.replace(/(最强|最高分|第一|最高|最牛|圣遗物|评分|群)/g, '')
}
if (/(详情|详细|面板|面版)\s*$/.test(msg) && !/更新|录入|输入/.test(msg)) {
mode = 'profile'
name = name.replace(/(详情|详细|面板)/, '').trim()

View File

@ -146,6 +146,10 @@ export default class ProfileData extends Base {
return {}
}
get hasDmg () {
return this.hasData && !!ProfileDmg.dmgRulePath(this.name)
}
// 计算当前profileData的伤害信息
async calcDmg ({ enemyLv = 91, mode = 'profile', dmgIdx = 0 }) {
if (!this.dmg) {

View File

@ -17,6 +17,15 @@ export default class ProfileDmg extends Base {
}
}
static dmgRulePath (name) {
const _path = process.cwd()
let path = `${_path}/plugins/miao-plugin/resources/meta/character/${name}/calc.js`
if (fs.existsSync(path)) {
return path
}
return false
}
// 获取天赋数据
talent () {
let char = this.char
@ -65,16 +74,16 @@ export default class ProfileDmg extends Base {
}
async getCalcRule () {
const _path = process.cwd()
const cfgPath = `${_path}/plugins/miao-plugin/resources/meta/character/${this.char?.name}/calc.js`
const cfgPath = ProfileDmg.dmgRulePath(this.char?.name)
let cfg = {}
if (fs.existsSync(cfgPath)) {
if (cfgPath) {
cfg = await import(`file://${cfgPath}`)
return {
details: cfg.details || false, // 计算详情
buffs: cfg.buffs || [], // 角色buff
defParams: cfg.defParams || {}, // 默认参数,一般为空
defDmgIdx: cfg.defDmgIdx || -1, // 默认详情index
defDmgKey: cfg.defDmgKey || '',
mainAttr: cfg.mainAttr || 'atk,cpct,cdmg', // 伤害属性
enemyName: cfg.enemyName || '小宝' // 敌人名称
}
@ -92,7 +101,7 @@ export default class ProfileDmg extends Base {
if (!charCalcData) {
return false
}
let { buffs, details, defParams, mainAttr, defDmgIdx, enemyName } = charCalcData
let { buffs, details, defParams, mainAttr, defDmgIdx, defDmgKey, enemyName } = charCalcData
let talent = this.talent()
@ -115,7 +124,21 @@ export default class ProfileDmg extends Base {
let dmgRet = []
let dmgDetail = {}
if (mode === 'single') {
dmgIdx = defDmgIdx > -1 ? defDmgIdx : 0
}
lodash.forEach(details, (detail, detailSysIdx) => {
if (mode === 'single') {
if (defDmgKey) {
if (detail.dmgKey !== defDmgKey) {
return true
}
} else if (detailSysIdx !== dmgIdx) {
return true
}
}
if (lodash.isFunction(detail)) {
let { attr } = DmgAttr.calcAttr({ originalAttr, buffs, meta })
let ds = lodash.merge({ talent }, DmgAttr.getDs(attr, meta))
@ -196,6 +219,10 @@ export default class ProfileDmg extends Base {
})
}
if (mode === 'single') {
return ret[0]
}
return {
ret,
msg,

View File

@ -20,26 +20,51 @@ export default class ProfileRank {
if (!profile.hasData) {
return false
}
const key = this.key(profile, 'mark')
let rank = await redis.zRevRank(key, this.uid)
if (!lodash.isNumber(rank) || force) {
let ret = {}
const markKey = this.key(profile, 'mark')
let markRank = await redis.zRevRank(markKey, this.uid)
if (!lodash.isNumber(markRank) || force) {
let mark = profile.getArtisMark(false)
if (mark) {
await redis.zAdd(key, { score: mark._mark, value: this.uid })
rank = await redis.zRevRank(key, this.uid)
await redis.zAdd(markKey, { score: mark._mark, value: this.uid })
markRank = await redis.zRevRank(markKey, this.uid)
}
}
if (lodash.isNumber(rank)) {
let count = await redis.zCard(key)
let mark = await redis.zScore(key, this.uid)
return {
rank: rank + 1,
count,
value: Format.comma(mark, 1),
_value: mark,
pct: Format.percent(Math.max(0.01, Math.min(0.999, (count - rank) / count)))
if (lodash.isNumber(markRank)) {
let markCount = await redis.zCard(markKey)
ret.markRank = markRank + 1
ret.markCount = markCount
}
if (profile.hasDmg) {
const dmgKey = this.key(profile, 'dmg')
let dmgRank = await redis.zRevRank(dmgKey, this.uid)
if (!lodash.isNumber(dmgRank) || force) {
let dmg = await profile.calcDmg({ mode: 'single' })
if (dmg) {
await redis.zAdd(dmgKey, { score: dmg.avg, value: this.uid })
dmgRank = await redis.zRevRank(dmgKey, this.uid)
}
}
if (lodash.isNumber(dmgRank)) {
let dmgCount = await redis.zCard(dmgKey)
ret.dmgRank = dmgRank + 1
ret.dmgCount = dmgCount
}
}
if (lodash.isEmpty(ret)) {
return false
}
if (!ret.dmgRank || ret.markRank < ret.dmgRank) {
ret.rank = ret.markRank
ret.rankType = 'mark'
} else {
ret.rank = ret.dmgRank
ret.rankType = 'dmg'
}
return ret
}
static async getGroupMaxUid (groupId, charId, type = 'mark') {
return await redis.zRange(`miao:rank:${groupId}:${type}:${charId}`, -1, -1)
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 73 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

View File

@ -47,7 +47,7 @@ body,
}
.char-item .group-rank {
position: absolute;
background: url('./imgs/rank-bg.png') left top no-repeat;
background: url('./imgs/dmg-rank-bg.png') left top no-repeat;
background-size: auto 100%;
left: 0;
top: 0;
@ -55,6 +55,9 @@ body,
width: 74px;
height: 74px;
}
.char-item .group-rank.rank-type-mark {
background-image: url('./imgs/mark-rank-bg.png');
}
.char-item .group-rank span {
position: absolute;
font-size: 12px;
@ -117,7 +120,20 @@ body,
border-radius: 50%;
margin-right: 3px;
}
.no-rank .group-rank {
.group-rank-icon {
width: 16px;
height: 16px;
background: url("./imgs/mark-icon.png");
background-size: auto 100%;
display: inline-block;
vertical-align: middle;
margin-right: 2px;
}
.group-rank-icon.mark-icon {
background-position: 100% 0;
}
.no-rank .group-rank,
.no-rank .group-rank-tip {
display: none;
}
/*# sourceMappingURL=profile-list.css.map */

View File

@ -27,7 +27,7 @@
{{if char.groupRank}}
{{set gr = char.groupRank}}
{{set rank = gr.rank > 9 ? 10:(gr.rank <=3 ? gr.rank : 4)}}
<div class="group-rank rank-{{rank}}">
<div class="group-rank rank-{{rank}} rank-type-gr.type">
<span>{{gr.rank}}</span>
</div>
{{/if}}
@ -38,7 +38,10 @@
{{if hasNew}}
<span class="new-tip">本次更新角色</span>
{{else}}
<span></span>
<span class="group-rank-tip">群内排名:
<i class="group-rank-icon dmg-icon"></i>综合练度
<i class="group-rank-icon mark-icon"></i>圣遗物评分
</span>
{{/if}}
<span class="serv">当前更新服务:{{servName}}</span>
</div>

View File

@ -56,7 +56,7 @@ body, .container {
.group-rank {
position: absolute;
background: url('./imgs/rank-bg.png') left top no-repeat;
background: url('./imgs/dmg-rank-bg.png') left top no-repeat;
background-size: auto 100%;
left: 0;
top: 0;
@ -64,6 +64,10 @@ body, .container {
width: 74px;
height: 74px;
&.rank-type-mark {
background-image: url('./imgs/mark-rank-bg.png');
}
span {
position: absolute;
font-size: 12px;
@ -141,6 +145,21 @@ body, .container {
}
}
.no-rank .group-rank {
.group-rank-icon {
width: 16px;
height: 16px;
background: url("./imgs/mark-icon.png");
background-size: auto 100%;
display: inline-block;
vertical-align: middle;
margin-right: 2px;
&.mark-icon {
background-position: 100% 0;
}
}
.no-rank .group-rank,
.no-rank .group-rank-tip {
display: none;
}

View File

@ -41,6 +41,7 @@ export const details = [{
}
}]
export const defDmgIdx = 3
export const mainAttr = 'atk,cpct,cdmg'
export const enemyName = '魔偶/女士/雷神'

View File

@ -1,9 +1,11 @@
export const details = [{
check: ({ cons }) => cons < 2,
dmgKey: 'e',
title: '叄阶杀生樱伤害',
dmg: ({ talent, attr }, dmg) => dmg(talent.e['杀生樱伤害·叁阶'], 'e')
}, {
check: ({ cons }) => cons >= 2,
dmgKey: 'e',
title: '肆阶杀生樱伤害',
dmg: ({ talent, attr }, dmg) => dmg(talent.e['杀生樱伤害·肆阶'], 'e')
}, {
@ -15,6 +17,7 @@ export const details = [{
}]
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const defDmgKey = 'e'
export const buffs = [{
title: '被动天赋:基于元素精通提高杀生樱伤害[eDmg]%',

View File

@ -10,6 +10,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['技能伤害'] + talent.q['连斩伤害'] + talent.q['最后一击伤害'], 'q')
}]
export const defDmgIdx = 2
export const mainAttr = 'atk,cpct,cdmg'
export const buffs = [{

View File

@ -11,6 +11,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['轰轰火花伤害'], 'q')
}]
export const defDmgIdx = 1
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{

View File

@ -18,6 +18,7 @@ export const details = [{
}
}]
export const defDmgIdx = 2
export const mainAttr = 'hp,cpct,cdmg'
export const buffs = [{

View File

@ -12,6 +12,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.a['五段伤害'], 'a', 'vaporize')
}]
export const defDmgIdx = 2
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{

View File

@ -4,6 +4,7 @@ export const details = [{
}, {
title: 'Q单段伤害',
params: { q: true },
dmgKey: 'q',
dmg: ({ talent }, dmg) => dmg(talent.q['持续伤害'], 'q')
}, {
title: 'Q含转化单段',
@ -22,6 +23,7 @@ export const details = [{
dmg: ({}, { reaction }) => reaction('swirl')
}]
export const defDmgKey = 'q'
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{

View File

@ -10,7 +10,8 @@ export const details = [{
title: 'E伤害',
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
}]
export const defDmgIdx = 1
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{
title: '烟绯被动重击消耗4枚丹火印增加20%火伤',
cons: 6,

View File

@ -3,15 +3,19 @@ import lodash from 'lodash'
export const details = [{
check: ({ cons }) => cons < 2,
title: '水母每跳治疗',
dmgKey: 'q',
dmg: ({ attr, talent, calc }, { heal }) => {
let t = talent.e['治疗量2']; let hp = calc(attr.hp)
let t = talent.e['治疗量2'];
let hp = calc(attr.hp)
return heal(hp * t[0] / 100 + t[1] * 1)
}
}, {
cons: 2,
title: '半血水母每跳治疗',
dmgKey: 'q',
dmg: ({ attr, talent, calc }, { heal }) => {
let t = talent.e['治疗量2']; let hp = calc(attr.hp)
let t = talent.e['治疗量2'];
let hp = calc(attr.hp)
return heal(hp * t[0] / 100 + t[1] * 1 + hp * 0.045)
}
}, {
@ -37,7 +41,7 @@ export const details = [{
return ret
}
}]
export const defDmgKey = 'q'
export const defDmgIdx = 2
export const mainAttr = 'hp,atk'

View File

@ -7,6 +7,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['爆发伤害'], 'q')
}, {
title: 'Q爆发治疗',
dmgKey: 'qHeal',
dmg: ({ talent, calc, attr }, { heal }) =>
heal(talent.q['领域发动治疗量2'][0] * calc(attr.atk) / 100 + talent.q['领域发动治疗量2'][1] * 1)
}, {
@ -16,6 +17,7 @@ export const details = [{
}]
export const mainAttr = 'atk,cpct,cdmg'
export const defDmgKey = 'qHeal'
export const buffs = [{
cons: 1,

View File

@ -6,10 +6,12 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.e['技能伤害'], 'e')
}, {
title: '神里流·霜灭 单段伤害',
dmgKey: 'q',
dmg: ({ talent }, dmg) => dmg(talent.q['切割伤害'], 'q')
}]
export const mainAttr = 'atk,cpct,cdmg'
export const defDmgKey = 'q'
export const buffs = [{
passive: 1,

View File

@ -40,6 +40,7 @@ export const details = [{
}
}]
export const defDmgIdx = 4
export const mainAttr = 'atk,mastery,cpct,cdmg'
export const buffs = [{

View File

@ -10,11 +10,13 @@ export const details = [{
heal(talent.e['持续治疗量2'][0] * calc(attr.hp) / 100 + talent.e['持续治疗量2'][1] * 1)
}, {
title: 'Q治疗量',
dmgKey: 'qHeal',
dmg: ({ talent, attr, calc }, { heal }) =>
heal(talent.q['治疗量2'][0] * calc(attr.hp) / 100 + talent.q['治疗量2'][1] * 1)
}]
export const defDmgIdx = 1
export const defDmgKey = 'qHeal'
export const mainAttr = 'atk,hp,cpct,cdmg,mastery'
export const buffs = [{

View File

@ -23,6 +23,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(100, 'e')
}]
export const defDmgIdx = 2
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{
@ -38,7 +39,7 @@ export const buffs = [{
dmg: 50
}
}, {
title: '赛诺被动末途真眼状态提升E 35%伤害,发射渡荒之造成100%攻击力伤害',
title: '赛诺被动末途真眼状态提升E 35%伤害,发射渡荒之造成100%攻击力伤害',
data: {
ePlus: ({ params }) => [3, 4].includes(params.q) ? 35 : 0
}

View File

@ -3,6 +3,7 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.e['三段伤害'], 'e')
}, {
title: 'E三段蒸发',
dmgKey: 'e',
dmg: ({ talent }, dmg) => dmg(talent.e['三段伤害'], 'e', 'vaporize')
}, {
title: 'Q爆发伤害',
@ -15,6 +16,7 @@ export const details = [{
}]
export const defParams = { monv: 3 }
export const defDmgKey = 'e'
export const mainAttr = 'atk,cpct,cdmg,mastery'
export const buffs = [{

View File

@ -9,9 +9,11 @@ export const details = [{
dmg: ({ talent }, dmg) => dmg(talent.q['旋火轮伤害'], 'q')
}, {
title: '旋火轮单次蒸发',
dmgKey: 'q',
dmg: ({ talent }, dmg) => dmg(talent.q['旋火轮伤害'], 'q', 'vaporize')
}]
export const defDmgKey = 'q'
export const mainAttr = 'atk,cpct,cdmg'
export const buffs = [{