Home > other >  Node.js: How to avoid message repeating
Node.js: How to avoid message repeating

Time:08-14

I wrote a code for my discord.js bot. The bot randomly selects one quote from the list and sends it to the channel. I would like to prevent quotes from repeating but I'm not sure how.

const Discord = require('discord.js');
require('dotenv').config();
const client = new Discord.Client();

const config = require("./config.json");
    const quotes = [
    {
        id: "1",
        quote: "This is quote 1"
    },
    {   
        id: "2",
        quote: "This is quote 2"
    },
    {
        id: "3",
        quote: "This is quote 3"
    },
    {
        id: "4",
        quote: "This is quote 4"
    },
    {
        id: "5",
        quote: "This is quote 5"
    },
    ];

client.on('message', (msg) => {
    if (msg.content.startsWith("T!quote")) {
        const random = quotes[Math.floor(Math.random() * quotes.length)];
        msg.channel.send(`${random.quote}`   `Quote #: `   `${random.id}`);
    }
});

CodePudding user response:

You can use a hash set data structure to avoid duplicates.

var set = new Set();
client.on('message', (msg) => {
    if (msg.content.startsWith("T!quote")) {

          let random = quotes[Math.floor(Math.random() * quotes.length)];
        while(set.has(random[0].id)){
              random = quotes[Math.floor(Math.random() * quotes.length)];
        }

        msg.channel.send(`${random.quote}`   `Quote #: `   `${random.id}`);
    set.add(random[0].id)
    }
});

But using the random function, it is possible to choose the same item over and over, and the loop will work non-stop. Let's say you have a limited array of messages, so each time you add it to the set, you need to narrow your quotes array. So, storing quotes somewhere and then deleting items from the copy array is also a solution.

CodePudding user response:

Shuffle the array ... return each value in order ... when you've reached the end, re-shuffle, rinse and repeat

    const shuffler = inArray => {
        const array = [...inArray];
        let index = array.length;
        return () => {
            if (index === array.length) {
                // (re-)shuffle
                while(index) {
                    const j = Math.floor(Math.random() * (index--));
                    if (index !== j) {
                        [array[index], array[j]] = [array[j], array[index]];
                    }
                }
            }
            return array[index  ];
        }
    };

    const quotes = [
        {
            id: "1",
            quote: "This is quote 1"
        },
        {   
            id: "2",
            quote: "This is quote 2"
        },
        {
            id: "3",
            quote: "This is quote 3"
        },
        {
            id: "4",
            quote: "This is quote 4"
        },
        {
            id: "5",
            quote: "This is quote 5"
        },
    ];
    
    const getNextQuote = shuffler(quotes);
    /*
    client.on('message', (msg) => {
        if (msg.content.startsWith("T!quote")) {
            const random = getNextQuote();
            msg.channel.send(`${random.quote} Quote #: ${random.id}`);
        }
    });
    */
    for (let n = 0; n < 13; n  ) {
        const random = getNextQuote();
        console.log(`${random.quote} Quote #: ${random.id}`);
    }

Note: this won't always prevent two identical quotes in a row - since you could have

  • 1 3 4 2 5; then
  • 5 2 3 1 4

when the array is re-shuffled - you could add some logic to check what the last item was in the array before you shuffle, and make sure it's not the first item in the array after the shuffle

A trivial way to do this would be to "rotate" the array by one, say by shifting the first element off the array and pushing it to the end

if (index === array.length) {
    const lastItem = array[index - 1]; // prevent repetition
    while(index) {
        const j = Math.floor(Math.random() * (index--));
        if (index !== j) {
            [array[index], array[j]] = [array[j], array[index]];
        }
    }
    // prevent repetition
    if (array[lastItem] === array[0]) {
        array.push(array.shift());
    }
}
  • Related