User:Rolig Loon/Quiz From Notecard: Difference between revisions
Rolig Loon (talk | contribs) 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...' |
Rolig Loon (talk | contribs) No edit summary |
||
| Line 1: | Line 1: | ||
{{LSL Header}} | |||
A multiple-choice testing script that reads questions and answer choices from a notecard and presents them in dialog boxes. | |||
=== Features === | |||
* Allows only one student at a time to take the quiz. | |||
* Gives immediate feedback to the student when a dialog button is pushed. | |||
* Does not allow student to retake the quiz. | |||
* Stores quiz scores and gives instructor a report on chat command. | |||
* Quiz can be timed. | |||
=== Script === | |||
<lsl> | <lsl> | ||
//A Dialog-driven quiz, using text from a notecard -- Rolig Loon -- October 2009 | //A Dialog-driven quiz, using text from a notecard -- Rolig Loon -- October 2009 | ||
| Line 48: | Line 61: | ||
list gAnswers; //Answer key for the current question | list gAnswers; //Answer key for the current question | ||
list gAllScores = []; //Cumulative list of scores for quiz-takers | list gAllScores = []; //Cumulative list of scores for quiz-takers | ||
integer Timespan = 10; // | integer Timespan = 10; // This is the maximum time alloted for the quiz, in minutes. Change here if needed. | ||
integer IsNameOnList(list namelist, string name) //Verifies whether av has already taken the quiz | integer IsNameOnList(list namelist, string name) //Verifies whether av has already taken the quiz | ||
Revision as of 10:56, 22 February 2010
| LSL Portal | Functions | Events | Types | Operators | Constants | Flow Control | Script Library | Categorized Library | Tutorials |
A multiple-choice testing script that reads questions and answer choices from a notecard and presents them in dialog boxes.
Features
* Allows only one student at a time to take the quiz. * Gives immediate feedback to the student when a dialog button is pushed. * Does not allow student to retake the quiz. * Stores quiz scores and gives instructor a report on chat command. * Quiz can be timed.
Script
<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; // This is the maximum time alloted for the quiz, in minutes. Change here if needed.
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>