User:Void Singer/Functions
Jump to navigation
Jump to search
Get the First index in List Source of Any element in List Test
Get the Last index in List Source of Any element in List Test
How to incorporate into llDialog calls:
How to detect and handle responses:
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:
- "e" (Euler's Number: 2.7182817)
- "pi" (Archimedes' Constant: 3.1415927)
- "phi" (Golden Ratio: 1.6180340)
- 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. //*/
/*//-- --//*/
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 ] //*/
/*//-- --//*/
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 != []));
}
/*//-- 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 ] //*/
/*//-- --//*/
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 ] //*/
/*//-- --//*/
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 ] //*/
/*//-- --//*/
llDialog( Target_avatar_key, text_for_dialog_header, uDlgBtnLst( 0 ), chat_channel_to_use );
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
}
}
Questions or Comments?
Feel free to leave me a note on my User Talk page.