user3591126
user3591126

Reputation: 211

Payout Algorithm Ruby

Im building a rails app that has users and scores. I want the top half of the users to get paid out. I have a separate tiebreaker input stored for each user if they get happen to tie for last place (last paid out place). For example, I need help, if their are 8 users and 4th and 5th tie in points. Then it calls my tiebreaker.

This is what I have tried:

First I am counting the users and determening the top half of the players:

theUsersCount = ParticipatingUser.where(game_id: game_id).size
numofWinners = theUsersCount / 2

Then I am taking the users and their scores and pushing it to an array then only showing the top half of the users that won.

  userscores.push("#{user.username}" => playerScore})
userscores[0..numofWinners].sort_by { |y| y[:score] }

But I am unsure of how to take execute the tiebreaker if their is a tie for last place.

Upvotes: 0

Views: 74

Answers (1)

Uri Agassi
Uri Agassi

Reputation: 37409

To get the users count you should use count rather than size - size fetches all the rows, then counts them, while count counts the rows in the DB, and returns the number:

user_count = ParticipatingUser.where(game_id: game_id).count

(actually - the above is wrong - here is an explanation - you should use size which smartly chooses between length and count - thanks @nzifnab)

Now, find the score of the user in the user_count/2 place

minimal_score = ParticipatingUser.order(:score, :desc).pluck(:score).take(user_count/2).last

And take all the users with this score or more:

winning_users = ParticipatingUser.where('score >= ?', minimal_score).order(:score, :desc)

now check if there are more users than expected:

if winning_users.size > user_count/2

then break your ties:

 tie_breaker(winning_users[user_count/2-1..-1])

All together:

user_count = ParticipatingUser.where(game_id: game_id).size
minimal_score = ParticipatingUser.order(:score, :desc).pluck(:score).take(user_count/2).last

winning_users = ParticipatingUser.where('score >= ?', minimal_score).order(:score, :desc)

if winning_users.size > user_count/2
  losers = tie_breaker(winning_users[user_count/2-1..-1])
  winning_users -= losers
end
winning_users

Upvotes: 1

Related Questions