UNPKG

@instructure/quiz-interactions

Version:

A React UI component Library for quiz interaction types.

126 lines (110 loc) 3.72 kB
import React from 'react' import {addValidator, each, rule, onSelf} from 'instructure-validations' import {isScientificNotation} from '@instructure/quiz-scientific-notation' import {Text} from '@instructure/ui-text' import {FORMULA_SLUG} from '../../interaction_slugs' import InteractionType from '../InteractionType' import {formulaSyntaxError, variablesFromItemBody} from '../../util/formula' import {numericMessage} from '../../util/validationHelpers' import t from '@instructure/quiz-i18n/format-message' const hasVariables = itemBody => { if (variablesFromItemBody(itemBody).length === 0) { return t('Question Stem must contain variables') } } const formulaSyntax = (formula, options) => { const variables = variablesFromItemBody(options.itemBody) return formulaSyntaxError(variables, formula) } addValidator('hasVariables', hasVariables) addValidator('formulaSyntax', formulaSyntax) export const variableRules = variable => { const minRule = rule('numeric', {message: numericMessage(t('Min'))}) const maxRule = rule('numeric', { message: numericMessage(t('Maximum')), min: variable.min, minMessage: t('Must be larger than minimum value'), }) const scientificNotationRule = rule('scientificNotation', { message: t('Must be in scientific notation'), }) // Don't allow just min or max in scientific notation: it's both, or neither const min = isScientificNotation(variable.max) ? [scientificNotationRule, minRule] : [minRule] const max = isScientificNotation(variable.min) ? [scientificNotationRule, maxRule] : [maxRule] const precision = [ rule('numeric', { decMessage: t('Minimum value must have at least the same number of decimals as precision'), type: 'decimals', value: variable.min, }), rule('numeric', { decMessage: t('Maximum value must have at least the same number of decimals as precision'), type: 'decimals', value: variable.max, }), ] return {min, max, precision} } export default class FormulaInteractionType extends InteractionType { constructor(obj) { super() super.initializeProps(obj) } slug = FORMULA_SLUG translatedName = t('Formula') getDefaultScoringData = intData => { return { value: { answerCount: '200', formula: '', generatedSolutions: [], variables: [], // TODO: set this from the UI, rather than being stuck with the default numeric: { type: 'marginOfError', marginType: 'absolute', margin: '0', }, }, } } getDefaultInteractionData = () => ({}) getDefaultUserResponse() { return {value: ''} } getRenderedResponse = responseValue => { return <Text color="primary">{responseValue}</Text> } static validations = (obj = {}) => { const numeric = obj.scoringData.value.numeric && obj.scoringData.value.numeric.type === 'marginOfError' ? { margin: [rule('numeric', {message: numericMessage(t('Margin')), min: 0})], } : [] return { itemBody: [ rule('presence', {message: t('Question Stem cannot be blank')}), rule('hasVariables'), ], scoringData: { value: { variables: [each(variableRules)], formula: [ rule('presence', {message: t('Formula cannot be blank')}), rule('formulaSyntax', {itemBody: obj.itemBody}), ], numeric, generatedSolutions: [ onSelf( rule('listSize', { min: 1, minMessage: t('Must have at least one solution'), }), ), ], }, }, } } }