SA-MP Forums

Go Back   SA-MP Forums > SA-MP Scripting and Plugins > Scripting Help

Reply
 
Thread Tools Display Modes
Old 03/01/2020, 12:47 AM   #1
cipi89
Little Clucker
 
Join Date: Sep 2018
Posts: 17
Reputation: 3
Exclamation Help with highest scores on server

I'm running a deathmatch server and I didn't encounter this issue until today when my server reached more than 1000 registered accounts.

I'm using Ryder's quickSort to get 5 highest scores on server:
Code:
stock GetPlayerHighestScores(array[][rankingEnum], left, right)
{
    new
        tempLeft = left,
        tempRight = right,
        pivot = array[(left + right) / 2][user_Score],
        tempVar
    ;
    while(tempLeft <= tempRight)
    {
        while(array[tempLeft][user_Score] > pivot) tempLeft++;
        while(array[tempRight][user_Score] < pivot) tempRight--;

        if(tempLeft <= tempRight)
        {
            tempVar = array[tempLeft][user_Score], array[tempLeft][user_Score] = array[tempRight][user_Score], array[tempRight][user_Score] = tempVar;
            tempVar = array[tempLeft][user_ID], array[tempLeft][user_ID] = array[tempRight][user_ID], array[tempRight][user_ID] = tempVar;
            tempLeft++, tempRight--;
        }
    }
    if(left < tempRight) GetPlayerHighestScores(array, left, tempRight);
    if(tempLeft < right) GetPlayerHighestScores(array, tempLeft, right);
}
And it was all working like a charm up to now.
However as more and more players register my loop becomes higher and higher and once it reached +1000 users it stopped working (I'm aware of the issure I'm just looking for someone with more experience to provide me with some tips to solve this).

Function that is being called every 60 seconds:
Code:
forward updateTop5();
public updateTop5()
{
    new playerScores[1000][rankingEnum], index;
    new check_str[64];
    for(new i; i < MAX_USERS; ++i)
    {
        format(check_str, 64, USERID_FOLDER, i);
        if(fexist(check_str))
        {
	    playerScores[index][user_Score] = User[i][user_kills];
	    playerScores[index++][user_ID] = i;
	}
    }
    GetPlayerHighestScores(playerScores, 0, index);
    for(new i; i < 5; ++i)
    {
        if(i < index)
	{
	    topKills[i+1][tfKills] = playerScores[i][user_Score];
	    strmid(topKills[i+1][tfName], User[playerScores[i][user_ID]][user_Name], 0, strlen(User[playerScores[i][user_ID]][user_Name]), 255);
        }
	else
	{
            topKills[i+1][tfKills] = 0;
            strmid(topKills[i+1][tfName], "None", 0, strlen("None"), 255);
	}
    }
    SaveTopFive();
    UpdateTopFiveLabel();
    return 1;
}
The real issue is here:
Code:
new check_str[64];
for(new i; i < MAX_USERS; ++i)
{
    format(check_str, 64, USERID_FOLDER, i);
    if(fexist(check_str))
    {
	playerScores[index][user_Score] = User[i][user_kills];
	playerScores[index++][user_ID] = i;
    }
}
'MAX_USERS' is 15000 (Yeah ik..) but! i included fexist check to reduce the loop a bit and as I said, when loop exceeded 1000 or 1024 (not rly sure) it just don't function anymore so any help is appreciated.

I've heard that mysql would be much easier but I just have no experience with it and if there's any chance I could fix this it would be great.

Last edited by cipi89; 03/01/2020 at 02:41 AM.
cipi89 is offline   Reply With Quote
Old 03/01/2020, 02:40 AM   #2
Pottus
High-roller
 
Pottus's Avatar
 
Join Date: Jun 2012
Posts: 4,892
Reputation: 1321
Default Re: Help with highest scores on server

For one you don't need a timer to do this period you know when the scores change update it then.
Use sqlite or mysql I would recommend sqlite.
Trying to do this like you are is futile bite the bullet and do it right. It may take a week or two to update everything but in the end will make everything you do or need to much easier so you will save time in the long run.

Anyways consider this you load all the high scores at server run time nice that was easy! Now simply consider the conditions you will encounter.

