Difference between revisions of "User:Rolig Loon/High-Capacity Greeter-Counter"

From Second Life Wiki
Jump to navigation Jump to search
Line 117: Line 117:
                 if(llGetInventoryNumber(INVENTORY_NOTECARD))
                 if(llGetInventoryNumber(INVENTORY_NOTECARD))
                 {
                 {
                     llGiveInventory(llDetectedKey(0),llGetInventoryName(INVENTORY_NOTECARD,0));
                     llGiveInventory(llDetectedKey(i),llGetInventoryName(INVENTORY_NOTECARD,0));
                 }
                 }
             }
             }

Revision as of 16:25, 29 March 2010

Features

Uses a memory compression algorithm to store hashed visitor UUID's in a string instead of using a list, thus avoiding the extra memory overhead associated with lists as well as reducing the UUID to a 3-character element in that string. See notes in the script and the reference to Becky Pippen's User page for a description of the technique.

  • Records unique visitors only.
  • Offers a notecard to unique visitors, if a notecard has been placed in inventory.
  • Provides the current weekly count, if requested by chat command on channel 37.
  • Optionally, provides the owner with a week-end report of the total number of visitors that week.
  • Stores the weekly total each week in the object's Description field, which will survive if the script is reset for any reason or if the object is taken to the owner's inventory.

Script

<lsl>//High-Capacity greeter/counter -- Rolig Loon -- March 2010 //Incorporating a memory compression algorithm by Becky Pippen (https://wiki.secondlife.com/wiki/User:Becky_Pippen/Hashing) //Please keep all notes intact, including this header.

// Records unique visitors only, not repeaters. Stores the weekly count in the object's Description field and (optionally) sends a report to the owner

// Commands on channel 37: "list" gives the current traffic count since the previous Saturday midnight // "reports" toggles the weekly report to the owner on or off

// If there is a notecard in inventory, the counter will offer it on a visitor's first encounter.

integer count; integer restart = TRUE; integer TellOwner = TRUE; string hashedNames; integer hashSize = 3;

string getDay() {

   list weekdays = ["Thursday", "Friday", "Saturday", "Sunday", "Monday", "Tuesday", "Wednesday"];
   integer hours = llGetUnixTime()/3600;
   integer days = (hours -4)/24;
   integer day_of_week = days%7;
   return llList2String(weekdays, day_of_week);

}

string encode15BitsToChar(integer num) {

   num = 0x1000 + (num & 0x00007fff);
   return llUnescapeURL(
       escapeHexChar(0xe0 + (num >> 12)) +
       escapeHexChar(0x80 + ((num >> 6) & 0x3f)) +
       escapeHexChar(0x80 + (num & 0x3f)));

}

string escapeHexChar(integer n) {

   string hexChars = "0123456789abcdef";
   return "%" +
       llGetSubString(hexChars, n >> 4, n >> 4) +
       llGetSubString(hexChars, n & 0xf, n & 0xf);

}

default {

   state_entry(){
       llSensor( "", "", AGENT, 25.0, PI );
       llSetTimerEvent( 30.0 );
       llListen(37,"","","");
   }
   listen(integer channel, string name, key id, string msg)
   {
       if (llToLower(msg) == "list")
       {
           llSay(0, "We have had " + (string)count + " unique visitors since midnight last Saturday.");
       }
       else if (llToLower(msg) == "reports") // Toggles weekly report to owner on /off
       {
           TellOwner = !TellOwner;
       }
   }
   timer()
   {
       if (getDay() == "Sunday" && restart == TRUE)
       {
           llSetObjectDesc(llGetObjectDesc() + ","+(string)count);
           if(TellOwner)
           {
               llInstantMessage(llGetOwner(),"The count for the week is " + (string)count);
           }
           count = 0;
           restart = FALSE;
       }
       else if (getDay() == "Monday")
       {
           restart = TRUE;
       }
       llSensor( "", "", AGENT, 25.0, PI );
   }
   sensor( integer vIntTtl )
   {
       integer i;
       for (i=0;i<= vIntTtl; ++i)
       {
           if ((llStringLength( hashedNames ) * 4.2) > llGetFreeMemory()) // In case memory gets tight
           {
               hashedNames = llGetSubString(hashedNames,3,-1);
           }
           string AvKey = llDetectedKey(i);
           string md5 = llMD5String(AvKey, 0);
           integer n1 = (integer)("0x" + llGetSubString(md5, 0, 7));
           integer n2 = (integer)("0x" + llGetSubString(md5, 8, 11));
           string encoded3Chars =
               encode15BitsToChar(n1 >> 16) +
               encode15BitsToChar(n1) +
               encode15BitsToChar(n2);
           integer idx = llSubStringIndex(hashedNames, encoded3Chars);
           if (idx == -1) 
           {
           // this is a new one, so save it and send a notecard, if there is one
               hashedNames += encoded3Chars;
               ++count;
               if(llGetInventoryNumber(INVENTORY_NOTECARD))
               {
                   llGiveInventory(llDetectedKey(i),llGetInventoryName(INVENTORY_NOTECARD,0));
               }
           }
       }
   }

}</lsl>