Skip to content

Commit

Permalink
Merge 0655cad into 1dde1a1
Browse files Browse the repository at this point in the history
  • Loading branch information
sjschlapbach authored Dec 29, 2024
2 parents 1dde1a1 + 0655cad commit 41f8f44
Show file tree
Hide file tree
Showing 43 changed files with 1,170 additions and 366 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,35 @@ def compute_correctness_columns(df_element_instances, row):

elif element_instance["type"] == "NUMERICAL":
response_value = float(response["value"])
within_range = list(
map(
lambda range: float(range["min"])
<= response_value
<= float(range["max"]),
options["solutionRanges"],

if "solutionRanges" in options:
within_range = list(
map(
lambda range: float(range["min"])
<= response_value
<= float(range["max"]),
options["solutionRanges"],
)
)
)
if any(within_range):
return "CORRECT"
if any(within_range):
return "CORRECT"
else:
return "INCORRECT"

elif "exactSolutions" in options:
response_correct = list(
map(
lambda solution: float(solution) - 1e-10
<= response_value
<= float(solution) + 1e-10,
options["exactSolutions"],
)
)

if any(response_correct):
return "CORRECT"
else:
return "INCORRECT"

return "INCORRECT"

Expand Down
341 changes: 211 additions & 130 deletions apps/analytics/src/notebooks/archive/daily_participant_analytics.ipynb

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ function ElementChart({
type={instanceEvaluation.type}
responses={responses}
solutionRanges={instanceEvaluation.results.solutionRanges ?? []}
exactSolutions={instanceEvaluation.results.exactSolutions ?? []}
statistics={instanceEvaluation.statistics}
minValue={instanceEvaluation.results.minValue}
maxValue={instanceEvaluation.results.maxValue}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,24 @@ function NRSidebar({
{t('manage.evaluation.correctSolutionRanges')}:
</div>
{instance.results.solutionRanges.map((range, innerIndex) => (
<div key={innerIndex}>
<div key={`solution-range-${innerIndex}`}>
[{range?.min ?? '-∞'},{range?.max ?? '+∞'}]
</div>
))}
</div>
)}
{showSolution && instance.results.exactSolutions && (
<div className={textSize.textLg}>
<div className="mt-4 font-bold">
{t('manage.evaluation.correctExactSolutions')}:
</div>
<ul>
{instance.results.exactSolutions.map((solution, innerIndex) => (
<li key={`innerIndex-${innerIndex}`}>{solution}</li>
))}
</ul>
</div>
)}
</div>
{type === 'LiveQuiz' && !hideQR && (
<LiveQuizEvaluationQRCode setHideQR={setHideQR} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function Statistic({
size,
}: StatisticProps): React.ReactElement {
return (
<div className="mb-2 flex justify-between border-b-2">
<div className="mb-1 flex justify-between border-b-2">
<span
className={twMerge(
'flex flex-row items-center',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,41 @@ function ElementFormErrors({
errors.options.unit && (
<li>{`${t('shared.generic.unit')}: ${errors.options.unit}`}</li>
)}
{'options' in errors &&
errors.options &&
'solutionType' in errors.options &&
errors.options.solutionType && (
<li>{`${t('manage.questionForms.solutionTypeNumerical')}: ${
errors.options.solutionType
}`}</li>
)}
{'options' in errors &&
errors.options &&
'solutionRanges' in errors.options &&
errors.options.solutionRanges &&
typeof errors.options.solutionRanges === 'string' && (
(typeof errors.options.solutionRanges === 'string' ? (
<li>{`${t('manage.questionForms.solutionRanges')}: ${
errors.options.solutionRanges
}`}</li>
) : (
(errors.options.solutionRanges as string[]).map(
(rangeError, ix) => (
<li
key={`solution-range-error-${ix}`}
>{`${t('manage.questionForms.solutionRanges')} ${ix + 1}: ${
rangeError
}`}</li>
)
)
))}
{'options' in errors &&
errors.options &&
'exactSolutions' in errors.options &&
errors.options.exactSolutions &&
typeof errors.options.exactSolutions === 'string' && (
<li>{`${t('manage.questionForms.exactSolutions')}: ${
errors.options.exactSolutions
}`}</li>
)}

{/* error messages specific to FT questions */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,26 @@ export function prepareNumericalArgs({
? undefined
: parseFloat(String(values.options.restrictions.max)),
},
solutionRanges: values.options.solutionRanges?.map((range) => ({
min: range.min === '' ? undefined : parseFloat(String(range.min)),
max: range.max === '' ? undefined : parseFloat(String(range.max)),
})),
solutionRanges:
values.options.hasSampleSolution &&
values.options.solutionType === 'range'
? values.options.solutionRanges?.map((range) => ({
min: range.min === '' ? undefined : parseFloat(String(range.min)),
max: range.max === '' ? undefined : parseFloat(String(range.max)),
}))
: undefined,
exactSolutions:
values.options.hasSampleSolution &&
values.options.solutionType === 'exact'
? values.options.exactSolutions?.map((solution) => {
if (typeof solution === 'number') {
return solution
}

const precision = parseInt(String(values.options.accuracy))
return parseFloat(parseFloat(solution).toFixed(precision))
})
: undefined,
},
tags: values.tags,
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { Button, FormikNumberField, FormLabel } from '@uzh-bf/design-system'
import { FieldArray, FieldArrayRenderProps } from 'formik'
import { useTranslations } from 'next-intl'
import { ElementFormTypesNumerical } from '../types'

function NumericalExactSolutionsInput({
exactSolutions,
precision,
}: {
exactSolutions: ElementFormTypesNumerical['options']['exactSolutions']
precision?: string | null
}) {
const t = useTranslations()

return (
<div className="mt-3">
<FormLabel
required
label={t('manage.questionForms.exactSolutions')}
labelType="small"
tooltip={t('manage.questionForms.exactSolutionsTooltip')}
/>
<FieldArray name="options.exactSolutions">
{({ push, remove }: FieldArrayRenderProps) => (
<div className="flex w-max flex-col gap-1">
{exactSolutions?.map((_, index: number) => (
<div
className="flex flex-row items-end gap-2"
key={`exact-solution-${index}`}
>
<FormikNumberField
hideError
required={index === 0}
name={`options.exactSolutions.${index}`}
label={t('shared.generic.value')}
placeholder={`${t('shared.generic.value')} ${index + 1}`}
precision={precision ? parseInt(precision) : undefined}
data={{
cy: `set-exact-solution-${index}`,
}}
/>
<Button
onClick={() => remove(index)}
className={{
root: 'ml-2 h-9 bg-red-500 text-white hover:bg-red-600',
}}
data={{
cy: `delete-exact-solution-${index}`,
}}
>
{t('shared.generic.delete')}
</Button>
</div>
))}
<Button
fluid
className={{
root: 'border-uzh-grey-100 flex-1 border border-solid font-bold',
}}
onClick={() => push(undefined)}
data={{ cy: 'add-exact-solution' }}
>
{t('manage.questionForms.addExactSolution')}
</Button>
</div>
)}
</FieldArray>
</div>
)
}

export default NumericalExactSolutionsInput
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import {
Button,
FormLabel,
FormikNumberField,
FormikTextField,
} from '@uzh-bf/design-system'
import { FieldArray, FieldArrayRenderProps } from 'formik'
import { FormikNumberField, FormikTextField } from '@uzh-bf/design-system'
import { useTranslations } from 'next-intl'
import { ElementFormTypesNumerical } from '../types'
import NumericalExactSolutionsInput from './NumericalExactSolutionsInput'
import NumericalSolutionRangesInput from './NumericalSolutionRangesInput'
import NumericalSolutionTypeSwitch from './NumericalSolutionTypeSwitch'

interface NumericalOptionsProps {
values: ElementFormTypesNumerical
Expand Down Expand Up @@ -49,76 +46,23 @@ function NumericalOptions({ values }: NumericalOptionsProps) {
</div>
</div>
{values.options.hasSampleSolution && (
<div className="mt-3">
<FormLabel
required
label={t('manage.questionForms.solutionRanges')}
labelType="small"
tooltip={t('manage.questionForms.solutionRangesTooltip')}
/>
<FieldArray name="options.solutionRanges">
{({ push, remove }: FieldArrayRenderProps) => (
<div className="flex w-max flex-col gap-1">
{values.options.solutionRanges
? values.options.solutionRanges.map(
(_range: any, index: number) => (
<div
className="flex flex-row items-end gap-2"
key={`${index}-${values.options.solutionRanges!.length}`}
>
<FormikNumberField
required={index === 0}
name={`options.solutionRanges.${index}.min`}
label={t('shared.generic.min')}
placeholder={t('shared.generic.minLong')}
data={{
cy: `set-solution-range-min-${index}`,
}}
/>
<FormikNumberField
required={index === 0}
name={`options.solutionRanges.${index}.max`}
label={t('shared.generic.max')}
placeholder={t('shared.generic.maxLong')}
data={{
cy: `set-solution-range-max-${index}`,
}}
/>
<Button
onClick={() => remove(index)}
className={{
root: 'ml-2 h-9 bg-red-500 text-white hover:bg-red-600',
}}
data={{
cy: `delete-solution-range-ix-${index}`,
}}
>
{t('shared.generic.delete')}
</Button>
</div>
)
)
: null}
<Button
fluid
className={{
root: 'border-uzh-grey-100 flex-1 border border-solid font-bold',
}}
onClick={() =>
push({
min: undefined,
max: undefined,
})
}
data={{ cy: 'add-solution-range' }}
>
{t('manage.questionForms.addSolutionRange')}
</Button>
</div>
)}
</FieldArray>
</div>
<NumericalSolutionTypeSwitch
solutionType={values.options.solutionType}
/>
)}
{values.options.hasSampleSolution &&
values.options.solutionType === 'range' && (
<NumericalSolutionRangesInput
solutionRanges={values.options.solutionRanges}
/>
)}
{values.options.hasSampleSolution &&
values.options.solutionType === 'exact' && (
<NumericalExactSolutionsInput
exactSolutions={values.options.exactSolutions}
precision={String(values.options.accuracy)}
/>
)}
</div>
)
}
Expand Down
Loading

0 comments on commit 41f8f44

Please sign in to comment.