User:Void Singer/Functions

From Second Life Wiki
< User:Void Singer
Revision as of 19:49, 27 November 2016 by Void Singer (talk | contribs) (corrected mismatch, thanks KittenPaws)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

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;
}
/*//--                           License Text                           --//*/
/*//  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.  //*/
/*//--                                                                  --//*/
Return to top

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));
}
/*//--                       Anti-License Text                         --//*/
/*//     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 ]  //*/
/*//--                                                                 --//*/
Return to top

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.

uListFindAnyFirst

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 != []));
}
/*//--                       Anti-License Text                         --//*/
/*//     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 ]  //*/
/*//--                                                                 --//*/

uListFindAnyLast

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);
}
/*//--                       Anti-License Text                         --//*/
/*//     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 ]  //*/
/*//--                                                                 --//*/
Return to top

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
  • Support Re-menuing
  • 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
  • Individual button texts cannot' start with a non-breaking space (alt+255).
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 );
}
/*//--                       Anti-License Text                         --//*/
/*//     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 ]  //*/
/*//--                                                                 --//*/

Example Usage

How to incorporate into llDialog calls:
llDialog( Target_avatar_key, text_for_dialog_header, uDlgBtnLst( 0 ), chat_channel_to_use );

Response Detection

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,
                      "your dialog text goes here",
                      uDlgBtnLst( llStringLength( vStrMsg ) + llSubStringIndex( vStrMsg, "»" ) - 2 ),
                      vIntChn );
        }else{
            //-- button was not a page button, your code goes here,
            //-- use (llListFindList( gLstMnu, (list)vStrMsg ) / 10) for remenu command if present
        }
    }
Return to top

Questions or Comments?

Feel free to leave me a note on my User Talk page.