Generate a single elimination tournament - php

first , sorry for my english I'll do my best to explain my problem !
So , i'm trying to generate a single elimination tournament with an unlimited number of players.
for now i'm just thinking about it , i have nothing on paper , i think i will not have problem for tournament with power of two ( 2 4 8 16 32 players..) , my brain hangs on players going directly to round 2 , i don't know how to determine this number and where to place them.
eg (with 59 players)
I think there is a formula but I can't find it, I have some ideas but i think too specifically on a case, without knowing if it would work for another .
Thank you if you can help me !

For a given number N, find the difference between it and the smallest power of 2 at least as large as N. For 59, that'll be 5 (64 - 59). Those 5 players will be added to the tournament schedule at the second round.
This algorithm allows for all the players to be part of the game when the second round begins - i.e., as early as possible. Its explanation is very simple: imagine that originally there were 2**N players - but some just didn't come to their games, so their opponents went further without a fight. )
As a sidenote, your formula should take into account that it's strongest players that should enter the game from the second round, not the weakest ones. )
The first step apparently is calculating the number of players that will participate in the first round. Now, let's continue that 'missing players' metaphor - let's say there were 64 players originally, so the first round should have 32 games played. But 5 players (64 - 59) didn't come for those games - so the number of real games is 27 ( 64/2 - 5 ), and the number of real participants of the first round is 54 (27 * 2).
After the first round, there'll be 27 people left in the tournament - those people will be joined by those other 5 guys, so the total number of the 2nd round players is 32. The rest is trivial, I suppose. )
Actually, this is easy to commonize. Let's say we have N players, and the smallest power of 2 at least as large as N is P. Now...
The first round should have (N - (P - N)) (or just (2*N - P)) players.
The total number of the games in the first round is (N - P/2).
Apparently, the same is the number of players going into the 2nd round.
These will be joined by (P - N) players left without a play in the 1st round,
so the total number of players in the 2nd round will be...
N - P/2 + P - N => P - P/2 => P/2
... and from now you just go with the direct schedule of 2^N players (as P/2, as well as P, is the power of 2).

ooh thank you #raina77ow , you blew my mind , So here are my calculations:
64/2 = 32
59/2 = 29 ( rounded to the lower ) => nb of total player at left ( round 1 & 2)
32-29 = 3 => nb players at left going to round 2
29-3 = 26 => nb players at left going to round 1
59-29 = 30 => nb total players at right ( round 1 & 2 )
5-3 = 2 => nb players going to round 2 at right
30-2 = 28 = nb players round 1
`
I think I can make an algorithm now if that's right for each case.

Related

How do I make 2 teams of equal size and skill level given an array of 20 players with varying skills - and make it scalable in PHP

This was asked to be solved in PHP, but the concepts from any language would do.
This was asked to be scalable i.e. you can add players after, and your algo would still work.
You're given 20 total players (more can be added). Each is individually ranked with a skill level of 1-10.
You're asked to provide 2 teams with an equal amount of people, and as close to equal skill level as possible.
Sort the list of players by their skill level. Calculate the median value of the skill levels, such that as many players have skill levels above the median as players with skill levels below the median.
Find the next nearest player's skill level. The first two selected players, one on each team are the player with the median skill level, and the next nearest skill level.
Find the next two players whose score is closest to the first two players scores. Swap those players and place them on the teams. Then take the next two and don't swap them. The next two, swap them. And so on.
The algorithm should work whether you've got 8 players or 108 players. And with a few changes, it should support 2 teams with 20 players, or 100 teams with 20,000 players.
Let's create an example. 8 players, named A through H with skill levels 0 through 9. So player B7 is named B with a skill level 7.
Your available players are:
A4
B9
C7
D3
E5
F5
G1
H8
Sorting by skill level gives us:
G1
D3
A4
E5
F5
C7
H8
B9
The median skill level is 5. The next nearest skill level is also 5, so the first two players selected are E5 to TeamOne and F5 to TeamTwo.
The next two players would be A4 and C7. Swap them. C7 goes to TeamOne and A4 goes to TeamTwo.
The next two players would be D3 and H8. You swapped the last two, so don't swap these two. D3 goes to TeamOne and H8 goes to TeamTwo.
The next two players would be G1 and B9. You didn't swap the last two, so swap these. G1 goes to TeamTwo and B9 goes to TeamOne.
Now you have 2 teams, each with 4 players, whose skill levels are approximately the same.
The resultant teams would be:
TeamOne:
- E5
- C7
- D3
- B9
Average skill level is 6.
TeamTwo:
- F5
- A4
- H8
- G1
Average skill level is 5 (to the nearest whole skill level).
The more players you have to work with, the more closely team skill levels will be matched.
The PHP code to implement this should be fairly simple to write.

Getting the average grade from multiple subjects

So I have a game where a user has a grade in each subject and I want to get the overall grade when taking all current grades in to account..
So the subjects are: English, Science, ICT, Maths, Mechanics
And the grades are: A*, A, B, C, D, E, U.
Now for example each grade has an XP_NEEDED column, this column is known as the ending XP in the between and how I get the starting XP is the ending XP for the previous grade.
For example: U is 100XP, E is 200 XP, D is 500 XP, C is 1000 XP, B is 2000 XP, A is 3200 XP and A* is 4500 XP.
Possible outcomes:
If they had an A* and 4 U's, the overall grade would be around E
If they had 5 A*'s it would be A*
What is the best way to do this in PHP&Laravel 5.2? I havent tried anything yet because I dont have a clue where to start, and google doesnt help me at all.
So you should have a way of allotting XP to each user for each subject and I am assuming that each user is taking all of those five subjects.
What you basically have to implement is the Average formula which in this case would be the TotalXP(of all 5 subjects) divided by 5. This result will give you the average XP of a certain user and based on your column, you can then assign them the respective grade.
I mean the total xp a user has earned. Which will be the sum of individual XPs earned in each subject.
Let's say a user has the following XPs: 2000, 3200, 3200, 4500, 1000. The TotalXP for this user will be: (2000 + 3200 + 3200 + 4500 + 1000) = 13900.
Now to get the AverageXP: (13900/5) = 2780.
You have your limits for the grades, using comparison, see in which range does the AverageXP lie. Now you can allot the Average Grade. In this case, 2780 is a B.
(as 2000 < 2780 < 3200)

round robin tournament home away distribution

I am writing a script that creates a tournament fixtures using round robin algorithm with first team fixed. And it works well.
Problem is that when I create those fixtures I have to distribute home and away as close as possible to HAHAHA... pattern where H - is home and A - is away. Where limit is that team cannot play 3 home(or away) matches in a row.
What I tried is preserving how many home and away matches each team played and then team with lowest home or away number will play where it should.
For example
Team 1 (2 H and 1 A) VS Team 2 (with 2 H and 2 A)
Result would be :
Team 2(H) vs Team 1(A) // because Team 1 played least number away of games
Question: Is there other way to implement such home away distribution, and if is what would be the idea behind it?
The equal distribution pattern that you seek is not readily available. The suggestion to do a 'random shuffle' does not solve the problem. Distributing teams equally with opponents, equally as home & visitor, and equally to play in the time/location slots can be done. There are different requirements that must be met for an even number of teams and an odd number of teams. Add to this that the math to create each schedule is totally different (for example a 7 team league schedule is different than an 8 team league).
Checkout the information provided on this link about "equal distribution".
Equal distribution of; teams, time slots, & home & visitor is possible only if you have the correct number of time slots available for the number of teams you are scheduling. Understanding the structure of schedules is very important. Your question above about equal Home & Away (H & A) is answered in the link above. The best you can do is no more than two H or two A games in a row in each round robin. There is a minor exception where a team could have 3 Home or 3 Away games in a row when a round robin is ending and starting the next round robin. This only happens to a few teams, is unavoidable, but H & A is balanced at the end of each 2 round robins.
When scheduling teams for round robin play, in the simplest of terms you are looking to create a round robin of teams, a round robin of home & visitor status, and a round robin of time/location slots... all at the same time.
To further complicate the subject it takes a different number of round robins (one) to satisfy equal 'team' distribution, a different number of round robins (two) to satisfy 'home & visitor' balance, and a different number of round robins to satisfy 'time slot' balance. The number of round robins needed to balance all teams playing equally in all the time slots, for an even number of teams, is equal to half the number of teams being scheduled. This changes when scheduling an odd number of teams.
#Bob R The 'unavoidable' exception of 3H or 3A at the join is in fact avoidable. See D. de Werra (1981) 'Scheduling in sports', in 'Studies on Graphs and Discrete Programming' (editor P. Hansen), North Holland, pp 381-395.

Adding an extra factor (number of clicks) to a Bayesian ranking system

I run a music website for amateur musicians where we have a rating system based on a score out of 10, which is then calculated into an overall score out of 100. We have a "credibility" points system for users which directly influences the average score at the point of rating, but the next step is to implement a chart system which uses this data effectively.
I'll try and explain exactly how it all works so you can see which data I have at my disposal.
A site member rates a track between 1 and 10.
That site member has a "credibility" score, which is just a total of points accumulated for various activities around the site. A user gains, for example, 100 points for giving a rating so the more ratings they give, the higher their "credibility" score. Only the total credibility score is saved in the database, updated each time a user performs an activity with a points reward attached. These individual activities are not stored.
Based on the credibility of this user compared to other users who have rated the track, a weighted average is calculated for the track, which is then stored as a number between 1 and 100 in the tracks table.
In the tracks table, the number of times a track is listened to (i.e. number of plays) is also stored as a total.
So the data I have to work with is:
Overall rating for the track (number between 1 and 100)
Number of ratings for the track
Number of plays for the track
In the chart system I want to create a ranking that uses the above 3 sets of data to create a fair balance between quality (overall rating, normalized with number of ratings) and popularity (number of plays). BUT the system should factor quality more heavily than popularity, so for example the quality aspect makes up 75% of the normalized ranking and popularity 25%.
After a search on this site I found the IMDB Bayesian-style system which is helpful for working out the quality aspect, but how do I add in the popularity (number of plays) and have it balanced in the way I want?
The site is written in PHP and MySQL if that helps.
EDIT: the title says "number of clicks" but this is basically the direct equivalent of "number of plays".
You may want to try the following. The IMDB equation you mentioned uses weighing to lean toward either the average rating of the movie or the average rating of all movies:
WR = (v/(v+m)) × R + (m/(v+m)) × C
So
v << m => v/(v+m) -> 0; m/(v+m) -> 1 => WR -> C
and
v >> m => v/(v+m) -> 1; m/(v+m) -> 0 => WR -> R
This should generally be fair. Calculating a popularity score between 0 and 100 based on the number of plays is pretty tricky unless you really know your data. As a first try calculate the average number of plays avg(p) and the variance var(p) you can then use these to scale the number of plays using a technique call whitening:
WHITE(P) = (p - avg(p))/var(p)
This will give you a score between -1 and 1 by assuming your data looks like a bell curve. You can then scale this to be in the range 0 - 100 by scaling again:
POP = 50 * (1 + WHITE(P))
To combine the score based on some weighting factor w (e.g. 0.75) you'd simply do:
RATING = w x WR + (1 - w) x POP
Play with these and let me know how you get on.
NOTE: this does not account for the fact that a use can "game" the popularity buy playing a track many times. You could get around this by penalising multiple plays of a single song:
deltaP = (1 - (Puser - 1)/TPuser)
Where:
deltaP = Change in # plays
Puser = number of time this user has played this track
TPuser = total number of tracks (not unique) played by the user
So the more times a user plays just the one track the less it counts toward the total number of plays for that track. If the users listening habits are diverse then TPuser will be large and so deltaP will tend back to 1. This still can be gamed but is a good start.

Tournament bracket

Not sure of the best way to go about this?
I want to create a tournament bracket of 2,4,8,16,32, etc teams.
The winner of the first two will play winner of the next 2 etc.
All the way until there is a winner.
Like this
Can anyone help me?
OK so more information.
Initially I want to come up with a way to create the tournament with the 2,4,8,16,etc.
Then when I have all the users in place, if they are 16 players, there are 8 fixtures.
At this point I will send the fixture to the database.
When all the players that won are through to the next round, i would want another sql query again for the 2 winners that meet.
Can you understand what i mean?
I did something like this a few years ago. This was quite a while ago and I'm not sure I'd do it the same way (it doesn't really scale to double-elimintation or the like) How you output it might be a different question. I resorted to tables as it was in 2002-2003. There are certainly better techniques today.
The amount of rounds in the tournament is log2(players) + 1, as long as players is one of the numbers you specified above. Using this information you can calculate how many rounds there are. The last round contains the final winner.
I stored the player information something like this (tweek this for best practices)
Tournament
Name
Size
Players
Tournament
Name
Position (0 to tournament.size - 1)
Rounds
Tournament
Round
Position (max halves for each round)
Winner (player position)
Note in all my queries below, I don't include the "Tournament = [tournament]" to identify the tournament. They all need it.
It's rather simple to query this with one query and to split it out as needed for the different rounds. You could do something like this to get the next opponent (assuming there is one). For round 1, you'd simply need to get the next/previous player based on if it was even or odd:
SELECT * FROM Players WHERE Position = PlayerPosition + 1
SELECT * FROM Players WHERE Position = PlayerPosition - 1
For the next round, if the user's last Round.Position was even, you'll need to make suer that the next position up has a winner:
SELECT Player FROM Rounds WHERE Position = [playerRoundPosition] - 1
If not, the next player isn't decided, or there's a gap (don't allow gaps!)
If the users last Round.Position was odd, you'll need make sure there's a user below them AND that there's a winner below them, otherwise they should automatically be promoted to the next round (as there is no one to play)
SELECT COUNT(*) FROM Players WHERE Position > [Player.Position]
SELECT Player FROM Rounds WHERE Position = [playerRoundPosition] + 1
On a final note, I'm pretty sure you could use something like the following to reduce the queries you write by using something like:
SELECT Player FROM Rounds WHERE Position + Position % 2 = [playerRoundPosition]
SELECT Player FROM Rounds WHERE Position - Position % 2 = [playerRoundPosition]
Update:
Looking over my original post, I find that the Rounds table was a little ambigous. In reality, it should be named matches. A match is a competition between two players with a winner. The final table should look more like this (only the name changed):
Matches
Tournament
Round
Position (max halves for each round)
Winner (player position)
Hopefully that makes it a bit more clear. When the two players go up against each other (in a match), you store that information in this Matches table. This particular implementation depends on the position of the Match to know which players participated.
I started numbering the rounds at 1 because that was more clear in my implementation. You may choose 0 (or even do something completely different like go backwords), if you choose.
In the first round, match 1 means players 1 and 2 participated. In match 2, the players 3-4 participated. Essentially the first round is simply players position and position + 1 participated. You could also store this information in the rounds table if you need more access to it. Every time I used this data in the program, I needed all the round and player information anyways.
After the first round, you look at the last round of matches. In round 2, match 1, the winners from matches 1 and 2 participate. Round 2, match 2, the winners from match 3 and 4 participate. It should look pretty familiar, except that it uses the match table after round 1. I'm sure there's a more efficent way to do this repetitive task, I just never got enough time to refactor that code (it was refactored, just not that much).
Use arrays and remove the losing teams from the main array. (But keep 'em on a separate array, for reference and reuse purposes).

Categories