Like most teams, we take turns to speak in our daily stand-ups. When we gather around the sprint board, it's easy to know who speaks when - we start at one end and pass the role along the line.
At present, we're all working remotely, so there's no physical ordering that we would agree on. And we would get tired of using the same order every day, leading to diminished engagement. So we start the meeting by publishing the day's speaking sequence. I started with a random shuffle of the team members, but soon realised it would be better if any of us could generate the list, and we'd all get the same result. So I now use the date as a seed for shuffling.
I use a MD5 hash to quickly spread the entropy all around the random word (just using date +%F
unmodified resulted in the same sequence every day, because all the variation is near the end), and xxd
to convert its hexadecimal output into raw bytes.
#!/bin/bash
set -eu -o pipefail
team=(Alice Bob Charlie Dan Erin Frank)
# Header for today
date +%A:%n
# Team members in today's order
printf '%s\n' "${team[@]}" |
shuf --random-source <(date +%F|md5sum|xxd -r -p)
2 Answers 2
Some suggestions:
#!/usr/bin/env bash
is a more portable shebang line.- I would use long options for
set
andxxd
for readability. Soset -o errexit -o nounset -o pipefail
andxxd -revert -plain
. - If you quote the array members you can easily use full names.
- In case any remote workers are in another time zone offset you'll want to use a fixed one, such as
TZ=Pacific/Auckland date +%F
. If you want to be on the safe side, get the time zone where your meeting time is midday at that offset (in the same hemisphere if possible, to avoid a 2 hour offset half of the year). That way, anyone running this code within 12 hours of the meeting time will get the same result. - The output of
md5sum
is already completely scrambled. Passing it toxxd
doesn't make the randomness input any more random. As mentioned in the comments it may be thatshuf
only uses a very small part of that randomness, in which casexxd
is justified. Unfortunatelyman shuf
doesn't go into any detail about--random-source
. - You can randomize arguments to
shuf
:shuf --echo --random-source <(date +%F|md5sum|xxd -r -p) -- "${team[@]}"
achieves the same withoutprintf
. --random-source=<(...)
would make it obvious that it is a key/value pair rather than a flag followed by a file argument.
-
\$\begingroup\$ Thanks. I had to use
xxd
because themd5sum
output is only hex digits, so lots of the bits are unvarying (shuf
) has a tendency to use very few bits from the random source. Point 6 is new to me - I overlooked thatshuf
can use arguments as input, so thanks greatly for that. \$\endgroup\$Toby Speight– Toby Speight2021年01月22日 09:11:10 +00:00Commented Jan 22, 2021 at 9:11 -
1\$\begingroup\$ I was worried there wouldn't be enough to review in such a short script - constantly amazed by the quality of contributors here! :-) \$\endgroup\$Toby Speight– Toby Speight2021年01月22日 09:12:00 +00:00Commented Jan 22, 2021 at 9:12
-
\$\begingroup\$ I agree with most of this, but the
set
line is pretty idiomatic for bash strict mode. redsymbol.net/articles/unofficial-bash-strict-mode \$\endgroup\$chicks– chicks2021年01月22日 16:30:03 +00:00Commented Jan 22, 2021 at 16:30 -
\$\begingroup\$ @chicks For sure, I just deviate from idiomatic whenever I think it makes the code better. \$\endgroup\$l0b0– l0b02021年01月22日 19:08:11 +00:00Commented Jan 22, 2021 at 19:08
-
\$\begingroup\$ Fair enough. I'm usually a fan of making the code self-explanatory, but in this case I usually just drop that link in a comment above the two lines of strict mode. \$\endgroup\$chicks– chicks2021年01月22日 19:22:27 +00:00Commented Jan 22, 2021 at 19:22
Consider using a different language
Prompted by a comment, I chose to re-implement in Python. This has a couple of advantages:
- No external dependencies (
xxd
isn't part of a default Debian or Ubuntu system) - Perhaps portable to our peer teams using non-Linux platforms.
I didn't do anything to ensure consistent time zone handling, because my team are all in the same time zone. Even if we share with the other teams, none of those straddle the date line during working hours, so not a concern for us. But suggestions welcome in the comments to this answer, if you have them!
I was able to add a couple of features:
- We have guests who are not part of the development team, but often attend and have useful information to contribute. These people always speak after the core team, in a specific order.
- Attempt to copy to a clipboard, if we find one. This was previously done outside of the shuffle script itself, but doing it from Python increases our portability.
Note: I considered storing the team list in a file to separate code from data, but preferred to keep everything in the source file as it's then easier to share amongst the team.
#!/usr/bin/python
team = "Alice, Bob, Charlie, Dan, Erin, Frank".split(', ')
guests = "Eve, Mallory".split(', ')
import sys;
import datetime;
import random;
today = datetime.date.today()
random.seed(today.toordinal())
random.shuffle(team)
output = (today.strftime('%A:%n%n') +
'\n'.join(team + guests))
print(output)
# Save to clipboard if we can (for pasting into team chat)
try:
import pyperclip
pyperclip.copy(output)
except:
pass
-
1\$\begingroup\$ It looks good. You can remove the semicolons at the end of imports. I didn't check if the distribution is fair to every team member. You could use a for loop for the next 1000 days, to check that every team member is equally distributed to each position. \$\endgroup\$Eric Duminil– Eric Duminil2021年01月24日 10:38:37 +00:00Commented Jan 24, 2021 at 10:38
-
\$\begingroup\$ The semicolons are a remnant from unrolling your one-liner; I'll remove them. \$\endgroup\$Toby Speight– Toby Speight2021年01月25日 13:25:05 +00:00Commented Jan 25, 2021 at 13:25
python -c "import sys;from datetime import date;import random;team=sys.argv[1:];random.seed(date.today().toordinal());random.shuffle(team);print(' '.join(team))" Alice Bob Charlie Dan Erin Frank
\$\endgroup\$