From e86dc4f2b2d4434765aaa29962509fcda569dd0a Mon Sep 17 00:00:00 2001 From: Prabhdip Gill Date: Wed, 24 Jan 2024 09:01:53 -0800 Subject: [PATCH 1/2] Update tests and remove compute engine --- package-lock.json | 6 ++--- package.json | 2 +- specs/blocks.spec.ts | 2 +- src/components/InputProblem.tsx | 46 ++++++++++++++++++--------------- src/tests/InputProblem.test.tsx | 31 +++++++++++++++++++++- src/tests/kas.test.ts | 10 +++---- vite.config.ts | 2 -- 7 files changed, 64 insertions(+), 35 deletions(-) diff --git a/package-lock.json b/package-lock.json index b4e78342..16fdd998 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "k12-apps-raise", "version": "0.0.0", "dependencies": { - "@khanacademy/kas": "github:openstax/raise-kas#df0d0cf6941e20803050537536cc723733119859", + "@khanacademy/kas": "github:openstax/raise-kas#4bdde2d21310661f7dc8452389a9c0104bc0de27", "bootstrap": "^5.3.2", "formik": "^2.4.5", "mathlive": "^0.95.5", @@ -1893,8 +1893,8 @@ }, "node_modules/@khanacademy/kas": { "version": "0.3.1", - "resolved": "git+ssh://git@github.com/openstax/raise-kas.git#df0d0cf6941e20803050537536cc723733119859", - "integrity": "sha512-vBw5rtjNs5fFcGjLiTP+1Hqg2I8wlFLR4oPstDN411mVC9xtaaP4kQZUytjJjAekg99nzfZiKseYR2RGR10MUw==", + "resolved": "git+ssh://git@github.com/openstax/raise-kas.git#4bdde2d21310661f7dc8452389a9c0104bc0de27", + "integrity": "sha512-CiWjdOd03gKh5yRj9+Lo23eTlANVs9zq0R2rVaaYaEMhmiMRjUwXkg9ScqZGz57RfhXQuJAfA1PsCszdOEWXgw==", "license": "MIT", "peerDependencies": { "underscore": "^1.13.6" diff --git a/package.json b/package.json index 953af776..586b10eb 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build:authoring": "tsc && vite build -m authoring" }, "dependencies": { - "@khanacademy/kas": "github:openstax/raise-kas#df0d0cf6941e20803050537536cc723733119859", + "@khanacademy/kas": "github:openstax/raise-kas#4bdde2d21310661f7dc8452389a9c0104bc0de27", "bootstrap": "^5.3.2", "formik": "^2.4.5", "mathlive": "^0.95.5", diff --git a/specs/blocks.spec.ts b/specs/blocks.spec.ts index 58dfb017..fd0a8a88 100644 --- a/specs/blocks.spec.ts +++ b/specs/blocks.spec.ts @@ -308,7 +308,7 @@ test('attempts-exhausted response overrides answer-specific response', async ({ test('Math field component rendered', async ({ page }) => { const htmlContent = `
-
+

MultipleChoice problem content: \\( x^2 \\)

diff --git a/src/components/InputProblem.tsx b/src/components/InputProblem.tsx index 77dc7cf2..78e6e612 100644 --- a/src/components/InputProblem.tsx +++ b/src/components/InputProblem.tsx @@ -9,7 +9,6 @@ import { CorrectAnswerIcon, WrongAnswerIcon } from './Icons' import { Mathfield } from './Mathfield' import { type MathfieldElement } from 'mathlive' import { parse, compare } from '@khanacademy/kas' -import { ComputeEngine } from '@cortex-js/compute-engine' export const MAX_CHARACTER_INPUT_PROBLEM_LENGTH = 500 interface InputProblemProps extends BaseProblemProps { @@ -38,6 +37,30 @@ export function buildClassName(correct: boolean, formDisabled: boolean, errorRes return className } +export const detectAndTransform = (input: string): string => { + // Handle fractions with single digit numerators and denominators + const fractionRegex: RegExp = /\\frac(\d)(\d)/g + input = input.replace(fractionRegex, '\\frac{$1}{$2}') + + // Handle square roots with single digits + const sqrtRegex: RegExp = /\\sqrt(\d)/g + input = input.replace(sqrtRegex, '\\sqrt{$1}') + + return input +} + +export const evaluateMathComparator = (input: string, answer: string): boolean => { + const parsedInput = parse(detectAndTransform(input)) + const parsedAnswer = parse(detectAndTransform(answer)) + + if (!parsedInput.parsed || !parsedAnswer.parsed) { + console.error('KAS failed to parse solution or input') + return false + } + + return compare(parsedInput.expr, parsedAnswer.expr, { simplify: false, form: true }).equal +} + export const InputProblem = ({ solvedCallback, exhaustedCallback, allowedRetryCallback, attemptsExhaustedResponse, solution, retryLimit, content, contentId, comparator, encourageResponse, buttonText, correctResponse, answerResponses, onProblemAttempt @@ -82,26 +105,7 @@ export const InputProblem = ({ return parseFloat(trimmedInput) === parseFloat(trimmedAnswer) } if (comparator.toLowerCase() === 'math') { - const ce = new ComputeEngine() - - let parsedInput = parse(ce.serialize(ce.parse(trimmedInput))) - let parsedAnswer = parse(ce.serialize(ce.parse(trimmedAnswer))) - - // Sometimes compute engine produces an output that the KAS parse method does not understand - // If that is the case we can try to parse again with the raw trimmed input and answer - // An example of an expression that requires this is x>5 - if (!parsedInput.parsed) { - parsedInput = parse(trimmedInput) - } - if (!parsedAnswer.parsed) { - parsedAnswer = parse(trimmedAnswer) - } - - if (!parsedInput.parsed || !parsedAnswer.parsed) { - return false - } - - return compare(parsedInput.expr, parsedAnswer.expr, { simplify: false, form: true }).equal + return evaluateMathComparator(trimmedInput, trimmedAnswer) } return trimmedInput.toLowerCase() === trimmedAnswer.toLowerCase() } diff --git a/src/tests/InputProblem.test.tsx b/src/tests/InputProblem.test.tsx index b69972df..bf93fb06 100644 --- a/src/tests/InputProblem.test.tsx +++ b/src/tests/InputProblem.test.tsx @@ -1,5 +1,5 @@ import { render, screen, fireEvent, act } from '@testing-library/react' -import { InputProblem, MAX_CHARACTER_INPUT_PROBLEM_LENGTH, buildClassName } from '../components/InputProblem' +import { InputProblem, MAX_CHARACTER_INPUT_PROBLEM_LENGTH, buildClassName, detectAndTransform, evaluateMathComparator } from '../components/InputProblem' import '@testing-library/jest-dom' test('InputProblem renders with content, input and button', async () => { @@ -409,3 +409,32 @@ test('Test buildClassName', async () => { const validationError = buildClassName(false, false, 'error') expect(validationError).toBe('os-form-control os-wrong-answer-choice') }) + +test('Test detectAndTransform', async () => { + // If a fraction and sqrt transformation is needed + const input = 'x=\\frac12 + \\sqrt3' + const expectedOutput = 'x=\\frac{1}{2} + \\sqrt{3}' + let result = detectAndTransform(input) + expect(result).toEqual(expectedOutput) + + // No transformation is needed + const correctInput = 'x = \\frac{12}{2} + \\sqrt{9} + 4x' + result = detectAndTransform(input) + expect(correctInput).toEqual(correctInput) +}) + +test('Test evaluteMathComparator', async () => { + // Fraction test + expect(evaluateMathComparator('\\frac12', '\\frac{1}{2}')).toBe(true) + + // sqrt and nth root test + expect(evaluateMathComparator('x=\\sqrt4', 'x=\\sqrt[2]{4}')).toBe(true) + expect(evaluateMathComparator('x=\\sqrt4', 'x=\\sqrt[3]{4}')).toBe(false) + + // form test + expect(evaluateMathComparator('y=\\frac12x-3', 'y+3=\\frac12x')).toBe(false) + + // test \lt \gt + expect(evaluateMathComparator('x<\\frac{1}{3}', 'x\\lt\\frac{1}{3}')).toBe(true) + expect(evaluateMathComparator('x>\\frac13', 'x\\gt\\frac{1}{3}')).toBe(true) +}) diff --git a/src/tests/kas.test.ts b/src/tests/kas.test.ts index c337d4e9..46ee1a75 100644 --- a/src/tests/kas.test.ts +++ b/src/tests/kas.test.ts @@ -1,20 +1,18 @@ import { parse, compare } from '@khanacademy/kas' -import { ComputeEngine } from '@cortex-js/compute-engine' -test('Test kas with compute engine and edge cases', async () => { +test('Test kas', async () => { const options = { simplify: false, form: true } - const ce = new ComputeEngine() const consideredEqual = [ - { expr1: ce.serialize(ce.parse('\\frac42')), expr2: ce.serialize(ce.parse('\\frac{4}{2}')) }, { expr1: 'x>4', expr2: '4 { diff --git a/vite.config.ts b/vite.config.ts index 9bfb54b7..6ed425bc 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -43,8 +43,6 @@ export default defineConfig(({ mode }) => { config.build['rollupOptions'].output.manualChunks = { mathlive: ['mathlive'], - cortexjs: ['@cortex-js/compute-engine'] - } return config From 719cd75ca3e4acfb7764c888ecde8c121ba42987 Mon Sep 17 00:00:00 2001 From: Prabhdip Gill Date: Wed, 24 Jan 2024 11:59:09 -0800 Subject: [PATCH 2/2] Update KAS dependency after gt lt update --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 16fdd998..c7134fc2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,7 +8,7 @@ "name": "k12-apps-raise", "version": "0.0.0", "dependencies": { - "@khanacademy/kas": "github:openstax/raise-kas#4bdde2d21310661f7dc8452389a9c0104bc0de27", + "@khanacademy/kas": "github:openstax/raise-kas#6481127dacbd9fda7d34a6e79f27d0e4cb4798d5", "bootstrap": "^5.3.2", "formik": "^2.4.5", "mathlive": "^0.95.5", @@ -1893,7 +1893,7 @@ }, "node_modules/@khanacademy/kas": { "version": "0.3.1", - "resolved": "git+ssh://git@github.com/openstax/raise-kas.git#4bdde2d21310661f7dc8452389a9c0104bc0de27", + "resolved": "git+ssh://git@github.com/openstax/raise-kas.git#6481127dacbd9fda7d34a6e79f27d0e4cb4798d5", "integrity": "sha512-CiWjdOd03gKh5yRj9+Lo23eTlANVs9zq0R2rVaaYaEMhmiMRjUwXkg9ScqZGz57RfhXQuJAfA1PsCszdOEWXgw==", "license": "MIT", "peerDependencies": { diff --git a/package.json b/package.json index 586b10eb..65c5562a 100644 --- a/package.json +++ b/package.json @@ -16,7 +16,7 @@ "build:authoring": "tsc && vite build -m authoring" }, "dependencies": { - "@khanacademy/kas": "github:openstax/raise-kas#4bdde2d21310661f7dc8452389a9c0104bc0de27", + "@khanacademy/kas": "github:openstax/raise-kas#6481127dacbd9fda7d34a6e79f27d0e4cb4798d5", "bootstrap": "^5.3.2", "formik": "^2.4.5", "mathlive": "^0.95.5",