Skip to content

Commit

Permalink
2.4.0
Browse files Browse the repository at this point in the history
- Added conditional stats to artifacts. Now you can calculate builds using temporary stats.
- Added conditional stats to every artifact sets (if applicable)
- Added navigation menu toggle for mobile devices
- Small layout changes
  • Loading branch information
frzyc committed Dec 27, 2020
1 parent e5ead30 commit 980cad6
Show file tree
Hide file tree
Showing 57 changed files with 795 additions and 292 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"homepage": "https://frzyc.github.io/genshin-optimizer/",
"name": "genshin-optimizer",
"version": "2.3.2",
"version": "2.4.0",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-svg-core": "^1.2.32",
Expand Down
3 changes: 3 additions & 0 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ function App() {
<div id="content" className="flex-grow-1">
<Navbar bg="dark" variant="dark" expand="md">
<Navbar.Brand as={Link} to="/">Genshin Optimizer</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link as={Link} to="/artifact">
Artifacts</Nav.Link>
Expand All @@ -50,6 +52,7 @@ function App() {
</Nav.Link>
</ReactGA.OutboundLink>
</Nav>
</Navbar.Collapse>
</Navbar>
<Suspense fallback={<Container>
<Card bg="darkcontent" text="lightfont" className="mt-2">
Expand Down
89 changes: 75 additions & 14 deletions src/Artifact/Artifact.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ import CharacterDatabase from '../Character/CharacterDatabase';
import SlotIcon from '../Components/SlotIcon';
import { ArtifactMainSlotKeys, ArtifactMainStatsData, ArtifactSetsData, ArtifactSlotsData, ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import Stat from '../Stat';
import { clampPercent, closeEnoughFloat, closeEnoughInt, deepClone } from '../Util';
import ArtifactConditionals from '../Util/ArtifactConditionals';
import { clamp, clampPercent, closeEnoughFloat, closeEnoughInt, deepClone } from '../Util/Util';
import ArtifactBase from './ArtifactBase';
import ArtifactDatabase from './ArtifactDatabase';

Expand Down Expand Up @@ -145,36 +146,96 @@ export default class Artifact {
}

static setToSlots = ArtifactBase.setToSlots;

static getArtifactSets = (setKey, defVal = null) =>
ArtifactSetsData?.[setKey]?.sets || defVal
static getArtifactSetNumStats = (setKey, setNumKey, defVal = null) =>
this.getArtifactSets(setKey)?.[setNumKey]?.stats || defVal

static getArtifactConditionalStats = (setKey, setNumKey, conditionalNum, defVal = null) => {
if (!conditionalNum) return defVal
let conditional = ArtifactSetsData[setKey].sets[setNumKey].conditional
if (!conditional) return defVal
if (Array.isArray(conditional)) {
//multiconditional
let selectedConditionalNum = conditionalNum
let selectedConditional = null
for (const curConditional of conditional) {
if (selectedConditionalNum > curConditional.maxStack) selectedConditionalNum -= curConditional.maxStack
else {
selectedConditional = curConditional;
break;
}
}
if (!selectedConditional) return defVal
let stacks = clamp(selectedConditionalNum, 1, selectedConditional.maxStack)
return Object.fromEntries(Object.entries(selectedConditional.stats).map(([key, val]) => [key, val * stacks]))
} else if (conditional.maxStack > 1) {
//condtional with stacks
let stacks = clamp(conditionalNum, 1, conditional.maxStack)
return Object.fromEntries(Object.entries(conditional.stats).map(([key, val]) => [key, val * stacks]))
} else if (conditional.maxStack === 1)
//boolean conditional
return conditional.stats
return defVal
}
static getArtifactSetEffectsStats = (setToSlots) => {
let artifactSetEffect = []
Object.entries(setToSlots).forEach(([setKey, artArr]) =>
ArtifactSetsData?.[setKey]?.sets && Object.entries(ArtifactSetsData[setKey].sets).forEach(([setNumKey, value]) =>
parseInt(setNumKey) <= artArr.length && value.stats && Object.keys(value.stats).length &&
Object.entries(value.stats).forEach(([key, statVal]) =>
artifactSetEffect.push({ key, statVal }))))
return artifactSetEffect
}
static getArtifactSetEffects = (setToSlots) => {
let artifactSetEffect = {}
Object.entries(setToSlots).forEach(([setKey, arr]) => {
let numArts = arr.length;
if (ArtifactSetsData[setKey] && ArtifactSetsData[setKey].sets) {
Object.entries(ArtifactSetsData[setKey].sets).forEach(([num, value]) => {
if (parseInt(num) <= numArts) {
!artifactSetEffect[setKey] && (artifactSetEffect[setKey] = {})
artifactSetEffect[setKey][num] = deepClone(value);
}
})
Object.entries(setToSlots).forEach(([setKey, artArr]) => {
if (ArtifactSetsData?.[setKey]?.sets) {
let setNumKeys = Object.keys(ArtifactSetsData[setKey].sets).filter(setNumKey => parseInt(setNumKey) <= artArr.length)
if (setNumKeys.length)
artifactSetEffect[setKey] = setNumKeys
}
})
return artifactSetEffect
}
static getAllArtifactSetEffectsObj = (conditionals) => {

static getArtifactSetEffectText = (setKey, setNumKey, charFinalStats, defVal = "") => {
let setEffectText = ArtifactSetsData?.[setKey]?.sets?.[setNumKey]?.text
if (!setEffectText) return defVal
if (typeof setEffectText === "string")
return setEffectText
else if (typeof setEffectText === "function")
return setEffectText(charFinalStats || {})
return defVal
}
static getArtifactSetEffectConditional = (setKey, setNumKey, defVal = null) =>
ArtifactSetsData?.[setKey]?.sets?.[setNumKey]?.conditional || defVal

static getAllArtifactSetEffectsObj = (artifactConditionals) => {
let ArtifactSetEffectsObj = {};
Object.entries(ArtifactSetsData).forEach(([key, setObj]) => {
Object.entries(ArtifactSetsData).forEach(([setKey, setObj]) => {
let setEffect = {}
let hasSetEffect = false
if (setObj.sets)
Object.entries(setObj.sets).forEach(([setNumKey, setEffectObj]) => {
//TODO conditionals
if (setEffectObj.stats && Object.keys(setEffectObj.stats).length > 0) {
setEffect[setNumKey] = deepClone(setEffectObj.stats)
hasSetEffect = true
}
if (setEffectObj.conditional) {
let conditionalNum = ArtifactConditionals.getConditionalNum(artifactConditionals, setKey, setNumKey)
if (conditionalNum) {
let condStats = this.getArtifactConditionalStats(setKey, setNumKey, conditionalNum)
if (condStats) {
setEffect[setNumKey] = deepClone(condStats)
hasSetEffect = true
}
}
}
})
if (hasSetEffect)
ArtifactSetEffectsObj[key] = setEffect;
ArtifactSetEffectsObj[setKey] = setEffect;
})
return ArtifactSetEffectsObj
}
Expand Down
3 changes: 2 additions & 1 deletion src/Artifact/ArtifactBase.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ export default class ArtifactBase {
//do not instantiate.
constructor() { if (this instanceof ArtifactBase) throw Error('A static class cannot be instantiated.'); }

//returns {setKey:[slotKey...]}
static setToSlots = (artifacts) => {
let setToSlots = {};
Object.entries(artifacts).forEach(([key, art]) => {
if (!art) return
if (setToSlots[art.setKey]) setToSlots[art.setKey].push(key)
else setToSlots[art.setKey] = [key]
})
return setToSlots //{setKey:[slotKey...]}
return setToSlots
}
}
2 changes: 1 addition & 1 deletion src/Artifact/ArtifactDatabase.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util";
import { deepClone, loadFromLocalStorage, saveToLocalStorage } from "../Util/Util";
var initiated = false
var artifactDatabase = {};
var artIdIndex = 1;
Expand Down
2 changes: 1 addition & 1 deletion src/Artifact/ArtifactDisplay.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import { Stars } from '../Components/StarDisplay';
import { ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import { DatabaseInitAndVerify } from '../DatabaseUtil';
import Stat from '../Stat';
import { deepClone } from '../Util';
import Artifact from './Artifact';
import ArtifactCard from './ArtifactCard';
import ArtifactDatabase from './ArtifactDatabase';
import ArtifactEditor from './ArtifactEditor';
import ReactGA from 'react-ga';
import { deepClone } from '../Util/Util';

export default class ArtifactDisplay extends React.Component {
constructor(props) {
Expand Down
6 changes: 3 additions & 3 deletions src/Artifact/ArtifactEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { FloatFormControl, IntFormControl } from '../Components/CustomFormContro
import { Stars } from '../Components/StarDisplay';
import { ArtifactSetsData, ArtifactSlotsData, ArtifactStarsData, ArtifactSubStatsData } from '../Data/ArtifactData';
import Stat from '../Stat';
import { deepClone, getArrLastElement, getRandomElementFromArray, getRandomIntInclusive } from '../Util';
import { deepClone, getArrLastElement, getRandomElementFromArray, getRandomIntInclusive } from '../Util/Util';
import Artifact from './Artifact';
import ArtifactDatabase from './ArtifactDatabase';
import PercentBadge from './PercentBadge';
Expand Down Expand Up @@ -298,12 +298,12 @@ export default class ArtifactEditor extends React.Component {
</PercentBadge>
</span>
<OverlayTrigger
placement="left"
placement="bottom"
overlay={
<Popover >
<Popover.Title as="h5">Substat Efficiency</Popover.Title>
<Popover.Content>
<span>Every time 4 artifact upgrades, you get a substat roll. The <strong>substat efficiency</strong> calculates as a percentage how high the substat rolled. The <strong>Maximum Substat Efficiency</strong> of an artifact calculates the efficiency if the remaining upgrades rolled maximum.</span>
<span>Every 4 artifact upgrades, you get a substat roll. The <strong>substat efficiency</strong> calculates as a percentage how high the substat rolled. The <strong>Maximum Substat Efficiency</strong> of an artifact calculates the efficiency if the remaining upgrades rolled maximum.</span>
</Popover.Content>
</Popover>
}
Expand Down
Loading

0 comments on commit 980cad6

Please sign in to comment.