Need help with my Javascript

Need help with my Javascript

by Joseph Rézeau -
Number of replies: 3
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers Picture of Translators

Hi fellow developers! I am currently trying to  help an automatic gap deletion to my own version of the multianswer/cloze question type. It's working more or less as expected but in my script which sets a SHORTANSWER "gap" (in fact a SHORTANSWER sub-question) every nth word (at n intervals) I would like my script to skip capitalised words (as is the norm in such cloze tests). The following script does skip capitalised words, but... it also skips the next n words. I know this is due to the "continue" instruction in my script line 17. Any idea how I could modify my script to achieve the result I want?

Interval for gaps set at every 5th word. Original text example:

Once upon a time, many hundreds of years ago, there lived a boy named Dick. He was an orphan and had little in the way of comfort,...

With my script I'm getting this result:

Once upon a time, {1:SA:=many} hundreds of years ago, {1:SA:=there} lived a boy named Dick. He was an orphan {1:SA:=and} had little in the {1:SA:=way} of comfort,...

But I would like to get this result:

Once upon a time, {1:SA:=many} hundreds of years ago, {1:SA:=there} lived a boy named Dick. {1:SA:=He} was an orphan and {1:SA:=had} little in the way {1:SA:=of} comfort,...

and here's the script: (interval == 0)

 1        for (let i = 0; i < paragraphs.length; i++) {
 2          let paraText = $(paragraphs[i]).text();
 3          let words = paraText.split(' ');
 4          // Loop through the words and enclose every 5th or 9th word in SHORTANSWER marker.
 5          for (let index = 0; index < words.length; index++) {
 6            if ((index + 1) % interval === 0) {
 7              // Separate the word from any trailing punctuation
 8              let word = words[index];
 9              let punctuation = '';
10              if (/[.,!?;:]+$/.test(word)) {
11                  punctuation = word.slice(-1); // Get the punctuation mark
12                  word = word.slice(0, -1); // Remove the punctuation from the word
13              }
14              // Check if the word starts with a capital letter
15              if (word && word[0] === word[0].toUpperCase() && /[A-Za-z]/.test(word[0])) {
16                // If the word starts with a capital letter, skip the gapping transformation
17                continue;
18              }
19              // Enclose the word in SHORTANSWER (SA) brackets, then add back the punctuation
20              words[index] = `{1:SA:=${word}}${punctuation}`;
21            }
22          }
23          // Join the words back into a single string
24          let gappedText = words.join(' ');
25          if (gappedText !== '') {
26            $(paragraphs[i]).text(gappedText);
27          }
28        }

N.B. I did try ChatGPT for help but it keeps suggesting alternative scripts which do not work. 😡

Average of ratings: -
In reply to Joseph Rézeau

Re: Need help with my Javascript

by Mark Johnson -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Hi Joseph,

Try this for loop. Instead of adding 1 to the index each time to decide if we're targeting this word, we add a movable offset. When we encounter a word we want to skip, we subtract 1 from the offset before the continue, so that we try the next word instead, and so on.

It doesn't match your required output exactly, since "He" is capitalised so the next word it replaces is "was". If you do want to replace the first word of a sentence even if its capitalised, you'll need to modify the capital letter check.

https://jsfiddle.net/gk21qyfe/4/

           // Loop through the words and enclose every 5th or 9th word in SHORTANSWER marker.
           let offset = 1;
           for (let index = 0; index < words.length; index++) {
             if ((index + offset) % interval === 0) {
               // Separate the word from any trailing punctuation
               let word = words[index];
               let punctuation = '';
              if (/[.,!?;:]+$/.test(word)) {
                  punctuation = word.slice(-1); // Get the punctuation mark
                  word = word.slice(0, -1); // Remove the punctuation from the word
              }
              // Check if the word starts with a capital letter
              if (word && word[0] === word[0].toUpperCase() && /[A-Za-z]/.test(word[0])) {
                // If the word starts with a capital letter, skip the gapping transformation
                offset -= 1;
                continue;
              }
              // Enclose the word in SHORTANSWER (SA) brackets, then add back the punctuation
              words[index] = `{1:SA:=${word}}${punctuation}`;
Average of ratings: Useful (1)
In reply to Mark Johnson

Re: Need help with my Javascript

by Joseph Rézeau -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Plugin developers Picture of Testers Picture of Translators

Hi Mark,

Thanks for taking up my little challenge. Actually, soon after posting I had one of those "rubber duck" moments and came up with a working solution, but not as elegant as yours.😉 Thanks for mentioning the question of capitalised first word of sentences. Since it's not possible to automatically decide whether that first word is a capitalised common name or a proper name, I'll leave it as "non gappable".

Thanks also for posting your code to JSFiddle, but it looks like the code there works like my original code, not like the code you put in your forum message. I really ought to learn how to use JSFiddle some day. One question: how can I display the result of the output inside that "result" frame rather than in my browser's console?

One more feature I'd like to add to my automatic gapping routine is to only skip gapping the first occurrence of proper names, but to gap any ensuing occurrences. I guess that will require using an array of such proper names/words as I go through the text.

Thanks again for your help!

In reply to Joseph Rézeau

Re: Need help with my Javascript

by Mark Johnson -
Picture of Core developers Picture of Particularly helpful Moodlers Picture of Peer reviewers Picture of Plugin developers

Sorry, it looks like the URL I copied was for a "work in progress" rather than the final solution.

Here is the proper one, which also outputs to the output pane rather than the console: https://jsfiddle.net/mdo0hq6s/

Average of ratings: Useful (2)