Skip to content
This repository has been archived by the owner on Mar 23, 2022. It is now read-only.

Commit

Permalink
IMP - Reduce unnecessary calculations in ATK skill lookup
Browse files Browse the repository at this point in the history
Signed-off-by: RaenonX <[email protected]>
  • Loading branch information
RaenonX committed Jul 7, 2021
1 parent 1f83be1 commit 24f6300
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {ElementBonusData} from '../../../../../../api-def/resources';
import {UseFetchEnumsReturn} from '../../hooks/enums';
import {CalculatedSkillEntry} from '../../out/types';
import {calculateEntries, filterSkillEntries} from '../../out/utils';
import {calculateEntries, filterSkillEntries} from '../../out/utils/entries';
import {InputData} from '../types';


Expand Down
15 changes: 15 additions & 0 deletions src/components/elements/gameData/skillAtk/out/utils/calc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import {AttackingSkillData} from '../../../../../../api-def/resources';
import {Efficiency} from '../types';


export const calculateEfficiency = (totalSkillMods: number, entry: AttackingSkillData): Efficiency => ({
modPctPer1KSp: (totalSkillMods * 100) / (entry.skill.spMax / 1000),
modPctPer1KSsp: (totalSkillMods * 100) / (entry.skill.ssSp / 1000),
secPer1KSp: Object.fromEntries(entry.skill.afflictions.map((afflictionUnit) => (
[afflictionUnit.statusCode, afflictionUnit.duration / (entry.skill.spMax / 1000)]
))),
secPer1KSsp: Object.fromEntries(entry.skill.afflictions.map((afflictionUnit) => (
[afflictionUnit.statusCode, afflictionUnit.duration / (entry.skill.ssSp / 1000)]
))),
spFullFillSec: entry.skill.spGradualPctMax ? 100 / entry.skill.spGradualPctMax : 0,
});
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import {generateAttackingSkillEntry} from '../../../../../../test/data/mock/skill';
import {AttackingSkillData, ElementBonusData} from '../../../../../api-def/resources';
import {ResourceLoader} from '../../../../../utils/services/resources';
import {InputData} from '../in/types';
import {generateInputData} from '../in/utils/inputData';
import {calculateEntries, filterSkillEntries} from './utils';
import {generateAttackingSkillEntry} from '../../../../../../../test/data/mock/skill';
import {AttackingSkillData, ElementBonusData} from '../../../../../../api-def/resources';
import {ResourceLoader} from '../../../../../../utils/services/resources';
import {InputData} from '../../in/types';
import {generateInputData} from '../../in/utils/inputData';
import {calculateEntries, filterSkillEntries} from './entries';


const inputDataTemplate: InputData = generateInputData();
Expand Down Expand Up @@ -111,6 +111,10 @@ describe('Sort ATK skill entries', () => {
const inputData: InputData = {
...inputDataTemplate,
sortBy: 'damage',
display: {
...inputDataTemplate.display,
actualDamage: true,
},
};

const entries = calculateEntries(data, inputData, elemBonusData)
Expand Down Expand Up @@ -393,4 +397,30 @@ describe('Entry calculation', () => {
const entry = calculateEntries([data], inputDataTemplate, elemBonusData)[0];
expect(entry.efficiency.spFullFillSec).toBe(0);
});

it('does not calculate efficiency if SP info will not display', async () => {
const inputData: InputData = {
...inputDataTemplate,
display: {
...inputDataTemplate.display,
spInfo: false,
},
};

const entry = calculateEntries([data], inputData, elemBonusData)[0];
expect(entry.efficiency.modPctPer1KSp).toBe(0);
});

it('does not calculate actual damage if actual damage will not display', async () => {
const inputData: InputData = {
...inputDataTemplate,
display: {
...inputDataTemplate.display,
actualDamage: false,
},
};

const entry = calculateEntries([data], inputData, elemBonusData)[0];
expect(entry.skillDamage.expected).toBe(0);
});
});
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import {AttackingSkillData, ElementBonusData} from '../../../../../api-def/resources';
import {calculateDamage} from '../../../../../utils/game/damage';
import {InputData} from '../in/types';
import {sortFunc} from '../sorter/lookup';
import {CalculatedSkillEntry, Efficiency} from './types';
import {AttackingSkillData, ElementBonusData} from '../../../../../../api-def/resources';
import {calculateDamage} from '../../../../../../utils/game/damage';
import {InputData} from '../../in/types';
import {sortFunc} from '../../sorter/lookup';
import {CalculatedSkillEntry, Efficiency} from '../types';
import {calculateEfficiency} from './calc';


