Free email newsletter: “ES.next News

2014-05-23

Implementing a raffle in JavaScript

At two recent occasions, there were copies of “Speaking JavaScript” to be raffled off. This blog post describes two ways of drawing winners via JavaScript.

There is a list of the attendees’ names

If there is a list of the attendees’ names, drawing a winner is relatively easy. In my case, it was a MunichJS meetup and a list of names was online, as a web page. In a browser console, I accessed the DOM to make a random pick:

    // Once:
    var nameElements = document.querySelectorAll('span.D_name');
    var names = [].map.call(nameElements, function (elem) { // (1)
        return elem.textContent.trim();
    });
    
    // Repeatedly:
    names[Math.floor(Math.random() * names.length)] // (2)

At (1) I invoke map() generically, because the result of querySelectorAll() is not an array and does not have that method.

At (2), I use Math.random() and Math.floor() to compute an integer in the range [0, names.length).

You don’t know the attendees’ names

If you don’t have a list of the attendees’ names then you need figure out a way to pick a place. For many seating arrangements, there is an aisle in the middle. In such a case, I find a triple easy to understand as a coordinate:

  1. Row number (starting at zero)
  2. Column number (starting at zero, relative to left/right side of auditorium)
  3. 'left' or 'right'

#2 and #3 mean that you stand in the aisle and start counting chairs either to your left or to your right, once you are at the right row. The following function computes a random coordinate, if you provide it with the number of rows and the number of columns (in each side of the auditorium).

    function raffle(rowSize, colSize) {
        return {
            row: Math.floor(Math.random() * rowSize),
            colDir: (Math.random() < 0.5 ? 'left' : 'right'),
            column: Math.floor(Math.random() * colSize)
        }
    }

Using the function looks like this:

    > raffle(10, 5)
    { row: 3,
      colDir: 'right',
      column: 3 }

No comments: