Welcome to the Second Life Forums Archive

These forums are CLOSED. Please visit the new forums HERE

cutting output from httprequest (or notecard reader, depends on easiest solution)

Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
09-15-2009 17:55
Hey!

I am trying to get a script to create a menu from an httprequest output (or the same output in a notecard, the easiest and fastest way preferred) But I'm not quite sure how to do.

This is the output I get from the httprequest I make:


25_128_NADJ=450,25,128,30#
50_128_ADJ1024=1450,50,128,1024#
50_128_ADJ512=1200,50,128,512#
50_128_ADJ256=1000,50,128,256#
50_128_NADJ=650,50,128,30#
100_128_ADJ1024=1800,100,128,1024#
100_128_ADJ512=1550,100,128,512#
100_128_ADJ256=1350,100,128,256#
100_128_NADJ=1000,100,128,30#
96_50_ADJ512=1000,50,96,30#
100_96_NADJ=750,100,96,30#
100_96_ADJ256=1100,100,96,256#
100_96_ADJ512=1300,100,96,512#
100_96_ADJ1024=1550,100,96,1024#
50_96_ADJ256=800,50,96,256#
50_96_ADJ512=1000,50,96,512#
50_96_ADJ1024=1250,50,96,1024#
100_64_NADJ=550,100,64,30#
100_64_ADJ256=900,100,64,256#
100_64_ADJ512=1100,100,64,512#
100_64_ADJ1024=1350,100,64,1024#
50_64_NADJ=300,50,64,30#
50_64_ADJ256=650,50,64,256#
50_64_ADJ512=850,50,64,512#
50_64_ADJ1024=1100,50,64,1024#
50_96_NADJ=450,50,96,30#
50_128_25percent=488,50,128,30#


The output is however not cut up like this. It's outputed on one single row.

This is the script I have managed to make so far.

-----

key check_plancost;
string PLANS;
integer PRICE;
integer SLOTS;
integer BITRATE;
integer UPLOAD;
list PLANLIST;

default
{
touch_start(integer total_number)
{
check_plancost = llHTTPRequest("URL_HERE", [ HTTP_METHOD, "GET" ], "";);
}

http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == check_plancost)
{
list temp = llParseString2List(body, ["#"], []);
integer row = 0;
integer length = llGetListLength(temp);
for (; row < length; ++row)
{
// list PLANLIST = [ llList2String(temp, row) ];
llOwnerSay(llList2String(temp, row));
llOwnerSay("..";);
}
string PLANS = llList2String(temp,0);
PRICE = llList2Integer(temp,1);
SLOTS = llList2Integer(temp,2);
BITRATE = llList2Integer(temp,3);
UPLOAD = llList2Integer(temp,4);
llOwnerSay("There are " +(string)length + " entries in the list!";);
//llMessageLinked(LINK_THIS, 0, username, NULL_KEY);
}
}
}
-------------

What I want is to make the plans (temp,0) as a dropdown menu, with each item (everything before "=";) as a button.
And when one button (lets say "25_128_NADJ";) is clicked, a new one should drop down
with the text "You have chosen the a plan with 25 listeners at 128 kbit with 30 mb upload which will cost you 450 Lindens. Is this correct?" and a "yes" and "no" button.
If "Yes is clicked" PLAN, PRICE, SLOTS, BITRATE and UPLOAD should all be set accordingly. If no, the first menue comes back again.

Now, I can do menues, but what I can't figure out how to do, is how to cut up the output as I want, and create menu items from it.

Could someone please help me with the cuttings and creating the "menu buttons list"? I will be bald soon, because I just can't figure out how to do it. :(
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-15-2009 19:12
I think you've already got the idea of using llParseString2List(). You can simply follow the same idea to get any data you want from the string, just using different parsing identifier. The below example shows cutting the data first by separating from a "=", then a second cut by a ",". You can then use the result individual data to make the menus. :)


CODE

string tester_string = "25_128_NADJ=450,25,128,30#";
default
{
state_entry()
{
list body_list = llParseString2List(tester_string, ["="], []);
string body_list0 = llList2String(body_list, 0);
string body_list1 = llList2String(body_list, 1);

llOwnerSay("\nbody_list0 = "+body_list0+"\nbody_list1 = "+body_list1);

// Output:
// body_list0 = 25_128_NADJ
// body_list1 = 450,25,128,30#

list data_list = llParseString2List(body_list1, [","], []);
string data_list0 = llList2String(data_list, 0);
string data_list1 = llList2String(data_list, 1);
string data_list2 = llList2String(data_list, 2);
string data_list3 = llList2String(data_list, 3);

llOwnerSay("\ndata_list0 = "+data_list0+"\ndata_list1 = "+data_list1+"\ndata_list2 = "+data_list2+"\ndata_list3 = "+data_list3);

// Output:
// data_list0 = 450
// data_list1 = 25
// data_list2 = 128
// data_list3 = 30#
}
}
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
09-15-2009 19:19
But do I have to hardcode every menu item?

as to what I know, I have to do something like:

MENU_LIST = [ "Button1", "Button2" ];
to make the menu buttons.
Does that mean I have to manually hardcode all 28 buttons?
I was lookig for a way to have the script doing it for me, no matter how many plans I get from the output.
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-15-2009 23:12
Of course you don't need to hardcode all the menus. Just need to think of a little trick to manipulate the data you got. So what you have is the output you got from the httprequest, let's call them "data_list", those are, unfortunately, need to hardcode on the script as some kind of input of the whole thing - or you could use a standard notecard reader etc. if you put them on a notecard.

After you obtain the data_list, you just want a script to separate them into menu buttons and their corresponding data values. Below is the script i've just written in-world with your httprequest result. A person touches the prim, it'll generate a drop down menu with different pages, once a button is selected, its corresponding data values will be updated to the global variables you required. You may have any number of the httprequest (the size of the data_list), as long as the mono script memory can handle.

You only need to change the data_list on the top of the screen and automatically different menus will be shown as you save and re-compile the script. The only trick you need was a few "if"s to handle the menus with different page numbers etc. :)

I've also used numbers on the buttons instead of the original string before the "=". Since some of them are longer than the LSL button length limit, the rest would be cut off. E.g. "50_128_ADJ1024" would become "50_128_ADJ". But "50_128_ADJ512" will also become "50_128_ADJ", just to add confusion to the button response.

PS. For unknown reason this thread won't allow me to just post the whole thing in 1 reply. So i split into 2 snippets: variable definition and the default state script. Just put the first on the top the 2nd on a script.
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-15-2009 23:14
CODE

list data_list = [
"25_128_NADJ=450,25,128,30#",
"50_128_ADJ1024=1450,50,128,1024#",
"50_128_ADJ512=1200,50,128,512#",
"50_128_ADJ256=1000,50,128,256#",
"50_128_NADJ=650,50,128,30#",
"100_128_ADJ1024=1800,100,128,1024#",
"100_128_ADJ512=1550,100,128,512#",
"100_128_ADJ256=1350,100,128,256#",
"100_128_NADJ=1000,100,128,30#",
"96_50_ADJ512=1000,50,96,30#",
"100_96_NADJ=750,100,96,30#",
"100_96_ADJ256=1100,100,96,256#",
"100_96_ADJ512=1300,100,96,512#",
"100_96_ADJ1024=1550,100,96,1024#",
"50_96_ADJ256=800,50,96,256#",
"50_96_ADJ512=1000,50,96,512#",
"50_96_ADJ1024=1250,50,96,1024#",
"100_64_NADJ=550,100,64,30#",
"100_64_ADJ256=900,100,64,256#",
"100_64_ADJ512=1100,100,64,512#",
"100_64_ADJ1024=1350,100,64,1024#",
"50_64_NADJ=300,50,64,30#",
"50_64_ADJ256=650,50,64,256#",
"50_64_ADJ512=850,50,64,512#",
"50_64_ADJ1024=1100,50,64,1024#",
"50_96_NADJ=450,50,96,30#",
"50_128_25percent=488,50,128,30#"
];

//==== NOTHING NEED TO CHANGE FROM HERE ====
integer total_data = 0;
key toucher = NULL_KEY;
integer menu_chan = -1;
integer listen_num = -1;
integer menu_page = 1;
integer total_menu_page = 1;
list menu_button_list = [];
list info_list = [];
integer i = 0;
string menu_msg = "";
list menu_button = [];

string PLANS;
integer PRICE;
integer SLOTS;
integer BITRATE;
integer UPLOAD;

