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

feat: allow checking backwards strokes #252

Merged
merged 4 commits into from
Oct 2, 2021

Conversation

matt-tingen
Copy link
Contributor

The use case for this is to allow applications to notify a user when they make a backwards stroke (one which is correct except for the direction in which in which it's made) on a quiz. In such a case, the application will likely want to show some messaging to the user indicating the stroke was made in the wrong direction. The application may want to treat backwards strokes as correct or incorrect.

This change includes two API changes to fulfill the above use case:

  • The addition of a checkBackwardsStrokes ternary quiz option (defaulted off)
  • The onCorrectStroke and onMistake quiz handlers receive an isBackwards boolean property on the stroke data.

checkBackwardsStrokes is ternary to allow avoiding the perf hit of checking backwards strokes if the application does not care about them.

If checkBackwardsStrokes is false, the handlers will always receive isBackwards: false since the backwards check is skipped. The alternative here is to return e.g. null if the check was skipped. I opted against this to keep the API a bit simpler with a consistent type for isBackwards.

@codecov-commenter
Copy link

codecov-commenter commented Sep 15, 2021

Codecov Report

Merging #252 (755a3c6) into master (f1a810c) will increase coverage by 0.10%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #252      +/-   ##
==========================================
+ Coverage   96.16%   96.26%   +0.10%     
==========================================
  Files          32       32              
  Lines        1121     1126       +5     
  Branches      202      205       +3     
==========================================
+ Hits         1078     1084       +6     
+ Misses         39       38       -1     
  Partials        4        4              
Impacted Files Coverage Δ
src/defaultOptions.ts 100.00% <ø> (ø)
src/Quiz.ts 95.83% <100.00%> (+0.05%) ⬆️
src/strokeMatches.ts 100.00% <100.00%> (+1.26%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update f1a810c...755a3c6. Read the comment docs.

Copy link
Owner

@chanind chanind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is such a great idea! Thank you for submitting this! Some minor thoughts:

  • I think it's fine to always check whether the stroke is backwards, it shouldn't hurt anything to add an isStrokeBackwards: boolean into onMistake and isCorrect callbacks.
  • Likewise, IMO it should be fine to just add an option allowBackwardsStrokes: boolean or something similar to the options for quizzing, rather than inputting a 3-valued string

@@ -20,34 +20,44 @@ const START_AND_END_DIST_THRESHOLD = 250; // bigger = more lenient
const FRECHET_THRESHOLD = 0.4; // bigger = more lenient
const MIN_LEN_THRESHOLD = 0.35; // smaller = more lenient

export type StrokeMatchType = 'miss' | 'match' | 'backwards-match';
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I think it would be better to return an object here instead of a string, so that in the future we can enhance it further. I can imagine it might be useful to know why the stroke didn't match beyond only the direction. What do you think about returning something like the following:

type StrokeMatchResult {
  match: boolean; // whether or not the match is successful
  failureReasons?: Array<'direction' | 'position' | 'length' | 'shape'>
  // in the future we could add more details here about the match result if needed
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I'm happy to change allowBackwardsStrokes to boolean and to return an object from strokeMatches.

I like the idea of failureReasons, but are the *Match variables independent enough that they can be used to convey that level of specificity about failure? This may be my unfamiliarity with the code, but when I was playing around with it, I wasn't able to determine whether a stroke was valid aside from being backward just by looking at the existing vars. For instance, with the identifies backwards stroke when allowed test, the initial check has shapeMatch: false and startAndEndMatch: true which both seem incorrect (or at least unintuitive) to me. This is why I went the the approach of recursing with the reversed points array.

Screen Shot 2021-09-24 at 10 28 48 PM

Copy link
Owner

@chanind chanind Sep 27, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're doing it right I think. The shape match is using Frechet Distance, which is dependent on direction already. This is a good point, it's hard to isolate a single reason why a stroke failed, because it could fail for multiple reasons, and the reasons sort of overlap (Frechet distance is distance + shape + direction, for example).

Maybe something like this in that case?

type StrokeMatchResult {
  match: boolean; // whether or not the match is successful
  meta: {
    strokeIsBackwards: boolean // if the stroke is correct in all ways except it's backwards
    // in the future we can add more stuff here if we want
  }
}

Because it is recursive, it requires an explicit return type annotation.
Copy link
Owner

@chanind chanind left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work! 🥇

@chanind chanind merged commit 15d37e8 into chanind:master Oct 2, 2021
@chanind
Copy link
Owner

chanind commented Oct 2, 2021

🎉 This PR is included in version 3.3.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

@matt-tingen matt-tingen deleted the backwards-strokes branch October 2, 2021 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants