secret-santa/README.md
2023-12-01 15:36:40 +00:00

123 lines
4.1 KiB
Markdown

# README
This is a Python script for running a secret Santa draw.
This script:
- Ingests participant data in JSON format,
- Automates the randomised pairing of people to buy gifts for,
- Includes information about preferences or restrictions for gifts that participants may have,
- Automatically emails participants via GMail SMTP (requires external set-up), and
- Creates an output file of gift pairings for troubleshooting later.
The script only uses standard libraries that come bundled with Python distributions, and does not require installing any dependencies.
## Set Up
### GMail SMTP
This app uses GMail as an SMTP provider.
- This is because GMail accounts are free and easy to create,
- The server is trusted by spam filters and is unlikely to be flagged as junk, and
- The app can authenticate without using any external libraries.
This means that there will be a few steps of external set up.
- [ ] Create `secret.py` from a copy of `secret.py.bak`.
- [ ] Log in to (or create) a GMail account (a standard, free account should suffice).
- [ ] Enable two-factor authentication on the account.
- [ ] Under the two-factor authentication section, generate an `App Password`.
- [ ] Enter your GMail username and the generated app password in `secret.py`.
`secret.py`
```py
USERNAME = '<username>@gmail.com'
PASSWORD = '<app password>'
```
You can get more information on [how to do this in the GMail documentation](https://support.google.com/mail/answer/185833?hl=en-GB).
#### Using a Different SMTP Server
You can set up a different SMTP provider by editing the server information in `config.py` and providing the appropriate username and password in `secret.py`.
### Data
The script ingests data as a JSON file.
Create a file `data.json` (matching the file path in `config.py`) in the following format:
`data.json`
```json
{
"name0": {
"email": "string",
"preference": "string"
},
"name1": {
"email": "string",
"preference": "string"
}
}
```
> [!NOTE]
> **Punctuation**: Comma after every entry, except the last entry.
JSON syntax is very fragile and can break if not entered correctly.
> [!TIP]
> **Email Addresses**: If you have provided an `EMAIL_DOMAIN` value in `config.py`, then you do not need to add the full email address, and can just provide the username before the `@`.
If you do provide a full email address for a participant in the data file, it will override the domain name given.
### Configuration
You can configure the app to send the draw for the secret Santa, including the greeting and the sign-off used, via the values in `config.py`.
You can also edit the files in the `./templates` directory to customise the email message to include any additional instructions or text as needed.
The most important configurations, however, are the credentials in `secret.py` and the data in `data.json`
## Running the script
Because this script should work using standard libraries in Python 3, you should be able to execute the script using whatever Python 3 interpreter you have.
`PowerShell`
```powershell
> python app.py
```
`Bash`
```bash
$ python3 app.py
```
## The Algorithm
The algorithm I used for the secret santa draw is a very elegant one, as [illustrated by Prof Hannah Fry](https://www.youtube.com/watch?v=GhnCj7Fvqt0).
- Randomise the order of participants.
- Generate a derangement from the randomised order by shifting the top name to the bottom of the list.
- Match participants between the randomised list and derangement to pair who is buying for whom.
This ensures that:
- People know whom they are buying for, but do not know who else is buying for whom, and
- Everybody has an equal chance of buying for everybody else.
- The person running the draw also does not know who is buying for them (unless they peek behind the curtain, as it were).
## Troubleshooting
If you do need to see who is buying for whom, you can check the `output.json` file, or check the sent emails from the SMTP server.
## Isn't This an Over-Engineered Solution for a Trivial Problem?
Of course it is.
## Why Not Use an Existing Site for This?
Because where is the fun in that?