Merge pull request #4 from exzork/refactor-substat

ui/ux improvement
This commit is contained in:
Muhammad Eko Prasetyo 2022-05-16 08:22:35 +07:00 committed by GitHub
commit 579a5eea90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 40 deletions

View File

@ -21,6 +21,7 @@
"i18next-browser-languagedetector": "^6.1.4",
"i18next-http-backend": "^1.4.0",
"lodash": "^4.17.21",
"mathjs": "^10.5.3",
"postcss": "^8.4.12",
"react": "^18.1.0",
"react-dom": "^18.1.0",

View File

@ -1,7 +1,7 @@
import {ChangeEvent, useEffect, useState} from "react";
import ReliquaryDataProvider, {IReliquaryAffix, IReliquaryMain} from "../providers/ReliquaryDataProvider";
import {Autocomplete, Chip, createFilterOptions, TextField} from "@mui/material";
import {permutations} from "mathjs";
//@ts-ignore
import _ from "lodash";
import {useTranslation} from "react-i18next";
@ -11,15 +11,23 @@ interface IArtifact {
name: string;
}
interface IPropTypeValues {
[key: string]: number[]; //number is the values
}
interface ISelectedPropTypeValues{
[key: string]: number[]; //number is the ids
}
export default function Artifacts() {
const [reliquaryMains, setReliquaryMains] = useState<IReliquaryMain[]>([]);
const [reliquaryAffixes, setReliquaryAffixes] = useState<IReliquaryAffix[]>([]);
const [uid, setUid] = useState(0);
const [selectedArtifact, setSelectedArtifact] = useState(0);
const [selectedMainStat, setSelectedMainStat] = useState(0);
const [selectedAffixes, setSelectedAffixes] = useState<number[]>([]);
const [selectedAffixesAmount, setSelectedAffixesAmount] = useState<Record<number, number>>({});
const [artifactEnhancements, setArtifactEnhancements] = useState(0);
const [affixesValues, setAffixesValues] = useState<IPropTypeValues>({});
const [selectedAffixesValues, setSelectedAffixesValues] = useState<ISelectedPropTypeValues>({});
const {t} = useTranslation("artifact");
@ -54,9 +62,14 @@ export default function Artifacts() {
});
}, []);
useEffect(() => {
const av: IPropTypeValues = getPropTypeValues(reliquaryAffixes);
setAffixesValues(av);
}, [reliquaryAffixes]);
useEffect(() => {
handleGeneratedArtifact()
}, [uid, selectedArtifact, selectedMainStat, selectedAffixes, selectedAffixesAmount, artifactEnhancements]);
}, [uid, selectedArtifact, selectedMainStat, selectedAffixesValues , artifactEnhancements]);
const handleArtifactChange = (event: any, value: any) => {
if (value !== null) {
@ -70,40 +83,88 @@ export default function Artifacts() {
}
};
const handleAffixSelected = (event: ChangeEvent<HTMLInputElement>, amount = false, affixId=0) => {
let newSelectedAffixes = [...selectedAffixes];
let newSelectedAffixesAmount = {...selectedAffixesAmount};
if (amount) {
newSelectedAffixesAmount[affixId]=Number(event.target.value);
} else {
if (newSelectedAffixes.indexOf(Number(event.currentTarget.value)) === -1) {
newSelectedAffixes.push(Number(event.currentTarget.value));
newSelectedAffixesAmount[Number(event.currentTarget.value)] = 1;
} else {
newSelectedAffixes.splice(newSelectedAffixes.indexOf(Number(event.currentTarget.value)), 1);
newSelectedAffixesAmount[Number(event.currentTarget.value)] = 0;
}
}
setSelectedAffixes(newSelectedAffixes);
setSelectedAffixesAmount(newSelectedAffixesAmount);
const getAffixIdByPropTypeAndPropValue = (propType: string, propValue: number) => {
return reliquaryAffixes.filter((x) => x.PropType === propType && x.PropValue === propValue)[0].Id;
};
const getPercent = (affix:IReliquaryAffix)=>{
if (affix.PropType.indexOf("PERCENT") !== -1 || affix.PropType.indexOf("CRITICAL") !== -1 || affix.PropType.indexOf("EFFICIENCY") !== -1 || affix.PropType.indexOf("HURT") !== -1 || affix.PropType.indexOf("RATIO") !== -1 || affix.PropType.indexOf("ADD") !== -1) {
return parseFloat(String(affix.PropValue*100)).toPrecision(3) + "%";
const getListOfIdsByPropTypeAndRequestValue = (affixName: string, requestValue: number)=>{
const possibleValues = affixesValues[affixName];
let ids:number[] = [];
let closestValue = 0;
let less:number[] = [];
possibleValues.forEach((value) => {
if (value <= requestValue) {
less.push(value);
}
});
less.sort();
less.reverse();
for (let i of less) {
while ((closestValue+i) <= requestValue) {
closestValue += i;
const id = getAffixIdByPropTypeAndPropValue(affixName, i);
if (id !== undefined) {
ids.push(id);
}
}
if(closestValue === requestValue) break;
}
return parseInt(String(affix.PropValue));
return {ids, closestValue};
}
const handleAffixChange = (event: ChangeEvent<HTMLInputElement>, affixName:string) => {
let affixesSelected = {...selectedAffixesValues};
const affixValues = parseInt(event.target.value);
if (affixValues > 0) {
if (affixesSelected[affixName] === undefined) affixesSelected[affixName] = [];
if (affixName.indexOf("PERCENT") !== -1 || affixName.indexOf("CRITICAL") !== -1 || affixName.indexOf("EFFICIENCY") !== -1 || affixName.indexOf("HURT") !== -1 || affixName.indexOf("RATIO") !== -1 || affixName.indexOf("ADD") !== -1){
const {ids} = getListOfIdsByPropTypeAndRequestValue(affixName, affixValues/100);
affixesSelected[affixName] = ids;
} else {
const {ids} = getListOfIdsByPropTypeAndRequestValue(affixName, affixValues);
affixesSelected[affixName] = ids;
}
} else {
delete affixesSelected[affixName];
}
setSelectedAffixesValues(affixesSelected);
};
const handleGetAffixClosestValue = (event: ChangeEvent<HTMLInputElement>, affixName:string) => {
const affixValues = parseInt(event.target.value);
if (affixValues === 0) return;
const {closestValue} =getListOfIdsByPropTypeAndRequestValue(affixName, affixValues);
event.target.value = parseFloat(closestValue.toFixed(3)).toString();
}
const getPropTypeValues = (affixes:IReliquaryAffix[])=>{
let propTypeValues:IPropTypeValues = {};
affixes.forEach(affix=>{
if (propTypeValues[affix.PropType] === undefined) {
propTypeValues[affix.PropType] = [];
}
propTypeValues[affix.PropType].push(affix.PropValue);
});
return propTypeValues;
};
const handleGeneratedArtifact = () => {
let selectedAffixesCombine: (string | number)[] = [];
if (selectedAffixes.length > 0) {
selectedAffixesCombine = selectedAffixes.map(x => {
if (selectedAffixesAmount[x] > 1) {
return x + "," + selectedAffixesAmount[x];
}
return x;
});
if (Object.keys(selectedAffixesValues).length > 0) {
Object.keys(selectedAffixesValues).forEach(affixName => {
const affixValues = selectedAffixesValues[affixName];
const distinctValues = Array.from(new Set(affixValues));
distinctValues.forEach(value => {
const countAffixes = affixValues.filter(x => x === value).length;
if (countAffixes > 1) selectedAffixesCombine.push(value+","+countAffixes);
else selectedAffixesCombine.push(value);
})
})
}
const generated = "/giveart @"+uid+" "+selectedArtifact+" "+selectedMainStat+" "+selectedAffixesCombine.join(" ")+" "+Number(artifactEnhancements+1);
setGeneratedArtifact(generated);
@ -169,15 +230,27 @@ export default function Artifacts() {
className="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
{t('sub_stats')}
</label>
<div className="mt-1 sm:mt-0 sm:col-span-2 h-48 overflow-auto">
{reliquaryAffixes.map((affix, index) => {
<div className="mt-1 sm:mt-0 sm:col-span-2 h-48 overflow-auto grid gap-x-10 gap-y-2 grid-cols-2">
{Object.keys(affixesValues).map((key, index) => {
return (
<div key={index} className="flex">
<input type="checkbox" className="mr-4 ml-4 focus:ring-indigo-500 h-4 w-4 mt-1 text-indigo-600 border-gray-300 rounded" value={affix.Id} id={"select-"+affix.Id} onChange={(e)=>handleAffixSelected(e,false,0)}/>
<label className="flex-grow" htmlFor={"select-"+affix.Id}>{t(affix.PropType) +" - "+getPercent(affix)}</label>
<input type="number" defaultValue="1" min="1" className="flex-none block shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md" onChange={(e)=>handleAffixSelected(e,true, affix.Id)}/>
<div key={index} className="flex items-center mt-1">
<div className="ml-3 flex-grow ">
<div className="text-sm leading-5 text-gray-900">
{t(key)}
</div>
</div>
<div className="ml-auto flex-none">
<input type="number"
step={0.01}
className="block shadow-sm focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm border-gray-300 rounded-md"
id={key}
defaultValue={0}
onChange={(e)=>handleAffixChange(e,key)}
onBlur={(e)=>handleGetAffixClosestValue(e,key)}
/>
</div>
</div>
);
)
})}
</div>
</div>

View File

@ -1018,7 +1018,7 @@
core-js-pure "^3.20.2"
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
"@babel/runtime@^7.10.2", "@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.14.5", "@babel/runtime@^7.14.6", "@babel/runtime@^7.16.3", "@babel/runtime@^7.17.2", "@babel/runtime@^7.17.9", "@babel/runtime@^7.5.5", "@babel/runtime@^7.7.2", "@babel/runtime@^7.7.6", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2":
version "7.17.9"
resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.17.9.tgz"
integrity sha512-lSiBBvodq29uShpWGNbgFdKYNiFDo5/HIYsaCEY9ff4sb10x9jizo2+pRrSyF4jKZCXqgzuqBOQKbUm90gQwJg==
@ -3253,6 +3253,11 @@ commondir@^1.0.1:
resolved "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
complex.js@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/complex.js/-/complex.js-2.1.1.tgz#0675dac8e464ec431fb2ab7d30f41d889fb25c31"
integrity sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==
compressible@~2.0.16:
version "2.0.18"
resolved "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz"
@ -3622,7 +3627,7 @@ debug@^3.1.1, debug@^3.2.7:
dependencies:
ms "^2.1.1"
decimal.js@^10.2.1:
decimal.js@^10.2.1, decimal.js@^10.3.1:
version "10.3.1"
resolved "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz"
integrity sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==
@ -3999,6 +4004,11 @@ escape-html@~1.0.3:
resolved "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz"
integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=
escape-latex@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/escape-latex/-/escape-latex-1.2.0.tgz#07c03818cf7dac250cce517f4fda1b001ef2bca1"
integrity sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==
escape-string-regexp@^1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz"
@ -5334,6 +5344,11 @@ jake@^10.8.5:
filelist "^1.0.1"
minimatch "^3.0.4"
javascript-natural-sort@^0.7.1:
version "0.7.1"
resolved "https://registry.yarnpkg.com/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz#f9e2303d4507f6d74355a73664d1440fb5a0ef59"
integrity sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k=
jest-changed-files@^27.5.1:
version "27.5.1"
resolved "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-27.5.1.tgz"
@ -6118,6 +6133,21 @@ makeerror@1.0.12:
dependencies:
tmpl "1.0.5"
mathjs@^10.5.3:
version "10.5.3"
resolved "https://registry.yarnpkg.com/mathjs/-/mathjs-10.5.3.tgz#79e0dd9cf370adce80699cc40ed18c1c0cb6599e"
integrity sha512-RtF+F7SdRIf2E2+btyGDhuB6wmPjOH9KeNglfclaaaI6eK7ZNfsQS6IRAKvGyNsr8sFc6Pyb3JBLqEhYBuknVQ==
dependencies:
"@babel/runtime" "^7.17.9"
complex.js "^2.1.1"
decimal.js "^10.3.1"
escape-latex "^1.2.0"
fraction.js "^4.2.0"
javascript-natural-sort "^0.7.1"
seedrandom "^3.0.5"
tiny-emitter "^2.1.0"
typed-function "^2.1.0"
mdn-data@2.0.14:
version "2.0.14"
resolved "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz"
@ -7856,6 +7886,11 @@ schema-utils@^4.0.0:
ajv-formats "^2.1.1"
ajv-keywords "^5.0.0"
seedrandom@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/seedrandom/-/seedrandom-3.0.5.tgz#54edc85c95222525b0c7a6f6b3543d8e0b3aa0a7"
integrity sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==
select-hose@^2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz"
@ -8456,6 +8491,11 @@ thunky@^1.0.2:
resolved "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz"
integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==
tiny-emitter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tmpl@1.0.5:
version "1.0.5"
resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz"
@ -8580,6 +8620,11 @@ type-is@~1.6.18:
media-typer "0.3.0"
mime-types "~2.1.24"
typed-function@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/typed-function/-/typed-function-2.1.0.tgz#ded6f8a442ba8749ff3fe75bc41419c8d46ccc3f"
integrity sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==
typedarray-to-buffer@^3.1.5:
version "3.1.5"
resolved "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz"