This post was written in February 2020, but is dated back to January 2019, because that was when I wrote the web application.
Jump to: ↓ description of the code
In Aachen, Rudi rockt is a well-known running dinner organizer. Running Dinner (apparently Progressive dinner in English) is a dinner event where you form teams of two. There are three courses (starter, main course, and dessert) and each team prepares one course for two other teams – for the other two courses, each team is a guest of another team. (This means that you change locations between each course.) Over the evening, each participant meets 3 courses × 2 other teams × 2 team members = 12 new people. Normally, there is an afterparty at some club.
For my birthday in 2019, I organised a “running dinner pub crawl” through Aachen under the name of “Bernhard bechert”. 1 There where no teams, but each of my friends got a personal route through three bars, with about six people meeting at every bar. The timetable was as follows:
- 20:00: First round
- 20:45: Second round
- 21:30: Third round
- 22:15: Afterparty
(With at most 15 min’s travel time, this would give guests at least 30 min’s at each bar.)
I had set myself some constraints for the routes:
- I had to get reservations for each bar (or at least be very certain that there would be space for my guests).
- No guest should visit any bar twice. Also, I wanted guests to visit bars that were new to them.
- For every guest, consecutive bars had to be within walking distance. (With the exception of guests that had checked a “I can travel by bike”-checkbox.)
- Guests should not have to walk alone to the next bar.
- At every bar, there should be 6 guests (but at least 4 and at most 8).
- Everybody should know at least one other person (in order to be comfortable)
- Everybody should not know at least one other person (so that each group would feel new and exciting for every guest)
- Healthy mix of social circles (so people wouldn’t only talk about one topic specific to that clique)
I also had a few other rules, for example that couples could start together, but I would also separate them for at least one bar.
bernhard web application
For RSVP management, route planning, and the distribution of the routes, I wrote a website. Every participant got a personal login and could answer some fun questions on their user profile, view their route, and import an iCal feed of their route into their calendar application. The website was a relatively simple Django application, but a) fun to write and b) a good gag for the party 2.
I planned the routes manually, because I thought that would be easier than encoding all of the “soft” social constraints I had in my head into some optimization problem. The website helped me by showing me the travel times between bars, by color-coding people from the same clique/social circle, and with a handful different overviews I programmed that each highlighted a different aspect of the plan (an overview of every guests route, the guests in every bar over the evening, etc.):
I created the plan by starting with some assignments of guests to bars and then iteratively planning the routes of more and more guests. In the end, I got stuck and started over two times with until I had a plan that worked out.
During the event, I had to change an assignment in round one to handle a last-minute cancellation, which worked well — the guest whose route I changed sat next to me and could instantly see the new route on their phone (I know that I was very smug in that moment because I was such a capable programmer and event organiser). Other than that, the party went pretty much as planned.
I distributed the logins to my guests about two weeks before the event. Guests should login before the routes were ready to enter a nickname and answer a small questionnaire that would help me with planning the routes.
After the routes were ready, guests could view their personal route online. For each stop, the website showed guests the bar, a tagline/motto for the stop, a description of the bar, an address, information about the seat reservation, a small map, and nicknames and RSVP status of the other guests they would meet here.
I also gave little tasks to some guests (for example, I had one round playing secret Bingo: three guests got words they had to weave into the conversation, the three other guests got words they had to listen for). Guests could set a drink they wanted the other guests to pre-order for them if they were late.
Most of that information was also available in the iCal feed that guests could import into their calendar application.
The web application was written in Python 3.7 and with Django 2.1, I think I only had
django-cal as dependencies (for Bootstrap forms and the iCal feed, respectively).
Technically, it wasn’t a really complex application, but because I knew all of my friends would use it (and no one else) and because it was such a personal project, I had a lot of fun developing it.
Reviving the code a year later
When I tried to restart the web application about a year later to take a few screenshots for this post, I couldn’t login. If I used wrong login data, the login forms complained, but if I used a correct login, nothing at all seemed to happen – I was just being redirected to the start page again. At first I thought I was running the wrong version of Django or that somehow, something in the database, the passwords, or the virtual environment was broken.
After a lot of unsuccessful attempts to corner or circumvent the problem, I tried manual authentication in the Django shell with (example from the docs):
from django.contrib.auth import authenticate
user = authenticate(username='john', password='secret')
That seemed to work.
I then remembered that my deployment and coding setup had been very ad-hoc at the time, and that I was basically running production settings.
Firefox developer tools confirmed my suspicion that the session cookie was missing, and after I wrapped the following Django settings into a
if not DEBUG, everything worked fine again:
if not DEBUG:
SECURE_CONTENT_TYPE_NOSNIFF = True
SECURE_BROWSER_XSS_FILTER = True
SESSION_COOKIE_SECURE = True
X_FRAME_OPTIONS = 'DENY'
Takeaway: Don’t be lazy with your setup or you will waste a lot of time later.