Wednesday, April 21, 2021

Caption Me: Covid-19 Vaccine Edition

Despite the look on my face, the Covid-19 vaccination process was without drama. After months of hearing about the vaccine, it's pretty sweet to have a dose in my arm. A huge thank you to everyone that made this possible, from the scientists who did the basic research, to the CVS employee who offered me water while I waited to see if I had a reaction, and everyone in-between.

Thursday, April 15, 2021

Discovering and Critiquing the Shed Kit

This past weekend I was cleaning out our shed and made a bit of a discovery. Behind some old paint cans was a Tupperware container filled with emergency gear. I'd apparently found a kit I'd stashed in our shed for some future cataclysmic event. Let's critique it!

The container is of the 4 cup Ziploc variety and here's its contents:

The Good

Let's start with the good. What do I like about this kit?

1. I have to admit this was at least a creative attempt. So creative I forgot about it, but still, an attempt was made.

2. The container was an excellent choice. It's a good size and the contents were in pristine condition despite the shed being a hot and dusty place.

3. I was happy to see the kit consisted mainly of high-value universal items. Regardless of the emergency, a mylar blanket, drum-liner, Bic lighter, tap knife, sharpie, safety-pins and handkerchief are always going to be useful.

4. The candles were an especially good choice. They provide light and heat without requiring batteries and pair well with the Bic. As if to prove the point, the finger-lights were both dead, I assume because the batteries had failed.

5. It's nice to see extra gear getting put use, rather than being stashed away in a drawer.

The Bad

But it's not all sunshine and roses. Let's talk about the short-comings of the kit.

1. It's missing some obvious items. Most notably, where's the key to the house and cash? The most likely emergency I can imagine where I'd have access to the shed but not my house is if I'm locked out. In fairness, I do have a key stashed somewhere else on our property for just this scenario. But still, how could I not have dropped a few bucks into the kit? From a weight and volume perspective, it's hard to beat the problem-solving impact of cash.

2. And speaking of missing items, there's at least two universal items that are obviously missing: rope and duct-tape. I just watched this emergency gear preparedness video, much of which I could quibble with, but he does have a solid point: a 100 yard spool of dental floss would be a cheap and easy way to equip a kit like this with cordage.

3. I'm generally wary of the multi-kit approach to preparedness. In theory, having a car kit, bike kit, hunting kit, travel kit, etc. let's you optimize each for the constraints of the given scenario. In practice, I've found that it's too easy to forget what's in the kit. You end up, like I have, driving around thinking you have jumper cables in your car kit and don't. Or just as problematic, thinking you don't have jumper cables and do.

My preference is to build out a small universal kit, bring it more or less everywhere and augment it as needed. Fore example, I always try to have a Bic lighter, duct tape and heat sheet on me, and then in our car I've added a battery-powered jump starter.

This doesn't work when space is especially tight (I'm looking at you, trail running kit), but generally there are many benefits to this core gear approach.

4. And my biggest critique: what problem was I actually trying to solve here? I'm all for simple joy of kit building, but the first step in the process is understanding what you're actually preparing for. In this case, the kit cost me almost nothing in terms of space, time and money, so there wasn't any real downside to it. And caching items in alternative locations is a clever strategy to experiment with. But to make this a truly effective kit, I'd need to identify when I'd want to deploy it, and practice using the kit in that capacity.

That's one of the primary issues with the gear video I noted above. It's an interesting take on emergency gear, but without specifics of how it's going to be used, there's no real way to know if it hits the mark or not.

Now What?

I've mulled over what I'm going to do with the kit and here's where I've landed: I've removed the cheapy items (like the knock-off Swiss Army knife and non-functional finger lights), added some cash and I've put the kit back in my shed.

Ultimately, it's doing no harm there and has got me thinking about what kind of emergency would benefit from having gear stashed in our shed. And most importantly, it's a sort of gift to my future self who will no doubt be delightfully shocked when, in a few years, I rediscover it.

Tuesday, April 13, 2021

The Lazy Gabbai: Shell Scripting ShulCloud

As a programmer, I'm all about embracing laziness. So when I found myself week-after-week clumsily clicking through the yahrzeit section of ShulCloud I knew I needed a better way. The shell script below is that better way.

The What

Taking a step back, ShulCloud is the platform my synagogue uses to help manage itself. One feature of ShulCloud is the ability to track yahrzeit's, that is the date an individual has passed away. We use this information to help loved ones honor their deceased relatives on the anniversary of their death.

As a gabbai in my shul, I use this information to let me know who should be honored in the upcoming week.

The How

ShulCloud doesn't offer a developer's API (not that I blame them, but a programmer can dream). So the strategy I'd have to use is good 'ol fashion web page scraping. Every time I want to download the list of yahrzeits I use curl to re-login into the site and invoke the export URL. The ability to pass a cookie jar file to curl (via -b $COOKIE_JAR and -c $COOKIE_JAR) means that cookies set during the login process are carried forward when I attempt to download the export.

I do a bit of date math to allow me to specify the time frame I want to view in terms of an offset. For example, I can run the following:

  # this week's yahrzeits
  $ shulcloudassist -a yz
  ...

  # last week's yahrzeits
  $ shulcloudassist -a yz -w -1
  ...

  # two week's from now yahrzeits
  $ shulcloudassist -a yz -w 2

A couple other notes of interest: I had to do use gdate on Mac to get access to GNU date. A case $(uname) in statement at the top of the script lets me set the date command to use and should make this script cross-platform. And finally, I used csvkit to process the exported data.

