@instructure/quiz-interactions
Version:
A React UI component Library for quiz interaction types.
73 lines (71 loc) • 2.91 kB
JavaScript
import uniq from 'lodash/uniq';
import { mathjsLoadingWrapper } from '../components/formula/common/util';
import { Decimal } from '@instructure/quiz-i18n';
import t from '@instructure/quiz-i18n/es/format-message';
export var variablesFromItemBody = function variablesFromItemBody(itemBody) {
var body = itemBody || '';
var matches = body.match(/`[A-Za-z]\w*`/g) || [];
var matchesWithoutBackticks = matches.map(function (match) {
return match.replace(/`/g, '');
});
return uniq(matchesWithoutBackticks).sort();
};
export var formulaSyntaxError = function formulaSyntaxError(variables, formula) {
var substitutions = {};
variables.forEach(function (varName) {
return substitutions[varName] = 1;
});
try {
// TODO: This will fail if nothing has called components/formula/Edit/util/loadMathJs() yet.
// we should either change this function signature to return a promise and do
// loadMathjs().then(mathjs => mathjs.eval...) or make sure it is always preloaded by
// the time we get here.,
var math = mathjsLoadingWrapper.mathjs;
// This parses the formula detecting if the locale uses comma as separator
var parsedFormula = parseFormulaDecimalSeparator(window.document.documentElement.lang || 'en-US', formula);
// we replace function e() with the constant e
// and function pi() with the constant pi
// this is to match legacy canvas quizzes behavior which accepted both e/pi and e()/pi()
var node = math.parse(parsedFormula);
var transformed = node.transform(function (node, path, parent) {
if (node.isFunctionNode && node.fn.isSymbolNode && node.fn.name === 'e') {
return new math.expression.node.ConstantNode(Math.E);
} else if (node.isFunctionNode && node.fn.isSymbolNode && node.fn.name === 'pi') {
return new math.expression.node.ConstantNode(Math.PI);
} else {
return node;
}
});
var compiled = transformed.compile();
compiled.eval(substitutions);
} catch (e) {
var message = e.message;
console.error('Formula Error: ' + e.message);
var match = message.match(/Undefined symbol ([A-Za-z]+)/);
if (match) {
return t('Undefined symbol {symbol}', {
symbol: match[1]
});
}
match = message.match(/Unexpected end of expression/);
if (match) {
return t('Unexpected end of expression');
}
match = message.match(/Unexpected operator ([^\s]+)/);
if (match) {
return t('Unexpected operator {operator}', {
operator: match[1]
});
}
return t('Invalid formula');
}
return null;
};
export var parseFormulaDecimalSeparator = function parseFormulaDecimalSeparator(locale, formula) {
var _Decimal$getDelimiter = Decimal.getDelimiters(locale),
decimal = _Decimal$getDelimiter.decimal;
if (decimal === '.') {
return formula;
}
return formula.replace(/(\d+),(\d+)/g, '$1.$2');
};