How to disallow certain player input in textbox Twine 2 Sugarcube 2.35

Hi guys me again. I am wondering if I could disallow certain input to a textbox.

Context:
I am planning to make a creative writing tool to help students who struggle to get words down for short story writing. I’d like to make a kind of timer bar that depletes over x amount of time. In this time, the student will enter text into a textbox (based on a picture stimulus etc.) and they get points if they have over x words. Easy enough so far.

What I am worried about is that a student’s desire to beat a level may trump their desire to get better at writing, resulting in a desperate word spam (“asd asd bsdl sldj sdlkj dfkj”) just to beat the level.
So I am wanting a way to pick up on (and disincentivize) some of that kind of behavior.

In the absence of being able to check a player’s inputted spelling/grammar easily within a twine game itself, I wonder if I can just disallow really basic cheat attempts:

1. Repeated words in sequence
So if a player writes “bob ran up the hall hall hall” and clicks “submit” on a button it might return something like "hmm… looks you’re just spamming words here! You lose 5 xp. Try again.

2. Copied phrases of 2-4 words.
So the following examples would also return an error like above:
“bob ran bob ran” (2 words copy pasted)
“bob ran fast bob ran fast” (3 words copy pasted)
“bob ran fast to bob ran fast to” (4 words copy pasted)

3. Phrases that contain 2 or more words with no vowels
So “asd dlkj” wouldn’t be allowed but “Bob ran quikly towards th hall. the light was on” would be allowed because only 1 word (“th”) is without a vowel. (Basically, I’m allowing for one spelling error where the student misses a vowel in a word.)

4. Phrases that contain lots of a certain word (maybe 5?).
So the phrase “bob ran bob quickly bob down bob the hall bob” wouldn’t be allowed because it contains 5 “bobs” even though it doesn’t have repeated words!

5. A way to check all this stuff in lowercase regardless of what the student has written, but still keep the students original formatting to return to them later.
So this input “Bob bob Bob bob the The the The” would get checked in all lowercase and trigger some of the above alarms ^^ but could still be returned to the student with their capitalization :wink:

I’m open to other ideas too! Just trying to think of some basic hacks students might try. I know I can’t cover everything, but if students lose enough points they might just decide to try and write for real :slight_smile:

Thanks so much for your help!

EDIT: Does anyone know of existing code that does something like the above?

I hope I wasn’t too discouraging in the other thread. There are spell-checking libraries out there (I didn’t really look for grammar-checking), they would just take a certain amount of programming to use, and aren’t just a drop-in “check this textarea and tell me how many errors there were” sort of thing. Typo.js looks fairly straightforward, for instance.

I guess we should ask what is your level of programming experience or comfort?
So. Rough notes on how I’d do things (sorry if this is too high-level or low-level for where you’re at; you’re clearly thinking like a programmer but then number 5 sounds like you’re not at all; I can’t tell).

IIRC the Twine Cookbook has code for timed progress/countdown bars, and I think ChapelR’s macros has improved versions if you need them?

SugarCube includes jQuery, so if you give the textarea an id attribute you can get its contents with JavaScript similar to $("#my-textarea").value. Then you can add .toLowerCase() to get a lowercase version, and .split(/\s+/m) to split it into words. And of course you can keep a copy of the original value to show to the student.

Then you could loop over all the words and check if they’re misspelled with Typo.js. That would also catch things without vowels, of course. If you want to get really fancy you could use something like simplediff to look at how the word is misspelled, but…yeah. How much work do you want to put into this?

For copied phrases, I’d either loop over the words and use a sliding window to check for repeated phrases, or I’d compute n-grams and their frequencies (possibly more robust).

That is, for each word, grab a chunk of the input that’s twice as long as the longest repeated phrase that you want to check for (chunk = words.slice(index, index+8)) and then check that chunk for repeats.

Or (n-grams) loop over all the words, grab the single word, two words, three words, four words. Join each set back into a string (chunk.join(' ')) and build a dictionary that counts how many times you’ve seen this phrase (if the phrase is not in the dictionary, add phrase=1; if it is, add 1 to the current entry for that phrase). This might be more robust because it catches copies even if they’re not adjacent (Error: the word “Bob” makes up more than 10% of your “story”).

So…yeah. Dunno how helpful that is…

1 Like

Hi Josh, thanks heaps for your reply. You weren’t discouraging! And yea, you got me - I’m not a programmer at all so integrating libraries is probably a bit beyond me. I’ve gotten this far mostly off the back of other ppls amazing coding.

To be honest most of what you posted is waaay above my head, but it sounds like it might be possible for me a few years from now lol! I don’t suppose you know of any ppl who have done similar things in the past that i could look at?
I guess it is a pretty unusual objective?