integer temp_slot = -1;
integer temp_price = -1;
string temp_plans = "";
integer temp_bitrate = -1;
integer temp_upload = -1;
//=====================================
create_menu(integer current_page)
{
llListenRemove(listen_num);
menu_chan = 0 - (integer)llFrand(2147483647);
listen_num = llListen(menu_chan,"", toucher,"");
menu_button = [];
menu_msg = "";

if (total_menu_page == 1) // only 1 total menu page
{
for (i = 0; i <= 11; i++)
{
menu_msg += (string)(i + 1)+" => "+llList2String(menu_button_list,i)+"\n";
menu_button += [(string)(i + 1)];
}
}
else if (current_page == 1) // more than 1 total menu page, and the current page is 1
{
for (i = 0; i <= 10; i++)
{
menu_msg += (string)(i + 1)+" => "+llList2String(menu_button_list,i)+"\n";
menu_button += [(string)(i + 1)];
}
menu_button = llListInsertList(menu_button,["NEXT PAGE >"],2); // add a next page button
}
else if (current_page == total_menu_page) // more than 1 total menu page, and now is the last page
{
for (i = (total_menu_page - 1) * 10; i <= (total_data - 1); i++)
{
menu_msg += (string)(i + 1)+" => "+llList2String(menu_button_list,i)+"\n";
menu_button += [(string)(i + 1)];
}
menu_button = llListInsertList(menu_button,["< PREV PAGE"],0); // add a previous page button
}
else // more than 1 total menu page, it is now in the middle page
{
for (i = (current_page - 1) * 10; i <= (current_page - 1) * 10 + 9; i++)
{
menu_msg += (string)(i + 1)+" => "+llList2String(menu_button_list,i)+"\n";
menu_button += [(string)(i + 1)];
}
menu_button = llListInsertList(menu_button,["< PREV PAGE"],0); // add a previous page button
menu_button = llListInsertList(menu_button,["NEXT PAGE >"],2); // add a next page button
}

llDialog(toucher, "Select option (page "+(string)current_page+"/"+(string)total_menu_page+"):\n"+menu_msg, menu_button, menu_chan);
llSetTimerEvent(60.0);
}
//=====================================
integer get_total_page(integer total_data)
{
integer output = 1;
while ((float)output * 10.0 + 2.0 < total_data)
{
output += 1;
}
return output;
}
//=====================================
create_Y_N_menu(string menu_message,list menu_button)
{
llListenRemove(listen_num);
menu_chan = 0 - (integer)llFrand(2147483647);
listen_num = llListen(menu_chan,"", toucher,"");
llDialog(toucher, menu_message, menu_button, menu_chan);
llSetTimerEvent(60.0);
}
//=====================================
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-15-2009 23:15
CODE

default
{
state_entry()
{
total_data = llGetListLength(data_list);
total_menu_page = get_total_page(total_data);

list temp_list = [];
for (i = 0; i <= total_data; i++)
{
temp_list = llParseString2List(llList2String(data_list,i), ["="], []);
menu_button_list += llList2String(temp_list,0); // menu button name
info_list += llList2String(temp_list,1); // info from that button
}
}
touch_start(integer int)
{
if (menu_button_list != [])
{
toucher = llDetectedKey(0);
menu_page = 1;
create_menu(menu_page);
}
}
listen(integer channel, string name, key id, string message)
{
if (message == "NEXT PAGE >")
{
menu_page += 1;
create_menu(menu_page);
}
else if (message == "< PREV PAGE")
{
menu_page -= 1;
create_menu(menu_page);
}
else if (message == "Yes")
{
PLANS = temp_plans;
PRICE = temp_price;
SLOTS = temp_slot + 1; // could take out the +1 depends what you want the slot to start with
BITRATE = temp_bitrate;
UPLOAD = temp_upload;
llOwnerSay(" data updated as follow:\nPLANS = "+PLANS+" listeners\nPRICE = L$"+(string)PRICE+"\nSLOTS = "+(string)SLOTS+"\nBITRATE = "+(string)BITRATE+" kbit\nUPLOAD = "+(string)UPLOAD+"mb");
}
else if (message == "No")
{
create_menu(menu_page);
}
else // menu button selected
{
temp_slot = (integer)message - 1; // minus 1 since menu button starts from 1, not 0
list sub_info_list = llParseString2List(llList2String(info_list,temp_slot), [","], []);
temp_price = llList2Integer(sub_info_list,0);
temp_plans = llList2String(sub_info_list,1);
temp_bitrate = llList2Integer(sub_info_list,2);
temp_upload = llList2Integer(sub_info_list,3);

create_Y_N_menu("You have chosen the plan with "+temp_plans+" listeners at "+(string)temp_bitrate+" kbit with "+(string)temp_upload+" mb upload which will cost you "+(string)temp_price+" Lindens. Is this correct?",["Yes","No"]);
}
}
timer()
{
llListenRemove(listen_num);
llSetTimerEvent(0.0);
}
}
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
09-16-2009 02:31
Thanks a lot for that...

