Skip to content

Instantly share code, notes, and snippets.

@benjclark
Created February 20, 2020 15:34
Show Gist options
  • Select an option

  • Save benjclark/feb71161649df3691e7d81bc3fdfd75a to your computer and use it in GitHub Desktop.

Select an option

Save benjclark/feb71161649df3691e7d81bc3fdfd75a to your computer and use it in GitHub Desktop.
import React, { useState, useCallback, useMemo } from 'react';
import Fuse from 'fuse.js';
function FuzzyMatchInput({ answer, threshold = 0.2 }) {
const [isFuzzyMatch, setIsFuzzyMatch] = useState(false);
function sanitiseText(text) {
// as per https://stackoverflow.com/questions/4328500/how-can-i-strip-all-punctuation-from-a-string-in-javascript-using-regex
const punctuationLess = text.replace(/[\.,-\/#!$%\^&\*;:{}=\-_`~()@\+\?><\[\]\+]/g, '');
return punctuationLess.replace(/\s{2,}/g, ' ');
}
function isAcceptableLength(textInput) {
const passLengthMin = Math.round(sanitiseText(answer).length * 0.9);
const passLengthMax = Math.round(sanitiseText(answer).length * 1.1);
return textInput.length <= passLengthMax && textInput.length >= passLengthMin;
}
const fuse = useMemo(
() => new Fuse([sanitiseText(answer)], { threshold }),
[answer],
);
const handleInputChange = useCallback(
(e) => setIsFuzzyMatch(
!!fuse.search(sanitiseText(e.target.value)).length
&& isAcceptableLength(sanitiseText(e.target.value))
),
[answer, fuse],
);
return (
<div>
<label>
<div>We apply fuzzy matching to a user%apos;s answers.</div>
<div>You can test what words will pass and fail for your answer below:</div>
</label>
<input
type="text"
onChange={handleInputChange}
style={{
display: 'inline-block',
border: `1px solid ${isFuzzyMatch ? 'green' : 'red'}`,
}}
/>
<div>
<span style={{ color: isFuzzyMatch ? 'green' : 'red' }}>
{isFuzzyMatch ? 'Pass' : 'Fail'}
</span>
</div>
</div>
);
}
export default FuzzyMatchInput;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment