scoreboard.lsl
//////////////////////////////////////////////////////////
// (c) Wizardry and Steamworks - 2013, License GPLv3    //
// Please see: http://www.gnu.org/licenses/gpl.html     //
// for legal details, rights of fair usage and          //
// the disclaimer and warranty conditions.              //
//////////////////////////////////////////////////////////
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasTextDisplayList(list input, integer spacing) {
    string c = "";
    integer p = 0;
    do {
        string in = llList2String(input, 0);
        c = osMovePen(c, 0, p);
        p += spacing;
        c = osDrawText(c, in);
        input = llDeleteSubList(input, 0, 0);
    } while(llGetListLength(input));
    return c;
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
list wasDualQuicksort(list a, list b) {
    if(llGetListLength(a) <= 1) return a+b;
 
    integer pivot_a = llList2Integer(a, 0);
    a = llDeleteSubList(a, 0, 0);
    string pivot_b = llList2String(b, 0);
    b = llDeleteSubList(b, 0, 0);
 
    list less = [];
    list less_b = [];
    list more = [];
    list more_b = [];
 
    do {
        if(llList2Integer(a, 0) > pivot_a) {
            less += llList2List(a, 0, 0);
            less_b += llList2List(b, 0, 0);
            jump continue;
        }
        more += llList2List(a, 0, 0);
        more_b += llList2List(b, 0, 0);
@continue;
        a = llDeleteSubList(a, 0, 0);
        b = llDeleteSubList(b, 0, 0);
    } while(llGetListLength(a));
    return wasDualQuicksort(less, less_b) + [ pivot_a ] + [ pivot_b ] + wasDualQuicksort(more, more_b);
}
 
///////////////////////////////////////////////////////////////////////////
//    Copyright (C) 2013 Wizardry and Steamworks - License: GNU GPLv3    //
///////////////////////////////////////////////////////////////////////////
string wasKeyValueGet(string var, string kvp) {
    list dVars = llParseString2List(kvp, ["&"], []);
    do {
        list data = llParseString2List(llList2String(dVars, 0), ["="], []);
        string k = llList2String(data, 0);
        if(k != var) jump continue;
        return llList2String(data, 1);
@continue;
        dVars = llDeleteSubList(dVars, 0, 0);
    } while(llGetListLength(dVars));
    return "";
}
 
default {
    state_entry() {
        integer comChannel = (integer)("0x8" + llGetSubString(llGetCreator(), 0, 6));
        llListen(comChannel, "Exposure Tracker", "", "");
    }
    listen(integer channel, string name, key id, string message) {
        string a = wasKeyValueGet("owner", message);
        string h = wasKeyValueGet("health", message);
        list score = llParseString2List(osGetNotecard("Score"), ["\n"], []);
        integer i = llGetListLength(score)-1;
        do {
            list data = llCSV2List(llList2String(score, i));
            if(llList2String(data, 0) != a) jump continue;
            if(llList2String(data, 1) == h) return;
            score = llDeleteSubList(score, i, i);
            // alarm 60, schedule
            llSetTimerEvent(60);
            jump break;
@continue;
        } while(--i>-1);
@break;
        score += a + "," + h;
        llRemoveInventory("Score");
        osMakeNotecard("Score", llDumpList2String(score, "\n"));
    }
    timer() {
        list score = llParseString2List(osGetNotecard("Score"), ["\n", ","], []);
        list names = llList2ListStrided(score, 0, -1, 2);
        list scores = llList2ListStrided(llDeleteSubList(score, 0, 0), 0, -1, 2);
        score = wasDualQuicksort(scores, names);
        string display = "";
        integer count = 0;
        do {
            display += llList2String(score, 1);
            display += " -> ";
            display += llList2String(score, 0);
            display += "\n";
            score = llDeleteSubList(score, 0, 1);
            if(++count==10) jump show;
        } while(llGetListLength(score));
@show;
        osSetDynamicTextureDataBlendFace("", "vector", wasTextDisplayList(llParseString2List(display, ["\n"], []), 20), "width:512,height:256", FALSE, 2, 0, 255, 0);
        llSetTimerEvent(0);
    }
}