Coffee Shouts
Yet another side project that got a bit out-of hand.
For those unaccustomed, in Australia "shouting a round of drinks" means one person buys drinks for everyone in the group. No idea where the term comes from. Google it yourself if you care.
My run club has a hard, hilly run scheduled every Thursday morning.
Afterwards we gather at a local cafe for coffee. There are regularly between 10 and 15 runners present.
Tradition dictates that one of the runners shout the drinks.
A month or two back a couple of mates suggested (tongue it cheek) that I should get off my backside and write an app that would allow us to keep track of whose turn it was to pay for the drinks.
Challenge accepted.
The app has two main functions:
- Compiling the order (who needs what).
- Figuring out who will pay.
Function 1: Who gets what?
Coding this was pretty straight forward, although a bit finnicky and tedious.
Growing up, the only coffee I knew about came out of a can.
There were limited options: +/- milk and +/- sugar.
Fast forward 40 years and the landscape is now considerably different.
The above graphic barely scratches the surface. Other variables include milk type, cup size, sweetener, and beverage heat.
I don't pretend to yet understand all the combinations and permutations. But I've made a start adding the options my group seems to use.
When someone participates in a round their preference is set as their default for the next round as well. So generally the shout setup only involves confirming that a group member is present.
The finalized round is displayed in a way that is hopefully easy to take to the counter and order.
Function 2: Whose turn?
Figuring out who should shout took a bit more thinking. Ideas about length of time since last shout, or total number of drinks previously bought were quickly shelved. Group members come and go, and the frequency of their presence is too variable for this to make sense.
I ended up formulating an algorithm that tracks the drinks each individual either buys for, or receives from, every other person. At a given gathering, members are ranked based on their aggregate deficit/surplus of drinks bought/received - but only for the combination of participants currently present. In this way different group members can be present or absent on any particular day and they are neither advantaged or penalized in the rankings.
The participant with the greatest deficit is suggested as the designated shouter. Ties are broken by random selection. This selection can be manually changed, and multiple shouters can be nominated if the shout is split two or more ways. Split rounds are recorded proportionally (ie., it is possible to shout someone half a cup, or a third etc.).
No effort is made to put dollar amounts to the beverages. This app is meant to facilitate casual interactions between friends. It's not an accountant's wet dream for balancing every last cent and nitpicking relative contributions to group activities.
That said, sometimes it is good to know who is not pulling their weight, and know that they know you know... 😜
Design considerations
There were three main considerations when designing this app.
- It had to be mobile.
- It had to be distributed
- all groups members should have access
- It had to be simple.
- no tedious signups or logins
To create a mobile and distributed app I chose to build a progressive web app (PWA) utilizing a PouchDB / CouchDB backend.
To keep things simple I decided to give each coffee group a UUID based identifier. To join a group you have to know this code.
Each group member has equal access rights. This means that someone could try to 'game' the system by adding false orders or something. I haven't tried to prevent this. If members of your social group are likely to do this maybe they shouldn't be members of your social group...
Workflow
The app itself can be found at https://s4ag.com/drinkshout/.
Regardless of whether you are on a PC or a mobile device you can (and should) 'install' this locally for easy access. The process of doing so depends on your device but is generally pretty obvious.
According to this guide: "On most desktop browsers, the install prompt is in the URL bar. On mobile, the install prompt is generally found in the menu of browser options."
Once installed it will behave like other applications that are installed on the device. No App Store or Google Play required.
Create a group
If your friends don't already have a Drink Shout group you will need to make one. Use the hamburger menu icon at top right and navigate to "Create Group".
After you have entered a group name you'll see a screen like this.
You don't have to share your group. You can be the sole person in charge of record keeping for your group.
If you do want others to share the load, press the "Share" button.
Note that I have a message on there about the potential for sharing to be a paid feature. This is simply because this is the one part of this application that could be burdensome for me if it became popular. Right now the backend runs on a Raspberry Pi in the corner of my office. I'm thinking that is fine for the few people that will likely ever use this app. But just in case...
"Sharing" the group will get you to this screen:
The details on this page are what you need to share the group with others.
In this case the group code is "23WHBV1K9DzCU8-qTWNCS8NJTHChj58mzvD3C". Try this one if you like. If it doesn't get abused I'll keep it live as a test group.
Don't share your group code with anyone you don't want to be a member of your group. They will have full read/write access and you probably don't want that.
Join a group
To join an existing group use a code a friend has given you. Copy and paste. Alternatively use the "Start scan" button to scan the QR code directly off their phone.
Create a shout
If a group is new it won't have any members. That's ok. You add them when you set up a round. Members are only identified by their names, and there cannot be duplicates.
If a friend is participating in the round use the little on/off switch beside their name to include them.
You will then be able to alter their drink option
In the case above you can see that both participants are equally likely to be nominated to shout (as no participants have yet shouted).
You then review the shout (making sure to nominate whoever is shouting if it is not the automatically selected person)
When happy, choose the "Finalize" button and you are done.
For the moment I have only included a limited ability to alter past shouts. This is about stopping bad actors, and could change. So try to get the shout right before you finalize!
That's it! The remainder of the app is mainly screens showing various aspects of group and user shouting history. Note that if you have multiple groups, and members who are common between them, the app doesn't make the connection. It treats members as being unique to each group. You can add the same name to different groups, but the app will not share member preferences and history across groups.
🍵🍵🍵
Disclaimer. This is something I maintain for my friends. It comes with zero warranties of any type. Shit will probably break.