npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

tiny-matchmaking

v0.0.1

Published

Tiny matchmaking server.

Downloads

2

Readme

tiny-matchmaking

Tiny Node.js matchmaking server.

Install

$ npm i tiny-matchmaking --s

Info

This package exposes two classes (MatchMakingServer and MatchMakingClient). The server class encapsulates a WebSocket server, and a Map of objects submitted by remote clients.

The server must take a callback function as a constructor argument whose purpose is to determine whether any two objects in the pool should be considered matches (takes two client objects as arguments and returns boolean).

The server constructor can take a second (optional) callback argument which also accepts two client objects as arguments, the return value of this function will be sent back to both clients.

If this second callback is not passed the response to each client will look like:

{
    client: any, // object initially submitted to pool
    opponent: any // client object which was considered a match
}

These functions can both consider whatever predicates you like as long as the relevant information is contained within the client objects. Each client object must:

  • Expose the same fields
  • Contain a unique id field

For example:

const client_obj = {
    id: 34523, // can be number or string
    elo: 500,
    power: 9000,
    name: "p4_"
}

You can send a client object with any fields you like as long as each client is exposing the same interface. Using the above example, the callback functions would be working with two client objects in the form:

{
    socket: WebSocket,  // no methods for working with this are exposed, socket operations are handled internally by the MatchMakingServer and MatchMakingClient instances.
    time_joined: number, // time this client joined queue
    id: number,
    elo: number,
    power: number,
    name: string
}

Server Callbacks

Example function that determines whether two objects should be considered a match. Function is always called with two parameters, both are client objects from the pool. Must return boolean.

const is_match = (user_1, user_2) => {
    return Math.abs(user_1.elo - user_2.elo) < 100;
}

Example function for parsing results if the default response doesn't suit your use case. Function is always called with two parameters, both are client objects from the pool.

const results_func = (client_1, client_2) => {
    return client_1.power > client_2.power
        ? {winner: client_1.id, loser: client_2.id}
        : {winner: client_2.id, loser: client_1.id};
}

MatchMakingServer Example

From here, instantiating the server is as simple as:

// Constructor params
// @port: number 
// @match_function: (client_1, client_2) => boolean -> (whatever you want beyond that)
// @results_function? (optional): ((client_1, client_2) => any) | null;
// @options? (optional): {
//  queue_time: number  -> (how many ms for each client to stay in queue before giving up)
//  poll_interval: number -> (how often to check the pool for matches
//  allowed_clients: string[] -> (ip whitelist, not considered if nothing is passed in)
//  disallowed_clients: string[] -> (ip blacklist, not considered if nothing is passed in)
//  https_server: HttpsServer -> (if you want to use wss you will need to pass you own server in, otherwise a http server is created for you) (UNTESTED)
// }

const { MatchMakingServer } = require('tiny-matchmaking');

// with results function
const server = new MatchMakingServer(5000, is_match, results_function, {poll_interval: 1000, queue_time: 20000});
// without
const server = new MatchMakingServer(5000, is_match, null, {poll_interval: 1000, queue_time: 20000});

The results sent back to the clients will be handled by a callback function passed in to the MatchMakingClient constructor.

Client instances can be instantiated at a single middlepoint to handle multiple clients (like on a Discord bot) or on individual application instances.

The constructor takes a server URL and the callback discussed above, and exposes a single method (match) which will send a client to the matchmaking pool and execute the callback when the server responds with the match results.

Client Callback

Example function to handle whatever you sent back from the server on each client.

const client_match_result_handler = (args) => {
    // eg. you might call client_post_match(args); here
    console.log(`client received results:\n${JSON.stringify(args)}`);
}

MatchMakingClient Example

const { MatchMakingClient } = require('tiny-matchmaking');

const client = new MatchMakingClient('ws://127.0.0.1:5000', client_match_result_handler);
const player_1 = {id: 1, elo: 150, power: 700, name: "Charlie"};
client.match(player_1);

The MatchMakingClient instance can be used to keep sending clients to the matchmaking pool (like you might on a Discord bot), or instantiated as needed on each client application instance.

Full Example

Server.js

const { MatchMakingServer } = require('tiny-matchmaking');

const is_match_func = (client_1, client_2) => { // MUST RETURN BOOLEAN
    return Math.abs(client_1.elo - client_2.elo) < 100;

}

const results_func = (client_1, client_2) => {
    return client_1.power > client_2.power
        ? {winner: client_1.id, loser: client_2.id}
        : {winner: client_2.id, loser: client_1.id};
}

// choosing not to pass results_func here
const server = new MatchMakingServer(5000, is_match_func, null, {poll_interval: 1000, queue_time: 20000});

Client.js

All client objects are being sent from the same client machine here, in practice they can come from any number of different remote machines.

const {MatchMakingClient} = require('tiny-matchmaking');

const client_match_result_handler = (args) => {
    // eg. you might call client_post_match(args); here
    console.log(`client received results:\n${JSON.stringify(args)}`);
}

const client = new MatchMakingClient('ws://127.0.0.1:5000', client_match_result_handler);

const player_1 = {id: 1, elo: 150, power: 700, name: "John"};
client.match(player_1);

const player_2 = {id: 2, elo: 320, power: 900, name: "Sergio"};
client.match(player_2);

const player_3 = {id: 3, elo: 380, power: 300, name: "Brooklyn"};
client.match(player_3);

const player_4 = {id: 4, elo: 160, power: 450, name: "Miguel"};
client.match(player_4);

example scripts