diff --git a/libs/common/util/src/lib/object.ts b/libs/common/util/src/lib/object.ts index 92e6fa3aec..5d22934e42 100644 --- a/libs/common/util/src/lib/object.ts +++ b/libs/common/util/src/lib/object.ts @@ -247,3 +247,26 @@ export function objFindValue( ): K | undefined { return Object.keys(obj).find((k) => obj[k as K] === value) as K | undefined } + +/** + * Returns a new object that is the sum of `a` and `b` + */ +export function objSum( + a: Record, + b: Record +): Record { + const sum = { ...a } + for (const k in b) sum[k] = (sum[k] ?? 0) + b[k] + return sum +} + +/** + * Apply obj `add` to the `base` object + */ +export function objSumInPlace( + base: Record, + add: Record +): Record { + for (const k in add) base[k] = (base[k] ?? 0) + add[k] + return base +} diff --git a/libs/zzz/db/src/Database/DataManagers/CharacterDataManager.ts b/libs/zzz/db/src/Database/DataManagers/CharacterDataManager.ts index 7a63fe1217..420673e68b 100644 --- a/libs/zzz/db/src/Database/DataManagers/CharacterDataManager.ts +++ b/libs/zzz/db/src/Database/DataManagers/CharacterDataManager.ts @@ -3,11 +3,13 @@ import { clamp, objFilter, validateArr } from '@genshin-optimizer/common/util' import type { CharacterKey, DiscMainStatKey, + DiscSetKey, FormulaKey, WengineKey, } from '@genshin-optimizer/zzz/consts' import { allCharacterKeys, + allDiscSetKeys, allFormulaKeys, allWengineKeys, discSlotToMainStatKeys, @@ -32,6 +34,8 @@ export type CharacterData = { slot6: DiscMainStatKey[] levelLow: number levelHigh: number + setFilter2: DiscSetKey[] + setFilter4: DiscSetKey[] } function initialCharacterData(key: CharacterKey): CharacterData { @@ -53,6 +57,8 @@ function initialCharacterData(key: CharacterKey): CharacterData { slot6: [...discSlotToMainStatKeys['6']], levelLow: 15, levelHigh: 15, + setFilter2: [], + setFilter4: [], } } export class CharacterDataManager extends DataManager< @@ -81,6 +87,8 @@ export class CharacterDataManager extends DataManager< slot6, levelLow, levelHigh, + setFilter2, + setFilter4, } = obj as CharacterData if (!allCharacterKeys.includes(characterKey)) return undefined // non-recoverable @@ -122,6 +130,10 @@ export class CharacterDataManager extends DataManager< if (typeof levelHigh !== 'number') levelHigh = 15 levelHigh = clamp(levelHigh, 0, 15) + + setFilter2 = validateArr(setFilter2, allDiscSetKeys, []) + setFilter4 = validateArr(setFilter4, allDiscSetKeys, []) + const char: CharacterData = { key: characterKey, level, @@ -137,6 +149,8 @@ export class CharacterDataManager extends DataManager< slot6, levelLow, levelHigh, + setFilter2, + setFilter4, } return char } diff --git a/libs/zzz/page-optimize/src/BuildsDisplay.tsx b/libs/zzz/page-optimize/src/BuildsDisplay.tsx index f44a556b71..574662dde2 100644 --- a/libs/zzz/page-optimize/src/BuildsDisplay.tsx +++ b/libs/zzz/page-optimize/src/BuildsDisplay.tsx @@ -4,7 +4,7 @@ import type { LocationKey } from '@genshin-optimizer/zzz/consts' import type { Stats } from '@genshin-optimizer/zzz/db' import { useDatabaseContext, useDisc } from '@genshin-optimizer/zzz/db-ui' import type { BuildResult } from '@genshin-optimizer/zzz/solver' -import { convertDiscToStats, getSum } from '@genshin-optimizer/zzz/solver' +import { applyCalc, convertDiscToStats } from '@genshin-optimizer/zzz/solver' import { DiscCard } from '@genshin-optimizer/zzz/ui' import { Box, Button, CardContent, Stack, Typography } from '@mui/material' import { useCallback, useMemo } from 'react' @@ -48,7 +48,7 @@ function Build({ const { database } = useDatabaseContext() const sum = useMemo( () => - getSum( + applyCalc( baseStats, Object.values(build.discIds) .map((d) => database.discs.get(d)) diff --git a/libs/zzz/page-optimize/src/CharacterContext.ts b/libs/zzz/page-optimize/src/CharacterContext.ts new file mode 100644 index 0000000000..f9b5951992 --- /dev/null +++ b/libs/zzz/page-optimize/src/CharacterContext.ts @@ -0,0 +1,10 @@ +import type { CharacterData } from '@genshin-optimizer/zzz/db' +import { createContext, useContext } from 'react' + +export const CharacterContext = createContext( + undefined as CharacterData | undefined +) + +export function useCharacterContext() { + return useContext(CharacterContext) +} diff --git a/libs/zzz/page-optimize/src/LevelFilter.tsx b/libs/zzz/page-optimize/src/LevelFilter.tsx index 8d4958f0ae..f1b4d62032 100644 --- a/libs/zzz/page-optimize/src/LevelFilter.tsx +++ b/libs/zzz/page-optimize/src/LevelFilter.tsx @@ -18,7 +18,8 @@ export const LevelFilter = memo(function LevelFilter({ - Artifact Level Filter + Disc Level Filter + {/* TODO: Translate */} {/* {t('levelFilter')} */} diff --git a/libs/zzz/page-optimize/src/Optimize.tsx b/libs/zzz/page-optimize/src/Optimize.tsx index 5bc4dad418..e6375b22f9 100644 --- a/libs/zzz/page-optimize/src/Optimize.tsx +++ b/libs/zzz/page-optimize/src/Optimize.tsx @@ -1,26 +1,20 @@ import { useForceUpdate } from '@genshin-optimizer/common/react-util' -import { - CardThemed, - DropdownButton, - SqBadge, -} from '@genshin-optimizer/common/ui' +import { CardThemed, SqBadge } from '@genshin-optimizer/common/ui' import { objMap, toDecimal, toggleInArr } from '@genshin-optimizer/common/util' import type { DiscMainStatKey, - DiscSetKey, FormulaKey, LocationKey, } from '@genshin-optimizer/zzz/consts' import { - allDiscSetKeys, discSlotToMainStatKeys, type DiscSlotKey, } from '@genshin-optimizer/zzz/consts' import type { Constraints, ICachedDisc, Stats } from '@genshin-optimizer/zzz/db' -import { useCharacter, useDatabaseContext } from '@genshin-optimizer/zzz/db-ui' +import { useDatabaseContext } from '@genshin-optimizer/zzz/db-ui' import type { BuildResult, ProgressResult } from '@genshin-optimizer/zzz/solver' import { MAX_BUILDS, Solver } from '@genshin-optimizer/zzz/solver' -import { DiscSetName, StatDisplay } from '@genshin-optimizer/zzz/ui' +import { StatDisplay } from '@genshin-optimizer/zzz/ui' import CloseIcon from '@mui/icons-material/Close' import TrendingUpIcon from '@mui/icons-material/TrendingUp' import { @@ -30,13 +24,14 @@ import { CardHeader, Divider, LinearProgress, - MenuItem, Typography, } from '@mui/material' import { Stack } from '@mui/system' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' +import { useCharacterContext } from './CharacterContext' import { LevelFilter } from './LevelFilter' +import { SetFilter } from './SetFilter' import { StatFilterCard } from './StatFilterCard' import { WorkerSelector } from './WorkerSelector' @@ -58,7 +53,7 @@ export default function OptimizeWrapper({ const [progress, setProgress] = useState( undefined ) - const character = useCharacter(location) + const character = useCharacterContext() useEffect(() => { setProgress(undefined) }, [character]) @@ -80,24 +75,16 @@ export default function OptimizeWrapper({ database.discs.values.reduce( (discsBySlot, disc) => { if (!character) return discsBySlot - if ( - disc.level < character.levelLow || - disc.level > character.levelHigh - ) + const { levelLow, levelHigh, useEquipped, slot4, slot5, slot6 } = + character + if (disc.level < levelLow || disc.level > levelHigh) return discsBySlot - if ( - disc.location && - !character.useEquipped && - disc.location !== location - ) + if (disc.location && !useEquipped && disc.location !== location) return discsBySlot if ( - (disc.slotKey === '4' && - !character.slot4.includes(disc.mainStatKey)) || - (disc.slotKey === '5' && - !character.slot5.includes(disc.mainStatKey)) || - (disc.slotKey === '6' && - !character.slot6.includes(disc.mainStatKey)) + (disc.slotKey === '4' && !slot4.includes(disc.mainStatKey)) || + (disc.slotKey === '5' && !slot5.includes(disc.mainStatKey)) || + (disc.slotKey === '6' && !slot6.includes(disc.mainStatKey)) ) return discsBySlot discsBySlot[disc.slotKey].push(disc) @@ -134,6 +121,7 @@ export default function OptimizeWrapper({ const onOptimize = useCallback(async () => { if (!character) return + const { setFilter2, setFilter4 } = character const cancelled = new Promise((r) => (cancelToken.current = r)) setResults([]) setProgress(undefined) @@ -146,6 +134,8 @@ export default function OptimizeWrapper({ ...c, value: toDecimal(c.value, k), })), + setFilter2, + setFilter4, discsBySlot, numWorkers, setProgress @@ -207,6 +197,11 @@ export default function OptimizeWrapper({ + @@ -225,19 +220,8 @@ export default function OptimizeWrapper({ - - - - NOTE: the solver currently accounts for 2-set effects only. - + + + + + NOTE: the solver currently accounts for 2-set effects only. + + + ) } - -function Set4Selector({ - disabled = false, - constraints, - setConstraints, -}: { - disabled?: boolean - constraints: Constraints - setConstraints: (c: Constraints) => void -}) { - const set4 = Object.entries(constraints).find( - ([k, { value }]) => allDiscSetKeys.includes(k as DiscSetKey) && value === 4 - )?.[0] - const set2 = Object.entries(constraints).find( - ([k, { value }]) => allDiscSetKeys.includes(k as DiscSetKey) && value === 2 - )?.[0] - return ( - <> - - Force 4-Set: {set4} - - ) : ( - 'Select to force 4-Set' - ) - } - sx={{ flexGrow: 1 }} - > - - setConstraints( - Object.fromEntries( - Object.entries(constraints).filter( - ([k, { value }]) => - !(allDiscSetKeys.includes(k as DiscSetKey) && value === 4) - ) - ) - ) - } - > - No 4-Set - - - {allDiscSetKeys.map((d) => ( - - setConstraints({ - ...Object.fromEntries( - Object.entries(constraints).filter( - ([k, { value }]) => - !(allDiscSetKeys.includes(k as DiscSetKey) && value === 4) - ) - ), - [d]: { value: 4, isMax: false }, - }) - } - > - - - ))} - - - Force 2-Set: {set2} - - ) : ( - 'Select to force 2-Set' - ) - } - sx={{ flexGrow: 1 }} - > - - setConstraints( - Object.fromEntries( - Object.entries(constraints).filter( - ([k, { value }]) => - !(allDiscSetKeys.includes(k as DiscSetKey) && value === 2) - ) - ) - ) - } - > - No 2-Set - - {allDiscSetKeys.map((d) => ( - - setConstraints({ - ...Object.fromEntries( - Object.entries(constraints).filter( - ([k, { value }]) => - !(allDiscSetKeys.includes(k as DiscSetKey) && value === 2) - ) - ), - [d]: { value: 2, isMax: false }, - }) - } - > - - - ))} - - - ) -} diff --git a/libs/zzz/page-optimize/src/SetFilter.tsx b/libs/zzz/page-optimize/src/SetFilter.tsx new file mode 100644 index 0000000000..e777713c00 --- /dev/null +++ b/libs/zzz/page-optimize/src/SetFilter.tsx @@ -0,0 +1,253 @@ +import { useBoolState } from '@genshin-optimizer/common/react-util' +import { + CardThemed, + DropdownButton, + ModalWrapper, +} from '@genshin-optimizer/common/ui' +import { toggleInArr } from '@genshin-optimizer/common/util' +import type { DiscSetKey } from '@genshin-optimizer/zzz/consts' +import { allDiscSetKeys } from '@genshin-optimizer/zzz/consts' +import { useDatabaseContext } from '@genshin-optimizer/zzz/db-ui' +import { DiscSetName } from '@genshin-optimizer/zzz/ui' +import CloseIcon from '@mui/icons-material/Close' +import { + Box, + Button, + ButtonGroup, + CardContent, + CardHeader, + Divider, + Grid, + IconButton, + MenuItem, +} from '@mui/material' +import { useCharacterContext } from './CharacterContext' + +export function SetFilter({ disabled = false }: { disabled?: boolean }) { + const { database } = useDatabaseContext() + const [open, onOpen, onClose] = useBoolState() + const character = useCharacterContext() + const { + setFilter2 = [], + setFilter4 = [], + key: characterKey, + } = character ?? {} + return ( + + + + + + + {setFilter4.length <= 1 ? ( + + Force 4-Set:{' '} + + + + + ) : ( + 'Select to force 4-Set' + ) + } + sx={{ flexGrow: 1 }} + > + + characterKey && + database.chars.set(characterKey, { + setFilter4: [], + }) + } + > + No 4-Set + + + {allDiscSetKeys.map((d) => ( + + characterKey && + database.chars.set(characterKey, { + setFilter4: [d], + }) + } + > + + + ))} + + ) : ( + + )} + + {setFilter2.length <= 1 ? ( + + Force 2-Set:{' '} + + + + + ) : ( + 'Select to force 2-Set' + ) + } + sx={{ flexGrow: 1 }} + > + + characterKey && + database.chars.set(characterKey, { + setFilter2: [], + }) + } + > + No 2-Set + + + {allDiscSetKeys.map((d) => ( + + characterKey && + database.chars.set(characterKey, { + setFilter2: [d], + }) + } + > + + + ))} + + ) : ( + + )} + + + + + + + ) +} +function AdvSetFilterCard({ onClose }: { onClose: () => void }) { + const { database } = useDatabaseContext() + const character = useCharacterContext() + const { + setFilter2 = [], + setFilter4 = [], + key: characterKey, + } = character ?? {} + return ( + + + + + } + /> + + + + + + + + {allDiscSetKeys.map((d) => ( + + + + ))} + + + + ) +} +function AdvSetFilterDiscCard({ setKey }: { setKey: DiscSetKey }) { + const { database } = useDatabaseContext() + const character = useCharacterContext() + const { + setFilter2 = [], + setFilter4 = [], + key: characterKey, + } = character ?? {} + return ( + + } /> + + + + + + ) +} diff --git a/libs/zzz/page-optimize/src/index.tsx b/libs/zzz/page-optimize/src/index.tsx index 0d87d270e3..924323c2b1 100644 --- a/libs/zzz/page-optimize/src/index.tsx +++ b/libs/zzz/page-optimize/src/index.tsx @@ -32,6 +32,7 @@ import { Stack } from '@mui/system' import { useCallback, useMemo, useState } from 'react' import BaseStatCard from './BaseStatCard' import { BuildsDisplay } from './BuildsDisplay' +import { CharacterContext } from './CharacterContext' import OptimizeWrapper from './Optimize' import { OptimizeTargetSelector } from './OptimizeTargetSelector' import { StatsDisplay } from './StatsDisplay' @@ -81,116 +82,124 @@ export default function PageOptimize() { ) return ( - - - - - Character - - { - setLocationKey(lk) - setBuilds([]) - }} - sx={{ flexGrow: 1 }} - autoFocus - /> + + + + + + Character + + { + setLocationKey(lk) + setBuilds([]) + }} + sx={{ flexGrow: 1 }} + autoFocus + /> - - l !== undefined && - character && - database.chars.set(character.key, { level: l }) - } - size="small" - inputProps={{ - sx: { width: '2ch' }, - max: 60, - min: 1, - }} - InputProps={{ - startAdornment: ( - Lv. - ), - }} - /> + + l !== undefined && + character && + database.chars.set(character.key, { level: l }) + } + size="small" + inputProps={{ + sx: { width: '2ch' }, + max: 60, + min: 1, + }} + InputProps={{ + startAdornment: ( + Lv. + ), + }} + /> - - {allCoreKeysWithNone.map((n, i) => ( - - character && - database.chars.set(character.key, { core: i }) - } - > - {n} - - ))} - - - {characterStats && } - - Wengine - - - wk && - character && - database.chars.set(character.key, { wengineKey: wk }) - } - sx={{ flexGrow: 1 }} - autoFocus - /> - + {allCoreKeysWithNone.map((n, i) => ( + + character && + database.chars.set(character.key, { core: i }) + } + > + {n} + + ))} + + + {characterStats && ( + + )} + - l !== undefined && - character && - database.chars.set(character.key, { wengineLvl: l }) - } - size="small" - inputProps={{ - sx: { width: '2ch' }, - max: 60, - min: 1, - }} - InputProps={{ - startAdornment: ( - Lv. - ), - }} + formulaKey={character?.formulaKey ?? allFormulaKeys[0]} + setFormulaKey={setFormulaKey} /> - - {wengineStats && } - - - - - - - + Wengine + + + wk && + character && + database.chars.set(character.key, { wengineKey: wk }) + } + sx={{ flexGrow: 1 }} + autoFocus + /> + + l !== undefined && + character && + database.chars.set(character.key, { wengineLvl: l }) + } + size="small" + inputProps={{ + sx: { width: '2ch' }, + max: 60, + min: 1, + }} + InputProps={{ + startAdornment: ( + Lv. + ), + }} + /> + + {wengineStats && } + + + + + + + + ) } diff --git a/libs/zzz/solver/src/calc.ts b/libs/zzz/solver/src/calc.ts index e6ee4c6c08..8f8578df70 100644 --- a/libs/zzz/solver/src/calc.ts +++ b/libs/zzz/solver/src/calc.ts @@ -1,4 +1,8 @@ -import { clamp01, objKeyMap } from '@genshin-optimizer/common/util' +import { + clamp01, + objKeyMap, + objSumInPlace, +} from '@genshin-optimizer/common/util' import type { AnomalyDamageKey, AttributeDamageKey, @@ -13,22 +17,58 @@ import { import type { Stats } from '@genshin-optimizer/zzz/db' import type { DiscStats } from './common' +export function passSetFilter( + discs: DiscStats[], + filter2: DiscSetKey[], + filter4: DiscSetKey[] +): boolean { + const setCount: Partial> = {} + if (!filter4.length && !filter2.length) return true + for (const { setKey } of discs) setCount[setKey] = (setCount[setKey] || 0) + 1 + + if (filter4.length) { + let has4 = false + for (const key in setCount) { + const k = key as DiscSetKey + if (setCount[k]! >= 4 && filter4.includes(k)) { + has4 = true + break // can break out because there is only one 4p + } + } + if (!has4) return false + } + if (filter2.length) { + for (const key in setCount) { + const k = key as DiscSetKey + const val = setCount[k]! + if (val === 1) return false // Rainbow + if (val >= 2 && val < 4 && !filter2.includes(k)) return false + } + } + return true +} + /** * sum up stats from base + discs + 2p effects */ -export function getSum(baseStats: Stats, discs: DiscStats[]) { +export function applyCalc(baseStats: Stats, discs: DiscStats[]) { const sum = { ...baseStats } const s = (key: string) => sum[key] || 0 - for (const d of discs) { - for (const key in d.stats) { - sum[key] = s(key) + d.stats[key] + + const setCount: Partial> = {} + // Apply disc set counts + for (const { setKey } of discs) setCount[setKey] = (setCount[setKey] || 0) + 1 + objSumInPlace(sum, setCount) + + // Apply 2p effects + for (const key in setCount) { + const k = key as DiscSetKey + if (setCount[k]! >= 2) { + const p2 = disc2pEffect[k] + if (p2) objSumInPlace(sum, p2) } } - for (const [key, value] of Object.entries(sum)) { - if (value >= 2 && disc2pEffect[key as DiscSetKey]) - for (const [k, v] of Object.entries(disc2pEffect[key as DiscSetKey])) - sum[k] = s(k) + v - } + // Rudimentary Calculations sum['initial_hp'] = s('hp_base') * (1 + s('hp_')) + s('hp') sum['initial_atk'] = s('atk_base') * (1 + s('atk_')) + s('atk') diff --git a/libs/zzz/solver/src/childWorker.ts b/libs/zzz/solver/src/childWorker.ts index 1326e95978..151561c4ac 100644 --- a/libs/zzz/solver/src/childWorker.ts +++ b/libs/zzz/solver/src/childWorker.ts @@ -1,6 +1,10 @@ -import type { DiscSlotKey, FormulaKey } from '@genshin-optimizer/zzz/consts' +import type { + DiscSetKey, + DiscSlotKey, + FormulaKey, +} from '@genshin-optimizer/zzz/consts' import type { Constraints, Stats } from '@genshin-optimizer/zzz/db' -import { calcFormula, getSum } from './calc' +import { applyCalc, calcFormula, passSetFilter } from './calc' import type { BuildResult, DiscStats } from './common' import { MAX_BUILDS } from './common' @@ -9,6 +13,8 @@ let discStatsBySlot: Record let constraints: Constraints let baseStats: Stats let formulaKey: FormulaKey +let setFilter2p: DiscSetKey[] +let setFilter4p: DiscSetKey[] export interface ChildCommandInit { command: 'init' @@ -16,6 +22,8 @@ export interface ChildCommandInit { discStatsBySlot: Record constraints: Constraints formulaKey: FormulaKey + setFilter2: DiscSetKey[] // [] means rainbow + setFilter4: DiscSetKey[] // [] means rainbow } export interface ChildCommandStart { command: 'start' @@ -76,11 +84,15 @@ async function init({ discStatsBySlot: discs, constraints: initCons, formulaKey: fk, + setFilter2, + setFilter4, }: ChildCommandInit) { baseStats = bs discStatsBySlot = discs constraints = initCons formulaKey = fk + setFilter2p = setFilter2 + setFilter4p = setFilter4 // Let parent know we are ready to optimize postMessage({ resultType: 'initialized' }) @@ -135,13 +147,32 @@ async function start() { } const constraintArr = Object.entries(constraints) for (const { d1, d2, d3, d4, d5, d6 } of generateCombinations()) { - const sum = getSum(baseStats, [d1, d2, d3, d4, d5, d6]) + /** + * Calculation takes several steps: + * 1. `passSetFilter()` filtering 2/4p effects + * 2. `applyCalc()` sum up stats from base + discs + 2p effects + * 3. filter using constraints + * 4. `calcFormula()` calculate final value of target + * 5. return build with calculated value. + */ + + const discs = [d1, d2, d3, d4, d5, d6] + // 1. Filter using set filter + if (!passSetFilter(discs, setFilter2p, setFilter4p)) { + // Skip early due to failing set filter + skipped++ + continue + } + // 2. Calculate base stats. + const sum = applyCalc(baseStats, discs) + // 3Filter using constraints if ( constraintArr.every(([k, { value, isMax }]) => isMax ? sum[k] <= value : sum[k] >= value ) ) { builds.push({ + // 4. Calculate final value value: calcFormula(sum, formulaKey), discIds: { 1: d1.id, diff --git a/libs/zzz/solver/src/common.ts b/libs/zzz/solver/src/common.ts index 12f8e7b954..8ce8a3d1ce 100644 --- a/libs/zzz/solver/src/common.ts +++ b/libs/zzz/solver/src/common.ts @@ -1,3 +1,4 @@ +import type { DiscSetKey } from '@genshin-optimizer/zzz/consts' import { getDiscMainStatVal, getDiscSubStatBaseVal, @@ -10,6 +11,7 @@ export const MAX_BUILDS = 50_000 export type DiscStats = { id: string stats: Record + setKey: DiscSetKey } export interface BuildResult { @@ -38,7 +40,7 @@ export function convertDiscToStats(disc: ICachedDisc): DiscStats { getDiscSubStatBaseVal(key, rarity) * upgrades, ]) ), - [setKey]: 1, }, + setKey, } } diff --git a/libs/zzz/solver/src/parentWorker.ts b/libs/zzz/solver/src/parentWorker.ts index b82f2f9097..1af45f8dbc 100644 --- a/libs/zzz/solver/src/parentWorker.ts +++ b/libs/zzz/solver/src/parentWorker.ts @@ -1,5 +1,5 @@ import { objKeyMap, range } from '@genshin-optimizer/common/util' -import type { FormulaKey } from '@genshin-optimizer/zzz/consts' +import type { DiscSetKey, FormulaKey } from '@genshin-optimizer/zzz/consts' import { allDiscSlotKeys, type DiscSlotKey, @@ -16,6 +16,8 @@ export interface ParentCommandStart { command: 'start' baseStats: Stats constraints: Constraints + setFilter2: DiscSetKey[] // [] means rainbow + setFilter4: DiscSetKey[] // [] means rainbow // lightCones: ICachedLightCone[] discsBySlot: Record // detachedNodes: NumTagFree[] @@ -81,6 +83,8 @@ async function start({ baseStats, discsBySlot, constraints, + setFilter2, + setFilter4, numWorkers, formulaKey, }: ParentCommandStart) { @@ -180,6 +184,8 @@ async function start({ discStatsBySlot: chunkedDiscStatsBySlot[index], constraints, formulaKey, + setFilter2, + setFilter4, } worker.postMessage(message) }) diff --git a/libs/zzz/solver/src/solver.ts b/libs/zzz/solver/src/solver.ts index 4880c562e8..5d02e6a9de 100644 --- a/libs/zzz/solver/src/solver.ts +++ b/libs/zzz/solver/src/solver.ts @@ -1,4 +1,8 @@ -import type { DiscSlotKey, FormulaKey } from '@genshin-optimizer/zzz/consts' +import type { + DiscSetKey, + DiscSlotKey, + FormulaKey, +} from '@genshin-optimizer/zzz/consts' import type { Constraints, ICachedDisc, Stats } from '@genshin-optimizer/zzz/db' import type { BuildResult } from './common' import type { @@ -20,11 +24,15 @@ export class Solver { private numWorkers: number private setProgress: (progress: ProgressResult) => void private worker: Worker + private setFilter2: DiscSetKey[] // [] means rainbow + private setFilter4: DiscSetKey[] // [] means rainbow constructor( formulaKey: FormulaKey, baseStats: Stats, constraints: Constraints, + setFilter2: DiscSetKey[], // [] means rainbow + setFilter4: DiscSetKey[], // [] means rainbow discsBySlot: Record, numWorkers: number, setProgress: (progress: ProgressResult) => void @@ -35,6 +43,8 @@ export class Solver { this.discsBySlot = discsBySlot this.numWorkers = numWorkers this.setProgress = setProgress + this.setFilter2 = setFilter2 + this.setFilter4 = setFilter4 // Spawn a parent worker to compile nodes, split/filter discs and spawn child workers for calculating results this.worker = new Worker(new URL('./parentWorker.ts', import.meta.url), { @@ -70,6 +80,8 @@ export class Solver { constraints: this.constraints, numWorkers: this.numWorkers, formulaKey: this.formulaKey, + setFilter2: this.setFilter2, + setFilter4: this.setFilter4, } this.worker.postMessage(message) })