User talk:Rolig Loon/HUD: Record Volunteer Service

From Second Life Wiki
Jump to: navigation, search

Overview

I created this pair of scripts for use by volunteers at the library reference desk on Info Island International or elsewhere in SL. As it is attached, the HUD offers its user an opportunity to position it anywhere on the screen with the use of simple dialog box controls. Thereafter, the only control a user needs is a one-prim button that acts as an ON/OFF toggle. (I distribute the HUD script in a 0.05m diameter cylindrical button that attaches to the Bottom attachment point.) Clicking the control button turns it from red to green and sends a logon message (time and Region) to the companion server script. Clicking it again (or detaching the HUD, or going off line) turns the button red and sends a logoff message.

The server script receives messages from user HUDs and passes the information to an external PHP server which maintains an SQL database and prepares a statistical report on demand. I have removed both the server key and the URL of our external server from the scripts on this page, replacing them with descriptive placeholders.

This HUD system is in use by approximately 50 library volunteers. It maintains a record of the total hours that each volunteer has served in world and can be used to help the duty librarian at the reference desk know which other volunteers are currently logged in and where they logged in from. Statistical summaries from the external server are valuable as we prepare reports for RL agencies and apply for grant funding.

The HUD Script

<lsl> //SLLVR OnDuty System Client //Rolig Loon, December 2008 // //==========================================WARNING=================================================== //=======DO NOT MESS WITH ANYTHING BELOW THIS LINE======================================= string serverKey = "The Server's UUID goes here";//What the server whispers when you put the script in the server or reset it. integer ON; string statflag; vector CurrPos; integer CHANNEL = -57; //Emergency chat override to reset the server key if necessary list buttons = ["Done","Up","Down","Left","Right", "Rotate"]; integer dialog; integer move; init() {

   dialog = llListen(CHANNEL,"",NULL_KEY,"");
   move = llListen(99,"",llGetOwner(),"");

} setCur() {

   llDialog(llGetOwner(), "Can't see the HUD?" + "\n\n Move it with direction buttons." + "\n Click \"Done\" to end setup.", buttons, CHANNEL);
   CurrPos = llGetLocalPos();

}

default {

   on_rez(integer param)
   {
       llInstantMessage(llGetOwner(), "Welcome to the SLLVR system, " + llKey2Name(llGetOwner()) + ". Initalizing ...");
       init();
       llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5]);
       ON = -1;
   }
   state_entry()
   {
       ON = -1;
       init();
   }
   touch_start(integer num_detected)
   {
       if (ON == (-1))
       {
           llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <0, 1, 0>, 0.5]);
           statflag = "a";
           ON = -ON;
           llInstantMessage(llGetOwner(),"Hello, " + llKey2Name(llGetOwner()) + "! Connecting ... ");
       }
       else if (ON == 1)
       {
           llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5]);
           statflag = "z";
           ON = -ON;
           llInstantMessage(llGetOwner(),"Thank you for your volunteer service today, " + llKey2Name(llGetOwner()) + ". Disconnecting ... ");
       }
       llEmail(serverKey + "@lsl.secondlife.com", llKey2Name(llGetOwner()) + "|" + llGetRegionName() + "|"  + statflag, (string)llGetOwner());
       if (ON == 1)
       {
           llInstantMessage(llGetOwner(),"... You are now logged in as a reference library volunteer.");
       }
       else if (ON == (-1))
       {
           llInstantMessage(llGetOwner()," ... You have been logged out of the SLLVR system.");
       }
   }
   listen(integer channel, string name, key id, string message)
   {
       list temp = llParseString2List(message,["="],[]);
       string tag = llToLower(llStringTrim(llList2String(temp,0),STRING_TRIM));
       if (llToLower(message) == "help")
       {
           llSetPos(<0.0,0.0,0.0>);
           llSetLocalRot(ZERO_ROTATION);
           setCur();
       }
       else if (message == "Done")
           {
               llListenRemove(dialog);
               llListenRemove(move);
               return;
           }
           else if (message == "Right")
           {
               llSetPos(CurrPos + <0.0,-0.1,0.0>);
               setCur();
           }
           else if (message == "Left")
           {
               llSetPos(CurrPos + <0.0,0.1,0.0>);
               setCur();
           }
           else if (message == "Up")
           {
               llSetPos(CurrPos + <0.0,0.0,0.1>);
               setCur();
           }
           else if (message == "Down")
           {
               llSetPos(CurrPos + <0.0,0.0,-0.1>);
               setCur();
           }
           else if (message == "Rotate")
           {
               rotation y_90 = llEuler2Rot( <0, 90 * DEG_TO_RAD, 0> );
               rotation new_rot = y_90 * llGetLocalRot();
               llSetRot(new_rot);
               setCur();
           }
       else if (tag == "newkey")
       {
           serverKey = llToLower(llStringTrim(llList2String(temp,1),STRING_TRIM));
       }
   }
   attach(key attached)
   {
       if (attached == NULL_KEY)
       {
           llEmail(serverKey + "@lsl.secondlife.com", llKey2Name(llGetOwner()) + "|" + llGetRegionName() + "|z", (string)llGetOwner());
           llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5]);
           ON = -1;
       }
       else
       {
           llInstantMessage(llGetOwner(),"To adjust this HUD, type \" /99 help \"."); 
           llSetPrimitiveParams([PRIM_COLOR, ALL_SIDES, <1, 0, 0>, 0.5]);
           ON = -1;
           llSetTimerEvent(300.0);
       }
   }
   timer()
   {
       llListenRemove(dialog);
       llListenRemove(move);
       llSetTimerEvent(0.0);
   }

} </lsl>

The Server Script

<lsl> //SLLVR Server // Rolig Loon, December 2008

