0

I've been at this for awhile. I am building a simple lottery website and I am generating random tickets. On my local machine random numbers are generated, however, on the server they are duplicated.

I have tried multiple versions of what I have, but the duplicates is the same.

I need to create a random ticket number per ticket and ensure that it hasn't bee created.

This my like 50th version:

 a = Account.find(current_account)
    numTics = params[:num_tickets].to_i
    t = a.tickets.where(:item_id => item.id).count
    total = t + numTics
    if total > 5
      left = 5 - t
      flash[:message] = "The total amount of tickets you can purchase per item is five.  You can purchase #{left} more tickets."
      redirect_to buy_tickets_path(item.id)
    else
        i = 1
        taken = []
        random = Random.new
        taken.push(random.rand(100.10000000000000))
        code = 0
        while i <= numTics do
          while(true)
            code = random.rand(100.10000000000000)
            if !taken.include?(code)
              taken.push(code)
              if Ticket.exists?(:ticket_number => code) == false
                  a.tickets.build(
                    :item_id => item.id,
                    :ticket_number => code
                  )
                  a.save
                  break
              end
              code = 0
            end
          end
          i = i + 1
        end
        session['item_name'] = item.name
        price = item.price.to_i * 0.05
        total = price * numTics
        session['amount_due'] = total.to_i
        redirect_to confirmation_path
    end
Brian
  • 5,951
  • 14
  • 53
  • 77
  • A note on idiomatic Ruby... `if Ticket.exists?(:ticket_number => code) == false` should be rewritten as `unless Ticket.exists?(:ticket_number => code)`. You should virtually *never* find yourself using `== false` or `== true`. – user229044 Sep 30 '12 at 23:49
  • Yes, I know, but like I said I've been fed up with this and tried a million different approaches. Thanks! – Brian Oct 01 '12 at 00:00

2 Answers2

2

You should be using SecureRandom if possible, not Random. It works the same way but is much more random and doesn't need to be initialized like Random does:

SecureRandom.random_number * 100.1

If you're using Ruby 1.8.7 you can try the ActiveSupport::SecureRandom equivalent.

Also if you're generating lottery tickets, you will want to make sure your generator is cryptographically secure. Generating random numbers alone is probably not sufficient. You will likely want to apply some other function to generate these.

Keep in mind that most actual lotteries do not generate random tickets at the point of purchase, but generate large batches in advance and then issue these to purchasers. This means you are able to preview the tickets and ensure they are sufficiently random.

tadman
  • 208,517
  • 23
  • 234
  • 262
0

The problem is not with Ruby's pseudo random number generator but that fact that you are creating generators all the time with Random.new. As explained in this answer, you should not have to call Random.new more than once. Store the result in a global object and you'll be good to go.

Community
  • 1
  • 1
Marc-André Lafortune
  • 78,216
  • 16
  • 166
  • 166