Here's what this week's yahrzeit list looks like. Note that I'm running the output through scrub_names.sh to replace real names with random ones. The output tells me not just who the mourner is and the anniversary date of their loved one, but also the date's offset relative to today. Below Berry Guss is remembering Randall Royce, and I can see that the exact yahrzeit was 2 days ago.

$ shulcloudassist -a yz |  sh ./scrub_names.sh 
Sat Apr 10 (-3d) Shannon & CorneliusAnn Portia, Rodger Hans: Ann Ezra
Sun Apr 11 (-2d) Berry Guss: Randall Royce
Mon Apr 12 (-1d) Teri Esmeralda, Lacy Willis: Margret Kathryne
Mon Apr 12 (-1d) Valorie Frank: Gregg Craig
Mon Apr 12 (-1d) Rodrigo Kattie: Madelyn Sol Gena
Tue Apr 13 (0d) Dixie Maud: Neal Toni
Wed Apr 14 (1d) grandmother of Alec Charlie: Norman William Dorian Ramon
Thu Apr 15 (2d) Christi Bryce: Jessie Sebastian

Even if you don't use ShulCloud, you may find this web scraping and date mashing example helpful. Happy Hacking!

The Script

#!/bin/bash

##
## Script to automate stuff within shulcloud
##

USER=XXXXXXXXXXXXXXXXXXXX
PASSWORD=XXXXXXXXXXXXXXXXXXXX
BASE=https://someurl.shulcloud.com
COOKIE_JAR=$HOME/.shulcloudassist.cookies

case $(uname) in
  Darwin)
    DATE=gdate
    ;;
  *)
    DATE=date
    ;;
esac

usage() {
  echo "Usage: $(basename $0) -a yz [-w <week-offset>]"
  exit 1
}


login() {
  sccsrf=$(curl -s -c $COOKIE_JAR $BASE/  | grep sccsrf | sed -e 's/^.*value="//' -e 's/".*//')
  curl -d action=login \
       -d redirect=$BASE \
       -d sccsrf=$sccsrf \
       -d "email=$USER" \
       -d "password=$PASSWORD" \
       -c $COOKIE_JAR -b $COOKIE_JAR \
       -s -i $BASE/login.php > /dev/null
}

while getopts ":a:w:h" o; do
  case "${o}" in
    a)
      action=$OPTARG
      ;;
    w)
      week=$OPTARG
      ;;
    * | h)
      usage
      ;;
  esac
done

case "$action" in
  yz)
    if [ -z "$week" ] ; then
      week=0
    fi
    shift=$(($week * 7))

    sow=$(($($DATE +%u) + 1 - $shift))
    eow=$((6 - $sow))
    start=$($DATE -d "$sow days ago" +%Y-%m-%d )
    end=$($DATE -d "$eow days" +%Y-%m-%d )
    start_fmt=$($DATE -d "$start" +%m/%d/%Y)
    end_fmt=$($DATE -d "$end" +%m/%d/%Y)
    now=$($DATE -d 00:00 +%s)
    
    login
    
    curl -s -G \
         -d order=next_date \
         -d order_asc=1 \
         -d search= \
         -d is_active= \
         -d search_mourners= \
         -d gender= \
         -d setPerPage=100 \
         -d start_date=$start \
         -d text_start_date=$start_fmt \
         -d last_start_date=$end \
         -d end_date=$end \
         -d text_end_date=$end \
         -d last_end_date=$end_fmt \
         -d has_plot= \
         -d has_plaque= \
         -d has_relatives=Y \
         -d action=export \
         -b $COOKIE_JAR -c $COOKIE_JAR \
         $BASE/admin/yahrzeits.php | \
      sed '1d' | 
      while read line ; do
        d_fname=$(echo $line | csvcut -c 3)
        d_lname=$(echo $line | csvcut -c 4)
        mourner=$(echo $line | csvcut -c 22 | tr -d '"')
        observed=$(echo $line | csvcut -c 10)
        offset=$(($(($($DATE -d "$observed" +%s) - $now)) / 86400))
        date=$($DATE -d "$observed" +"%a %b %d")
        echo "$date (${offset}d) $mourner: $d_fname $d_lname"
      done
    
    ;;

  *)
    usage
    ;;
esac

A Bonus

Here's the script I used to randomize names in an input stream. This script was intended as a throw-away, which is why it's not particularly elegant.

#!/bin/bash

##
## scrub names from input. Replace what appears to be a name
## with a random name from baby-names.csv.
##
## Grab baby-names.csv from
## https://github.com/hadley/data-baby-names/blob/master/baby-names.csv
##
sed 's/[A-Z][a-z][a-z][a-z][a-z]*/NAME/g' | tr '\n' '@' > /tmp/ping

while [ -n "$(grep NAME /tmp/ping)" ] ; do
  name=$(shuf -n 1 baby-names.csv | csvcut -c 2)
  sed "s/NAME/$name/" /tmp/ping > /tmp/pong
  mv /tmp/pong /tmp/ping
done

cat /tmp/ping | tr '@' '\n'

Friday, April 09, 2021

Cheap, Loved and Sharp(er) | Putting an Edge on a $1.00 Hatchet

Earlier this week I found myself scrounging through drawers looking for a tool to pry a plastic disk from the glue pad it was cemented to. I found just the tool in my Columbia Must-Have Multi-Tool. Between the heat from the hairdryer and the leverage from the multi-tool, I had the project completed in no time.

I also got to relish in the joy my Columbia Must-Have Multi-Tool gives me.

Back in 2016 Shira and I visited Bogota, Columbia. While there we found ourselves in the equivalent of $1.00 store, and while shopping I spied a bin full of these beauties:

Did I need a poorly made combination hammer, pry-bar, hatchet, nail puller? Uh, yeah. I did. Badly. The 10 year old boy in me needed one, and the adult in me figured it would be a novel souvenir.

Back from our travels, I hadn't found a use for the multi-tool. One reason why: the hatchet blade was comically dull.

After my experience earlier this week using the pry-bar, I got to thinking that sharpening the blade may be a worthwhile undertaking. I'd end up with a more useful tool and perhaps learn something along the way.

I followed the advice offered in Home Built Workshop's How to Sharpen an Axe video. I ordered an $8.00 axe file off of Amazon, clamped the multi-tool to our kitchen island, and cautiously started to scrape away at the blade.

It was like magic! With just a few strokes of the file I could tell that I was removing metal, shaping the blade and generally making things better. It's almost like the axe file is designed for sharpening axes (spoiler alert: uh, yeah. What else would it do?). I suppose I figured that the file required a skilled operator; apparently not.

All told, I probably spent 30 minutes sharpening both sides of the blade. I found the repetitive process oddly soothing. I'm the farthest thing from an expert, but I'm almost certain I could feel when the file was at the right angle and I was making forward progress.

The blade is definitely not 'shaving sharp.' But it's vastly sharper than when I started. As you can see from the carrot I sacrificed to the cause, not only could I chop, but I could slice shavings, too. I do believe I finally have a functional blade on this sucker.

Overall, I'm really pleased with this little project. I avoided buying gimmicky or over-priced products to get the job done. Instead, I focused on learning a new skill in a low-pressure way. I couldn't have dulled the hatchet any further. About the worst I could done would have been to ruin an $8.00 file. That's a risk I was glad to take.

Want your own Columbia Must-Have Multi-Tool? You can buy the same tool on Amazon for $12.00. It's not the $1.00 or so I paid for mine in Columbia, but of course, you won't have to buy plane tickets to Bogata. So there's that.

The hatchet even comes with this notice: comes dull for your own safety, sharpen it to your own preference. You see, the dullness is a feature, not a bug! And I think they're on to something: buying a cheap hatchet and file will give you a chance to be amazed at what a little elbow grease can produce.

Thursday, April 08, 2021

Four Photos, Four Truths

 

I captured the above photos by running by the same set of trees for 4 weeks. Here's four take-aways from this experiment.

1. Trees are Amazing

They take whatever abuse nature and humans throw at them during the winter, and just when you think they can't possibly be alive, they explode with growth. I know this is how trees work, but still, it's amazing.

2. Unix is Great

I had dozens of the photos of the above scene, yet I needed to pick the best four photos to work with. After downloading a zip file of all images, I ran the following Unix commands to organize them:

# Make a directory for each day and store all the day's photos
# in it
$ for f in *.jpg; do d=$(identify -verbose $f  | \
                         grep exif:DateTime: | \
                         awk '{print $2}' | \
                         sed 's/:/-/g'); \
    mkdir -p $d ;  \
    mv -v $f $d; \
done
renamed '20210311_165836.jpg' -> '2021:03:11/20210311_165836.jpg'
renamed '20210311_165840.jpg' -> '2021:03:11/20210311_165840.jpg'
renamed '20210311_165842.jpg' -> '2021:03:11/20210311_165842.jpg'
renamed '20210316_165538.jpg' -> '2021:03:16/20210316_165538.jpg'
...

# Launch the feh image viewer to preview each
# directory's images at once
for d in *; do (cd $d ; feh --auto-rotate -i  -E 300 -y 300  *.jpg &) ; done

Using feh I was able to get a visual overview and then pick the four best matching photos.

3. Art is Hard

In my mind's eye, this project was going to result in a composite image that displayed the breathtaking transition from lifeless landscape to Cherry Blossom Greatness that the DC area is known for.

Needless to say, I missed that mark:

You can see the transition in the above photos, but there's nothing jaw dropping about it. My attempt to capture the scene precisely the same way every week was a bust, and many of the trees around where I took these photos were bursting with flowers while the trees I focused on where relatively bare.

Ultimately, I got out of this project what I put it into. I grabbed photos while out on my run, and the results look like this.

All this makes me appreciate a well crafted art project, the likes of which takes notable time and attention. And if you do it right, folks will almost certainly think I could have done that.

4.The App I Needed

To do this project right, at a minimum I'd need more care in picking my location, more time to allow shooting multiple locations, and the use of instruments (measuring tape, compass and tripod) to confirm consistent camera placement.

However, I could have shortcut this a bit if I had a camera app that supported Onion Skinning. That is, the ability to show a partially-transparent imagine in the camera preview. This allows lining up a shot using a guide-photo.

A quick search on Google Play returned a couple of options for a camera app like this, though none of them looked like a fit for me. Ionic, my app building framework of choice, has a Camera Preview plugin. An interesting test would be to place a partially transparent image over the Image Preview component. If that works, then I could make my own 'Onion Skinning Camera App' with relative ease.

Tuesday, April 06, 2021

Review: A Minute to Midnight

Every once in a while Shira will be reading a book she thinks we might both enjoy, and she'll opt to read it aloud. I enjoy audio books, so I find this quite the treat. It turns reading into a shared activity, like binging a TV series. Unlike TV, we can do this while multi-tasking.

So for the last few weeks, while I loaded and unloaded the dishwasher or was cleaning the kitchen for Passover, Shira narrated David Baldacci's A Minute to Midnight.

In A Minute to Midnight I got to meet Atlee Pine, the hero of the book. I like her. Mostly. She's thoughtful and confident, without being insufferable and cocky. I can't tell if her weight lifting past adds detail to her character, or puts her over the top.

The pace of the book felt slow, but if I'm kind, I can chalk that up to Baldacci trying to keep things realistic. She encounters a series of puzzling murders, and I can appreciate that it takes time to put all the pieces together.

One aspect of the book I found surprisingly enjoyable was how Baldacci had a number of plot details that initially seemed like author goofs, but upon further reflection made sense.

Take Pine's childhood. Are we to believe that a trained FBI agent wouldn't spot the massive inconsistencies in her own parent's behavior? She can tell when a stranger is lying to her, but doesn't recognize the suspicious behavior in her own parents?

Actually, I buy that. For must of us, whatever our childhood was, was by definition normal. We can't imagine our parents as inexperienced human beings with their own baggage because to us they are Mom and Dad, not real people.

Or consider the presence of the Pagani. Are we to believe that a baddy would opt to be seen in a 20 million dollar car in a resident neighborhood? That's ridiculous. But when we consider the role of the car was to attract attention and that the person who selected the car didn't know the details of what they were picking, the choice seems plausible. Who would have thought the flashiest car in the garage would turn out to be absurdly unique?

One quirk of the book I haven't decoded: its title. I missed the first chapter (Shira started reading the book to herself before she made it an audio book), so maybe the answer was in there. But honestly, I have no idea what the title is referring to. I guess I'll have to hit Google to find out.

Should you drop everything and read A Minute To Midnight? Sadly, no. It's a fine read if you like a good o'l murder mystery, but there wasn't anything here to make it stand out for me. The story was generally slow and snapped into place at the last moment in typical fashion.

Still, as a shared reading experience, it was a positive one. And we will definitely be back for the next book in the series.

Monday, April 05, 2021

Two Tuna Based Observations

Two observations on this fine Monday morning:

First, what a world we live in! You're telling me that I can order 48 packets of tuna on Sunday night at 8pm, and they're delivered to my front door by 9am the next day? In time for second breakfast, no less! And, all this convenience for a price that's cheaper than buying at the supermarket?

Amazing.

And second, while we've never had an issue with our packages being stolen, and I'd never condone the practice, I can say that an itty-bitty-teensy-weensy part of me wishes that a porch pirate had nicked this one. They'd pick it up and think, hmmm, this has some heft to it I bet it's pricey electronics.

And when they opened the goods they'd be shocked to find they just stole some freak's tuna stash. Oh the very thought of the hypothetical look on their face makes me smile.

Tuna, anyone? I've got more than enough to share.

Friday, April 02, 2021

Build Your Own LG V60 Floating Bar

Shira's new LG V60 ThinQ is a sweet phone. The jury is out on whether the dual screen is genius or gimmick, but I applaud LG for the attempt. As someone who regularly busts out a bluetooth keyboard to program directly on my phone, all that screen real estate is a dream.

The Challenge

One feature that Shira misses with her new phone is the LG Floating Bar. This compact menu bar could be expanded to quickly access apps or contacts. For a while, there was a recipe for running an old version of the Floating Bar on the V60, but recently that stopped working.

Knowing her husband has mad next level programming skills (my words, not hers), she asked if I could help build her an alternative app. A quick Tasker search encouraged me that I could.

My search turned up a video I'd watched years ago, but had forgotten about. Floating Bar Demo: Auto Tools Web Screens:

So this was possible. It took me a couple of attempts, however, to figure out how to build and customize my own floating bar. I'd like to save you the trouble of figuring this out yourself, so here's a quick tutorial to get you started. Enjoy!

Step 1: Install The Tools

To make your own bar you'll need Tasker, AutoApps and AutoTools. These apps are worth paying for, so do so if you can.

Step 2: Install the Demo Floating Bar

Fire up tasker and make a new Task called FloatingBar Launcher. Add a single action: Plugins » AutoTools » Web Screen. Configure the action, selecting 'Screen Preset' and choosing 'Floating Bar.' Click the check-mark to save your work.

If all goes well, you'll find yourself back at the task definition. Run the task and you should see a floating bar appear at the top of the screen. Awesome, right?

Step 3: Try, Fail and Fix the Gravity Setting

Let's say you want the Floating Bar to appear on the right hand side of the screen versus the top. It's easy enough to edit the action you created, going to Window Settings » Gravity » Right.

Save your work and re-run the Task. If all goes as expected, then you'll notice nothing happened. You changed the gravity, but the toolbar still shows itself at the top of the screen. What gives?

What seems to be going on is that the first time you ran the task you launched your floating bar. The floating bar is still running, so when you executed the task again, no new floating bar was created. My fix, therefore, is to insert a new action into the task that closes the floating bar. This forces every execution of FloatingBar Launcher to create a fresh floating bar and use whatever settings have been selected.

Create a new action: Plugin » AutoTools » Web Screen. Configure the action and select Display Mode » Close. Yes, to close a web screen you have to make a new web screen. Just go with it. Make sure this closing action is first in the list of actions to execute and then try running the Task. If all goes well, you'll have a floating bar that respects your choice of right-side positioning.

Obviously, you'll need to use this close action with care. As it's setup above, it closes all web screens. Ultimately, you'll want to tweak it so that it just closes the one floating bar you're creating, otherwise this will mess with your other Web Screen creations; probably not what you want.

Step 4: Make It Your Own

You've now got a floating bar that you can control. The next mystery is how to replace the stock icons with your own. Turns out, that's easy. Edit the Configuration of the Floating Bar Web Screen and go to Items. Here you'll configure key aspects of your floating bar. Start by selecting the icons you want to include. AutoTools will help you out by letting you graphically select them.

Next, click on the 'Commands' field. This brings up a text box that you need to fill in with care. You want to enter a comma separated list of words here, where each word will correspond to the icon you selected. Given the icons I've chosen, I entered the following:

  Lamp,House,Clock,Calc

It's important that there are no spaces after the commas and that capitalization is consistent. Finally, I filled in the Command Prefix with FloatingBar

When I re-run the FloatingBar Launcher Task I now see a floating bar with my selected icons on it. When I click the icons I see a message showing me the word I put in the Command list prefixed by the Command Prefix. Sweet, right?

Step 5: Make It Work

We've customized our toolbar so that it shows the icons we want and generates the commands we want. Now how do we respond to those commands? Easy. Make a new Profile: Event » Plugin » AutoApps. Notice here we selected 'AutoApps' when creating the profile, not AutoTools. This wasn't obvious to me, but this is what you're after.

Configure the plugin by entering a command that your floating bar generates, for example: FloatingBar=:=Calc.

I'm going to continue with the theme of building out 'FloatingBar=:=Calc', so I created a new Task named 'FloatingBar Calc'. That task has a single Action: App » Launch App » RPN Calc.

With that profile enabled, when I click on the calculator icon in the toolbar the RPN Calc app is launched. The floating bar works!

Step 6: Make it Awesome

At this point, you should have a functional floating bar. You need to make corresponding actions for every command, and you'll want to tweak the floating bar so it looks good. Take time to browse through the AutoTools Web Screens options and customize away.

Thursday, April 01, 2021

Insights from Passover, 2021 Edition

Passover 2021 is on! We're still in pandemic mode over here, so our seders were small and I attended services over Zoom. Still, I've picked up a number of new insights this year which I'm always eager to share.

A huge thanks to my Mother-in-Law for getting me a copy of The Szyk Haggadah. The graphics are both gorgeous and profound, and the commentary is terrifically insightful. I can't recommend it highly enough. You'll see below that this text is responsible for a number of fresh insights this year.

D'Za"Kh, 'ADa"Sh, Be'aCha"V

On the first day of services I posed a question we've had at past seders but kept forgetting to research. Why does the Hagadah include Rabbi Yehudah's ten letter abbreviation for the plagues?

A number of members, including Andy and Fred, suggested that the abbreviation was there for the same reason why my math teacher had me learn Please Excuse My Dear Aunt Sally; it's a useful device for remembering a sequence. In their eyes, as an educational aid it needs no additional explanation for its inclusion.

Rav Natan added that the Rabbis of the Talmud often liked to create mnemonics. In a section of the Haggadah where we just finished doing textual analysis (linking verses from Deuteronomy 26 to the entire Passover story), it makes sense that the Rabbis would add another favorite move of theirs, a mnemonic. In other words, we're in 'Talmud Mode,' and the Haggadah fully embraces this.

Others, like myself have looked for deeper meaning. Eliezer Segal compiled a number of these hypothesis including the the possibility that the gematria or letter grouping of Rabbi Yahudah's abbreviation has meaning.

Another explanation: there's a midrash that suggests the plagues were written on Moses' staff. Rashi neatly proposes that it was Rabbi Yehuda's abbreviation that was written there. This solution is both mystical and practical!

Finally, I can glimpse a sort of political reasoning for this inclusion as well. We take the 10 plagues for granted, though they aren't clearly enumerated in the Torah this way. Things get even more complicated when you consider Psalms 78 and 105 have different listings of plagues. Perhaps Rabbi Yehuda's inclusion is yet another attempt to cement the 10 plagues as the Haggadah has them noted.

Drops of Wine

Also at our services the discussion of spilling out wine at each of the plagues came up. There was near universal agreement that one had to be careful with the spilled wine, as surely that wine had been compromised due to being associated with plagues. It was funny to hear the jocular warning about having to avoid licking the finger you dipped into the wine glass from others, as I thought that was something only our family joked about.

Thanks to the Syzk Haggadah I learned two new variations on this tradition. The first is that some Jews spilled out wine at each of the plagues to appease the evil eye. What better way to keep your seder running smoothly than to take a moment and get the evil eye a bit drunk?

Another, more serious observation is that Szyk avoids all mention of the pouring out of wine during the recitation of the plagues. It's not clear why this is. One possibility is that given the political climate he found himself in (think Europe, 1930's) he was in no mood to embrace the custom of pouring out wine as a sign of sympathizing with the Egyptians. To Szyk, his enemies deserved the justice they had coming; there was no need for an extra serving of empathy.

On B'nai Brak

The commentary on the Syzk Haggadah suggests that the B'nai Brak seder paragraph is more than a cute story proving the point that all who are wise should continue to recite the Passover story. It suggests that this description is there to add weight to the new type of seder that Jews were supposed to embrace: one that wasn't dependent on the Temple and Pascal Sacrifice.

While a seder spent noshing and talking is familiar to us, to our ancestors it would have seen woefully incomplete, or at the very the least a dramatic change.

