Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Remove compute engine #142

Merged
merged 3 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions package-lock.json

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

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
"build:authoring": "tsc && vite build -m authoring"
},
"dependencies": {
"@khanacademy/kas": "github:openstax/raise-kas#1ab668e5032bcf4ede04f5f28f9beafc4f9d218f",
"@khanacademy/kas": "github:openstax/raise-kas#6481127dacbd9fda7d34a6e79f27d0e4cb4798d5",
"bootstrap": "^5.3.2",
"formik": "^2.4.5",
"mathlive": "^0.95.5",
Expand Down
2 changes: 1 addition & 1 deletion specs/blocks.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ test('attempts-exhausted response overrides answer-specific response', async ({
test('Math field component rendered', async ({ page }) => {
const htmlContent = `
<div class="os-raise-ib-pset" data-schema-version="1.0" data-retry-limit="3">
<div class="os-raise-ib-pset-problem" data-problem-type="input" data-solution='3\\sqrt2+\\frac42' data-problem-comparator='math'>
<div class="os-raise-ib-pset-problem" data-problem-type="input" data-solution='3\\sqrt2+2' data-problem-comparator='math'>
rnathuji marked this conversation as resolved.
Show resolved Hide resolved
<div class="os-raise-ib-pset-problem-content">
<p id="problem">MultipleChoice problem content: \\( x^2 \\)</p>
</div>
Expand Down
46 changes: 25 additions & 21 deletions src/components/InputProblem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
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 {
Expand Down Expand Up @@ -38,6 +37,30 @@
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

Check warning on line 58 in src/components/InputProblem.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/InputProblem.tsx#L57-L58

Added lines #L57 - L58 were not covered by tests
}

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
Expand Down Expand Up @@ -82,26 +105,7 @@
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)

Check warning on line 108 in src/components/InputProblem.tsx

View check run for this annotation

Codecov / codecov/patch

src/components/InputProblem.tsx#L108

Added line #L108 was not covered by tests
}
return trimmedInput.toLowerCase() === trimmedAnswer.toLowerCase()
}
Expand Down
31 changes: 30 additions & 1 deletion src/tests/InputProblem.test.tsx
Original file line number Diff line number Diff line change
@@ -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 () => {
Expand Down Expand Up @@ -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)
})
10 changes: 4 additions & 6 deletions src/tests/kas.test.ts
Original file line number Diff line number Diff line change
@@ -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<x' },
{ expr1: 'x\\le4', expr2: '4\\gex' },
{ expr1: 'x\\lt4', expr2: '4\\gtx' },
{ expr1: 'x\\gt4', expr2: '4\\ltx' },
{ expr1: '|-4|', expr2: '|4|' },
{ expr1: '\\sqrt[3]{27}', expr2: '\\sqrt[3]{27}' },
{ expr1: ce.serialize(ce.parse('y=\\frac{1}{2}x+2')), expr2: ce.serialize(ce.parse('y=\\frac{x}{2}+2')) }
{ expr1: '\\sqrt[3]{27}', expr2: '\\sqrt[3]{27}' }
]
// If the options simplify is true the nth root tests fail.
consideredEqual.forEach((val) => {
Expand Down
2 changes: 0 additions & 2 deletions vite.config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,6 @@ export default defineConfig(({ mode }) => {

config.build['rollupOptions'].output.manualChunks = {
mathlive: ['mathlive'],
cortexjs: ['@cortex-js/compute-engine']

}

return config
Expand Down