My english is not very well, but i try to explain.
I must create a schedule for championship. We have 8 players. They play in one league. THeir will be 7 tournaments played in cup system. So, every player will be play with every player, and it's not problem:
schedule
I want to every player when he goes to semifinals play with every player two times (assuming they get promoted to semifinals). So player number one must play ones in quaterfinal with player 2, and two times when he get promoted to semifinals.
Related
I am writing a perl program to schedule N number of teams to play each other team once as home team and once as visitor. We use two fields and two time periods. So up to eight teams play in a day. No team can play at the same time on both fields or play twice in the same day. Any team not playing for the day is put on the BYE list.
I have written the code to define all the required games. But when I try to schedule each game and remove it from the array of games to be played, I arrive at conditions where there are no games left that can satisfy the rules for field or time periods in a day. This is most pronounced if I do not shuffle the array of games to be played. Even with 8 teams, I get these conflicts near the end.
What is the logic to deconflict the schedule sequence?
Do not simply create a list of all games and select from that at random: you need an algorithm to create the rounds - the circular method being the "standard" one (see for instance the link in the comment by #David Eisenstat).
Once you created the rounds you still have to define a calendar that will respect the limitation of 4 games per day (and no team playing more than once per day). This is straightforward: if one round fills exactly one or more days, i.e. if you have 8, 16, 24, ... teams, then you simply split each round in the requested number of days. But even if N is not a multiple of 8, there are no problems.
Lets' keep things simple, and consider the case of N = 12, so each round requires one day and a half: on day 1 you select (randomly) 4 of the 6 games of round 1; on day 2 you select the 2 missing games of round 1, and 2 games of round 2, taking care to avoid that the same team plays twice in a day; finally on day 3 you complete round 2, and so on. Can we be sure that we will always able to assign day 2 avoiding the duplication of a team? Yes, we can: when you assign the last two games from round 1, you have 4 teams affected; even if in round 2 there are no games between those 4, you only exclude 4 games from day 2, so you still have 2 games available for placement on that day.
Final notes: as you can see there's no need for a bye list. The only situation to deal with is when N is odd, and it is usually handled by adding a dummy team.
Regarding home vs visitors, you will need to repeat the full calendar a second time. Just note that it is not possible to have every team alternating between home and visitors at each round. For instance with 4 teams you may have TeamA (h) vs TeamB and TeamC (h) vs TeamD; at the second round you may still do TeamD (h) vs TeamA and TeamB (h) vs TeamC; but at the third round TeamA and TeamC must play each other, and both come from a visitor round. And the same hold for TeamB and TeamD, who both come from a home round.
I have an application where users sign on to play a quick 1v1 game (20 seconds duration). I would like to know the most efficient way to pair each user up with another user to play the game and move onto the next user without playing the same user multiple times in a row.
My first idea was to have two queue's containing the user id's of each online user. Whenever a new user goes online I would add them to whichever queue is the shortest and constantly be popping one person off the top of each queue to play each other. After the game I would simply add each user to the same queue to avoid them playing each other again. This seems good but I would like to see if there are any other more efficient ways to do this concept without needing to keep a list of previous users played on the server.
You need to matchmaking system that will prioritize players who have been waiting the longest.
You only need 1 queue and you also need to keep track of users history using a table. The table can either be temporary session data or a database table if you want permanent data across multiple sessions or if the match making server crashes. The table should have the playerID and an array of previous playerIDs that they previously played against. It can be best to limit the size of the array and use LIFO as you might not want to just store the players most recent match ups i.e. match history. Also the player could run out of players to play against if they already played against everyone else online. The table should look like this:
playerID (integer)
previousPlayerIDs (array of integers)
When a match starts you can update the the previousPlayerIDs for all the players in the match. You need to listen to an event when a player has joined the queue lets call it onPlayerJoin(). If the queue has more than 1 player you should take longest queuing player and compare their playerID against the previousPlayerIDs of each player until you find no history of a match up.
const historyLimit = 10;
function onPlayerJoin(Player newPlayer){
playerQueue.push(newPlayer);
if(playerQueue.length > 1){
for(let a=0; a<playerQueue.length-1; a++){
Player player = playerQueue[a];
for(int i=a+1; i<playerQueue.length; i++){
Player otherPlayer = playerQueue[i];
//if the player have not played before
if(otherPlayer.previousPlayerIDs.indexOf(player.id) > -1){
//save match up
player.previousPlayerIDs.push(otherPlayer.id);
otherPlayer.previousPlayerIDs.push(player.id);
//limit matchup histroy
if(player.previousPlayerIDs.length > historyLimit){
player.previousPlayerIDs.removeAt(0);
}
if(otherPlayer.previousPlayerIDs.length > historyLimit){
otherPlayer.previousPlayerIDs.removeAt(0);
}
//create lobby and remove players from the queue
createLobby(player, otherPlayer);
playerQueue.removeAt(a);
playerQueue.removeAt(i);
}
}
}
}
}
It is possible for a player to have played everyone else and they are waiting for someone to come online that they haven't played against before. You will need a reoccurring event to check if the longest waiting player has been waiting too long. If this is the case just ignore the matching of previousPlayerIDs and create a lobby for the the player up with another potentially long waiting player.
If you want you could add more columns to the table such as a timestamp when they joined the queue and their match making rank (elo). But if you just want to prioritize the most recent player you don't need these other columns.
Also this solution might not scale up very well if you have massive amounts of concurrent user but it should be fine if you have less than 1,000-10,000
Your idea doesn't work. Eventually (possibly very quickly), you'll end up in a position where two players who have played previously end up in separate queues. You can't guarantee that they'll never be selected to play together again.
Imagine this simple case:
Queue 1 Queue 2
A B
C
A and B play, and get added to Queue 2:
Queue 1 Queue 2
C A
B
A and C play, and get added to Queue 1:
Queue 1 Queue 2
A B
C
Now A and B play again. C never got the opportunity to play B.
This particular example is unlikely to occur, true. But something similar can happen even with larger queues as the space between player X and all the players he's played over time increases. The likelihood of ending up with two players playing each other again without having played every other potential player is quite high. I suspect the probability is similar to the birthday problem.
Your solution seems fine, but you should just use a single queue.
I would like to ask for help with an algorithm I’ve been working on for quite some time. I actually programmed it a few years ago using greedy pairing mostly but I’m not satisfied. Any help would be greatly appreciated!
So getting down to business. I have an application for tournament play (beachvolleyball to be precise, but should work for any pair-sport played in tournament format). The players show up on tournament day and gets randomly-ish put together with other participants and against other random teams. Top focus is to play as much as possible, however the number of players aren’t always divisible by the number of simultaneous playing spots. Therefor there will always be a number of players resting, standing the round out that is, and I’m trying to make sure this is as fair as possible by using 2 variables:
Rests (total number of rests during the day)
Rests in a row (Resting several games in a row, obviously)
The original concept of the tournament was mixing the teams with 1 male(m) and 1 female(f) in each team, playing against another team of m/f. However, the resting part is more important and there is often a lot more players of one sex than the other (i.e. 20 f and 7 m). Instead of letting the males play every single round, the program should make teams of f/f playing against f/f. Same-sex vs f/m should be avoided though.
Players should get new partners every round and play against new teams every round. Preferably you should play with all players of the opposite sex before playing with someone again. Players are allowed to come and leave as they like, and also take a break at any time (voluntary rest).
I’ve looked into the unstable marriage problem and the roommate problem, but my problem seems to be a mix of the two. Normally there will be two lists of players (m/f) and pairing, but under certain premises there should be teams made from just one list as described. Let me give you an example:
EXAMPLE:
43 players show up for a tournament with 6 courts.
17 Females (f) and 26 Males (m).
The 6 courts fit 12 teams with a total of 24 players per round.
Round 1
*12 m - 12 f*
*19 resting (5f, 14m)*
Round 2
5f and 14m have 1 rest and should play.
The best solution would be:
*4 f - 4 m*
*1f - 1m*
*4m - 4m*
*1f - 1m* (these players played last round as well).
In this example there will normally not be more than 1 rests in a row, if there woud’ve been 49 players from the start on the other hand..
In future updates, I’m also planning on letting the user choose number of players per team, and also to skip the m/f requisite.
Any thoughts?
I'm creating a single function called progress() that is called after a player acts.
I think there are only 3 possible ways to end a poker game:
Game ends normally, there are 2 or more players until last round ends, do the "showdown" phase, and determine winners
Game ends abruptly, there is only one player remaining (all other players folded), that player wins, and his/her cards are not shown
Game ends fast-forward, there are no players who can act (e.g.: all players act "all-in"), the remaining community cards are drawn, do showdown and determine winners.
Here's the current pseudocode:
Determine 'players in game' (i.e. players who hasn't folded)
If there are two or more players in game
If there are players who hasn't acted
Start next player turn
Else (all players has acted)
If all players all-in, OR all players ALL-IN except one player
(If there are less than one player who can act)
Ends game fast-forward: showdown and determine winners
Else (two or more players who didn't act ALL-IN)
If this round is last round ('River')
Ends game normally: showdown and determine winners
Else
Begin next round
Else (there is only one player in game)
Ends game abruptly: that one remaining player wins
Is there anything I missed?
I think it's important to think in terms of betting rounds, not the
game as a whole. A poker hand is a sequence of betting rounds. At the
start of each round, some cards are dealt, some player is chosen to
act first, and then players are visited in order until the round ends.
Among the data you need to keep (it's a lot) is the identity of the
player who made the most recent raise in the current round (call him
"the agressor" even though it might just be big blind), and that
amount. The actions that end a betting round are these:
A player calls. Next player is the agressor.
End round, continue game.
A player folds. Next player is the agressor.
a. If more than one player has cards and unbet money, end round,
continue game as normal.
b. If two or more eligible players remain, but all but agressor
are all in, end round, continue game, but no more betting.
c. If only the agressor has cards, end game and round.
Do not deal any more cards.
If the game was not previously ended by (2c), then after the end
of the final betting round, showdown cards, award pots.
(Note: minor exception here for live blinds and straddles, so
add that bit in. And a bit of special-case code needed for the all-in for more than a call but less than a raise situation).
In pseudocode:
for each hand:
set "bluff" flag to false
clear all betting data
for each round:
if "bluff", break
deal some cards
while true:
visit each player
either force his action, or offer choices
if his action ends the round:
if it also ends the game (2c), set "bluff"
break (end round)
if "bluff", award all to bluffer.
else showdown, award pots as required
This question isn't really language specific, it's more about the logic behind ALGORITHMS that would be used in pairing players in a 1v1 match-making game.
This is a two part question.
If I have a game that's match-making 1v1 type game and you open your phone's app, select "play" and it finds an opponent for you, what's the best way to go about this?
Let's say in my database of players I have a key called "pairing" with a BOOL value YES/NO.
Someone opens the app, clicks play, so I need to pair them, so I flip this BOOL to YES and then we look for someone else with a YES value and make a confirmation and then they play?
What happens if the first user closes the app while they were waiting to paid up because they got bored and left, the server value would stay as "Yes" because I can't switch it to NO because the app is closed. So this won't work.
So instead I have a key "Pairing" with an int value and 0 = no and anything other than 0 is yes, so every second I increase this value by 1 from the client, to the server. At any given time if this value has not changed after 10 seconds or so (server side) I assume the user closed the app and left, so we flip the value to "0".
Okay so now we have proper pairing-mode detection (Question 1: Is this the best way to detect proper pairing mode? A dynamic variable)
But, now that I have 10,000 players on a server all in pairing mode, what's the best way to make matches? What if I end up with 5 players (Players A,B,C,D,&E) all getting paired to the same player (Player F), sure I just use some simple rand() tie breaking algorithm, but it seems someone could end up in ties ALL the time and keep getting tossed around, it could take 20 seconds just to make a confirmation that two players are set to battle each other. The optimal algorithm would pair everyone efficiently, any thoughts? I have a feeling it will involve a queue of some sort, in order of how long you've been waiting to be paired. (That's question 2)
The way I would implement this is as follows:
Every player has a unique player_id in the database.
When a player connects to your server (it should not be connecting to the database itself), add them to a list of active sessions.
Have a specific interval as the timeout. The client should send a ping packet to the server every second (or whatever time period you would like). If the server has not received a ping from the client after a specified amount of time, disconnect the client. If the player was in a game when this happened, notify the other user that their opponent has disconnected, and consider the match void.
If you would like to prevent void matches, you could save the current game session state to the database (or other external source) and when both players are ready again, notify each of them that the match is ready.
At this point, we've solved the connectivity issue. Now, to your question about if multiple users get paired up to the same person. The easiest thing to do would be something like
while server is running
if player is not currently in a match
if there are available opponents
set the first player's opponent to the opponent
set the opponent's opponent to the first player
remove each of them from the list of available players
else
wait for an opponent to become available
You should also remove the player from the list of available players if the server has not received a ping packet after n time from the client.