This explanation makes even more sense to me during the Covid-19 Pandemic. Suddenly we find ourselves having to alter our Passover practices. It's no longer families smooshed together around a table loudly arguing; or reciting Hallel in shul with devoted regulars. It's a quiet Seder evening and services over Zoom in my basement. There's still Hallel, but I'm on mute and only the leader can be heard.

While Passover may be different, it's not gone. If the Rabbis at B'nai Brak can find meaning in their new arrangement, so can we.

The Other Wicked Son

After the Four Sons we read a paragraph that talks about the timing of the seder:

It could be from Rosh Chodesh [that one would have to discuss the Exodus. However] we learn [otherwise, since] it is stated, "on that day." If it is [written] "on that day," it could be from while it is still day [before the night of the fifteenth of Nissan. However] we learn [otherwise, since] it is stated, "for the sake of this." I didn't say 'for the sake of this' except [that it be observed] when [this] matsa and maror are resting in front of you [meaning, on the night of the fifteenth].

I appreciate how this fits the theme set earlier in Haggadah with with the B'nai Brak story and the paragraph that follows it. It's teaching us that what we are doing is Kosher even though it may vary from what the Torah or Temple practices prescribed.

But why put this paragraph describing the timing of the seder after the Four Sons? Why not group it with the other paragraphs closer to the start of the seder?

Perhaps I was just in a feisty mood this year, but if I squint I can see this paragraph's placement as intentional. We imagine four personalities sitting around the table and the answers we wish to give them. I can see how this paragraph on timing speaks to a fifth personality.

This fifth 'son' I imagine is a mash-up of the wicked and wise sons. Like the Rasha he's up to no good, but he's got the wisdom of the Hacham to try to derail the seder from the inside. Why are we even here tonight? He or she offers up. The Torah tell us that we should tell the story on Rosh Chodesh. That's the first day of the month and today is the 14th. Y'all are 13 days late on your seder!

This individual has come to the table with 'proof' that his fellow seder participants are all wrong.

The Haggadah is unfazed; it has points and counter-points at the ready.

Perhaps I'm being too harsh here. Maybe this mixture of Wicked and Wise is a good thing. Perhaps the Haggadah is sending us a message that asking sharp questions is exactly what we should be doing, and that's why this answer on timing is so verbose. Don't avoid thorny questions it seems to be saying, lean in and ask away!

Wednesday, March 24, 2021

Art on the Run

One of my favorite pieces of art is Ripple by Tejo Remy and Rene Veenhuizen. You won't need to make an appointment at a gallery to see this piece as it's bolted to the outside of Arlington County's Water Treatment plant. You need only stroll along a delightful trail to take in its 800 feet of social commentary.

I enjoy Ripple for a number of reasons. It's creatively placed and has a well camouflaged meaning. I've come to appreciate that what looks like kids detritus is actually a novel statement on unexpected consequences, ripples if you will, of our behavior. And I get to ponder all this while jogging by.

Given my affinity for seemingly random acts of art, you can appreciate my joy of when I was running the Four Mile Run Wetlands Trail (not far from Ripple) and came across what seemed to be a painted stack of rocks. It wasn't immediately obvious what I was looking at: something discarded, a one off art project? As I ran further on, I saw another stack of painted rocks. Now I had to stop and take some pics. Check it out:

So what I did discover? It seems the Alexandria Commision on the Arts has sponsored three recent art installations. One of them is by Alexander Rudd. And on Alex's Instagram page are these pics:

Those are the sculptures I saw on the trail. In Alex's feed they were in the back of a moving truck.

As for more details, the article describing the art installations says only: "the Alexandria Commission on the Arts did not release information on the nature of those projects."

We got a good 'ol fashion public art puzzle to decode.

I don't think Alex is going to give us much in the way of hints. His 'gram bio reads:

Conceptual read vs arbitrary appearance + algorithmic disposability = objectivity confusion

Yeah, that clears everything up.

Still, challenge-excepted. I'll have to add Four Mile Run to my upcoming running routes to get some more viewing time in.

Tuesday, March 23, 2021

Caption Me: Divorced Birds Edition

I caught this scene on my run yesterday:

While I'm not sure of the caption yet, these pics do feel worthy of the r/DivorcedBirds treatment. And what is DivorcedBirds you ask? Reddit explains:

For pictures of fabulous fowl who look like serial monogamists. Please post pictures of birds who look like they are twice divorced (or more!) Pictures/Videos must be of actual birds (feathered fowl), not human women, not art or paintings or photoshopped. No dead birds.

In truth, that description doesn't do the sub-reddit justice. Divorced Birds is an exercise in (very) short story writing with the theme of, well, divorce. It captures so many emotions: anger, hope, envy, shame and more with just a pithy headline and follow-up comments. It ranges from unbelievably wholesome to downright wicked. Here's an example that's currently on the home page:

So, what's the deal with the above birds? Leave your divorce, or not, related captions as a comment.

Thursday, March 18, 2021

Who's reading what? Tracking User Interaction in WordPress's Arconix FAQ Plugin

I added a FAQ to my website and found myself with a new question: what FAQs were people actually reading? I'm using the WordPress Arconix FAQ plugin which let me easily author and display questions and answers, but doesn't appear to track usage.

My solution: push an event to Google Analytics every time a user expands a FAQ. Google Analytics does the heavy lifting, as it will store and report on event activity. All I have to do is to convince WordPress to send the event when the user clicks on a question. Here's how I did that.

Step 1: Add Event Tracking to my Theme

In my theme's functions.php I added the following code:

