From a83ff24292d046738d33b4808b16a0c2aaaa5165 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adomas=20Volungevi=C4=8Dius?= <81253282+priolette@users.noreply.github.com> Date: Mon, 10 Mar 2025 06:21:09 +0200 Subject: [PATCH] SRO: Implement floor (#2829) --- libs/game-opt/engine/src/index.ts | 14 ++++++++++++++ .../game-opt/formula-ui/src/context/CalcContext.ts | 2 +- libs/game-opt/sheet-ui/src/types/conditional.ts | 9 +++++++-- libs/sr/formula/src/calculator.ts | 4 ++-- libs/sr/formula/src/formulaText.ts | 14 ++++++++++++++ libs/sr/formula/src/util.ts | 6 +++++- 6 files changed, 43 insertions(+), 6 deletions(-) diff --git a/libs/game-opt/engine/src/index.ts b/libs/game-opt/engine/src/index.ts index 05d3bd44e1..64040354c6 100644 --- a/libs/game-opt/engine/src/index.ts +++ b/libs/game-opt/engine/src/index.ts @@ -1,6 +1,20 @@ +import { addCustomOperation } from '@genshin-optimizer/pando/engine' + export * from './calculator' export * from './IConditionalData' export * from './listing' export * from './read' export * from './tag' export * from './util' + +{ + const floorCalc = (args: (number | string)[]): number => { + const x = args[0] as number + return Math.floor(x) + } + addCustomOperation('floor', { + range: ([r]) => ({ min: floorCalc([r.max]), max: floorCalc([r.min]) }), + monotonicity: () => [{ inc: true, dec: false }], + calc: floorCalc, + }) +} diff --git a/libs/game-opt/formula-ui/src/context/CalcContext.ts b/libs/game-opt/formula-ui/src/context/CalcContext.ts index 41184e8dee..9d8a8ad0aa 100644 --- a/libs/game-opt/formula-ui/src/context/CalcContext.ts +++ b/libs/game-opt/formula-ui/src/context/CalcContext.ts @@ -3,4 +3,4 @@ import type { Calculator, Tag } from '@genshin-optimizer/game-opt/engine' import { createContext } from 'react' // Use the game-opt generic Calculator. // In game-specific UI, cast this calc to the game's Calculator -export const CalcContext = createContext | null>(null) +export const CalcContext = createContext | null>(null) diff --git a/libs/game-opt/sheet-ui/src/types/conditional.ts b/libs/game-opt/sheet-ui/src/types/conditional.ts index 800c1acee1..ee76fe3762 100644 --- a/libs/game-opt/sheet-ui/src/types/conditional.ts +++ b/libs/game-opt/sheet-ui/src/types/conditional.ts @@ -1,6 +1,7 @@ import type { Calculator, IConditionalData, + Tag, } from '@genshin-optimizer/game-opt/engine' import type { ReactNode } from 'react' import type { Field } from './field' @@ -8,8 +9,12 @@ import type { Header } from './header' export type Conditional = { metadata: IConditionalData - label: ReactNode | ((calc: Calculator, value: number) => ReactNode) - badge?: ReactNode | ((calc: Calculator, value: number) => ReactNode) + label: + | ReactNode + | ((calc: Calculator, value: number) => ReactNode) + badge?: + | ReactNode + | ((calc: Calculator, value: number) => ReactNode) header?: Header fields?: Field[] targeted?: boolean diff --git a/libs/sr/formula/src/calculator.ts b/libs/sr/formula/src/calculator.ts index e9bb80bee6..44bb22c24b 100644 --- a/libs/sr/formula/src/calculator.ts +++ b/libs/sr/formula/src/calculator.ts @@ -6,9 +6,9 @@ import { allLightConeKeys, allRelicSetKeys } from '@genshin-optimizer/sr/consts' import type { Tag } from './data/util' import { tagStr } from './data/util' -export type PartialMeta = PartialMetaBase +export type PartialMeta = PartialMetaBase -export class Calculator extends Base { +export class Calculator extends Base { override toDebug(): DebugCalculator { return new DebugCalculator( this, diff --git a/libs/sr/formula/src/formulaText.ts b/libs/sr/formula/src/formulaText.ts index 8f1c133204..d89b67ed30 100644 --- a/libs/sr/formula/src/formulaText.ts +++ b/libs/sr/formula/src/formulaText.ts @@ -1,3 +1,4 @@ +import { assertUnreachable } from '@genshin-optimizer/common/util' import type { CalcResult } from '@genshin-optimizer/pando/engine' import type { PartialMeta } from './calculator' @@ -37,6 +38,9 @@ export function translate( let formula: string, prec: number switch (op) { + // TODO: handle `subscript` and `vtag` + case 'subscript': + case 'vtag': case 'const': formula = `${val}` // TODO: Add % here if `tag` indicates percent constant prec = Infinity @@ -57,7 +61,17 @@ export function translate( formula = `${dem} / (${num1} + ${num2})` prec = details.prod.prec + break + } + case 'floor': { + const [x] = ops + + formula = `\u230A${x}\u230B` + prec = Infinity + break } + default: + assertUnreachable(op) } let name: string | undefined, sheet: string | undefined if (tag) { diff --git a/libs/sr/formula/src/util.ts b/libs/sr/formula/src/util.ts index a0d2ba88f7..ac0bd441ff 100644 --- a/libs/sr/formula/src/util.ts +++ b/libs/sr/formula/src/util.ts @@ -1,5 +1,6 @@ import type { Preset } from '@genshin-optimizer/game-opt/engine' -import { cmpEq, cmpNE } from '@genshin-optimizer/pando/engine' +import type { NumNode, OP } from '@genshin-optimizer/pando/engine' +import { cmpEq, cmpNE, custom } from '@genshin-optimizer/pando/engine' import type { AscensionKey, LightConeKey, @@ -23,6 +24,9 @@ import { reader, } from './data/util' +export const floor =

(x: NumNode

| number) => + custom('floor', x) + export function withPreset( preset: Preset, ...data: TagMapNodeEntries