Skip to content

Commit

Permalink
feat: add spd benchmark showase ui (#863)
Browse files Browse the repository at this point in the history
* feat: add spd benchmark showase ui

* feat: custom showcase options implementation

* feat: refactor spd matching logic for poet + custom benchmarks

* feat: add 4p general conds to everyone, min the custom benchmark against baseline

* feat: cleanup

* feat: set -1 as current spd option
  • Loading branch information
fribbels authored Jan 23, 2025
1 parent c7ff2a9 commit d110cb3
Show file tree
Hide file tree
Showing 19 changed files with 770 additions and 566 deletions.
3 changes: 3 additions & 0 deletions src/lib/characterPreview/CharacterPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export function CharacterPreview(props: {
const refreshOnSpdValueChange = window.store((s) => s.scoringMetadataOverrides[character?.id]?.stats[Stats.SPD])
const refreshOnTraceChange = window.store((s) => s.scoringMetadataOverrides[character?.id]?.traces)
const refreshOnDeprioritizeBuffsChange = window.store((s) => s.scoringMetadataOverrides[character?.id]?.simulation?.deprioritizeBuffs)
const showcaseTemporaryOptions = window.store((s) => s.showcaseTemporaryOptions)

if (!character || (activeKey != AppPages.CHARACTERS && activeKey != AppPages.SHOWCASE)) {
return (
Expand Down Expand Up @@ -135,6 +136,7 @@ export function CharacterPreview(props: {
scoringType,
currentSelection,
showcaseMetadata,
showcaseTemporaryOptions,
)

// ===== Portrait =====
Expand Down Expand Up @@ -218,6 +220,7 @@ export function CharacterPreview(props: {
ref={sidebarRef}
id={props.id}
characterId={character.id}
simScoringResult={simScoringResult}
token={seedToken}
showcasePreferences={characterShowcasePreferences}
setOverrideTheme={() => {
Expand Down
3 changes: 2 additions & 1 deletion src/lib/characterPreview/CharacterScoringSummary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import { defaultGap, iconSize } from 'lib/constants/constantsUi'
import { SortOption } from 'lib/optimization/sortOptions'
import { StatCalculator } from 'lib/relics/statCalculator'
import { Assets } from 'lib/rendering/assets'
import { diminishingReturnsFormula, SimulationScore, SimulationStatUpgrade, spdDiminishingReturnsFormula } from 'lib/scoring/characterScorer'
import { SimulationStatUpgrade } from 'lib/scoring/characterScorer'
import { diminishingReturnsFormula, SimulationScore, spdDiminishingReturnsFormula } from 'lib/scoring/simScoringUtils'
import { Simulation } from 'lib/simulations/statSimulationController'
import DB from 'lib/state/db'
import { ColorizedLinkWithIcon } from 'lib/ui/ColorizedLink'
Expand Down
2 changes: 1 addition & 1 deletion src/lib/characterPreview/ShowcaseBuildAnalysis.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ShowcaseMetadata } from 'lib/characterPreview/characterPreviewControlle
import { CharacterScoringSummary } from 'lib/characterPreview/CharacterScoringSummary'
import { CHARACTER_SCORE, COMBAT_STATS, DAMAGE_UPGRADES, NONE_SCORE, SIMULATION_SCORE } from 'lib/constants/constants'
import { SavedSessionKeys } from 'lib/constants/constantsSession'
import { SimulationScore } from 'lib/scoring/characterScorer'
import { SimulationScore } from 'lib/scoring/simScoringUtils'
import { SaveState } from 'lib/state/saveState'
import { TsUtils } from 'lib/utils/TsUtils'
import React from 'react'
Expand Down
103 changes: 100 additions & 3 deletions src/lib/characterPreview/ShowcaseCustomizationSidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
import { CameraOutlined, DownloadOutlined, MoonOutlined, SettingOutlined, SunOutlined } from '@ant-design/icons'
import { Button, ColorPicker, Flex, Segmented, ThemeConfig } from 'antd'
import { Button, ColorPicker, Flex, InputNumber, Segmented, Select, ThemeConfig } from 'antd'
import { AggregationColor } from 'antd/es/color-picker/color'
import { GlobalToken } from 'antd/lib/theme/interface'
import { usePublish } from 'hooks/usePublish'
import { DEFAULT_SHOWCASE_COLOR, editShowcasePreferences } from 'lib/characterPreview/showcaseCustomizationController'
import { ShowcaseColorMode, Stats } from 'lib/constants/constants'
import { SavedSessionKeys } from 'lib/constants/constantsSession'
import { SimulationScore } from 'lib/scoring/simScoringUtils'
import DB from 'lib/state/db'
import { generateSpdPresets } from 'lib/tabs/tabOptimizer/optimizerForm/components/RecommendedPresetsButton'
import { defaultPadding } from 'lib/tabs/tabOptimizer/optimizerForm/grid/optimizerGridColumns'
import { HorizontalDivider } from 'lib/ui/Dividers'
import { HeaderText } from 'lib/ui/HeaderText'
import { organizeColors, selectClosestColor } from 'lib/utils/colorUtils'
import { TsUtils } from 'lib/utils/TsUtils'
import { Utils } from 'lib/utils/utils'
import { getPalette, PaletteResponse } from 'lib/utils/vibrantFork'
import React, { forwardRef, useImperativeHandle, useState } from 'react'
import React, { forwardRef, useImperativeHandle, useMemo, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Character } from 'types/character'
import { ShowcasePreferences } from 'types/metadata'
Expand All @@ -28,6 +30,7 @@ export interface ShowcaseCustomizationSidebarProps {
characterId: string
token: GlobalToken
showcasePreferences: ShowcasePreferences
simScoringResult: SimulationScore | null
setOverrideTheme: (overrideTheme: ThemeConfig) => void
seedColor: string
setSeedColor: (color: string) => void
Expand All @@ -44,6 +47,7 @@ export const ShowcaseCustomizationSidebar = forwardRef<ShowcaseCustomizationSide
const {
id,
characterId,
simScoringResult,
seedColor,
setSeedColor,
colorMode,
Expand Down Expand Up @@ -137,6 +141,31 @@ export const ShowcaseCustomizationSidebar = forwardRef<ShowcaseCustomizationSide
pubRefreshRelicsScore('refreshRelicsScore', 'null')
}

function onShowcaseSpdBenchmarkChangeEvent(event: React.FocusEvent<HTMLInputElement> | React.KeyboardEvent<HTMLInputElement>) {
// @ts-ignore
const value: string = event?.target?.value
if (value == null) return onShowcaseSpdBenchmarkChange(undefined)

const spdBenchmark = parseFloat(value as string)
if (isNaN(spdBenchmark)) return onShowcaseSpdBenchmarkChange(undefined)

onShowcaseSpdBenchmarkChange(spdBenchmark)
}

function onShowcaseSpdBenchmarkChange(spdBenchmark: number | undefined) {
console.log('Set spd benchmark to', spdBenchmark)

const showcaseTemporaryOptions = TsUtils.clone(window.store.getState().showcaseTemporaryOptions)
if (!showcaseTemporaryOptions[characterId]) showcaseTemporaryOptions[characterId] = {}

// -1 is used as the "current" setting
const actualValue = spdBenchmark == -1 ? undefined : spdBenchmark

showcaseTemporaryOptions[characterId].spdBenchmark = actualValue

window.store.getState().setShowcaseTemporaryOptions(showcaseTemporaryOptions)
}

function onTraceClick() {
window.store.getState().setStatTracesDrawerFocusCharacter(characterId)
window.store.getState().setStatTracesDrawerOpen(true)
Expand Down Expand Up @@ -226,6 +255,28 @@ export const ShowcaseCustomizationSidebar = forwardRef<ShowcaseCustomizationSide
value={spdValue}
onChange={onShowcaseSpdValueChange}
/>

{scoringMetadata.simulation &&
<>
<HorizontalDivider/>

<HeaderText style={{ textAlign: 'center', marginBottom: 2 }}>
SPD benchmark
</HeaderText>

<InputNumber
size='small'
controls={false}
style={{ width: '100%' }}
value={nonZeroOrUndefined(window.store.getState().showcaseTemporaryOptions[characterId]?.spdBenchmark)}
addonAfter={<SelectSpdPresets onShowcaseSpdBenchmarkChange={onShowcaseSpdBenchmarkChange}/>}
min={0}
onBlur={onShowcaseSpdBenchmarkChangeEvent}
onPressEnter={onShowcaseSpdBenchmarkChangeEvent}
/>
</>
}

{scoringMetadata.simulation &&
<>
<HorizontalDivider/>
Expand Down Expand Up @@ -326,6 +377,48 @@ export const ShowcaseCustomizationSidebar = forwardRef<ShowcaseCustomizationSide
},
)

function SelectSpdPresets(props: {
onShowcaseSpdBenchmarkChange: (n: number) => void
}) {
const { t } = useTranslation('optimizerTab', { keyPrefix: 'Presets' })

const spdPresetOptions = useMemo(() => {
return [
{
label: <span>Benchmark options</span>,
title: 'benchmark',
options: [
{
label: <b><span>Current SPD - The benchmark will match your basic SPD</span></b>,
value: -1,
},
{
label: <span>Base SPD - The benchmark will target a zero SPD build</span>,
value: 0,
},
],
},
{
label: <span>Common SPD breakpoint presets</span>,
title: 'presets',
options: Object.values(generateSpdPresets(t)).slice(1),
},
]
}, [t])

return (
<Select
style={{ width: 34 }}
labelRender={() => <></>}
dropdownStyle={{ width: 'fit-content' }}
options={spdPresetOptions}
placement='bottomRight'
listHeight={800}
onChange={props.onShowcaseSpdBenchmarkChange}
/>
)
}

function clipboardClicked(elementId: string, action: string, setLoading: (b: boolean) => void, color: string) {
setLoading(true)
setTimeout(() => {
Expand All @@ -335,6 +428,10 @@ function clipboardClicked(elementId: string, action: string, setLoading: (b: boo
}, 100)
}

function nonZeroOrUndefined(n?: number) {
return n == undefined || n < 0 ? undefined : n
}

const shadow = 'rgba(0, 0, 0, 0.25) 0px 0.0625em 0.0625em, rgba(0, 0, 0, 0.25) 0px 0.125em 0.5em, rgba(255, 255, 255, 0.15) 0px 0px 0px 1px inset'

const STANDARD_COLOR = '#628ae9'
Expand Down Expand Up @@ -387,7 +484,7 @@ export function getDefaultColor(characterId: string, portraitUrl: string, colorM
1002: ['#7dd3ea'], // danheng
1003: ['#d6b5c2'], // himeko
1004: ['#6385d8'], // welt
1005: ['#ed85b4'], // kafka
1005: ['#ea8abc'], // kafka
1006: ['#8483eb'], // silverwolf
1008: ['#817fd1'], // arlan
1009: ['#9e80e6'], // asta
Expand Down
2 changes: 1 addition & 1 deletion src/lib/characterPreview/ShowcasePortrait.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { ShowcaseDisplayDimensions } from 'lib/characterPreview/characterPreview
import { parentH, parentW } from 'lib/constants/constantsUi'
import EditImageModal from 'lib/overlays/modals/EditImageModal'
import { Assets } from 'lib/rendering/assets'
import { SimulationScore } from 'lib/scoring/characterScorer'
import { SimulationScore } from 'lib/scoring/simScoringUtils'
import { LoadingBlurredImage } from 'lib/ui/LoadingBlurredImage'
import React from 'react'
import { useTranslation } from 'react-i18next'
Expand Down
6 changes: 4 additions & 2 deletions src/lib/characterPreview/characterPreviewController.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { Utils } from 'lib/utils/utils'
import { MutableRefObject } from 'react'
import { Character } from 'types/character'
import { CustomImageConfig, CustomImagePayload } from 'types/customImage'
import { DBMetadataCharacter, DBMetadataLightCone, ElementalDamageType, ImageCenter } from 'types/metadata'
import { DBMetadataCharacter, DBMetadataLightCone, ElementalDamageType, ImageCenter, ShowcaseTemporaryOptions } from 'types/metadata'
import { Relic } from 'types/relic'

export type ShowcaseMetadata = {
Expand Down Expand Up @@ -167,12 +167,14 @@ export function getShowcaseSimScoringResult(
scoringType: string,
teamSelection: string,
showcaseMetadata: ShowcaseMetadata,
showcaseTemporaryOptions: Record<string, ShowcaseTemporaryOptions>,
) {
if (scoringType != SIMULATION_SCORE) {
return null
}

let simScoringResult = scoreCharacterSimulation(character, displayRelics, teamSelection)
const characterShowcaseTemporaryOptions = showcaseTemporaryOptions[character.id] ?? {}
let simScoringResult = scoreCharacterSimulation(character, displayRelics, teamSelection, characterShowcaseTemporaryOptions)

if (!simScoringResult?.originalSim) {
simScoringResult = null
Expand Down
2 changes: 1 addition & 1 deletion src/lib/optimization/calculateStats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,7 @@ export function calculateComputedStats(x: ComputedStatsArray, action: OptimizerA
x.CR.buff(0.12, Source.IzumoGenseiAndTakamaDivineRealm)
}
if (p4(sets.PoetOfMourningCollapse)) {
x.CR.buffDual((c[Stats.SPD] < 110 ? 0.20 : 0) + (c[Stats.SPD] < 95 ? 0.12 : 0), Source.PoetOfMourningCollapse)
x.CR.buffBaseDual((c[Stats.SPD] < 110 ? 0.20 : 0) + (c[Stats.SPD] < 95 ? 0.12 : 0), Source.PoetOfMourningCollapse)
}

// BE
Expand Down
11 changes: 10 additions & 1 deletion src/lib/optimization/computedStatsArray.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export type StatController = {
buffMemo: (value: number, source: string) => void
buffTeam: (value: number, source: string) => void
buffDual: (value: number, source: string) => void
buffBaseDual: (value: number, source: string) => void
multiply: (value: number, source: string) => void
multiplyTeam: (value: number, source: string) => void
set: (value: number, source: string) => void
Expand Down Expand Up @@ -82,6 +83,14 @@ export class ComputedStatsArrayCore {
this.m.a[index] += value
}
},
buffTeam: (value: number, source: string) => {
if (value == 0) return
this.a[index] += value

if (this.m) {
this.m.a[index] += value
}
},
buffDual: (value: number, source: string) => {
if (value == 0) return
if (this.a[Key.DEPRIORITIZE_BUFFS]) return
Expand All @@ -91,7 +100,7 @@ export class ComputedStatsArrayCore {
this.m.a[index] += value
}
},
buffTeam: (value: number, source: string) => {
buffBaseDual: (value: number, source: string) => {
if (value == 0) return
this.a[index] += value

Expand Down
Loading

0 comments on commit d110cb3

Please sign in to comment.