Skip to content

Commit

Permalink
Merge pull request #336 from BoostV/cap-suggestion-count
Browse files Browse the repository at this point in the history
Cap suggestion count
  • Loading branch information
j-or authored Nov 9, 2023
2 parents 4362a44 + e5c91ef commit 3f093e4
Show file tree
Hide file tree
Showing 8 changed files with 88 additions and 17 deletions.
6 changes: 6 additions & 0 deletions .changeset/swift-starfishes-learn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@boostv/process-optimizer-frontend-core': minor
'@boostv/process-optimizer-frontend-ui': minor
---

Cap suggestion count
16 changes: 14 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 14 additions & 3 deletions packages/core/src/context/experiment/experiment-reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,10 @@ export type ExperimentAction =
}
| {
type: 'updateSuggestionCount'
payload: string
payload: {
suggestionCount: string
maxSuggestionCount?: number
}
}
| {
type: 'copySuggestedToDataPoints'
Expand Down Expand Up @@ -182,9 +185,17 @@ export const experimentReducer = produce(
state.info.description =
experimentSchema.shape.info.shape.description.parse(action.payload)
break
case 'updateSuggestionCount':
state.extras.experimentSuggestionCount = Number(action.payload)
case 'updateSuggestionCount': {
const payloadVal = Number(action.payload.suggestionCount)
// TODO: Move max out of reducer if used in application settings
const maxSuggestionCount =
action.payload.maxSuggestionCount ?? Number.MAX_VALUE
state.extras.experimentSuggestionCount = Math.max(
1,
Math.min(maxSuggestionCount, payloadVal)
)
break
}
case 'copySuggestedToDataPoints': {
const nextValues = selectNextValues(state)
const variables = selectActiveVariablesFromExperiment(state)
Expand Down
24 changes: 22 additions & 2 deletions packages/core/src/context/experiment/reducers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,16 +197,36 @@ describe('experiment reducer', () => {
})

describe('updateSuggestionCount', () => {
it('should change suggestion count', () => {
it('should cap suggestion count to max', () => {
const actual = rootReducer(initState, {
type: 'updateSuggestionCount',
payload: '42',
payload: { suggestionCount: '42', maxSuggestionCount: 10 },
})
expect(actual.experiment.extras).toMatchObject({
experimentSuggestionCount: 10,
})
expect(actual.experiment.changedSinceLastEvaluation).toBeTruthy()
})
it('should not cap suggestion count to max when unset', () => {
const actual = rootReducer(initState, {
type: 'updateSuggestionCount',
payload: { suggestionCount: '42' },
})
expect(actual.experiment.extras).toMatchObject({
experimentSuggestionCount: 42,
})
expect(actual.experiment.changedSinceLastEvaluation).toBeTruthy()
})
it('should set suggestion count to min 1', () => {
const actual = rootReducer(initState, {
type: 'updateSuggestionCount',
payload: { suggestionCount: '0' },
})
expect(actual.experiment.extras).toMatchObject({
experimentSuggestionCount: 1,
})
expect(actual.experiment.changedSinceLastEvaluation).toBeTruthy()
})
})

describe('Constraints', () => {
Expand Down
4 changes: 3 additions & 1 deletion packages/core/src/context/experiment/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,9 @@ export const dummyPayloads: Payloads = {
updateExperimentDescription: '',
updateConfiguration: initialState.experiment.optimizerConfig,
updateDataPoints: initialState.experiment.dataPoints,
updateSuggestionCount: '',
updateSuggestionCount: {
suggestionCount: '',
},
copySuggestedToDataPoints: [],
'experiment/toggleMultiObjective': undefined,
'experiment/setConstraintSum': 0,
Expand Down
1 change: 1 addition & 0 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
"dependencies": {
"@boostv/process-optimizer-frontend-core": "*",
"@boostv/process-optimizer-frontend-plots": "*",
"lodash.debounce": "^4.0.8",
"react-hook-form": "^7.33.0",
"remeda": "^1.12.0",
"tss-react": "^4.8.2"
Expand Down
17 changes: 13 additions & 4 deletions packages/ui/src/containers/result-data/experimentation-guide.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import { ReactNode } from 'react'
import { experimentResultSchema } from '@boostv/process-optimizer-frontend-core'
import { z } from 'zod'
import { isArray } from 'remeda'
import _ from 'lodash'

interface ResultDataProps {
id?: string
Expand All @@ -39,6 +40,7 @@ interface ResultDataProps {
warning?: string
padding?: number
allowIndividualSuggestionCopy?: boolean
maxSuggestionCount?: number
toggleUISize?: () => void
onMouseEnterExpand?: () => void
onMouseLeaveExpand?: () => void
Expand All @@ -54,6 +56,7 @@ export const ExperimentationGuide = (props: ResultDataProps) => {
padding,
loadingMode,
allowIndividualSuggestionCopy = true,
maxSuggestionCount,
toggleUISize,
onMouseEnterExpand,
onMouseLeaveExpand,
Expand Down Expand Up @@ -112,6 +115,14 @@ export const ExperimentationGuide = (props: ResultDataProps) => {
) : (
<Box p={2}>Please run optimizer</Box>
)

const debouncedUpdate = _.debounce(suggestionCount => {
dispatchExperiment({
type: 'updateSuggestionCount',
payload: { suggestionCount, maxSuggestionCount },
})
}, 1000)

return (
<TitleCard
id={id}
Expand Down Expand Up @@ -174,11 +185,9 @@ export const ExperimentationGuide = (props: ResultDataProps) => {
{!isInitializing && (
<Box width={160}>
<NextExperiments
maxSuggestionCount={maxSuggestionCount}
onSuggestionChange={suggestionCount =>
dispatchExperiment({
type: 'updateSuggestionCount',
payload: suggestionCount,
})
debouncedUpdate(suggestionCount)
}
/>
</Box>
Expand Down
20 changes: 15 additions & 5 deletions packages/ui/src/features/result-data/next-experiments.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import { TextField, Tooltip } from '@mui/material'
import { ChangeEvent, FC } from 'react'
import { ChangeEvent, FC, useState } from 'react'
import {
selectIsSuggestionCountEditable,
selectCalculatedSuggestionCount,
useSelector,
} from '@boostv/process-optimizer-frontend-core'

type Props = {
maxSuggestionCount?: number
onSuggestionChange: (suggestionCount: string) => void
}

export const NextExperiments: FC<Props> = ({ onSuggestionChange }) => {
export const NextExperiments: FC<Props> = ({
onSuggestionChange,
maxSuggestionCount,
}) => {
const isSuggestionCountEditable = useSelector(selectIsSuggestionCountEditable)
const suggestionCount = useSelector(selectCalculatedSuggestionCount)
const [suggestionCountUI, setSuggestionCountUI] = useState(suggestionCount)

const handleSuggestionChange = (
e: ChangeEvent<HTMLInputElement | HTMLTextAreaElement>
Expand All @@ -29,11 +34,16 @@ export const NextExperiments: FC<Props> = ({ onSuggestionChange }) => {
>
<TextField
type="number"
value={suggestionCount}
value={suggestionCountUI + ''}
name="numberOfSuggestions"
label="Suggestions"
label={`Suggestions${
maxSuggestionCount !== undefined ? ` (1-${maxSuggestionCount})` : ''
}`}
size="small"
onChange={handleSuggestionChange}
onChange={val => {
setSuggestionCountUI(Number(val.target.value))
handleSuggestionChange(val)
}}
disabled={!isSuggestionCountEditable}
/>
</Tooltip>
Expand Down

0 comments on commit 3f093e4

Please sign in to comment.