/simple-secret-santa

🎁 Organize a Secret Santa 🎅 with constraints to avoid unfortunate combinations.

Primary LanguageTypeScript

An emoji picture of Santa Claus

Simple Secret Santa
(with constraints)

A backendless application for organizing a Secret Santa 🎁 with your friends, removing the stress of drawing names and enabling constraints to avoid unfortunate combinations.

Motivation

A: Let's do Secret Santa this year! 🎅🎉🎉

Everyone: Oh gosh, why? 😩

A: Come on, it's gonna be fun! 🤩🤗

B: Aight, let's do this... 🤦

C: Fine, but please don't put me with X 🙏

D: Yeah, and please I don't want presents from Y, last year it was terrible! 😬

Does this conversation pattern fit your group of friends too? Then let this Simple Secret Santa (with constraints) help your case.

Deploy

To deploy your own instance of Simple Secret Santa (with constraints) you will have to:

  1. write your own configuration file with participants and constraints
  2. run the drawing script
  3. build the frontend with the resulting pairs
  4. upload the frontend bundle on your favorite hosting platform

For convenience, all this process is automated via GitHub Actions. You'll simply have to take the resulting bundle and throw it into your favorite static site hosting platform (Cloudflare Pages, AWS Amplify, what have you).

Step 1: copy this repo

First things first, you'll need to make your own copy of this repo in order to be able to freely configure and run the GitHub Actions workflow. Hence, let's fork it or click on Use this template.

I also suggest you make it private, otherwise everyone will be able to read your configuration and tell which of your friends love/hate each other.

Step 2: write your own configuration

The configuration needs to be written in a GitHub Actions variable named CONFIG.

Navigate to the repository settings and select Secrets and variablesActionsVariables .

The GitHub repository variables section

Then click on New repository variable and create the CONFIG variable with your own configuration:

The GitHub form for adding a new variable

How to write a configuration

The configuration file structure is quite straightforward and self explanatory:

[Participants]
# ...

[Constraints]
# ...

The [Participants] section should contain the names of the people involved in the secret santa drawing. One name per line (without commas).

[Participants]
Sallie
Gianni
Bryan
Waleed

The [Constraints] sections is where you can play god without being acquainted with the devil.

Suppose Bryan must not draw Waleed. Just write:

Bryan /-> Waleed

Suppose now you want Sallie to draw one of Gianni or Waleed. Just write:

Sallie --> Gianni, Waleed

Step 3: draw and build

It's now finally time to let the CI do the drawing and build your site.

Navigate to the Actions tab of the repository, select the Build workflow and run it.

The GitHub Actions section for running the workflow

Note: here you'll also have the chance to customize parts of the final site like language and texts. Simply fill the fields that you'd like to override.

Step 4: upload the frontend bundle

As soon as the workflow completes, you'll find a bunch of artifacts available for download.

The workflow summary with artifacts and codes

Grab dist and drop it on your favorite hosting platform.

🎉 Congratulations! You saved your friends from an unpleasant Secret Santa! Just share them their code and let's see how many of you will receive ugly socks this year 🧦.

Note: for the sake of debugging, artifact pairs.json contains the drawing result. To safeguard you from erroneusly looking at pairs, names are base-64 encoded. However, it would be great if you could hand over the combinations to someone for double-checking. I'm not responsible for people not receiving presents because of bugs in the drawing process.

Demo

Check out the live demo.

Here are some screenshots btw.

F.A.Q

Answers to questions you've never asked.

How does the magical drawing algorithm work?

The configuration is parsed into a directed graph which is then reduced until every node (participant) makes and receives one and only one present.

For example, the following configuration file

[Participants]
Sallie
Gianni
Bryan
Waleed

[Constraints]
Bryan  /-> Waleed
Sallie --> Gianni, Waleed

is parsed into the following graph (left), which is then reduced to the final result (right), where it's clear who makes presents to who.

The initial graph into which the configuration is parsed The reduced graph represeting who makes presents to who

I have a trillion friends and a quintillion constraints. The drawing script crashes my PC.

The drawing algorithm uses recursion and backtracking; i.e., sucks. It's not efficient, not optimized, and I'm not planning to improve it.

My configuration is correct but the drawing script doesn't work.

You've probably been blinded by the immense power of playing with constraints and your requirements are unsatisfiable.

Consider removing some constraints... After all, why shouldn't Bryan make a present to Waleed?

Nevertheless, if you can show me a solution you found by hand that the drawing algorithm was not able to generate, you might have found a bug. Congratz! Feel free to open an Issue.

I'm a bare-hands-old-school-self-hosting aficionado. Screw your pipelines! I want to manually do the drawing, building and hosting.

There's a Dockerfile tailored to you!

# Write your configuration.
touch my.conf

# Build the image.
#
# You can customize language/texts by passing build arguments.
# Have a look at the Dockerfile to figure out all the configurable arguments.
#
# For example, to build the italian version use
#   --build-arg I18N_LANGUAGE=it
# Or to tell everyone that the budget is 20€ use
#   --build-arg I18N_OVERRIDE_SANTA_EXTRA="The budget is 20€"
#
docker build -t simple-secret-santa --build-arg CONFIG=my.conf .

# Print the codes. You'll have to share these with the participants somehow.
docker run --rm -it simple-secret-santa cat /codes.json

# Host the site.
docker run --rm -it -p80:80 simple-secret-santa

Why is this written in Vue Astro + SolidJS in the first place? It's litterally a single page with a form...

I've been asking myself the same question...