Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

llGetLinesInNotecard(string notecard)

Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
06-30-2003 18:07
I really want something like this, looping with llGetNotecardLine is very unreliable IMO, and an llGetLinesInNotecard would at least help with that...

Im very against the dataserver() event, I hope it gets faster/gets removed/ functions get revised in the future to not use the dataserver.

I wrote up a script to get the lines in a notecard, it bugs out if there are any empty lines in the notecard, and its pretty slow to respond with long notecards (has to go through every line).


Here it is:

CODE
 
key request;
integer count;
string name;

GetLinesInNotecard(string notecard)
{
request = llGetNotecardLine(notecard,count);
}

default
{
state_entry()
{
name = llGetInventoryName(INVENTORY_NOTECARD,0);
GetLinesInNotecard(name);
}
dataserver(key id, string data)
{
if(id == request)
{
if(data != EOF && data != "")
{
count++;
GetLinesInNotecard(name);
}
else if(data == EOF || data == "")
{
if(count == 0) llSay(0,"Empty notecard.");
else llSay(0,(string)count + " line(s) in notecard.");
}
}
}
}


I hope I didnt make any typos :rolleyes: .

Again, using this really sucks, since it usually takes long to get an answer out of it.

Lindens, please implement something better, or if anyone has anything else that is better please post. Feel free to use my script here any way you want, just give me a 'lil credit ;) .

-Chris

(Nada, if this is fit for the script library please say so, id gladly post there, except because of the kind-of-buggyness of this one I decided against it initially.)
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Jake Cellardoor
CHM builder
Join date: 27 Mar 2003
Posts: 528
06-30-2003 20:59
A possible workaround would be to adopt a convention where the first line of the notecard is an integer representing the number of lines in the card. It's not a good workaround if you expect naive users to be writing/editing notecards, but it might be suitable in certain situations.
Ama Omega
Lost Wanderer
Join date: 11 Dec 2002
Posts: 1,770
06-30-2003 22:15
CODE
integer count;
string name;

default
{
state_entry()
{
name = llGetInventoryName(INVENTORY_NOTECARD,0);
llGetNotecardLine(name,0);
}
dataserver(key id, string data)
{
if(id == request)
{
if(data != EOF)
{
count++;
llGetNotecardLine(name,count);
}
else if(data == EOF)
{
if(count == 0) llSay(0,"Empty notecard.");
else llSay(0,(string)count + " line(s) in notecard.");
}
}
}
}


I didn't change much. But here is what I would argue:
- A blank line is still a line and not necessarily the end of the card. So treat it like all the other lines.
- You don't need to worry about request ids unless you are doing other data_server queries while this is going on. And it will do things in order. Why? Because you don't even ask for the next one until you got the one you already asked for. You are basically saying "Get a Line, Got it, Get next, Got it, Get next, Got it" there is no way for it to get out of order. If you were asking for the next line in any place besides the data_server event then there might be the possibility. But as written there isn't.

I removed the method just to make it shorter, but there is no reason you can't have it.

And I agree a method to get the number of lines in a notecard is greatly needed. :)
Alondria LeFay
Registered User
Join date: 2 May 2003
Posts: 725
07-01-2003 06:21
Hmmm... I think a script that guesses the number of lines and then adjusting it guess would be faster (besides perhaps really small notecards). Basically have it guess 10, if EOF, guess 5, if EOF guess 3, etc..
OF course the inverse is true also, if 10 != EOF, guess 20, if != EOF, guess 30. I'll work on some code after work and run some speed tests.
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
07-01-2003 16:33
Alondria, I thought something like that may work, but... as Ive found in my little limited experiance with LSL, is that when scripts guess psuedo random numbers, the solutions tend to be *way* out there... With hugely long notecards, I think yours would probobally work better, but if a notecard is three lines long, with my script it only needs to cycle 4 times (3 and one for the EOF).
With your idea It would guess 100... EOF, 90... EOF, 40...EOF, 10... EOF, 5... EOF, 2 would get a responce, but then it might guess 1... get anothe responce, then guess 4, and get another EOF... I mean, IMO I think that takes alot more steps... unless you find some sort of algorithim to make LSL a bit wiser.

TY SO MUCH FOR THE REVISION AMA :-D. I had the method in there just for aesthetic purposes... the reason for the "" was because if the notecard is empty, the dataserver() event still returns ""... when it should return EOF (IMO).

Edit: oopsie... it does return EOF :rolleyes:

Edit Edit: Nope, it doesnt return EOF, next reply will be a revised script.

(I had taken a break from a scripting frenzy to write the script I posted yesterday, so my brain's logic circuit was still sizzling...) :D

-Chris
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Christopher Omega
Oxymoron
Join date: 28 Mar 2003
Posts: 1,828
07-01-2003 16:52
A combo of Ama's and my script:

CODE

string name;
integer count;

default
{
state_entry()
{
name = llGetInventoryName(INVENTORY_NOTECARD,0);
llGetNotecardLine(name,0);
}
dataserver(key id, string data)
{
if(data != EOF)
{
if(count == 0 && data == "") llSay(0,"Empty Notecard.");
else
{
count++;
llGetNotecardLine(name,count);
}
}
else if(data == EOF)
{
if(count != 0) llSay(0,(string)count + " line(s) in notecard.");
}
}
}


Now the only problem with this is that it repeats itself if the notecard isnt empty... if it has one line it says:

"1 line(s) in notecard."
"1 line(s) in notecard,"

Anyone know whats wrong?

-Chris :confused:
_____________________
October 3rd is the Day Against DRM (Digital Restrictions Management), learn more at http://www.defectivebydesign.org/what_is_drm
Alondria LeFay
Registered User
Join date: 2 May 2003
Posts: 725
07-01-2003 17:15
Yikes! Setting 100 to max is way beyond where I would think would be necessary. I figure the average notecards (of course this depends upon application) would be between ten an twenty. When I say guess, that may not be accurate, but rather algarythmically. For example, say a script has 13 lines.

Hit 1 of 10, in range,
Hit 2 of 20, out of range.
Hit 3 of 15, out of range.
Hit 4 of 13, in range.
Hit 5 of 14, out of range.

Since the difference betwen the in and out of range is 1 at the last test, 13 is determined... 5 hits versus 14.

A smaller example lets take your suggestion of 3.

Hit 1 of 10, out of range.
Hit 2 of 5, out of range.
Hit 3 of 3, in range.
Hit 4 of 4, out range...

Once again, since 4 was determined out of range, and 3 was determined in range, 3 would be declaired. This time it breaks even, 4 hits versus 4 hits.


The only time the sequential search would be faster is for scripts of 2 lines or less, which is a small minority....

Code to follow (after IW testing).
Jake Cellardoor
CHM builder
Join date: 27 Mar 2003
Posts: 528
07-01-2003 18:54
From: someone
Originally posted by Christopher Omega
Now the only problem with this is that it repeats itself if the notecard isnt empty... if it has one line it says:

"1 line(s) in notecard."
"1 line(s) in notecard,"

Anyone know whats wrong?


In my experience, the dataserver event often returns EOF twice at the end of a notecard. I dealt with it by setting a global flag the first time I receive an EOF, and then checking for it the next time.
Ama Omega
Lost Wanderer
Join date: 11 Dec 2002
Posts: 1,770
07-01-2003 23:10
Yes Alondra that is a great way to do it - a binary search! :D

Here is my untested version. ;) I wrote it up in textpad heh. I think it works though. It looks longer than it is cuz I filled it with comments.

[edit]Ok the below code is crap. It reports several list lengths. I finally got it to only report one if I jumped to a different state. However it wasn't always right. Hence the code is crap. Why am I leaving it here? Maybe Chris or Alondra or someone can fix it. Hehehehehehe. I gotta get to bed though so good luck.

;)

CODE
integer inc = 10; // to easily adjust.

string name;
integer count;
integer prevCount = 30;
integer tempCount;

default
{
state_entry()
{
name = llGetInventoryName(INVENTORY_NOTECARD,0);
llGetNotecardLine(name,count);
}
dataserver(key id, string data)
{
// Save count because we want to save it to prevCount
// But we need to use prevCount now, so hold it til end.
tempCount = count;

// The line was found! Not far enough.
if(data != EOF)
{
// If the we just moved back 1 and found a line we are done.
if ( count + 1 == prevCount )
{
llWhisper(0,(string)count + " lines in notecard " + name);
}

// If count < prevCount we went back and found a line
else if ( count < prevCount )
{

// Set inc to half difference
inc = inc / 2;

// Move up by inc
count += inc;

// Check for line
llGetNotecardLine(name,count);
}

// If count < prevCount we still have valid, keep moving up.
else if ( count > prevCount )
{
count += inc;
llGetNotecardLine(name,count);
}

// All that is left is they are equal. Shouldn't happen.
// If it does we move up one and try again.
else if (count == prevCount )
{
inc = 1;
count++;
llGetNotecardLine(name,count);
}
}

// No line found, went too far.
else if(data == EOF)
{
tempCount = count;

// If we just moved up 1 line we must have found a line before so done.
if ( count - 1 == prevCount )
{
llWhisper(0,(string)count + " lines in notecard " + name);
}

// If count < prevCount we didn't find before and still didn't find.
// So move down again.
else if ( count < prevCount )
{
count -= inc;
llGetNotecardLine(name,count);
}

// If count > prevCount we found a line last time, but not this time.
// Cut inc in half and move back down half the difference
else if ( count > prevCount )
{
inc = inc / 2;
count -= inc;
llGetNotecardLine(name,count);
}

// Only left if they are equal.
// Shouldn't happen, but if it does go back one
// The first case in (data != EOF) will catch it.
else if ( count == prevCount )
{
inc = 1;
count -= inc;
llGetNotecardLine(name,count);
}

prevCount = tempCount;
}
prevCount = tempCount;
}
}