Skip to content

Commit

Permalink
feat: prototype for the new optimizer system
Browse files Browse the repository at this point in the history
see fribbels#173 for more details
  • Loading branch information
Hà Trung Kiên committed Mar 15, 2024
1 parent 372f58f commit 9c80f26
Show file tree
Hide file tree
Showing 3 changed files with 685 additions and 0 deletions.
122 changes: 122 additions & 0 deletions src/lib/optimizer/new/formula.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import { FinalStats } from './stats/stat'

/**
* Formula contains all the metadata that makes up the computation of an
* {@link OptimizationTarget}. In particular, each formula provides information
* about:
* - How many calculation steps are there?
* - How is each step computed?
*/
export class Formula {
/**
* @param steps all {@link Step} that makes up this calculation
*/
constructor(readonly steps: Step[]) {}

/**
* This method assumes the supplied multipliers array is always correct to
* skip validations.
* @param muls the final {@link FinalStats} to be used with each steps
* @returns a result that can be used for comparision the value of a build
* created by aggregating the result of each step.
*/
calculate(muls: FinalStats[]): number {
return this.steps.reduce(
(prev, step, index) => prev + step.calculate(muls[index]),
0,
)
}
}

export type StepBuilder = {
// TODO
}
/**
* A step contains the instruction to get the optimization target index that
* could be used for comparision. Each step has a single final
* {@link FinalStats} that it could works with, it cannot modify any stats.
*/
type Step = {
calculate(stat: FinalStats): number
}

export abstract class DamageStep implements Step {
constructor(private broken: boolean) {}
/* eslint-disable @stylistic/operator-linebreak */
calculate(stat: FinalStats): number {
return (
this.base(stat) *
this.def(
stat.basic.lv,
stat.targetDef.baseDef,
stat.targetDef.percent,
stat.targetDef.flat,
) *
Math.min(Math.max(1 - stat.res, 0.1), 2) *
this.dmgBoost(stat.dmgBoost) *
Math.min(1 + stat.vulnerability, 3.5) *
(this.broken ? 1 : 0.9) *
this.crit(stat.crit.critRate, stat.crit.critDmg) *
this.dmgReduction(stat.dmgReductions)
)
}
/* eslint-enable @stylistic/operator-linebreak */

protected abstract base(stat: FinalStats): number

protected dmgBoost(percent: number) {
return 1 + percent
}

protected dmgReduction(reductions: number[]) {
return reductions.reduce((prev, val) => prev * (1 - val), 1)
}

protected crit(critRate: number, critDmg: number) {
return 1 + Math.min(1, critRate) * critDmg
}

private def(
sourceLv: number,
baseDef: number,
percent: number,
flat: number,
) {
const def = Math.max(baseDef * (1 + percent) + flat, 0)
return 1 - def / (def + 200 + 10 * sourceLv)
}
}

export class NormalDamageStep extends DamageStep {
constructor(
broken: boolean,
private multiplier: number,
private type: 'ATK' | 'HP' | 'DEF',
private flat: number,
) {
super(broken)
}

protected override base(stat: FinalStats): number {
return this.multiplier * stat.basic[this.type] + this.flat
}
}

/* eslint-disable @typescript-eslint/no-unused-vars */
// This rule is poorly configured
export class DotDamageStep extends NormalDamageStep {
protected override crit(_cr: number, _cd: number): number {
return 1
}
}

export class BreakDamage extends DotDamageStep {
protected dmgBoost(_: number): number {
return 1
}

protected dmgReduction(_s: number[]): number {
return 1
}
}
/* eslint-enable @typescript-eslint/no-unused-vars */
63 changes: 63 additions & 0 deletions src/lib/optimizer/new/stats/conditional.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
type __Elements = {
physical
lightning
fire
wind
ice
quantum
imaginary
}

export enum Elements {
PHYSICAL,
LIGHTING,
FIRE,
WIND,
ICE,
QUANTUM,
IMAGINARY,
}

export enum Traits {
NORMAL,
SKILL,
ULTIMATE,
FOLLOW_UP,
DOT,
DOT_BLEED,
DOT_BURN,
DOT_WIND_SHEAR,
DOT_SHOCK,
DELAY,
DELAY_FREEZE,
DELAY_ENTANGLEMENT,
}

type __Traits = {
normal
skill
ultimate
followUp
dot: {
all
bleed
burn
windShear
shock
}
delayDamage: {
all
freeze
entanglement
}
}
export type Conditional<TRAIT, ELEMENT> = {
traits: {
[K in keyof __Traits]: K extends 'dot' | 'delayDamage'
? { [T in keyof __Traits[K]]: TRAIT }
: TRAIT
}
elements: {
[K in keyof __Elements]: ELEMENT
}
}
Loading

0 comments on commit 9c80f26

Please sign in to comment.