// Manages remote login data from SLLVR client users

list ActiveUsers = []; list messageList = []; string When = ""; string IsOn = ""; string body = ""; string ServerKey = ""; integer logged_time; integer keyCurrent; integer timerflag; key http1 = NULL_KEY; key http2 = NULL_KEY; key http3 = NULL_KEY; key gRequest = NULL_KEY; string URL = " ....... /set.php?pass=Key-1D&obj=SLLVRServer&id="; //Sends server Key to the external server for storage string URLin = "..... /login.php?pass=volunteer&name="; // Receives logon information string URLout = "..... /logout.php?pass=volunteer&name="; // Receives logoff information

init() {

   ServerKey = (string)llGetKey();
   URL = URL + ServerKey;
   llOwnerSay(ServerKey + "  " + URL);
   http3 = llHTTPRequest(URL,[HTTP_METHOD, "POST"],"");
   llSetObjectDesc(ServerKey);
   llWhisper(0, "/3781 newkey = " + ServerKey);

}

default {

   on_rez(integer start_param)
   {
       init();
   }
   state_entry()
   {
       llSetTimerEvent(3.0);//Poll for emails.
       timerflag = 1;
   }
   timer()
   {
       if (timerflag == 1)
       {
           llGetNextEmail("","");
           timerflag = -timerflag;
           if(llGetFreeMemory() < 100)
           {
               llInstantMessage(llGetOwner(), "/me is running low on available memory, script is resetting in 5 seconds.");
               llSleep(5);
               llResetScript();
           }
       }
       else if (timerflag == -1)
       {
           timerflag = -timerflag;
           state signoff;
       }
   }
   email(string time, string address, string subj, string message, integer num_left)
   {
       llOwnerSay(subj);
       integer timein = (integer)llGetWallclock(); // seconds since midnight SLT
       list messageList = llParseString2List(subj, ["|"], []);
       string User =  llList2String(messageList,0);
       string avatar_name = User;
       string where = llList2String(messageList,1);
       string IsOn = llList2String(messageList,2);
       key inputUser = llDeleteSubString(message, 0, llSubStringIndex(message, "\n\n") + 1);
       if (IsOn == "a")
       {
       ActiveUsers = ActiveUsers + [User, inputUser, where, timein];
       string sendthis = User + "|" + where + "|" + (string)timein; //Avatar name|location|time logged in
       llOwnerSay("Joining: " + sendthis);
       //            integer k;
       //            for (k=0;k<=4;k++)
       //            {llOwnerSay("ActiveUsers("+(string)k+") = " + llList2String(ActiveUsers,k));}
       http1 = llHTTPRequest(URLin + avatar_name + "&location=" + where ,[HTTP_METHOD, "POST"],""); // Send the data string to URL
       }
       else if (IsOn == "z")
       {
           integer temp1 = llListFindList(ActiveUsers, [User]);
           integer When = (integer) llList2String(ActiveUsers,temp1+3);
           integer now = (integer)llGetWallclock();
           logged_time = now - When;
           llOwnerSay((string)now + " " + (string)When + " "+ (string)logged_time);
           if (now <= When)
           {
               logged_time = logged_time + 86400;
           }
           string sendthis = User + "|" + (string) logged_time + "|" + llGetTimestamp(); //Avatar name|lapsed time on duty(secs)|date and time logged off
           llOwnerSay("Leaving: " + sendthis);
           // The timestamp is in the format YYYY-MM-DDThh:mm:ss.ff..fZ The date and time are GMT, not SLT.
           http2 = llHTTPRequest(URLout + avatar_name,[HTTP_METHOD, "POST"], ""); //Send the data string to URL
           ActiveUsers = llDeleteSubList(ActiveUsers, temp1, temp1+3);
           }
           if (num_left != 0)
           {
               llGetNextEmail("","");
           }
   }
   touch_start(integer total_number)
   {
       key temp = llDetectedKey(0);
       //        if(llSameGroup(temp) == TRUE)
   {
       integer i;
       integer length = llGetListLength(ActiveUsers);
       for (i = 0; i <= length; i=i+4)
       {
           llSay(0,(string)i + ": " +llList2String(ActiveUsers,i)+ "|" + llList2String(ActiveUsers,i+2) + "|" + llList2String(ActiveUsers,i+3));
       }
   }
   }

}

state signoff {

   on_rez(integer start_param)
   {
       init();
   }
   state_entry()
   {
       integer length = llGetListLength(ActiveUsers);
       keyCurrent = length-3;
       gRequest = llRequestAgentData(llList2String(ActiveUsers, keyCurrent),DATA_ONLINE);
   }
   dataserver(key queryid, string data)
   {
       if (queryid == gRequest)
       {
           if (data == (string)(0))
           {
               string User = llList2String(ActiveUsers, keyCurrent-1);
               string avatar_name = User;
               integer When = (integer) llList2String(ActiveUsers, keyCurrent+2);
               integer now = (integer)llGetWallclock();
               logged_time = now - When;
               if (now <= When)
               {
                   logged_time = logged_time + 86400;
               }
               string sendthis = User + "|" + (string) logged_time + "|" + llGetTimestamp(); //Avatar name|lapsed time on duty(secs)|date and time logged off
               http2 = llHTTPRequest(URLout + avatar_name,[HTTP_METHOD, "POST"], "");//Send the data string to URL
               ActiveUsers = llDeleteSubList(ActiveUsers, keyCurrent-1, keyCurrent+2);
           }
           keyCurrent = keyCurrent - 4;
           if(keyCurrent >= -1)
           {
               gRequest = llRequestAgentData(llList2String(ActiveUsers,keyCurrent),DATA_ONLINE);
           }
           else
           {
               state default;
           }
       }
   }

} </lsl>