// SPDX-License-Identifier: MIT // Copyright (c) 2026 Incoprea // Named measurement notebook // Not compiled or tested in-world // Setup: Place in your own object and touch. Enter label|number or list. Up to 12 values. // Stop / restore: Remove or reset to erase session data. Input listeners close after one reply or after 45 seconds. // Notes: Data lives only in script memory and is lost on reset. No visitors are logged and no external requests are sent. A manual notebook; it does not measure avatars or geometry automatically. Restricts input to digits, sign, and decimal point before casting. // License: see LICENSE in this distribution. // Original Incoprea example. MIT. list readings; integer decimalOK(string v) { integer n=llStringLength(v); if(n<1 || n>12)return FALSE; integer i; integer digits; integer dots; if(llGetSubString(v,0,0)=="-" || llGetSubString(v,0,0)=="+")i=1; for(;i0 && dots<=1; } integer handle; integer channel; closeInput() { if(handle)llListenRemove(handle); handle=0; llSetTimerEvent(0); } respond(string input) { input=llStringTrim(input,STRING_TRIM); if(llStringLength(input)>200) { llOwnerSay("Use at most 200 characters."); return; } if(input=="list") { integer i; for(i=0;i=24) { llOwnerSay("Use label|number; maximum 12 readings."); return; } string number=llList2String(p,1); if(!decimalOK(number) || llFabs((float)number)>1000000) { llOwnerSay("Invalid or excessive number."); return; } readings += [llList2String(p,0),(float)number]; llOwnerSay("Measurement recorded."); } default { touch_start(integer touches) { if(llDetectedKey(0)!=llGetOwner())return; closeInput(); channel=-10000-(integer)llFrand(1000000000); handle=llListen(channel,"",llGetOwner(),""); llSetTimerEvent(45); llTextBox(llGetOwner(),"Enter label|number or list. Up to 12 values.",channel); } listen(integer c,string name,key speaker,string input) { if(c!=channel || speaker!=llGetOwner())return; closeInput(); respond(input); } timer() { closeInput(); llOwnerSay("Input closed."); } changed(integer flags) { if(flags & CHANGED_OWNER)llResetScript(); } }