Jump to content
Sign in to follow this  
Ronie5ive

"Quiz from Notecard" Script - Delay next question?

You are about to reply to a thread that has been inactive for 2445 days.

Please take a moment to consider if this thread is worth bumping.

Recommended Posts

Greetings, this question may be one for "Rolig Loon" the developer of the 'Quiz from Notecard' script but if anyone could provide any advice, I'd greatly appreciate it! The script can be found here: http://wiki.secondlife.com/wiki/User:Rolig_Loon/Quiz_From_Notecard

I'm looking to create a delay (20 seconds) after a particular question is answered, so that the next question within the notecard doesn't popup until after the delay.

Share this post


Link to post
Share on other sites

I haven't looked back at that script in ages.  Let's see.....

Here's one way to do what you want.

1. At the very top of the script, create a new global integer variable, gDelay, by adding the line

integer gDelay;

 2.Insert the following line right at the end of the touch_start event, just before the line that starts gQID = ...

llResetTime();

 3. Replace the timer event with the following ...

timer(){    if (gDelay)    {        gQuestion = ""; //Erase the current question        gAnswers = []; //And its answer key        ++gLine;        gQID = llGetNotecardLine(gCard,gLine); // Get the next question        llSetTimerEvent((Timespan - llGetTime())*60);        gDelay = FALSE;    }    else    {        llInstantMessage(gAvKey,"Your time is up. Thank you for taking the quiz. Your score is "+ (string)gScore);            init(); //Restart the quiz for the next person    }}

 4. Change the last block of code of the listen event to read .....,

   else // A question has been displayed in a dialog box    {        gDelay = TRUE;        llSetTimerEvent(20.0);        integer pos = llListFindList(gAnswers,["1"]); //Search the answer key. The correct answer is pos+1        if(message == (string)(pos+1))        {            ++gScore;            llInstantMessage(gAvKey,"Correct! Your score is now "+ (string)gScore+ ". Next ...");        }        else if (pos != -1)        {            llInstantMessage(gAvKey,"Wrong. The correct answer was "+ (string)(pos+1) + ". Next ....");        }        else if (pos == -1) //The teacher screwed up and didn't code a correct answer        {            llInstantMessage(gAvKey,"Ooops! There is no right answer to this question. Let's move on.");        }        llInstantMessage(gAvKey,"Please wait for the next question ....");    }

 I think that ought to do the job, although I can't get in world at the moment to test it.  There are several other things I would do to the script if I were writing it today, but those are mostly internal efficiencies.

Good luck with it.  :smileyhappy:

  • Like 1

Share this post


Link to post
Share on other sites

It occurs to me that each of those 20 second delays will rob 20 seconds from the total time that you allot for the quiz with the variable Timespan (set by default to 10 minutes).  It also occurs to me that I misread my own script in correcting the timer event earlier.  So.....

Look for the line in the timer event that says

        llSetTimerEvent((Timespan - llGetTime())*60);

and change it to

        llSetTimerEvent(Timespan*60.0  - llGetTime() + 20.0);

 

Share this post


Link to post
Share on other sites

You're much better in marketing than I am :) I made a somewhat similar device (though it may be more generic) and the only name I could come up with was Forms and Surveys Agent  which is of course a terrible name...lol. Yours is much better.

Share this post


Link to post
Share on other sites

I really want to try out the suggestions above but it seems I have another issue or issues to work out. The first would be that whenever I quit the quiz on a particular question, when I restart it, the quiz pops up the last question I was on in addition to the first question of the quiz.

The second is that when I attempt to quit the quiz and select "no" from the question "Do you want to QUIT now?", the dialog boxes disappear completely when I confident it's supposed to return to the last question. The code I've been working with is below. I've modified it a bit and now it's not much of a quiz but its very helpful for the medical scenarios that I need to create.

I've compared it to the original quiz and I cannot find too many differences in the basic structure. I haven't made many if any critical changes to it.

 

//A Dialog-driven quiz, using text from a notecard -- Rolig Loon -- October 2009// Free for public use -- please don't do something crass like selling my script.// Modify if you must, but please keep these header lines intact.  Be nice.//// Notecard format:// A line beginning with a "Q" is part of a question// A line beginning with an "A" is a string of comma-delimited zeros (wrong) and a one (right) to identify the answer// A line beginning with a "#" is a comment// Blank lines are ignored//// Dialog boxes are limited to 512 characters, so make each question (including choices) short enough to fit.// There is no limit to the number of questions in a quiz, and you may have up to 12 answer choices per question//// =============== sample notecard ===========//# Lines starting with Q appear verbatim in a dialog box//# You may have as many Q lines as you want per question, but only one A line//# Interpreted data begins immediately after the lead character in a line//QWhat is the capital of Minnesota?//Q1. St. Paul//Q2. Minneapolis//Q3. Iowa City//Q4. Boston//A1,0,0,0//QHow many fingers are on my right hand?//Q1. One//Q2. Two//Q3. Three//Q4. Four//Q5. Five//A0,0,0,0,1// ================= end of sample =================//// Instructor types "results" in channel 24 to get a report of all student scoresstring gCard; //Notecard nameinteger gLine; //Current line being readkey gQID; //Dataserver keyinteger gtouch; //Activates/deactivates touch_start event list gAvList = []; //Cumulative list of people who have taken this quizstring gAv; //Name of the current quiz-takerkey gAvKey; //Key of the current quiz-takerinteger CHAN; //Channel for dialog communicationinteger Handle; //Listen handle for dialog//integer gScore; //This quiz-taker's scorestring gQuestion; //Text for the current questionlist gAnswers; //Answer key for the current questionlist gAllScores = []; //Cumulative list of scores for quiz-takersinteger Timespan = 30;  // [highlight]This is the maximum time alloted for the quiz, in minutes. Change here if needed.[/highlight] integer countQues = 0; // Counts the current questioninteger t = 0; // Rotation for Red Medical Symbol              integer IsNameOnList(list namelist, string name)  //Verifies whether av has already taken the quiz{    integer i;    integer len = llGetListLength(namelist);    for (i=0; i<=len-1;++i)        if(llList2String(namelist,i) == "adadfhh")        {            return TRUE;        }    return FALSE;}init()  //Resets parameters for the next quiz-taker{    llSetTimerEvent(0);    gtouch = 0;    gAv = "";    gAvKey = NULL_KEY;    gLine = 0;   // gAllScores += gScore;   // gScore = 0;    gAvList = [];    llListenControl(Handle,FALSE);    countQues = 0;    llSay(-3000, "stopped"); // Simulation isn't in progress, send the message out    t = 0; // Begin Rotation        // Rotate the symbol and set the hovering text        llTargetOmega(<4.0,0.0,0.0>*llGetRot(),0.1,0.01);        llSetText("Click to begin the simulation.", <1.0, 1.0, 1.0>, 2.0);            //Loop Rotation until t=1            do { llSetPrimitiveParams( [ PRIM_GLOW, ALL_SIDES, .3 ] );}            while(t = 0);}list order_buttons(list buttons){return llList2List(buttons, -3, -1) + llList2List(buttons, -6, -4)+ llList2List(buttons, -9, -7) + llList2List(buttons, -12, -10);}default{    state_entry()    {        gCard = llGetInventoryName(INVENTORY_NOTECARD,0);        gAvList = [];        CHAN = (integer)(llFrand(100000000))* (-1);        Handle = llListen(CHAN,"","","");        llListen(24,"",llGetOwner(),"");        init();    }    touch_start(integer total_number)    {            if (gtouch == 0)  // Starting quiz with a new person        {            t = 1; // Stop Rotation by setting t = 1            llSetPrimitiveParams( [ PRIM_GLOW, ALL_SIDES, .0 ] );            llSetText("Simulation in Progress", <1.0, 0.0, 0.0>, 1.0);                        if(IsNameOnList(gAvList,llDetectedName(0)))            {                llInstantMessage(llDetectedKey(0),"Sorry, "+ llDetectedName(0) + ". You have already taken the quiz. You cannot take it twice.");                return;            }            else            {                gAvList += llDetectedName(0); // Add av to the list of people who have attempted this quiz            }            gAv = llDetectedName(0);            gAvKey = llDetectedKey(0);            llInstantMessage(gAvKey,"Hello " +gAv+ "! Welcome to the Smart Alarm Simulation - Scenario #3 (Lead partially dislodged)!\n\n");           // llInstantMessage(gAvKey, "You will have "+(string)Timespan+" minutes to finish this Simulation. Respond to choices as they appear in dialog boxes on the top right corner of your screen.");            llInstantMessage(gAvKey,"Click the symbol again if you want to stop the simulation before it is finished.\n");            llSetTimerEvent(Timespan*60);        }        if (gAv != llDetectedName(0)) //Only accept touches from this av until the quiz is finished        {            llInstantMessage(llDetectedKey(0),"Someone else is experiencing the simulation now.  Please wait.");            return;        }        if (gtouch >=1) // This is the emergency stop. Av wants to stop taking the quiz before the last question        {            llListenControl(Handle,TRUE);            llDialog(gAvKey,"Do you want to QUIT now?", ["YES", "NO"],CHAN);            return;        }        // An av should only reach this point if it is the first touch        gQID = llGetNotecardLine(gCard,gLine); //Read the first line of the notecard        ++gtouch;    }    changed(integer change)    {        if(change & CHANGED_INVENTORY)        {            llResetScript();        }    }timer(){    llInstantMessage(gAvKey,"Your time is up. Thank you for trying Smart Alarm Scenario #3.");// Your score is " + (string)gScore);    llSay(-3000, "DONE");       // llEmail(gMailAddr, gAv+" Simulation Score", "Simulation Score is "+ (string)gScore);    init(); //Restart the quiz for the next person}dataserver(key query_id, string data){    if(query_id == gQID) //If the data request came from this script    {        if(data != EOF) //If there is still data to be read from the notecard        {            if(llGetSubString(data,0,0) == "#"||llGetSubString(data,0,0) == "") //Ignore comment lines and blank lines            {                ++gLine;                gQID = llGetNotecardLine(gCard,gLine);            }            else if (llGetSubString(data,0,0) == "Q") //Read the question and all answer choices            {                gQuestion += llGetSubString(data,1,-1) + "\n"; //Format each "Q" line as a new line in the dialog box                ++gLine;                gQID = llGetNotecardLine(gCard,gLine);                            }            else if (llGetSubString(data,0,0) == "A") //Read the answer key            {                gAnswers = llParseString2List(llGetSubString(data,1,-1),[","],[]);                integer len = llGetListLength(gAnswers);                integer i;                list buttons = [];                for (i=1;i<=len;++i) //Create a numbered button for each choice                {                    buttons += [(string)i];                }                llListenControl(Handle,TRUE);                llDialog(gAvKey,gQuestion,["Done"],CHAN); //Display the question in a dialog box            }            else if (llGetSubString(data,0,0) == "N") //Read the answer key            {                gAnswers = llParseString2List(llGetSubString(data,1,-1),[","],[]);                integer len = llGetListLength(gAnswers);                integer i;                list buttons = [];                for (i=1;i<=len;++i) //Create a numbered button for each choice                {                    buttons += [(string)i];                }                llListenControl(Handle,TRUE);                llDialog(gAvKey,gQuestion,["Next"],CHAN); //Display the question in a dialog box            }            else if (llGetSubString(data,0,0) == "B") //Read the answer key            {                gAnswers = llParseString2List(llGetSubString(data,1,-1),[","],[]);                integer len = llGetListLength(gAnswers);                integer i;                list buttons = [];                for (i=1;i<=len;++i) //Create a numbered button for each choice                {                    buttons += [(string)i];                }                llListenControl(Handle,TRUE);                llDialog(gAvKey,gQuestion,["Yes", "No"],CHAN); //Display the question in a dialog box            }                            else if (llGetSubString(data,0,0) == "C") //Read the answer key            {                gAnswers = llParseString2List(llGetSubString(data,1,-1),[","],[]);                integer len = llGetListLength(gAnswers);                integer i;                list buttons = [];                for (i=1;i<=len;++i) //Create a numbered button for each choice                {                    buttons += [(string)i];                }                llListenControl(Handle,TRUE);                llDialog(gAvKey,gQuestion,["Awesome!"],CHAN); //Display the question in a dialog box            }             }                         else // If there are no more lines on the notecard        {            llInstantMessage(gAvKey,"You have finished Smart Alarm Scenario #3!");// Your score is "+(string)gScore);            llSay(-3000, "DONE");                     init(); //Restart the quiz for the next person        }    }}listen (integer channel, string name, key id, string message){    if (channel == 24) //Teacher said something on channel 24    {        if (llToLower(message) == "results") //and the message was "results"        {            integer len = llGetListLength(gAvList);            integer i;            for (i=0;i<=len-1;++i)            {                llOwnerSay(llList2String(gAvList,i) +  "....  Score = " + llList2String(gAllScores,i+1));            }        }    }    else if (message == "YES") // Av has touched the panel and wants to quit    {        llInstantMessage(gAvKey,"Thank you for trying out Smart Alarm Scenario #3!" );        llSay(-3000, "DONE");        init();    }    else if(message == "NO") // Av has touched the panel and does NOT want to quit    {        return;    }    else // A question has been displayed in a dialog box    {        integer pos = llListFindList(gAnswers,["1"]); //Search the answer key. The correct answer is pos+1        if((message == "Next") || (message == "Yes") || (message == "Done"))//(string)(pos+1))        {           ++countQues;           // llPlaySound("correct",1.0);           // llInstantMessage(gAvKey,"Correct! Your score is now "+ (string)gScore+ ". Next ...");                    }             if(countQues == 4)                {                    llSay(-3000, "appear"); // For Handset                }                            if(countQues == 3)                {                    llSay(-3000, "occuring");                }                             if(countQues == 1)                {                    llSay(-3000, "show"); // For Wristband                }           else if (message == "No")        {            // llPlaySound("WrongAnswer",1.0);           llInstantMessage(gAvKey,"Incorrect, please re-start Smart Alarm Scenario #3." );            llSay(-3000, "DONE");            init();        }        /*else if (pos == -1) //The teacher screwed up and didn't code a correct answer        {           // llInstantMessage(gAvKey,"Ooops! There is no right answer to this question. Let's move on....");        }*/        gQuestion = ""; //Erase the current question        gAnswers = []; //And its answer key        ++gLine;        gQID = llGetNotecardLine(gCard,gLine); // Get the next question    }}}

 

Share this post


Link to post
Share on other sites

I don't have time to go through and debug the entire script, but a few things pop out right away.  First, I'm not surprised that the dialog boxes disappear when you answer "NO".  That 's what I would expect, since you wrote

    else if(message == "NO") // Av has touched the panel and does NOT want to quit    {        return;    }

When the script reaches return, it will jump out of the listen event and never see the lines at the end of the event that initiate the reading of new question and then set up a new dialog.  I don't immediately see why it's asking the last question again if you abort, but maybe I am misunderstanding your problem.

There are several other issues, though, some of which might be at the root of your problem.  In the dataserver event, your write that if the first character in the line just read is "A", "N", "B", or "C", the script is supposed to load a list called "buttons".  You never use that information, however. Instead, for the various options you have dialog buttons labeled "Yes", "No", DONE", Next", and "Awsome!". 

Less important to this issue, but puzzling, is the code at the end of the init() routine that says

            do { llSetPrimitiveParams( [ PRIM_GLOW, ALL_SIDES, .3 ] );}            while(t = 0);

I don't see any purpose for the do loop, which never ends anyway because t never changes value.  Even if it did change, PRIM_GLOW only changes once, and then init() ends.

Overall, you have made substantial changes to the logic of the script you started with, so it's not surprising that you are getting some unexpected results.  The best strategy when you are working on something like this is to make changes slowly -- a few at a time -- rather than tackling the whole thing at once.  Then, when it blows up in your face, it's easier to guess what caused the problem.  At this point, you should probably start inserting diagnostic llOwnerSay statements at key points in the script to see whether variables have the values that you think they do.

Share this post


Link to post
Share on other sites


steph Arnott wrote:

I try to figure out the script logic and bugs and my brain crashed.

LOL

 

I stayed awake last night trying to figure out who/what was listening to channel -3000 and for why.

Share this post


Link to post
Share on other sites

I think Pandora's Box has been opened here. :smileysurprised:

 

I'd suggest the OP start learning LSL with something much simpler and work their way up to this level of complexity. Otherwise, I'm afraid they're going to get so frustrated they'll quit trying.

Share this post


Link to post
Share on other sites

I agree, LepreKhaun.  That script can probably be modified to do what the OP wants, but if I were doing it myself, I'd start from scratch rather than trying to retrofit. (Actually, if I were writing the basic script again, I'd do it differently too.  But that's another story.)

Share this post


Link to post
Share on other sites

:matte-motes-big-grin: Sorry for not fully explaining. Any channels at "-3000" in the script are for either listening or talking to other objects in my scenarios. There are a lot of messages going back and forth which makes it pretty confusing.

I have a fix for when the questions would appear out of order upon restarting the quiz. I place llResetScript(); in after the init() function whenever the quiz is finished (either by quitting, or running out of lines). That'll reset the script entirely and there won't be leftover questions that appear.

I also have a fix for the dialog box disappearance after clicking "no". I placed the following code within the conditional statement when (the message == "no" // Av has touched the panel and does NOT want to quit).

 

 else if(message == "NO") // Av has touched the panel and does NOT want to quit    {       if (checkAnswer == "D") {llDialog(gAvKey,gQuestion,["Done"],CHAN);}       if (checkAnswer == "N") {llDialog(gAvKey,gQuestion,["Next"],CHAN);}       if (checkAnswer == "A") {llDialog(gAvKey,gQuestion,["Awesome"],CHAN);}    }

checkAnswer is a string which sets its value equal to a letter representing the answer key name for the current question: 'D' for Done, 'N' for Next, etc...

If the current question you're on has a "Done" answer for instance, when you click "no" after attempting to quit the quiz, it'll display that question again correctly (with a "Done" answer) because the script knows the answer key for that question. Hopefully that makes since :)

Share this post


Link to post
Share on other sites

It makes sense.  Congratulations.  :smileywink:

There's still cleanup to do, but if the script does what you expect it to do, that's 9/10 of the challenge.

Share this post


Link to post
Share on other sites
You are about to reply to a thread that has been inactive for 2445 days.

Please take a moment to consider if this thread is worth bumping.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this  

×
×
  • Create New...