I want to build a realtime quiz game which randomly matches two players (according to their winning rate if they are logged in). I've read through the book Discover Meteor and have a basic understanding of the framework, but I just have no idea of how to implement the matching part. Anyone know how to do that?
-
I needed to pair together opponent randomly in my game, so I started on writing a package doing that ([peppelg:random-opponent-matcher](https://atmospherejs.com/peppelg/random-opponent-matcher)). Feel free to use/improve it, and please let me know if you come across/start writing on your own package that's better. – Peppe L-G Feb 27 '15 at 08:21
-
Good job @PeppeL-G. I've read your package's README but kind of confused by its logic. Can you provide a demo app or maybe describe a simple use case? – irrigator Feb 28 '15 at 02:54
-
I posted it as a solution. Feel free to ask your questions as comments to it. – Peppe L-G Feb 28 '15 at 08:59
3 Answers
if you want to match users who have scores close to each other, you can do something like this : mongodb - Find document with closest integer value
The Meteor code for those Mongo queries is very similar, but there are some subtle differences that are kind of tricky. In Meteor, it would look something like this :
SP // "selected player" = the User you want to match someone up with
var score = SP.score; // selected player's score
var queryLow = {score: {$lte:score},_id:{$ne:SP._id}};
var queryHigh = {score:{$gte:score},_id:{$ne:SP._id}};
// "L" is the player with the closest lower score
var L=Players.findOne(queryLow,{sort:{score:-1},limit:1});
// "H" is the player with the closest higher score
var H=Players.findOne(queryHigh,{sort:{score:1},limit:1});
so, now you have references to the players with scores right above and right below the 'selected player'. In terms of making it random, perhaps start with a simple algorithm like "match me with the next available player who's score is closest" , then if it's too predictable and boring you can throw some randomness into the algorithm.
you can view the above Meteor code working live here http://meteorpad.com/pad/4umMP4iY8AkB9ct2d/ClosestScore and you can Fork it and mess about with the queries to see how it works. good luck! Meteor is great, I really like it.
One implementation might be as follows:
A user somehow triggers a 'looking for game' event that sets an attribute on user.profile.lookingForGame to true. The event then makes a call to a server side Meteor method which queries for all other online users looking for games.
From there you it really depends on how you want to handle users once they 'match'.
To determine all online users, try using the User Status package: https://github.com/mizzao/meteor-user-status
Once added, any online user will have an attribute in the profile object of 'online'. You can use this to query for all online users.

- 944
- 1
- 11
- 26
-
Sorry for any poor formatting - did this from my phone. I'll update with more detailed explanation tomorrow. – Eric T Feb 26 '15 at 04:39
-
Thanks for your answer Eric. As for determining online users, I come up with this solution: When a player click the 'Match' button, his/her user document's 'ready' attribute will be set to 'true'. As soon as a round of game is over, both players 'ready' attributes will be set to 'false'. Therefore when the server is matching two players it can choose among those that are 'ready'. What do you think this solution? – irrigator Feb 27 '15 at 00:48
If you add the package peppelg:random-opponent-matcher to your application, you can match together opponents like this:
On the server, you need to have an instance of RandomOpponentMatcher
like this:
new RandomOpponentMatcher('my-matcher', {name: 'fifo'}, function(user1, user2){
// Create the match/game they should play.
})
The function you pass to RandomOpponentMatcher
will get called when two users been matched to play against each other. In it, you'll probably want to create the match the users should play against each other (this package does only match opponents together, it does not contain any functionality for playing games/matches).
On the client, you need to create an instance of RandomOpponentMatcher
as well, but you only pass the name to it (the same name as you used on the server):
myMatcher = new RandomOpponentMatcher('my-matcher')
Then when the users is logged in and which to be matched with a random opponent, all you need to do is to call the add
method. For example:
<template name="myTemplate">
<button class="clickMatchesWithOpponent">Match me with someone!</button>
</template>
Template.myTemplate.events({
'click .clickMatchesWithOpponent': function(event, template){
myMatcher.add()
}
})
When two different logged in users has clicked on the button, the function you passed to RandomOpponentMatcher
on the server will get called.

- 7,351
- 2
- 25
- 50
-
Great, now I understand much better. One question though: does your package detect users that have been matched thus avoiding match users who already are in a game, or should I implement it myself? – irrigator Feb 28 '15 at 09:36
-
The server has a list of users seeking for an opponent, and when the user calls the add method, the user is just added to that list. When there are two users in that list, those two users are removed from that lists and matched together. So the user is matched with at most one opponent each time it calls the add method. – Peppe L-G Feb 28 '15 at 09:41
-
The README of your package says it does not provide a way to notify the client when it's been matched. What I want to do is to first route the user to a waiting page when he clicks the 'match' button (where he may click 'cancel' to trigger matcher.remove()), then when onMatch gets called I'll create a new game document and route the two matched users to the corresponding game template. But without the user being noticed when he has been matched, how can I do that routing? – irrigator Mar 01 '15 at 12:36
-
When two opponents are matched, you create a new game document containing (among other things) the two users who should play it (probably their ids). The users will subscribe on the game documents they should play (I presume, how else will they know the matches they should play?), and you can therefor use [observe](http://docs.meteor.com/#/full/observe) (the added callback) to get notified when the current user got a match to play. Are you with me? – Peppe L-G Mar 01 '15 at 13:42