Difference between revisions of "User:Rolig Loon/Quiz From Notecard"

From Second Life Wiki
Jump to: navigation, search
(Created page with '<lsl> //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. // Mod...')
(No difference)

Revision as of 10:46, 22 February 2010

<lsl> //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 scores

string gCard; //Notecard name integer gLine; //Current line being read key gQID; //Dataserver key integer gtouch; //Activates/deactivates touch_start event list gAvList = []; //Cumulative list of people who have taken this quiz string gAv; //Name of the current quiz-taker key gAvKey; //Key of the current quiz-taker integer CHAN; //Channel for dialog communication integer Handle; //Listen handle for dialog integer gScore; //This quiz-taker's score string gQuestion; //Text for the current question list gAnswers; //Answer key for the current question list gAllScores = []; //Cumulative list of scores for quiz-takers integer Timespan = 10; // [highlight]This is the maximum time alloted for the quiz, in minutes. Change here if needed.[/highlight]

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) == name)
       {
           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;
   llListenControl(Handle,FALSE);

}

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
       {
           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+ ". You will have "+(string)Timespan+" minutes to finish this quiz. Respond to questions as they appear in blue dialog boxes on your screen.");
           llInstantMessage(gAvKey,"Touch this panel again to stop the quiz.");
           llSetTimerEvent(Timespan*60);
       }
       if (gAv != llDetectedName(0)) //Only accept touches from this av until the quiz is finished
       {
           llInstantMessage(llDetectedKey(0),"Someone else is taking the quiz 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,"If you stop now, you may not restart later. \nDo 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 taking the quiz. Your 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,order_buttons(buttons),CHAN); //Display the question in a dialog box
           }
       }
       else // If there are no more lines on the notecard
       {
           llInstantMessage(gAvKey,"You have finished the quiz. Congratulations. Your score is "+(string)gScore);
           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,"You have left the quiz with a score of "+(string)gScore +". Goodbye!");
       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 == (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....");
       }
       gQuestion = ""; //Erase the current question
       gAnswers = []; //And its answer key
       ++gLine;
       gQID = llGetNotecardLine(gCard,gLine); // Get the next question
   }

} } </lsl>