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

gift-exchange

v4.0.1

Published

A utility to generate pairs of names for a gift exchange.

Downloads

11

Readme

gift-exchange npm CI Coverage Status

An algorithm to generate unbiased pairs of names for a gift exchange or secret santa.

No person can be matched with themselves, anyone in the same group as themselves, or against any of the custom exclusions that can be set.

Install

npm i gift-exchange

Usage

The library ships CommonJS, ES module, and UMD builds. The UMD build makes the library available with the GiftExchange name.

calculate

function calculate(people: Person[], exclusions?: Exclusion[]): Person[];
// or
function calculate(
  people: Person[],
  options?: {
    exclusions?: Exclusion[];
    timeout?: number;
  }
): Person[];

A Person array is always required. A Person must have a unique name and optionally a group. A Person cannot be matched with another person in the same group nor with themselves. A mix of people that both have and do not have a group is supported. Additional exclusion logic can be configured with Exclusions.

calculate returns a new Person array or throws an Error if the matching algorithm fails to find a valid match after 1 second (or custom timeout, if provided), indicating that an impossible combination of people and exclusions was provided. If given an impossible configuration or one with few possible matches, and many people, this will block the thread. To avoid this, it is recommended to run the script in a WebWorker.

import { calculate, Person } from "gift-exchange";

const people: Person[] = [
  {
    name: "Brian",
  },
  {
    name: "Freja",
  },
];

try {
  const matches = calculate(people);
  const pairs: { from: string; to: string }[] = people.map((person, i) => ({
    from: person.name,
    to: matches[i].name,
  }));
  console.table(pairs);
} catch (e) {
  console.error(e);
}

validateMatches

validateMatches(a: Person[], b: Person[], exclusions?: Exclusion[]): boolean;

This is an internal helper function that validates that two Person arrays and an optional Exclusion array are valid matches where no person is matched with themselves, in the same group, or violating any exclusions. This could be helpful if you are creating your own implementation.

Exclusions

Exclusions build beyond the existing concept that no person can match another in the same group.

Exclusions are single directional. Use the type and subject properties to select a base Person or group of Persons (base selection). Then select an excludedType and excludedSubject to select the Person or group of Persons that the base selection cannot be matched with.

The There are two exclusion types, one of type name and one of type group. The type refers to a key on the Person interface. The subject is a selector for any number of people that have the given type equal to the subject.

import { Person, Exclusion } from "gift-exchange";

const people: Person[] = [
  {
    name: "Brian",
    group: "Mitchell",
  },
  {
    name: "Freja",
    group: "Andersen",
  },
];
const exclusions: Exclusion[] = [
  // a person with the name "Brian" cannot be assigned to a person with the name
  // "Freja" (but "Freja" could still be assigned to "Brian")
  {
    type: "name",
    subject: "Brian",
    excludedType: "name",
    excludedSubject: "Freja",
  },
  // anyone with the group "Andersen" cannot be assigned to a person with the
  // name "Brian"
  {
    type: "group",
    subject: "Andersen",
    excludedType: "name",
    excludedSubject: "Brian",
  },
  // anyone with the group "Andersen" cannot be assigned to a person with the
  // group "Mitchell"
  {
    type: "group",
    subject: "Andersen",
    excludedType: "group",
    excludedSubject: "Mitchell",
  },
];

Notes

The algorithm is based off of Dr Hannah Dry's solution for secret santa as described in Numberphile video The Problems with Secret Santa. This type of problem is called a derangement. This approach gives each person an equal chance for being matched with any other person. We make a derangement, then check for the same group followed by each exclusion in the list of exclusions. If the derangement does not satisfy each exclusion rule, then we shuffle the list of people and make a new derangement.