commit 6a6ecabe4caa645b1e820db4bb766c861316becd Author: june Date: Tue Nov 25 14:28:53 2025 -0800 first commit :3 diff --git a/README.md b/README.md new file mode 100644 index 0000000..471c01b --- /dev/null +++ b/README.md @@ -0,0 +1,33 @@ +# June's Small Secret Santa Selection Script (JS⁵) + +JS⁵ (or JS5, if you can't be bothered to copy-paste the unicode superscript 5) is a small utility script for planning secret santa events, or similar, over the internet. Most existing solutions require either drawing names out of a physical hat, or some centralized organization service, which is annoying to me specifically. + +JS⁵ is my attempt to remedy all of these problems. It's run locally, and allows planning a secret santa without revealing, even to yourself, who the recipients are. It assigns everyone a recipient, such that the directed graph forms a hamiltonian cycle. It then shuffles the assignments, and outputs them with each participant's target listed in base64-encoded text, salted so as to make the assignments non-obvious. + +## Usage + +To use JS⁵, modify the list `participants`, run the script, and send each person their base64-encoded string. + +Example usage: +`python js5.py | out.txt` + +Example output (using placeholder names): +```text +Alice: RGF3biBpcyB5b3VyIHNlY3JldCBzYW50YSByZWNpcGllbnQgPV4uXj0= +Dawn: RXZlIGlzIHlvdXIgc2VjcmV0IHNhbnRhIHJlY2lwaWVudCA6Mw== +Eve: eW91ciB0YXJnZXQgZm9yIHNlY3JldCBzYW50YSBpcyBCb2IgOjM= +Carol: eW91J3ZlIGJlZW4gYXNzaWduZWQgQWxpY2UgZm9yIHNlY3JldCBzYW50YSA6Mw== +Bob: Q2Fyb2wgaXMgeW91ciBzZWNyZXQgc2FudGEgcmVjaXBpZW50IG8uTw== +``` + +## Strengths and limitations + +The main appeal of JS⁵ is that you can run it locally and send the assignments to your friends over any messaging service, with no need for any action on their end. You can also participate in the secret santa yourself, without knowing who is assigned to who. + +This does come with a couple of drawbacks. First and foremost, there's no way for you to prove to your friends that you haven't peeked -- it's entirely honor system. In addition, the randomness is obviously and trivially cryptographically insecure, and the limitation of a hamiltonian cycle may conflict with others' design ethos for a secret santa. In my opinion, all of these are worth it. I actually really like the fact that the assignments form a hamiltonian cycle, since it means that no two people will ever be assigned each other. The issue of the "honor system" requirement doesn't matter to me; it's a secret santa, why would you ruin the fun for yourself? + +Nonetheless, I thought it worth cataloguing the design tradeoffs here. + +## Dependencies + +JS⁵ is written and tested on python 3.13.7. \ No newline at end of file diff --git a/js5.py b/js5.py new file mode 100644 index 0000000..50d72bb --- /dev/null +++ b/js5.py @@ -0,0 +1,37 @@ +import random +import base64 + +# Modify +participants = [ + "Alice", + "Bob", + "Carol", + "Dawn", + "Eve" +] + +# this is just a lot of junk to make sure all the base64 text is somewhat visually indistinct +def get_recipient_text(recipient): + format_strings = [ + "{} is your secret santa recipient", + "your target for secret santa is {}", + "you've been assigned {} for secret santa", + ] + salts = [ + ":3", + "^_^", + "=^.^=", + "o.O", + ">:3c", + ] + return random.choice(format_strings).format(recipient) + " " + random.choice(salts) + +# make a random loop of all participants, assigning each person to the next +random.shuffle(participants) +recipients = list(map(lambda s: base64.b64encode((get_recipient_text(s)).encode('utf-8')).decode('utf-8'), participants)) +participants = participants[1:] + participants[:1] # list rotation +assignments = list(zip(participants, recipients)) +random.shuffle(assignments) + +for participant, recipient in assignments: + print(f"{participant}: {recipient}") \ No newline at end of file