add_action('wp_enqueue_scripts', function() {
  wp_enqueue_script('theme-analytics',
                    get_template_directory_uri() . "/js/analytics.js",
                    ['jquery'],
                    md5_file(__DIR__ . "/js/analytics.js"));
});

This loads js/analytics.js when my theme loads, and forces the browser to pick up changes when I modify analytics.js. I've made analytics.js depend on jquery. This simplifies the code that will be found in analytics.js.

Step 2: Add The Event Tracking Code

Inside of js/analytics.js I added the following code:

jQuery(document).ready(function($) {
  var MEASUREMENT_ID = 'UA-XXXXXXXXXX-1';

  function sendEvent(action, category, label) {
    console.log("GA Event", action, category, label);
    
    gtag('event', action, {
      event_category: category,
      event_label: label,
      value: 1,
      send_to: MEASUREMENT_ID
    });  
  }

  $(document).on('click', '.arconix-faq-title', function() {
    var me = this;
    setTimeout(function() {
      var expanded = $(me).hasClass('faq-open');

      if(expanded) {
        sendEvent('show', 'faq', $(me).text());
      }
    }, 100);
  });

});

You'll want to be sure you update the value of MEASUREMENT_ID so that it contains your analytics property identifier.

I'm monitoring clicks on the CSS class .arconix-faq-title. I added a 100 millisecond delay because I'm not confident of the timing of things. I want to check if the FAQ is expanded, the time delay insures that when I do this check the UI code will have already run.

With these bits of code in place I can now check out FAQ activity in Google Analyics:

If I drill down into Event Category and set the Event Label as the secondary dimension I'm able to see the questions that get the most traction.

But Wait, There's More!

Now that I've gotten the hang of sending events, I couldn't stop at just tracking the FAQ page. I added this code to analytics.js to track Contact Form 7 submissions. In this case, I'm using the subject of the e-mail as the event label:

  $(document).on('wpcf7submit', function() {
    var subject = event.detail.formData.get('your-subject');

    sendEvent('submit', 'contact-us', subject);
  });

My company's home page includes a call to action button and a mini FAQ. I added events to track their interaction as well:

$(document).on('click', '.q-and-a-grid .entry', function() {
    var q = $(this).find('.question').text();
    sendEvent('click', 'home-faq', q);
  });


  $('a[href="#content-start"]').click(function() {
    sendEvent('click', 'home-button', 'learn-more');
    return true;
  });

You've Got To Have Goals

Along with viewing these events within Google Analytics, it's possible to set these up as goals. For example, here's the goal definition for my FAQ page:

One interesting use for goals is to power experiments within Google Optimize. For example, you could run A/B tests on different wording for a question, and have Google pick the one that's read most frequently.

Want a Hand?

Want help setting up custom even tracking for your website? I'll spare you reading the FAQ and tell you that I'm glad to help. Drop me an email via questions@ideas2executables.com or hit me up on my contact-us page.

Tuesday, March 16, 2021

On This Day, Blogger Edition

I recently built On This Day: Google Photos Edition. This tiny web app shows you photos you took on the current date going back 15 years. I built it originally for finding Zoom Backgrounds, but found it to be a suprising source of inspiration and entertainment.

