Hot Commands
#1

Hi,

For my server I would like to create a textdraw under the HUD showing HOT commands. In other words, commands that have been used a lot, recently.

So like, say 5 players type two commands: /race and /jump. These two would become hot since they've been used recently and a lot, so they would display in the textdraw.

Just wondering the best way to do this? An example would be great. Storing all commands inputted into a large string and then comparing which command has been used the most at the end? meh dunno
Reply
#2

There are a few ways to approach this. I would personally make an array with the amount of cells as there is commands. Assign each command a unique ID, then add to the array's appropriate cell 1 for each time it's used. Unique IDs so you don't have to worry about the slower string comparison. Then, when it's time to update the textdraw, use some sort of algorithm to sort them and see which was used the most. You can find it on ******, or even this forums.

An example of how it would look
pawn Code:
#define COMMAND_JUMP   (0)
#define COMMAND_RACE   (1)

new g_Command[ MAX_COMMANDS ]; // Adjust MAX_COMMANDS to however many commands you have

COMMAND:jump( playerid, params[ ] )
{
   // command stuff
   g_Command[ COMMAND_JUMP ]++;
   return 1;
}
Reply
#3

Hmm, I was hoping for a more dynamic approach. This is one method I had in mind:
pawn Code:
#define HOT_CMD_INDEX   30

static  szHotCmds[HOT_CMD_INDEX][128];
static  iHotCmdUsed[HOT_CMD_INDEX];
static  iHotCommandCount;

public OnPlayerCommandText(playerid, cmdtext[])
{
    if(iHotCommandStorage == HOT_CMD_INDEX - 1) // Array has reached its limit so we start again
    {
        iHotCommandCount = 0;
    }
   
    // loop through all previously stored commands and see if the
    // cmd we're using now is already stored. if it is, then it's obviously
    // been used more than once very recently.
    for(new i = 0; i < iHotCommandCount; i++)
    {
        // we found a match. Just increase the amount of times this
        // cmd has been used
            if(!strcmp(szHotCmds[i], cmdtext, false))
        {
            iHotCmdUsed[i]++;
            break;
        }

        // Reached the end of the loop with no match
        // so store this as a new cmd
        if(i == iHotCommandCount - 1)
        {
            format(szHotCmds[iHotCommandCount], 128, "%s", cmdtext);
            // Increase both the overall count of commands stored
            // as well as the current number of times this particular cmd has been used
            iHotCommandCount++;
            iHotCmd[iHotCommandCount]++;
        }
    }
Writing a little function from there to determine which commands are hot is then easy.

The problem is though not only is it horribly inefficient but after 30 commands have globally been used it would result in the counter being reset thus those "hot" commands loosing their "hot" aspect.

I'm pretty sure there are other more efficient, dynamic and easier methods. Hopefully if a few experienced scripters see this topic it will turn into a good discussion.
Reply
#4

That way will work, but as you said, it would be rather slow. Instead of adding it in and checking with string manipulation, as it is far slower, just use a hash function with a unique key to store and compare the values of the command (by name, don't hash the value of times they've been used). That would quicken the process up slightly.

And if you want endless amount of commands to be added, you could simply use properties.

EDIT: And a possible flaw with the above code would be this:
pawn Code:
if(!strcmp(szHotCmds[i], cmdtext, false))
{
   iHotCmdUsed[i]++;
   break;
}
If you had commands that would have optional or per-player input, like inserting of IDs or messages, it would count "kick 1" and "kick 2" differently.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)