diff --git a/package.json b/package.json index 88626e3..694ef0a 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/pages/Artifacts.tsx b/src/components/pages/Artifacts.tsx index 18e9af5..fc2e76a 100644 --- a/src/components/pages/Artifacts.tsx +++ b/src/components/pages/Artifacts.tsx @@ -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([]); const [reliquaryAffixes, setReliquaryAffixes] = useState([]); const [uid, setUid] = useState(0); const [selectedArtifact, setSelectedArtifact] = useState(0); const [selectedMainStat, setSelectedMainStat] = useState(0); - const [selectedAffixes, setSelectedAffixes] = useState([]); - const [selectedAffixesAmount, setSelectedAffixesAmount] = useState>({}); const [artifactEnhancements, setArtifactEnhancements] = useState(0); + const [affixesValues, setAffixesValues] = useState({}); + const [selectedAffixesValues, setSelectedAffixesValues] = useState({}); 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, 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, 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, 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')} -
- {reliquaryAffixes.map((affix, index) => { +
+ {Object.keys(affixesValues).map((key, index) => { return ( -
- handleAffixSelected(e,false,0)}/> - - handleAffixSelected(e,true, affix.Id)}/> +
+
+
+ {t(key)} +
+
+
+ handleAffixChange(e,key)} + onBlur={(e)=>handleGetAffixClosestValue(e,key)} + /> +
- ); + ) })}
diff --git a/yarn.lock b/yarn.lock index dfe7806..f3cf2e4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -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"