Ruthven Ravenhurst Posted May 13, 2020 Share Posted May 13, 2020 I'm trying to figure out how to sort a list of scores, and names, but maintain the player's place on the scoreboard if someone ties with them. for example, player 1 has a score of 15, then player 3 gets a score of 15, player 1 should stay in 1st place, and player 3 should move up to second place. following? i used the following script, but it didn't maintain the places as i expected. list scores = [15,"player 1", 12, "player 2", 19, "player 3", 15, "player 4", 12, "player 5"]; default { state_entry() { scores = llListSort(scores, 2, FALSE); llOwnerSay(llList2CSV(scores)); } } //Returns: [19:42] 19, player 3, 15, player 4, 15, player 1, 12, player 5, 12, player 2 So i thought what about adding another "column" of the unix time when that player last scored. but i don't know how i'd go about sorting the list both by the scores descending, and the unix time ascending. someone suggested crunching the score, unix time and name together in a string, sorting, then extracting them again, but that didn't work either, and sorts it the same way since the lower unix time added to the same score is also going to sort in descending order list scores = [15,2001,"player 1", 12,2004, "player 2", 19,2004, "player 3", 15,2002, "player 4", 12,2005, "player 5"]; default { state_entry() { list temp = []; integer i; integer len = llGetListLength(scores); for(i = 0; i < len; i += 3) { temp += llDumpList2String(llList2List(scores, i, i+2),""); } llOwnerSay(llList2CSV(temp)); temp = llListSort(temp,1,FALSE); llOwnerSay(llList2CSV(temp)); scores = llListSort(scores, 3, FALSE); llOwnerSay(llList2CSV(scores)); } } //returns: [20:32] 152001player 1, 122004player 2, 192004player 3, 152002player 4, 122005player 5 [20:32] 192004player 3, 152002player 4, 152001player 1, 122005player 5, 122004player 2 [20:32] 19, 2004, player 3, 15, 2002, player 4, 15, 2001, player 1, 12, 2005, player 5, 12, 2004, player 2 Â Link to comment Share on other sites More sharing options...
Wulfie Reanimator Posted May 13, 2020 Share Posted May 13, 2020 (edited) Generally speaking, if you want to sort by multiple categories, first sort by one category before the other. This is a pretty common solution in many places, and it's basically an "accidental coincidence" that it works this way, because of how sorting functions typically work. It's a bit hard to explain without illustrating it. The biggest problem is that you can't sort strides by a specific column, the strides are sorted by the first element only. So you would have to rebuild the list in a different format before sorting it the second time. For that reason, it might be simple to combine the score and timestamp as you suggested. I'd recommend a string format of "score-unixtime" as in "15-2004" This way, if two players have the same score, you would sort "15-2004" and "15-4008" next to each other in ascending/descending order. Â Edited May 13, 2020 by Wulfie Reanimator Link to comment Share on other sites More sharing options...
Ruthven Ravenhurst Posted May 13, 2020 Author Share Posted May 13, 2020 think i figured it out, but there's gotta be a more efficient way of doing it 😕 it's getting the time when the loop is about to start, then replaces the unix time in the temp list with the time since that player's score was last updated. formatted by lumping it together as "score-timesince-name" then sorting, it sorts how i wanted it to. then it parses each of those lumped strings, then converts the timesince back to the original unix time, and reconstructs the score list list scores = [15,2001,"player 1", 12,2004, "player 2", 19,2004, "player 3", 15,2002, "player 4", 12,2005, "player 5"]; default { state_entry() { list temp = []; integer i; integer len = llGetListLength(scores); integer now = 2006; for(i = 0; i < len; i += 3) { integer score = llList2Integer(scores,i); integer since = now - llList2Integer(scores, i+1); string name = llList2String(scores,i+2); temp += llDumpList2String([score,since,name],"-"); } llOwnerSay(llList2CSV(temp)); temp = llListSort(temp,1,FALSE); llOwnerSay(llList2CSV(temp)); len = llGetListLength(temp); scores = []; for(i = 0;i < len; i++) { list temp2 = llParseString2List(llList2String(temp,i),["-"],[]); integer score = llList2Integer(temp2,0); integer time = now - llList2Integer(temp2,1); string name = llList2String(temp2,2); scores += [score,time,name]; } llOwnerSay(llList2CSV(scores)); } } //returns: [21:35] 15-5-player 1, 12-2-player 2, 19-2-player 3, 15-4-player 4, 12-1-player 5 [21:35] 19-2-player 3, 15-5-player 1, 15-4-player 4, 12-2-player 2, 12-1-player 5 [21:35] 19, 2004, 2006, 15, 2001, 2006, 15, 2002, 2006, 12, 2004, 2006, 12, 2005, 2006 [21:35] 15-5-player 1, 12-2-player 2, 19-2-player 3, 15-4-player 4, 12-1-player 5 [21:35] 19-2-player 3, 15-5-player 1, 15-4-player 4, 12-2-player 2, 12-1-player 5 [21:35] 19, 2004, player 3, 15, 2001, player 1, 15, 2002, player 4, 12, 2004, player 2, 12, 2005, player 5  Link to comment Share on other sites More sharing options...
Mollymews Posted May 13, 2020 Share Posted May 13, 2020 (edited) 3 hours ago, Ruthven Ravenhurst said: I'm trying to figure out how to sort a list of scores, and names, but maintain the player's place on the scoreboard if someone ties with them. for example, player 1 has a score of 15, then player 3 gets a score of 15, player 1 should stay in 1st place, and player 3 should move up to second place. following? Â a way is have a unique record number for each new entry added to the list example: integer record_uid = 0xFFFFFFFF; // unique record ident list players; addnew_player(key player, integer score) { // decrement record_uid. when this rolls over from - to + then the current list needs to be reset --record_uid; if (record_uid == 0xFFFFFFFF) reset_record_uid(); // append new player. record format: // [score, record_uid, player] players += [score, record_uid, player]; // sort new player into list, in descending order // sort by Score - high to low // sort by record_id - which is unique to every entry in the list. - high to low // sort by player - high to low players = llListSort(players, 3, FALSE); } update_player(key player, integer score) { integer i = llListFindList(players, [player]); if (~i) players = llListSort(llListReplaceList(players, [score], i-2, i-2), 3, FALSE); } reset_record_uid() { record_uid = 0xFFFFFFFF; integer n = llGetListLength(players); integer i; for (i = 1; i < n; i += 3) players = llListReplaceList(players, [--record_uid], i, i); } Â Â Â Â Edited May 13, 2020 by Mollymews code typeo Link to comment Share on other sites More sharing options...
Recommended Posts
Please take a moment to consider if this thread is worth bumping.
Please sign in to comment
You will be able to leave a comment after signing in
Sign In Now