export const filterSkillEntries = (inputData: InputData, atkSkillEntries: Array<AttackingSkillData>) => {
Expand Down Expand Up @@ -39,35 +40,29 @@ export const calculateEntries = (
atkSkillEntries: Array<AttackingSkillData>, inputData: InputData, elemBonusData: ElementBonusData,
): Array<CalculatedSkillEntry> => {
return atkSkillEntries
.map((entry: AttackingSkillData) => {
.map((skillEntry: AttackingSkillData) => {
// Element bonus rate
const charaElementRate = elemBonusData.getElementBonus(
String(entry.chara.element),
String(skillEntry.chara.element),
String(inputData.target.elemCondCode),
);

// Calculate skill damage
const skillDamage = calculateDamage(inputData, entry, charaElementRate);
const skillDamage = calculateDamage(inputData, skillEntry, charaElementRate);

// Calculate efficiency
const efficiency: Efficiency = {
modPctPer1KSp: (skillDamage.totalMods * 100) / (entry.skill.spMax / 1000),
modPctPer1KSsp: (skillDamage.totalMods * 100) / (entry.skill.ssSp / 1000),
secPer1KSp: Object.fromEntries(entry.skill.afflictions.map((afflictionUnit) => (
[afflictionUnit.statusCode, afflictionUnit.duration / (entry.skill.spMax / 1000)]
))),
secPer1KSsp: Object.fromEntries(entry.skill.afflictions.map((afflictionUnit) => (
[afflictionUnit.statusCode, afflictionUnit.duration / (entry.skill.ssSp / 1000)]
))),
spFullFillSec: entry.skill.spGradualPctMax ? 100 / entry.skill.spGradualPctMax : 0,
};
const efficiency: Efficiency = inputData.display.spInfo ?
calculateEfficiency(skillDamage.totalMods, skillEntry) :
{
modPctPer1KSp: 0,
modPctPer1KSsp: 0,
secPer1KSp: {},
secPer1KSsp: {},
spFullFillSec: 0,
};

return {
skillDamage,
skillEntry: entry,
efficiency,
};
return {skillDamage, skillEntry, efficiency};
})
.filter((calcData) => calcData.skillDamage.expected > 0)
.filter((calcData) => calcData.skillDamage.totalMods > 0)
.sort(sortFunc[inputData.sortBy]);
};
3 changes: 3 additions & 0 deletions src/utils/game/damage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ describe('Damage calculation', () => {
},
state: ConditionCodes.TARGET_STATE_BK,
},
display: {
actualDamage: true,
},
});

const attackingSkillData = {
Expand Down
12 changes: 6 additions & 6 deletions src/utils/game/damage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ export const calculateDamage = (
})
.reduce((a, b) => a + b, 0);

// Omit numeric calculations if not to display
if (!inputData.display.actualDamage) {
return {lowest: 0, expected: 0, highest: 0, totalMods};
}

let damage = 5 / 3; // Base damage

// Damage from ATK
Expand Down Expand Up @@ -96,10 +101,5 @@ export const calculateDamage = (
// Special - Bog
damage *= inputData.target.afflictionCodes.includes(ConditionCodes.TARGET_BOGGED) ? 1.5 : 1;

return {
lowest: damage * 0.95,
expected: damage,
highest: damage * 1.05,
totalMods: totalMods,
};
return {lowest: damage * 0.95, expected: damage, highest: damage * 1.05, totalMods};
};

0 comments on commit 24f6300

Please sign in to comment.