I've been publishing this blog for almost 16 years. I've often struggled with maintaining past posts. Services (I'm looking at you, Google Picasa!) and technologies (and you, Flash!) have come and gone over the years, leaving some posts pathetically broken.

If had a tool like On This Day: Pics, that let me see what blog posts I created on this date, I could review and edit these posts. If I made this a daily habit, I could slowly work my way through my 6,500+ posts without breaking a sweat.

I give you: On This Day: Posts edition, a quick web app that dumps out the posts you authored on this day.

I see that most of the posts from today are still looking good. The video I shot of Shira driving in Australia back in 2009 still works, and the pics from our first day traveling in Singapore are also there.

I did find, however, that write-only a tool I made to experiment with append only writing was broken. After a few minutes of JavaScript debugging, it was back to working.

There's still a need for tools to help maintain my blog. The labels, for example, are a mess and a bulk-label-fixing tool has been on my radar for years. But this day by day, spot-check-and-fix approach seems to hold real promise.

Sunday, March 14, 2021

You've got Questions. I've got Answers. Finally.

If you have an online business, it's a no-brainer to offer a FAQ section on your website. And yet, for years, my website went without this basic page. I'd always been too busy, or had some other execuse, to put it together.

But no more! I finally forced myself to focus on this, and a few hours later the Ideas2Executables FAQs page was born. I've never been so excited over a list of questions and answers before.

Can you think of any business or software development questions you'd like answered that didn't make the list? I'm a question-answering beast now!

Thursday, March 11, 2021

You Need This Information | What to do in a Power Line Emergency

If you're think I'm blogging about power line safety as part of my disaster planning kick, I applaud your attentiveness. But no, this post is all thanks to the goofy sub-Reddit /r/ThatLookedExpensive.

Here's the Reddit post that inspired this PSA. It features a dump truck that makes contact with power lines and disaster strikes from there. The comments on the post talk about what actions you can safely take if you find yourself in this situation. Ultimately, someone linked to this dramatization offered by Puget Sound Energy.

As I watched this video, I thought to myself: how do I not know this information? This feels like information that I should know.

So yeah, because you live and drive near power lines, you need to know this information too. Take 5 minutes and watch the video.

For a quick recap of what to do during a power line emergency, check out my First Aid Cheat Sheet.

Wednesday, March 10, 2021

On This Day, Google Photos Edition

A First World Problem

With so many meetings and events being held on Zoom I found I had a new first world problem: what photo should I select for my background?

After a bit of experimentation I arrived at a solution: I'd look at    photos that I taken on the current date going back a few years, and pick from one of those.

While I did this to help narrow the photos to pick from, it had surprising side effects. I found it instructive and inspirational to look back through the years and see where I was traveling and what projects I was working on. Picking a background became a useful little exercise in itself.

The Manual Solution

Convincing Google Photos to show photos taken on a particular day took a bit of experimentation. I found what works best is to search for date spelled out and quoted like so: "March 10, 2010". Yes, the quotes are necessary. Attempts use other formats didn't work reliably.

The Automated Solution

Naturally, I got tired of searching by hand. So I made an app for that. I give you: https://code.benjisimon.com/on-this-day/.

This little web app is slow and buggy. Most of the coding effort was spent getting OAuth2 authentication to work, and even then it's struggling with token-refreshing. I also spent more time than I'd like to admit puzzling out how to call the searchMediaItems method on the PhotosLibraryClient. Ultimately, I figured out how to get it to accept the specific date and result size I was targeting.

Still, as rough as the app is, it meets the need. I can now visit the on-this-day, and after a few moments, I see photos I took going back to 2010.

I'm now using this to set my desktop background on a daily basis. I'm telling you, this little walk down memory lane is surprisingly enlightening.

Check out the code for on-this-day over at github. If you're looking for OAuth and Google Photo PHP API SDK examples, this code may be instructive. Or maybe it's a cautionary tale. Either way, I hope you find the code and site useful.

Monday, March 08, 2021

Review: The Unthinkable: Who Survives When Disaster Strikes - and Why

I finished The Unthinkable: Who Survives When Disaster Strikes - and Why by Amanda Ripley and couldn't help but feel overwhelmed. She covers so many disasters from some many different perspectives, that by the end of the text I was maxxed out.

I'm sure that wasn't her intention, but the comprehensive nature of of the book struck me as a disadvantage. Ripley's a journalist, not guru, so her mission is to share what survivors and experts have to say about their experiences, not tout her own philosophy. This leads to advice that naturally contradict each other.

Consider this example: first, to reduce information overload focus on disasters that are likely to happen. Ignore the media hype. You're more likely to be injured in a car accident, then be involved in an active shooter incident, so focus on steps you can take to increase your safety on the road.

However, a second tenet of the book is that it's precisely the outlier events, the unthinkable ones if you will, that leave you open to catastrophic handling because they so unfamiliar. So it's not likely that you will end up in an active shooter incident, but if you do and you've done no preparation, chances are you'll react poorly.

In short, by the end of the text, I didn't anymore anecdotes or experts; I just wanted to be told what to do!

After some reflection, however, I've come to appreciate The Unthinkable's approach. Yes, it's goal of being comprehensive can be daunting, but it also elucidates a novel strategy. To me, it goes like this:

During an emergency, a person travels through three stages: denial, deliberation and the decisive moment. Ideally, you'd zip through denial, have quick and intelligent deliberations and execute the best actions available to you during the decisive moment. Through Ripley's research, we appreciate that there's no way to guarantee an optimial traverse through these stages. Even your everday temperment isn't a strong indicator of how you'll perform.

But, there is good news: through small changes, you can improve your performance in a disaster. Take the active shooter scenario above. If you complete Run / Hide / Fight Training, get into the habit of noticing exits when you walk into buildings, practice leaving through different routes at your work place and keep a trauma kit at your desk, you'll be in a far better position to survive an active shooter. You'll also be in a better position to deal with a fire, earthquake or coutless other disasters that call for evacuation and the possiblity of mass casualties.

Using this approach, I can imagine a simple disaster optimization algorithm: identify risks, look for simple yet effective ways to mitigate these risks and put these discoveries into practice. And repeat.

So yes, Unthinkable is daunting. But in this context it's also uplifting. You don't need to spend huge amounts of money or re-work your entire life to be disaster ready. What you do is need is imagination, creativity and perseverance. As disaster after disaster shows in Ripley's book, small changes can have a mighty impact.

Thursday, March 04, 2021

Yum! Greens n Teff, Vegan Ethiopian Goodness

We tried Greens N Teff last night for the first time, and it was an all around fantastic experience. GnT is a purely vegan Ethiopian place that opened down the street from us. Considering how much we like Ethiopian food and how rare fully vegetarian restaruants are in the area, this is a bit like winning the lottery.

On paper the place seemed great, but we tried to temper our expectations.

While on a walk in the warm'ish weather yesterday we placed an order and 25 minutes later dropped by to pick it up. GnT is tucked away in a tired looking part of the Pike. What we found when walked in delighted us: a spotless location with a warm couple who welcomed us and had our food ready. I asked about Minchet, a dish that was available to order but didn't have a description on the menu. Their response: here, try a sample. It was tasty, perhaps we'll get it next time.

Once home, we chowed down on our order. The Mushroom Tibs was probably the winner for the tastiest dish, though they were all solid.

There hasn't been a whole lot of great resterauant news for us during the pandemic. Heck, we lost our donut shop at the end of last year. But a vegan restaurant walking distance from our home? What more could we ask for?

Between GnT and Dama (also on Columbia Pike), we're more than covered for all our Ethiopian food needs.

Update: Apparently we aren't the only ones who are impressed with Greens N Teff. Arlnow reports that the community in general is a fan.