From 9708e2a830f254477297e64131a71b4b19e716e7 Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:03:27 -0700 Subject: [PATCH 1/6] Add infrastructure for strikethrough on fields --- libs/gi/ui/src/components/FieldDisplay.tsx | 1 + libs/gi/ui/src/util/getCalcDisplay.tsx | 10 ++++++++-- libs/gi/wr/src/type.d.ts | 4 ++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/libs/gi/ui/src/components/FieldDisplay.tsx b/libs/gi/ui/src/components/FieldDisplay.tsx index d58afc9371..f4ec763dbd 100644 --- a/libs/gi/ui/src/components/FieldDisplay.tsx +++ b/libs/gi/ui/src/components/FieldDisplay.tsx @@ -198,6 +198,7 @@ export function NodeFieldDisplay({ gap: 1, boxShadow: emphasize ? '0px 0px 0px 2px red inset' : undefined, py: 0.25, + textDecoration: subVariant === 'strike' ? 'line-through' : undefined, }} component={component} > diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx index 531740096d..fe83a3fb08 100644 --- a/libs/gi/ui/src/util/getCalcDisplay.tsx +++ b/libs/gi/ui/src/util/getCalcDisplay.tsx @@ -13,6 +13,7 @@ import { import { Translate } from '@genshin-optimizer/gi/i18n' import type { CalcResult } from '@genshin-optimizer/gi/uidata' import type { Info, InfoExtra, KeyMapPrefix } from '@genshin-optimizer/gi/wr' +import { Typography } from '@mui/material' import { useContext, type ReactNode } from 'react' import { SillyContext } from '../context' import { resolveInfo } from './resolveInfo' @@ -220,11 +221,16 @@ function computeFormulaDisplay( components.filter((c) => c) result.formula = ( - <> + {components.map((x, i) => ( {x} ))} - + ) return result diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts index be2489e22d..d81ef12c9d 100644 --- a/libs/gi/wr/src/type.d.ts +++ b/libs/gi/wr/src/type.d.ts @@ -48,7 +48,7 @@ export type Info = { prefix?: KeyMapPrefix source?: CharacterSheetKey | WeaponKey | ArtifactSetKey variant?: InfoVariant - subVariant?: InfoVariant + subVariant?: InfoVariant | 'strike' asConst?: true pivot?: true fixed?: number @@ -179,7 +179,7 @@ interface DynamicNumInput { [key: string]: DisplaySub } conditional?: NodeData - teamBuff?: Input & { tally?: NodeData } + teamBuff?: Input & { tally?: NodeData } } export interface NodeData { [key: string]: typeof key extends 'operation' ? never : NodeData | T From 7efea3782304b199c0cd269b481e2d4933108aac Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Sun, 5 Jan 2025 19:18:30 -0700 Subject: [PATCH 2/6] Add non-stacking buffs for NO4 --- .../src/Artifacts/NoblesseOblige/index.tsx | 21 +++++++++++++--- libs/gi/sheets/src/SheetUtil.tsx | 25 ++++++++++++++++++- libs/gi/wr/src/formula.ts | 3 +++ 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx index 874d8a1215..1d1b6b0144 100644 --- a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx +++ b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx @@ -1,7 +1,13 @@ import type { ArtifactSetKey } from '@genshin-optimizer/gi/consts' import type { Data } from '@genshin-optimizer/gi/wr' -import { equal, greaterEq, input, percent } from '@genshin-optimizer/gi/wr' -import { cond, st, stg } from '../../SheetUtil' +import { + equalStr, + greaterEq, + greaterEqStr, + input, + percent, +} from '@genshin-optimizer/gi/wr' +import { cond, nonStackBuff, st, stg } from '../../SheetUtil' import { ArtifactSheet, setHeaderTemplate } from '../ArtifactSheet' import type { SetEffectSheet } from '../IArtifactSheet' import { dataObjForArtifactSheet } from '../dataUtil' @@ -12,11 +18,12 @@ const setHeader = setHeaderTemplate(key) const set2 = greaterEq(input.artSet.NoblesseOblige, 2, percent(0.2)) const [condSet4Path, condSet4] = cond(key, 'set4') -const set4 = greaterEq( +const set4TallyWrite = greaterEqStr( input.artSet.NoblesseOblige, 4, - equal(condSet4, 'on', percent(0.2)) + equalStr(condSet4, 'on', input.charKey) ) +const [set4, set4Inactive] = nonStackBuff('no4', 'atk_', percent(0.2)) export const data: Data = dataObjForArtifactSheet(key, { premod: { @@ -26,6 +33,9 @@ export const data: Data = dataObjForArtifactSheet(key, { premod: { atk_: set4, }, + tally: { + no4: set4TallyWrite, + }, }, }) @@ -45,6 +55,9 @@ const sheet: SetEffectSheet = { { node: set4, }, + { + node: set4Inactive, + }, { text: stg('duration'), value: 12, diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx index cc3105ade2..842202b7cb 100644 --- a/libs/gi/sheets/src/SheetUtil.tsx +++ b/libs/gi/sheets/src/SheetUtil.tsx @@ -5,12 +5,20 @@ import type { WeaponKey, } from '@genshin-optimizer/gi/consts' import { Translate } from '@genshin-optimizer/gi/i18n' -import type { Info, NumNode, ReadNode, StrNode } from '@genshin-optimizer/gi/wr' +import type { + Info, + NonStackBuff, + NumNode, + ReadNode, + StrNode, +} from '@genshin-optimizer/gi/wr' import { customStringRead, equal, infoMut, input, + tally, + unequal, } from '@genshin-optimizer/gi/wr' import type { ReactNode } from 'react' @@ -80,3 +88,18 @@ export function activeCharBuff( equal(input.activeCharKey, buffTargetKey, node), ] } + +export function nonStackBuff( + buffName: NonStackBuff, + path: string, + buffNode: NumNode +) { + return [ + equal(tally[buffName], input.charKey, buffNode), + unequal(tally[buffName], input.charKey, buffNode, { + path, + isTeamBuff: true, + subVariant: 'strike', + }), + ] +} diff --git a/libs/gi/wr/src/formula.ts b/libs/gi/wr/src/formula.ts index 3f0a59bb94..5e22edfa36 100644 --- a/libs/gi/wr/src/formula.ts +++ b/libs/gi/wr/src/formula.ts @@ -46,6 +46,8 @@ const asConst = true as const, const allElements = allElementWithPhyKeys const allTalents = ['auto', 'skill', 'burst'] as const +const allNonstackBuffs = ['no4'] as const +export type NonStackBuff = (typeof allNonstackBuffs)[number] const allMoves = [ 'normal', 'charged', @@ -578,6 +580,7 @@ const _tally = setReadNodeKeys( { ...objKeyMap([...allElements, ...allRegionKeys], (_) => read('add')), maxEleMas: read('max'), + ...objKeyMap(allNonstackBuffs, () => stringRead('small')), }, ['tally'] ) From 52c56f991b738d767dcb803262dcefc86e4a8eb0 Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Thu, 9 Jan 2025 15:23:35 -0700 Subject: [PATCH 3/6] Modify strikethrough to be a separate info field --- libs/gi/sheets/src/SheetUtil.tsx | 2 +- libs/gi/ui/src/components/FieldDisplay.tsx | 4 ++-- libs/gi/ui/src/util/getCalcDisplay.tsx | 2 +- libs/gi/wr/src/type.d.ts | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx index 842202b7cb..4cdfcc6888 100644 --- a/libs/gi/sheets/src/SheetUtil.tsx +++ b/libs/gi/sheets/src/SheetUtil.tsx @@ -99,7 +99,7 @@ export function nonStackBuff( unequal(tally[buffName], input.charKey, buffNode, { path, isTeamBuff: true, - subVariant: 'strike', + strikethrough: true, }), ] } diff --git a/libs/gi/ui/src/components/FieldDisplay.tsx b/libs/gi/ui/src/components/FieldDisplay.tsx index f4ec763dbd..78e6b2c45b 100644 --- a/libs/gi/ui/src/components/FieldDisplay.tsx +++ b/libs/gi/ui/src/components/FieldDisplay.tsx @@ -129,7 +129,7 @@ export function NodeFieldDisplay({ [setFormulaData, data, calcRes] ) if (!calcRes && !compareCalcRes) return null - const { multi } = calcRes?.info ?? compareCalcRes?.info ?? {} + const { multi, strikethrough } = calcRes?.info ?? compareCalcRes?.info ?? {} const multiDisplay = multi && {multi}× const calcValue = calcRes?.value ?? 0 @@ -198,7 +198,7 @@ export function NodeFieldDisplay({ gap: 1, boxShadow: emphasize ? '0px 0px 0px 2px red inset' : undefined, py: 0.25, - textDecoration: subVariant === 'strike' ? 'line-through' : undefined, + textDecoration: strikethrough ? 'line-through' : undefined, }} component={component} > diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx index fe83a3fb08..92c452f084 100644 --- a/libs/gi/ui/src/util/getCalcDisplay.tsx +++ b/libs/gi/ui/src/util/getCalcDisplay.tsx @@ -224,7 +224,7 @@ function computeFormulaDisplay( {components.map((x, i) => ( diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts index d81ef12c9d..12d69bd099 100644 --- a/libs/gi/wr/src/type.d.ts +++ b/libs/gi/wr/src/type.d.ts @@ -48,12 +48,13 @@ export type Info = { prefix?: KeyMapPrefix source?: CharacterSheetKey | WeaponKey | ArtifactSetKey variant?: InfoVariant - subVariant?: InfoVariant | 'strike' + subVariant?: InfoVariant asConst?: true pivot?: true fixed?: number isTeamBuff?: boolean multi?: number + strikethrough?: boolean } export type Variant = | ElementWithPhyKey From 948b1661a5e03e8639f2be6fb641856f59a7bc03 Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:39:49 -0700 Subject: [PATCH 4/6] Move nonstacking to its own namespace --- .../gi/sheets/src/Artifacts/NoblesseOblige/index.tsx | 2 +- libs/gi/sheets/src/SheetUtil.tsx | 5 +++-- libs/gi/uidata/src/uiData.ts | 3 +++ libs/gi/wr/src/api.ts | 12 +++++++++--- libs/gi/wr/src/formula.ts | 8 ++++++-- libs/gi/wr/src/type.d.ts | 7 +++++-- 6 files changed, 27 insertions(+), 10 deletions(-) diff --git a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx index 1d1b6b0144..0e1f0a033c 100644 --- a/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx +++ b/libs/gi/sheets/src/Artifacts/NoblesseOblige/index.tsx @@ -33,7 +33,7 @@ export const data: Data = dataObjForArtifactSheet(key, { premod: { atk_: set4, }, - tally: { + nonStacking: { no4: set4TallyWrite, }, }, diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx index 4cdfcc6888..7db643351e 100644 --- a/libs/gi/sheets/src/SheetUtil.tsx +++ b/libs/gi/sheets/src/SheetUtil.tsx @@ -17,6 +17,7 @@ import { equal, infoMut, input, + nonStacking, tally, unequal, } from '@genshin-optimizer/gi/wr' @@ -95,8 +96,8 @@ export function nonStackBuff( buffNode: NumNode ) { return [ - equal(tally[buffName], input.charKey, buffNode), - unequal(tally[buffName], input.charKey, buffNode, { + equal(nonStacking[buffName], input.charKey, buffNode), + unequal(nonStacking[buffName], input.charKey, buffNode, { path, isTeamBuff: true, strikethrough: true, diff --git a/libs/gi/uidata/src/uiData.ts b/libs/gi/uidata/src/uiData.ts index 14914244c6..23203ddd04 100644 --- a/libs/gi/uidata/src/uiData.ts +++ b/libs/gi/uidata/src/uiData.ts @@ -29,6 +29,7 @@ import { deepNodeClone, input, mergeData, + nonStacking, resetData, setReadNodeKeys, tally, @@ -537,6 +538,8 @@ export function uiDataForTeam( const newNode = customRead(path) if (path[0] === 'teamBuff' && path[1] === 'tally') newNode.accu = objPathValue(tally, path.slice(2))?.accu + if (path[0] === 'teamBuff' && path[1] === 'nonStacking') + newNode.accu = objPathValue(nonStacking, path.slice(2))?.accu layeredAssignment(customReadNodes, path, newNode) return newNode } diff --git a/libs/gi/wr/src/api.ts b/libs/gi/wr/src/api.ts index 70adcce29a..f69ef98f25 100644 --- a/libs/gi/wr/src/api.ts +++ b/libs/gi/wr/src/api.ts @@ -21,7 +21,7 @@ import type { } from '@genshin-optimizer/gi/db' import type { ICharacter } from '@genshin-optimizer/gi/good' import { getMainStatValue } from '@genshin-optimizer/gi/util' -import { input, tally } from './formula' +import { input, nonStacking, tally } from './formula' import type { Data, Info, NumNode, ReadNode, StrNode } from './type' import { constant, data, infoMut, none, percent, prod, sum } from './utils' @@ -41,7 +41,7 @@ export function inferInfoMut(data: Data, source?: Info['source']): Data { | undefined if (reference) x.info = { ...x.info, ...reference.info, prefix: undefined, source } - else if (path[0] !== 'tally') + else if (path[0] !== 'tally' && path[0] !== 'nonStacking') console.error( `Detect ${source} buff into non-existant key path ${path}` ) @@ -246,7 +246,13 @@ export function mergeData(data: Data[]): Data { if (data.length <= 1) return data[0] if (data[0].operation) { if (path[0] === 'teamBuff') path = path.slice(1) - const base = path[0] === 'tally' ? ((path = path.slice(1)), tally) : input + const base = + path[0] === 'tally' + ? tally + : path[0] === 'nonStacking' + ? nonStacking + : input + if (path[0] === 'tally' || path[0] === 'nonStacking') path = path.slice(1) /*eslint prefer-const: ["error", {"destructuring": "all"}]*/ let { accu, type } = (objPathValue(base, path) as ReadNode | undefined) ?? diff --git a/libs/gi/wr/src/formula.ts b/libs/gi/wr/src/formula.ts index 5e22edfa36..246e72c32f 100644 --- a/libs/gi/wr/src/formula.ts +++ b/libs/gi/wr/src/formula.ts @@ -580,7 +580,6 @@ const _tally = setReadNodeKeys( { ...objKeyMap([...allElements, ...allRegionKeys], (_) => read('add')), maxEleMas: read('max'), - ...objKeyMap(allNonstackBuffs, () => stringRead('small')), }, ['tally'] ) @@ -590,6 +589,11 @@ const tally = { ele: sum(...allElements.map((ele) => min(_tally[ele], 1))), } +const nonStacking = setReadNodeKeys( + objKeyMap(allNonstackBuffs, () => stringRead('small')), + ['nonStacking'] +) + /** * List of `input` nodes, rearranged to conform to the needs of the * UI code. This is a separate list so that the evolution of the UIs @@ -607,4 +611,4 @@ export const infusionNode = stringPrio( input.infusion.overridableSelf ) -export { common, customBonus, input, tally, target, uiInput } +export { common, customBonus, input, nonStacking, tally, target, uiInput } diff --git a/libs/gi/wr/src/type.d.ts b/libs/gi/wr/src/type.d.ts index 12d69bd099..5e90c35b6f 100644 --- a/libs/gi/wr/src/type.d.ts +++ b/libs/gi/wr/src/type.d.ts @@ -9,7 +9,7 @@ import type { AmplifyingReactionsKey, TransformativeReactionsKey, } from '@genshin-optimizer/gi/keymap' -import type { input, uiInput } from './formula' +import type { input, NonStackBuff, uiInput } from './formula' export type NumNode = | ComputeNode @@ -180,7 +180,10 @@ interface DynamicNumInput { [key: string]: DisplaySub } conditional?: NodeData - teamBuff?: Input & { tally?: NodeData } + teamBuff?: Input & { + tally?: NodeData + nonStacking?: Record + } } export interface NodeData { [key: string]: typeof key extends 'operation' ? never : NodeData | T From 6b01687393cc65adcaa077cd8229732934101b9b Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Thu, 9 Jan 2025 16:40:13 -0700 Subject: [PATCH 5/6] Fix format --- libs/gi/ui/src/util/getCalcDisplay.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libs/gi/ui/src/util/getCalcDisplay.tsx b/libs/gi/ui/src/util/getCalcDisplay.tsx index 92c452f084..67a1dbf775 100644 --- a/libs/gi/ui/src/util/getCalcDisplay.tsx +++ b/libs/gi/ui/src/util/getCalcDisplay.tsx @@ -223,8 +223,7 @@ function computeFormulaDisplay( result.formula = ( {components.map((x, i) => ( From 96b0cbbb146629ac2c5128f2f3293625b56594cf Mon Sep 17 00:00:00 2001 From: Van Nguyen <36019388+nguyentvan7@users.noreply.github.com> Date: Thu, 9 Jan 2025 19:10:09 -0700 Subject: [PATCH 6/6] Fix format --- libs/gi/sheets/src/SheetUtil.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/libs/gi/sheets/src/SheetUtil.tsx b/libs/gi/sheets/src/SheetUtil.tsx index 7db643351e..6341840c66 100644 --- a/libs/gi/sheets/src/SheetUtil.tsx +++ b/libs/gi/sheets/src/SheetUtil.tsx @@ -18,7 +18,6 @@ import { infoMut, input, nonStacking, - tally, unequal, } from '@genshin-optimizer/gi/wr' import type { ReactNode } from 'react'