Player logs on who has highscore
- Increment their score and update the list
- Is their score higher than the next highest score?
If yes swap the positions! No looping here.

Player logs on who has no highscore
- Increment their score
- Is their score higher than lowest high score?
If yes then update the last high score position. No looping here either!

No Looping
No Timers
No Bullshit
Pottus is offline   Reply With Quote
Old 03/01/2020, 02:44 AM   #3
cipi89
Little Clucker
 
Join Date: Sep 2018
Posts: 17
Reputation: 3
Default Re: Help with highest scores on server

The only reason I wanted it on 60 seconds timer is to not overwhelm script so much since there's thousands of kills on my server every day and I figured it would most likely cause lag sometimes.

I guess I'll have to give sqlite a shot then, tried mysql and couldn't really catch up with how it works since I've been working with Y_INI only.
cipi89 is offline   Reply With Quote
Old 03/01/2020, 02:50 AM   #4
Pottus
High-roller
 
Pottus's Avatar
 
Join Date: Jun 2012
Posts: 4,892
Reputation: 1321
Default Re: Help with highest scores on server

Excellent Tutorial
https://forum.sa-mp.com/showthread.php?t=449536

Once you grasp that consider using sqlitei
https://forum.sa-mp.com/showthread.php?t=303682

What is nice is queries are very versatile so you can automatically order your output from highest to lowest and specify a maximum number of results. That is another NO!

NO SORTING ALGORITHMS!
Pottus is offline   Reply With Quote
Old 03/01/2020, 03:05 AM   #5
CXdur
Big Clucker
 
CXdur's Avatar
 
Join Date: Jun 2014
Location: Norway
Posts: 57
Reputation: 6
Default Re: Help with highest scores on server

Quote:
Originally Posted by cipi89 View Post
The only reason I wanted it on 60 seconds timer is to not overwhelm script so much since there's thousands of kills on my server every day and I figured it would most likely cause lag sometimes.

I guess I'll have to give sqlite a shot then, tried mysql and couldn't really catch up with how it works since I've been working with Y_INI only.
The best way as Pottus said would be to save it in a database and simply select it this way when you need it. Or if you'd like to avoid querying the database often, query it every now and then and save the top player information. It is not a good idea to sort through the entire player set every time you'd like to get the highest scores.

The average complexity of the insertion sort algorithm is n*log(n). I'm not going to write worst / best case because it's unnecessary, but see this:

# avg case: n * log(n)
# 50 * log(50) = 84 dom operations
# 1000 * log(1000) = 3000 dom operations
# 10000 * log(10000) = 40000 dom operations

With 50 users, you would have 84 dominant operations which would be very quick, but you can see that this is quickly unmaintanable as your player base grows. You should simply never be sorting your entire player dataset because as your playerbase grows it simply can't be done efficiently.

For MySQL, there are various optimizations such as indexes, making it less complex, so the sorting will be a lot quicker, and you will also be able to do it asynchronously which means the SAMP server will not freeze while it is being sorted. Sorting it like you are doing now will essentially block the server thread until the sorting is complete, but with a plugin such as MySQL you could use a callback for when it is done.

It would also be far more trivial to do this with MySQL/SQLite, for instance:
Code:
SELECT `username`, `score` FROM `accounts` ORDER BY `score` DESC LIMIT 10
The query above would return the username and the score of the top 10 players in terms of score.
CXdur is offline   Reply With Quote
Old 03/01/2020, 03:08 AM   #6
Pottus
High-roller
 
Pottus's Avatar
 
Join Date: Jun 2012
Posts: 4,892
Reputation: 1321
Default Re: Help with highest scores on server

@CXDur I like that! However if you read what I was saying when thinking about this problem logically the solution is very simple.

"Player logs on who has highscore
- Increment their score and update the list
- Is their score higher than the next highest score?
If yes swap the positions! No looping here.

Player logs on who has no highscore
- Increment their score
- Is their score higher than lowest high score?
If yes then update the last high score position. No looping here either! "


Oh one thing though if the score increase by more than a value of 1 in any given instance the above logic needs to be modified in which case looping is perfectly acceptable to shift the other highscores down one place ultimately eliminating the last high score in the list if the player was not in the list - OR - shifting all the other highscore places down one place until the highscore place that player was at originally is reached if that player was already in the list.
Pottus is offline   Reply With Quote
Old 03/01/2020, 03:03 PM   #7
cipi89
Little Clucker
 
