User:Void Singer/Functions

uParseEquation

• Parses a string equation and returns a formatted result
• Supports the following operations and proper order of operations:
• Parenthesis("(",")")
• Negation ("-")
• Exponentiation ("^")
• Division and Multiplication ("/", "*")
• Subtraction & Addition ("-", "+")
• Supports (Case insensitive) constant replacement:
• Supports implied multiplication of parenthesis and constants
• (2)3 == 2*3
• 2pi == 2*pi
• Supports Roots in the format of x^(1/y) (the "y" root of "x", where both are decimal numbers)
• Supports error detection:
• Unsuported characters
• Invalid/Missing Operators
• Divide by Zero
• Empty/Missing Parenthesis
• Ignores spaces
```string uParseEquation( string vStrTmp ){
list    lst_OPS = ["+", "-", "*", "/", "^"];
list    vLstEqn;
list    vLstTmp;
list    vLstSwp;
integer vIdxFnd;
integer vIdxBgn;
integer vIdxEnd;
integer vIntCnt;
integer vIntErr;

vStrTmp = llToLower( "(" + vStrTmp + ")" );
vLstTmp = llParseString2List( vStrTmp, lst_OPS + ["pi", "phi"], [] );
vLstTmp = llParseString2List( (string)vLstTmp, ["0", "1", "2", "3", "4", "5", "6", "7"], [] );
vLstTmp = llParseString2List( (string)vLstTmp, ["8", "9", ".", "e", "(", ")", " ", "="], [] );
if (vLstTmp != []){
jump Err0;
}
vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["e"], [] ), "(2.7182817)" );
vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["pi"], [] ), "(3.1415927)" );
vStrTmp = llDumpList2String( llParseStringKeepNulls( vStrTmp, ["phi"], [] ), "(1.6180340)" );
vLstEqn = llParseString2List( vStrTmp, [" ", "="], lst_OPS + ["(", ")"] );
while (~(vIdxEnd = vIdxBgn = llListFindList( vLstEqn, (list)")" ))){
while (llList2String( vLstEqn, vIdxBgn ) != "(" && ~(--vIdxBgn));
if (~vIdxBgn){
if (vIdxEnd - vIdxBgn > 1){
if (~llListFindList( lst_OPS,
(list)llList2String( vLstTmp = llList2List( vLstEqn, -~vIdxBgn, ~-vIdxEnd ),
0xFFFFFFFF ) )){
jump Err1;
}
if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, 0 ) ))){
if (1 == vIdxFnd  && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, 1 ) )){
vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, 1 )), 0, 1 );
}else{
jump Err2;
}
}
vIntCnt = ([] != vLstTmp);
while(++vIntCnt < 0){
if (~llListFindList( lst_OPS, (list)llList2String( vLstTmp, vIntCnt) )){
if (~(vIdxFnd = llListFindList( lst_OPS, (list)llList2String( vLstTmp, ++vIntCnt ) ))){
if (1 == vIdxFnd && !~llListFindList( lst_OPS, (list)llList2String( vLstTmp, -~vIntCnt) )){
vLstTmp = llListReplaceList( vLstTmp, (list)(-llList2Float( vLstTmp, vIntCnt )), vIntCnt, -~vIntCnt );
--vIntCnt;
}else{
jump Err3;
}
}
}else{
jump Err4;
}
}
vIntCnt = 4;
do{
while (~(vIdxFnd = llListFindList( vLstTmp, (list)llList2String( lst_OPS, vIntCnt ) ))){
if (1 & vIntCnt){
if (2 & vIntCnt){
if (llList2String( vLstTmp, -~vIdxFnd )){
vLstSwp = ["*", 1 / llList2Float( vLstTmp, -~vIdxFnd )];
}else{
jump Err5;
}
}else{
vLstSwp = ["+", -llList2Float( vLstTmp, -~vIdxFnd )];
}
}else{
if (vIntCnt){
if (4 & vIntCnt){
vLstSwp = (list)llPow( llList2Float( vLstTmp, ~-vIdxFnd ), llList2Float( vLstTmp, -~vIdxFnd ) );
}else{
vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) * llList2Float( vLstTmp, -~vIdxFnd ) );
}
}else{
vLstSwp = (list)( llList2Float( vLstTmp, ~-vIdxFnd ) + llList2Float( vLstTmp, -~vIdxFnd ) );
}
}
vLstTmp = llListReplaceList( vLstTmp, vLstSwp, vIdxFnd - !(1 & vIntCnt), -~vIdxFnd );
}
}while (~(--vIntCnt));
vLstEqn = llListReplaceList( vLstEqn, vLstTmp, vIdxBgn, vIdxEnd );
}else{
jump Err6;
}
if (!~llListFindList( lst_OPS + [")", ""], (list)llList2String( vLstEqn, -~vIdxBgn ) )){
vLstEqn = llListInsertList( vLstEqn, (list)"*", -~vIdxBgn );
}
if (vIdxBgn){
if (!~llListFindList( lst_OPS + (list)"(", (list)llList2String( vLstEqn, ~-vIdxBgn ) )){
vLstEqn = llListInsertList( vLstEqn, (list)"*", vIdxBgn );
}
}
}else{
jump Err7;
}
}
if (~llListFindList( vLstEqn, (list)"(" )){
jump Err8;
}
if (vLstEqn != ["="]){
jump Err9;
}
if ((integer)vStrTmp == (float)(vStrTmp = llList2String( vLstEqn, 0 ))){
vStrTmp = (string)((integer)vStrTmp);
}else{
vIntCnt = llStringLength( vStrTmp );
while ("0" == llGetSubString( vStrTmp, --vIntCnt, vIntCnt  ));
vStrTmp = llGetSubString( vStrTmp, 0, vIntCnt );
}
jump Errors;
@Err9; ++vIntErr;
@Err7; @Err8; ++vIntErr;
@Err6; ++vIntErr;
@Err5; ++vIntErr;
@Err4; ++vIntErr;
@Err3; ++vIntErr;
@Err1; @Err2; ++vIntErr;
@Err0;
vStrTmp =
"Error: " +
llList2String( ["Unsupported Character(s)",
"Outside Operator(s)",
"Stacked Operator(s)",
"Missing Operator(s)",
"Divide By Zero",
"Empty Parenthesis",
"Missing Parenthesis",
"Catastrophic Failure"],
vIntErr ) +
"\n" + llDumpList2String( vLstEqn, " " ) + "\n" + vStrTmp;
@Errors;
return vStrTmp;
}
/*//  Free to copy, use, modify, distribute, or sell, with attribution.   //*/
/*//    (C)2010 (CC-BY) [ http://creativecommons.org/licenses/by/3.0 ]    //*/
/*//   Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//  All usages must contain a plain text copy of the previous 2 lines.  //*/
/*//--                                                                  --//*/```