I hope I can get everything to work the way I want it to with that...
Now I just need to figure out how to work the llMessageLinked to send the variables to another script.. but I think I can handle it.

Again, thanks a bunch.. :)
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
09-16-2009 10:34
There is just one more thing regarding this script that I can not find out houw to get.

In the llOwnerSay ( llOwnerSay(" data updated as follow:\nPLANS = "+PLANS+" listeners\nPRICE = L$"+(string)PRICE+"\nSLOTS = "+(string)SLOTS+"\nBITRATE = "+(string)BITRATE+" kbit\nUPLOAD = "+(string)UPLOAD+"mb";); )

I need the actual plan name outputted aswell.
So that the actual output would be something like:

"Data updated as follow:
Plan: 25_128_NADJ
Listeners: 25 listeners
Price: L$450
Bitrate: 128 kbit
Upload: 30mb"

But I can't figure out how to get what the user clicked on to get the plan name.
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-16-2009 23:19
You already have all the plan info stored in the menu_button_list, just need to get the required plan from the corresponding slot. :)

llOwnerSay(" data updated as follow:\nPLAN = "+llList2String(menu_button_list,temp_slot)+"\nLISTENERS = "+PLANS+" listeners\nPRICE = L$"+(string)PRICE+"\nBITRATE = "+(string)BITRATE+" kbit\nUPLOAD = "+(string)UPLOAD+"mb";);
Tadao Nordenskiold
Registered User
Join date: 9 May 2009
Posts: 37
09-16-2009 23:27
Yeah, I found it, but forgot to update the forum...

I also tried to convert the script to get all the data from an http output as in my original script, so that I don't have to update in the script if I add or remove anything in the future.. but I gave up as I didn't succeed and couldn't figure out how to make it.

I changed the output from the page to match as how you put it in the script...
But I ended up only getting the first row, and the rest was skipped..
Here's the page that outputs the data:
http://dev.gate5.se/get_menu_items.php
Klug Kuhn
Registered User
Join date: 7 Sep 2007
Posts: 126
09-16-2009 23:59
Instead of hardcode inputting the data_list at the beginning, simply read the info from your website, then parsing the website body into the data_list. Replace the data_list with an empty list variable declaration, then add a global http_request handler.

list data_list = [];
key http_request_id = NULL_KEY;

Before we were separating the data_list directly at the start, now simply replacing with the website response, then use the data from the body afterward. The idea is exactly the same. As long as your website format doesn't change, it'll read the correct data. However, though, before the size of the data_list was limited by the script memory; this time it is also limited by the website body size. It's a LSL limit that the response body is limited to 2048 bytes; if it is longer it will be truncated cut off. So you may need to pay attention to it.

Again using llParseString2List() to separate the data string into data_list. The separator this time is #"," which the " is a special character in LSL, you need to put an additional \ to tell it's a special character. So instead of using line:
data_list = llParseString2List(body, ["#",""], []);

should use:
data_list = llParseString2List(body, ["#\",\""], []);

All the rest of the script to be remained the same.


CODE

state_entry()
{
string website = "http://dev.gate5.se/get_menu_items.php";
http_request_id = llHTTPRequest(website, [], "");
}
http_response(key request_id, integer status, list metadata, string body)
{
if (request_id == http_request_id)
{
body = llDeleteSubString(body,0,0); // remove the very first "
body = llDeleteSubString(body,llStringLength(body) - 2,llStringLength(body) - 1); // remove the last 2 characters ",
data_list = llParseString2List(body, ["#\",\""], []); // parse the body into a list

total_data = llGetListLength(data_list);
total_menu_page = get_total_page(total_data);

list temp_list = [];
for (i = 0; i <= total_data; i++)
{
temp_list = llParseString2List(llList2String(data_list,i), ["="], []);
menu_button_list += llList2String(temp_list,0); // menu button name
info_list += llList2String(temp_list,1); // info from that button
}
}
}