Join Date: Sep 2018
Posts: 17
Reputation: 3
Default Re: Help with highest scores on server

@Pottus I've tried it the way you proposed before I've made the script I'm using currently, however your explanation does help a lot and yes it would be possible to make it that way but the way I see it there's many things that need to be covered in that "manual" update of the highscores. And yes I agree its more efficient lag wise.

Okay before I give your method a shot, is it possible to just include mysql and implement the code @CXdur gave? Or do I need to change other stuff too?
I've heard that Y_INI and mysql can work together, forgive me if its dumb question.
cipi89 is offline   Reply With Quote
Old 04/01/2020, 12:09 AM   #8
CXdur
Big Clucker
 
CXdur's Avatar
 
Join Date: Jun 2014
Location: Norway
Posts: 57
Reputation: 6
Default Re: Help with highest scores on server

Quote:
Originally Posted by cipi89 View Post
@Pottus I've tried it the way you proposed before I've made the script I'm using currently, however your explanation does help a lot and yes it would be possible to make it that way but the way I see it there's many things that need to be covered in that "manual" update of the highscores. And yes I agree its more efficient lag wise.

Okay before I give your method a shot, is it possible to just include mysql and implement the code @CXdur gave? Or do I need to change other stuff too?
I've heard that Y_INI and mysql can work together, forgive me if its dumb question.
Pottus's approach is a lot better than my suggestions when it comes to keeping the score list updated by the way! I was thinking you wanted offline players in the highscore as well when I suggested using one query for the score list.

No, the query I wrote was merely an example as to what a query looks like. MySQL is a database management system, and you will have to create a database and tables for your data. You will then basically use it the same way as ini:

1. Fetch info for username on login, if account doesn't exist allow creation
2. Scheduled data saves every now and then in case of server crash etc
3. Save data upon logout

I would suggest migrating away from y_ini in cases where data is retrieved often. For config files and such it is probably okay. The reason for this is because MySQL is a lot more efficient than y_ini. You could migrate by parsing the ini files and writing queries, or alternatively, you could migrate as players log in (check if they have ini, if so move to MySQL, delete ini). The first option is probably better though! There's no guarantee every old player would log in, and you could end up having migration code there forever.

Check out https://sqlbolt.com/ for an interactive introduction to SQL.
CXdur is offline   Reply With Quote
Old 04/01/2020, 12:46 AM   #9
cipi89
Little Clucker
 
Join Date: Sep 2018
Posts: 17
Reputation: 3
Default Re: Help with highest scores on server

So basically I would have to migrate to mysql in total to use your method?

I've made the code as @Pottus suggested.. But! Sometimes my server crashes and I can't think of why would the function I wrote crash it. (I'm not an expert)

FYI its long code and probably not how its supposed to be created but thats all I was able to come up with in 1 day.

If you'd like to see the code: https://pastebin.com/dHAKBamt

Edit: I want my highscore list to be able to look for offline players too, thats why I'm in need of your help since the method I was using no longer works and as you've said is inefficient.
cipi89 is offline   Reply With Quote
Old 04/01/2020, 09:07 AM   #10
Calisthenics
High-roller
 
Join Date: May 2018
Posts: 1,085
Reputation: 174
Default Re: Help with highest scores on server

No reason to complicate things. As the above users said, SQL is the best solution. All you need to do is:
1) update score when changes (hook SetPlayerScore).
2) set an index key for column `score` to speed it up.
__________________
Calisthenics is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
giving scores to people under 999 scores only Superhot Scripting Help 4 22/10/2013 04:05 AM
getting highest money on server.. kizla Scripting Help 1 30/04/2013 09:18 PM
how to get the highest score in the server? Rocky Balboa Help Archive 8 23/08/2010 05:22 PM
Server Side scores? Anthony_Brassi Help Archive 2 05/05/2010 04:27 PM
How to Get The Highest Kills Of The Player On the Server Bearfist Help Archive 2 10/05/2009 10:56 AM


All times are GMT. The time now is 10:34 PM.


Powered by vBulletin® Version 3.8.6
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.