uListFindListLast

• This function is a companion to llListFindList.
• designed for string data only.
• Can not handle empty string elements
• Returns 0 if list test is empty, but list source is not; just like llListFindList
• SPECIAL NOTE: data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.

Get Last Index of List Test in List Source

```integer uListFindListLast( list vLstSrc, list vLstTst ){
integer vIdxFnd =
(vLstSrc !=
(vLstTst +
llParseString2List(
llList2String(
llParseStringKeepNulls(
llDumpList2String( vLstSrc, "•" ),
(list)llDumpList2String( vLstTst, "•" ),
[] ),
0xFFFFFFFF ),
["•"],
[] )));
return (vIdxFnd | (vIdxFnd >> 31));
}
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/```

uListFindAny*

• These functions are companions to llListFindList.
• designed for string data only.
• Can not handle empty string elements
• SPECIAL NOTE: data should NOT contain the "•" character(alt+7)... please use a different character if this one is expected.

Get the First index in List Source of Any element in List Test
```integer uListFindAnyFirst( list vLstSrc, list vLstTst ){
return ~(~(
llParseString2List(
llList2String(
llParseStringKeepNulls(
llDumpList2String( vLstSrc, "•" ),
vLstTst, [] ),
0 ),
["•"], [] ) != []) %
~(vLstSrc != []));
}
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/```
Get the Last index in List Source of Any element in List Test
```integer uListFindAnyLast( list vLstSrc, list vLstTst ){
return ~(
llParseString2List(
llList2String(
llParseStringKeepNulls(
llDumpList2String( vLstSrc, "•" ),
vLstTst, [] ),
0xFFFFFFFF ),
["•"], [] )
!= vLstSrc);
}
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/```

uDlgBtnPagList

• Effectively allows more than 12 button on a dialog by breaking them up into pages and adding page change buttons as needed
• Corrects the button order to [left to right, top to bottom] (AKA English Order]
• Automatically wraps around from the last and first pages
• Supports up to 22 pages safely (220 items in the list)
• Supports multiple simultaneous users
• Requires the button text(s) to be in a global list named gLstMnu (which you can fill however you like)
• this function does NOT check that button text is valid (0 < button_text_length < 25), that's your job
```list uDlgBtnLst( integer vIdxPag ){
list vLstRtn;
if ((gLstMnu != []) > 12){ //-- we have more than one possible page
integer vIntTtl = -~((~([] != gLstMnu)) / 10);                                 //-- Total possible pages
integer vIdxBgn = (vIdxPag = (vIntTtl + vIdxPag) % vIntTtl) * 10;              //-- first menu index
string  vStrPag = llGetSubString( "                     ", 21 - vIdxPag, 21 ); //-- encode page number as spaces
//-- get ten (or less for the last page) entries from the list and insert back/fwd buttons
vLstRtn = llListInsertList( llList2List( gLstMnu, vIdxBgn, vIdxBgn + 9 ), (list)(" «" + vStrPag), 0xFFFFFFFF ) +
(list)(" »" + vStrPag);
}else{ //-- we only have 1 page
vLstRtn = gLstMnu; //-- just use the list as is
}
return //-- fix the order for [L2R,T2B] and send it out
llList2List( vLstRtn, -3, -1 ) + llList2List( vLstRtn, -6, -4 ) +
llList2List( vLstRtn, -9, -7 ) + llList2List( vLstRtn, -12, -10 );
}
/*//     Contributed Freely to the Public Domain without limitation.     //*/
/*//   2012 (CC0) [ http://creativecommons.org/publicdomain/zero/1.0 ]   //*/
/*//  Void Singer [ https://wiki.secondlife.com/wiki/User:Void_Singer ]  //*/
/*//--                                                                 --//*/```
How to incorporate into llDialog calls:
`llDialog( Target_avatar_key, text_for_dialog_header, uDlgBtnLst( 0 ), chat_channel_to_use );`
How to detect and handle responses:
```    listen( integer vIntChn, string vStrNom, key vKeySpk, string vStrMsg ){
if (!llSubStringIndex( vStrMsg, " " )){ //-- detects (hidden) leading non-breaking space of page change buttons
llDialog( vKeySpk,