April 26th, 2020

COVID-19 pyttsx3 Chilblains

Unless one has been living on Antarctica for the last few months, life has probably been affected by COVID-19 in some way, shape or form. It has been almost 7 weeks since the company I work for issued a recommended work from home (WFH) notice and I have not been into the office since. The communications went from voluntary WFH to recommended to strongly recommended to mandatory over a 16 day period.

At the very beginning, it seemed a little odd that I had stopped going into work while my daughter was still going to kindergarten. I tried to rationalize and explain to her that riding public transit and sharing an office space with thousands of other people who were possibly travelling all over the world, when it wasn’t really necessary, was more likely to spread the disease and endanger society as a whole as compare to her spending time with a few hundred kids and some adults at school. In other words, it wasn’t that it was more important for me not to get sick than her, but that if I were sick and didn’t know it, I might be exposing many more people, more quickly, than she would if she were sick. Based on this photo I happened to take 2 weeks earlier on my morning commute, there might be some truth to that. She does go to a public school, but the classrooms are not quite this overcrowded.

Nevertheless it felt bad and not 100% correct to try and explain this to her; and while we are fortunate enough to be in a position where we could have just taken her out of school without penalty, she wanted to go to school. Also part of the reason we live where we do is the belief that people in charge of the school district, health services, city and county government are knowledgeable and rational people who will “do the right thing”. So it was somewhat of a relief when 3 days after I started WFH the school district announced that Friday would be the last day of school for the next 3 weeks (one of which was spring break).

The first week was pretty rough, she already had a distaste for video chats even before the pandemic; so getting her to participate and deal with the technical difficulties of everyone trying to get setup with distance learning lead to quite a few more meltdowns than normal. We tried to emulate some of her school day to provide a semblance of normalcy e.g. she wrote out her standard Tuesday schedule.

I was probably only reaching about 60-80% of usual productivity on work matters; and that included staying up late to catch up on things while everyone else was asleep. There were plenty of other stressors e.g. attempting to get groceries delivered and then having to clean/sanitize them etc. None of this is unique nor is it comparable to the hardships that many other people are going through but life had certainly changed abruptly in significant (to us) ways.

Week two was better and then things changed for week 3. Since it was technically spring break we didn’t do any of the homeschooling and she could wear footie pajamas all day (we enforced having to get dressed in the morning for “school”). I was still playing catch-up at night with work but at this point I felt like it usually brought me close to 100% normal productivity. What I didn’t realize is that I was slowly injuring myself in a strange way. It wasn’t carpal tunnel or anything like that, though my WFH setup is less than ideal.

The monitor is 13 years old, my in-laws gave it to me several years ago after they got a new computer because they weren’t sure how to properly dispose of it. I had procrastinated taking it to the computer recycling center, so lucky me. The laptop is company owned. As someone who at varying points over the last 25 years has had as many as 5 different physical computers running in their apartment/loft/house at any given time and also ran their own firewall, nat, web, dns, mail, ftp, raid-5 etc. servers, it’s somewhat surprising that the only computer I own (not counting phones or an old chromebook I got from work) turned 8 years old a month ago. To be fair, I purposely configured it on the high end as a desktop replacement when I purchased it, planning for it to last at least 4 years e.g. Intel Quad Core i7 2.2GHz CPU w/6MB L3 cache, 4GB 1333Mhz DDR3 RAM, 16.4in 1080p screen, HDMI, Blu-Ray/DVD+RW, NVidia GeForce 520M w/512MB dedicated video RAM etc. And towards the end of 2018 I did upgrade to a SSD hard drive, but even with that and the end of Moore’s Law, it feels a little ridiculous to be typing this on a laptop from 2012.

I remember during an architecture course in college that focused on 3D animation (as opposed to CAD), someone from Industrial Light and Magic came to speak to us and mentioned he didn’t even own a computer (this would have been 1999). At the time I thought that was completely absurd given my room looked like this.

But now, I’m basically that guy who spoke to us (though I’m also likely 5-10 years older than he was at the time). I don’t have a desk at home, I spend 8-10hrs/day 5 days a week fairly intensely focused on making computers do things and while I’m still interested in continuing to educate myself about technology, I rarely practice it outside of work.

Some of that is due to a belief that we should not be exposing our daughter to too much technology too quickly and therefore want to engage her while playing with a basketball or dolls or Lego or a guitar etc. Though as part of the homeschooling, we asked our daughter to come up with electives, and I figured since she had started to have an interest in reading and doing arithmetic on her own, it might be worth trying to teach her how to code. She was open to the suggestion since she likes to type gibberish in a text editor and has seen me working from time to time asking “what are you coding now?” or “are you fixing a bug?” I had read Seymour Papert’s Mindstorms shortly after our daughter was born and read a little about a programming language geared towards kids called Scratch. I knew parents who’s kids had fun with Scratch and others who were uninterested. And there were those who’s kids liked Python and others who had rejected every language and attempt at interesting them in programming and computation. I had also reflected from time to time on my experience teaching 8-16 year olds HTML/CSSJavaScript and Macromedia Flash at a summer camp (also more than 20 years ago) as well as my own upbringing in BASIC.

In the mid-1980’s we had an Atari 800XL at home and then my middle school had TRS-80 Model III’s (10 years old at the time). I still remember this feeling like magic:

10 PRINT “HELLO JAMES!”
20 GOTO 10

Graphics seemed out of reach at the time, I could spend an hour typing in code from a magazine that I didn’t comprehend just to see an orange and green jack-o-lantern appear on screen. Another one I remember was typing in a bunch of code that rendered a green fractal fern. I learned about variables and conditionals, but not functions (that I remember) and certainly not the association coding/programming had with mathematics. It wasn’t until several years later, I taught myself a little VisualBasic (first project was writing a Celsius/Fahrenheit/Kelvin converter with a GUI) did I really start to see the power of the computer as a tool.

By the time I was teaching at a summer camp, I had more formal education under my belt and it was much easier to make visuals via code. With most kids only going to the camp for a week during the day time, and mixing in all the other camp activities, I probably had 15-20hrs of time with any given group to make an impression. So I decided to spend most of the time teaching them how to programatically draw and animate lines and shapes. There was much document.body vs document.layers in JavaScript juxtaposed with looping keyframes in Flash.

However, that still seemed like a bit too much for a 6 year old. One of the things we’ve been thankful for is that she got to have a birthday party before everything shut down. Some classmates have had to celebrate their birthdays over a video chat or having their neighbors setup a bear hunt. Her age is a big deal too e.g. when playing Monopoly, “oh I rolled a 6 because I’m 6 years old.” So I thought, maybe an age calculator would capture her attention in a similar way to how the temperature converter caught mine. But I also wanted to tap into whatever it was that made me so excited to see my “Hello James” printed repeatedly across the screen. However, given she has grown up swiping and tapping on touchscreens while talking to our Alexa and Google Mini, printing characters to a screen likely wouldn’t create the same sense of astonishment. But what if I could make the computer “speak” to her or better yet, have her instruct the computer what to “speak”?

A program that asked, “What year were you born?” and then “What month were you born?” and then if necessary, “What day were you born?” would be able to correctly state how old someone was (ignoring the detail of time of day since every birthday when I tell her she’s not N+1 years old yet due to her birth time being after her bedtime it just makes her roll her eyes). It would provide an opportunity to introduce concepts like input, output, variables, numbers, strings, conditionals, functions, errors and provide an opportunity for the computer to “speak”.

Without much trouble I could probably write this program in C, C#, C++, Java, JavaScript, Perl or Python. I ended up choosing Python because it seemed like it would be the simplest to teach. I also found the pyttsx3 library which seemed like a dirt simple way to get the computer to “speak”. My plan was to work through a bit of the program with her each day that she wanted to write code as part of her elective activities and then magically flip the “speaking” switch.

The basic premise was to have a series of print and input functions e.g

print("What is your name?")
name = input()
print(f"Hello {name}! What year were you born?")

interspersed with the various calculations. That would exercise her reading and typing and then the magic would be converting the print functions to a custom print_and_say function which would “speak” everything while also printing it to the screen as before. This worked out pretty well, though I am not sure she really grasped any of the concepts I had initially hoped to convey. Mainly she enjoyed having the computer say her name along with poop and pee at various speeds. The full program appears below.

import pyttsx3
import calendar
from datetime import date, datetime

def month_to_number(month):
  for i, m in enumerate(calendar.month_name):
    if m.startswith(month.lower()):
      return i
  raise ValueError(f"Could not convert {month} to a number.")

def print_and_say(message, speech_engine):
  print(message)
  speech_engine.say(message)
  speech_engine.runAndWait()

def main():
  speech_engine = pyttsx3.init()
  speech_engine.setProperty("rate", 165)
  speech_engine.setProperty("voice",
                            speech_engine.getProperty("voices")[1].id)

  print_and_say("helo, wut is your name?", speech_engine)
  name = input()
  print_and_say(f"nise to meet you, {name}! wut yeer wr you born?",
                speech_engine)
  year = int(input())
  now = datetime.now().date()
  years_old = int((now - date(year, 12, 31)).days / 365.2425)
  print_and_say(f"I think you are at least {years_old}. "
                f"what munth wer you born?", speech_engine)
  munth = input()
  month_number = month_to_number(munth)
  print_and_say(f"{munth} is month number {month_number}!", speech_engine)
  day = 1
  if month_number == now.month:
    #srhfhfhfhrgrgtgrhrhhvrvghfghtgrgsurfhgrhgryfhrgyhfgyygdyurgrreyutfyhfb657474656550r968767686urthfhfhfbfgfgfgfgtggtgffhftrgftrytyrrtr65tftbybrrgtvhgfhfgdbjhfhdgfygdrf
    print_and_say(f"Oh, I guess I also need to know what day you were born,"
                  f" can you please tell me?", speech_engine)
    day = int(input())
#hjudhhfhhghghgfghghghgyfhfhjgjgugfufufufugghhyghgyyughbvbhgygvtyg
  elif month_number == 12:
    pass
  else:
    month_number += 1
    
  years_old = int((now - date(year, month_number, day)).days / 365.2425)
  print_and_say(f"Ahh, now I am sure you are {years_old} years old!",
                speech_engine)
  speech_engine.stop()

if __name__ == "__main__":
  main()
#hgbtttytuybvrhutbgrghftvytyttvtytyvttytvtythttvhvbvfhfdjhnvmbkhlotpyorhejfhvbvogjghthghghgghtggghjgjghghgghhjhvtbyvhrbtvhryrghftggytr

The text-to-speech engine was actually pretty good at pronouncing her estimated words e.g. nise vs nice. I hadn’t thought to teach her what a comment was but when she was getting frustrated with having to write certain words, I showed her how she could use the # character to tell the computer to ignore it and I think that turned out to be her favorite part of programming. Upon further reflection, probably not a bad thing as most code would actually benefit from some well placed comments.

Maybe you’re wondering where the chilblains comes into play. During the first 3 weeks of WFH I was often barefoot (fully dressed otherwise) and as mentioned working late. My feet started to hurt as if I had blisters. I tried using bandaids to reduce friction but it didn’t help and it got to the point where I could not go jogging and even walking the dog was a struggle. After much reading I self-diagnosed chilblains and started wearing socks and shoes inside the house. I also applied petroleum jelly to the sensitive parts of the skin and within a couple of days there was a significant improvement, after a week I was able to go jogging again with only mild discomfort and a few days after that all the pain was gone.

Finally, about a week after that my wife came across an article about covid toes; so who knows, maybe I was infected and otherwise asymptomatic. Or maybe I just had one of the silliest self-inflicted WFH injuries.

May 19th, 2019

Bike to Work Day

When I was 11 years old, I biked for work; delivering ~20 papers along a ~1 mile route with a fairly steep hill. Alas, none of my jobs post-college have really been bike-able, given nearly all of them have been in San Francisco; and there isn’t a bike lane all the way across the Bay Bridge (yet).

The one exception was a period of time in 2004-2005 when the main office of CafePress was in San Leandro (they moved to San Mateo ~10 months after I started). Some days I would bike 1.7 miles to the West Oakland BART station and then 2.3 miles to the office from the San Leandro BART station, but that doesn’t really count as “biking to work”. It turns out I could have biked the whole way if I’d been willing to ride on some not-so-safe streets and/or known about the dirt/gravel trails. I partially blame the lack of Google Maps cycling directions at the time (in fact Google Maps had only recently launched and it was an accessory to getting me in trouble with HR, but that’s a story for another time). Plotting a route from where I used to live to the former CafePress office indicates it’s a little over 12 miles and an hour each way; so not necessarily something I would have done often, but certainly doable.

The last significant distance I’d traveled on a bike in one shot was almost 3.5 years ago when I biked 7 miles to the (then) terminus of the bike path on the eastern span of the Bay Bridge.

The old eastern span was still in the process of being disassembled.
Two “bridges to nowhere” side by side…
The view of Treasure Island from the previous terminus of the bike path.
An artsy shot of the new eastern tower.

An officemate who goes on 20+ mile bike rides for fun on the weekends mentioned Bike to Work Day was coming up, on a day she was schedule to work in Mountain View. She had signed up for a group ride and I should do it too. I looked at the map, it would be a little over 53 miles door-to-door, one way and I’d have to leave my house around 4:30a to meet the group at Lake Merritt in Oakland at 5a. Along the entire route, there was very little elevation gain other than the climb over the Dumbarton Bridge. I had been exercising regularly, my bike was probably in reasonable shape. I was also planning on working from Mountain View that day and it turned out another co-worker would be doing a ride from San Francisco. I’d thought about doing this in the past, a former co-worker and his girlfriend were currently on a 18,000 mile bike ride from Alaska to Argentina, what excuse did I have not to go?

Well, maybe the fact that the last time I biked more than 7 miles in one go was nearly 18 years ago in 2001? I had planned on doing the California AIDS Ride, 575 miles from San Francisco to Los Angeles, but the startup I was working at was falling apart, and with it went my matching sponsor. I documented a few of my training rides, but did not end up participating.

29 mile Briones Reservoir Loop (1300+ foot elevation gain)
35 miles on Hwy 1, north of Bodega Bay (~2000 foot elevation gain)
59 miles on and around Mt. Diablo (2700+ foot elevation gain)

So yeah, one time in my life I had biked 53+ miles in one go, I had no time to “train” for this ride, I’m significantly older and likely in worse shape; hmm, that’s more than one reason not to do this. Nevertheless, I bought a couple of spare bike inner-tubes and a portable pump, tuned up my bike as well as I knew how, rode it around a couple of blocks the night before and set my alarm for 3:45a.

The morning of the ride I had a big bowl of cereal for breakfast, packed my bike supplies, 2 liters of water, some granola bars, a change of clothes and my laptop into a backpack, threw on my reflective vest, helmet and bike lights and at 4:25a I was off. At 4:40a I realized I had forgotten my cell phone, but if I turned around to go back and get it I would not be able to meet up with the group (in hindsight this was likely wrong as people were late and if I sent a message as soon as I got my phone, that I too was going to be late, they’d have waited). Instead, I was the second one to arrive at the meeting point at 4:50a and already had my first facepalm moment to share with others (so yes this means no more pictures in this post, no Strava route times etc. you’ll just have to trust me).

My office mate had decided not to go after getting sick over the previous weekend and a couple of other people also cancelled, but we still had a good sized group of 9. Some people seemed fairly serious about cycling i.e. padded cycling shorts, clip in shoes, hydraulic or disk brakes, hydraulic shifters, aluminum frames etc. Others, like me, had flat pedals and sneakers, steel frames, non-cycling clothes etc. I even had part of a child seat support attached to my frame because it’s way too much trouble to take that part off (I of course didn’t have the seat itself attached). The group leader mentioned he planned on staying on dirt/gravel trails as much as possible to keep us closer to the bay and away from the cars, that sounded good to me. He followed that up with, “I usually do this route in about 2h 45min, but happy to go faster or slower”. Yikes, I had presumed this would be a 4hr+ ride given the amount of gravel/dirt trail that was planned. I think this is roughly the route we took: https://goo.gl/maps/GH8bQcxt16QyiAB76. It’s not the shortest, but it stays as close to the bay and out of traffic as possible.

We left at 5:10a and had our first flat tire within 20 minutes, hadn’t even made it to Alameda yet. I hadn’t invested in a water bottle cage so the timing worked out well to have a drink and a snack. We probably made it another 60 minutes before we had a second flat and at almost the same time a rider fell (minor cuts on the hands). At that point we had made it past the Oakland Airport and the person leading the ride said he had to go on without us since he needed to be showered and changed for a client meeting at 9a.

We proceed without incident to the toll plaza of the San Mateo Bridge. The ride along the bay had been quite nice, the skies were overcast which meant no view of the sunrise, but also comfortably cool weather. We met a woman on a mountain bike (enjoys spending weekends in the Santa Cruz mountains, Joaquin Miller Park etc.) She had started the day in Castro Valley and joined our group as she was on her way towards an office on Hwy 84 just before the Dumbarton Bridge; and that was how we were going to cross the bay. We suffered our final flat tire along the way, and after she left our group, made our way to the bridge.

By this point I’d biked over 35 miles, and even though it had been mostly flat, much of it was pretty bumpy and my body was starting to feel a little sore. Perfect timing for the first significant headwinds and incline. It was a great feeling to be moving faster than all the traffic on the northern side of the bridge (heading east/west) but it totally sucked to have the bike path on the southern side with oncoming traffic speeding along at 50mph+ (west/east). Every time a truck or bus rocketed by it was a face full of exhaust and a force trying to push me back down the bridge.

Once down, the rest of the ride went smoothly, no flat tires, no falls, and we rolled into work just after 9:30a. While the soreness in my arms and legs was gone by the next day, it wasn’t until a few days later that I could sit comfortably on my bike again.

February 21st, 2019

RIP Sweet, Tender CafePress

Somewhere along my circuitous route through paid employment I spent ~21 months at a company called CafePress. I met some great people, learned a lot and as part of the offer letter, received Incentive Stock Options (ISO) in the not-yet-public company. My previous encounter with stock options did not result in anything material i.e. my offer letter included them but shortly before the 1 year cliff the company shrunk to 4 people (including me) and I left a few months later without exercising anything when the company ceased to exist. While access to information about the mechanics of start up equity has increased significantly over the last 15 years, it rarely hurts to have more information and real-world examples.

Deciding to leave CafePress started a 90 day timer during which I either needed to buy my ISOs and pay taxes on the capital gains between the strike price and the current valuation, or forget about them (it was 2006 and startups had not yet gotten around to converting ISOs to non-qualified options [NSO] with longer exercise windows, oh well).  I had 8,750 shares at a strike price of $0.25/share. The then current valuation was $0.75/share, so that came out to $2,187.50 to buy them and then a taxable gain of $4,375 which set me back another ~$1,300. So I plunked down ~$3,500 figuring what the heck; there had been talk about going public in the next few years and I believed in the company (I just didn’t want to commute to San Mateo anymore and wanted to work on much larger problems/systems/datasets etc.) If the stock made it to $10/share that’d be the biggest lump sum of money I would have encountered to date by an order of magnitude. If it made it to $20/share I could self-fund a multi-year sabbatical etc.

A few years later, a company called SharesPost opened up a private equity marketplace and after a while CafePress appeared in their listings. If I had been willing to part with at least 5,000 shares I could fetch ~$5/share. I didn’t fully understand the process or fee structure and given the economy had recently collapsed, figured there was still significant upside in the future presuming things eventually recovered.

CafePress ended up going public nearly 6 years later, but before doing so, executed a reverse stock split i.e. I now owned 4,375 shares with a cost basis of $1.50. On 2012-03-29 PRSS opened at $19/share, rose to a high of $22 and then closed at $19.03.

CafePress ringing the opening bell at the NASDAQ.

Some friendly faces enjoying the moment.

Not too bad, had I been able to cash out right then, I could have purchased a Tesla Model S outright. Sadly, the stock never again traded above $20 and by the time the 180-day lockup period I was subject to ended on 2012-09-24 , it had experienced a steady drop to $9.32/share. I figured even if it were to go up again in the future, it would be prudent to offload a chunk.

Unfortunately I hadn’t paid attention to the state of my shares. I left them with a company called ComputerShare during the lockup period and it turned out I could not sell shares through ComputerShare as they were just a holding/transfer company. The shares needed to be transferred to a brokerage and none of the ones I had accounts with seemed to be able to accept the transfer electronically/immediately. So by the time I had figured out what needed to happen, assembled and sent all the forms, a few days had passed by. Then there was a weekend, processing time etc. In hindsight I should have sent the forms overnight express or paid to use a fax machine, as by the time I could finally access the shares and sell them on 2012-10-11 the share price had dropped below $7 i.e. a paper loss of ~$12,000 (after the taxes I would have owed on the gains) due to stupidity.  On that date, I liquidated 1,375 shares at an average price of $6.635/share 

In order to calm down, I kept telling myself this was all icing on the cake since the number of startups that actually have a liquidity event is small. The next day I sold another 500 shares at $6.02/share. The stock continued to decline but then bounced back a bit in early November. I sold 500 more shares at $6.15 on 2012-11-07, 1,000 shares at $5.01 on 2012-11-08 and 500 at $5.50 on 2012-11-14. At that point I only had 500 shares left and had sold 3,875 shares at an average price of $5.927/share. For 2 years after that the stock bounced around between $5 and $7/share and then in Q4 of 2014, it cratered to ~$2/share.

I still knew a few people who worked there and felt horrible for them, because even if they were following their passion, growing their technical, social, emotional skills etc. having one’s company’s stock, and therefore part of one’s total compensation, lose 90% from the IPO is hard to digest.

A ray of light emerged during the first half of 2015 as the stock went up 150% to just over $5/share in early June, but I did not act. From there it declined again over the next year and a half to under $3. On 2017-01-31 it was above $3 and I decided to donate 300 shares ($1,011) so as to avoid paying any long-term capital gains taxes; even at $3/share it was still a 100% gain over my strike price.

Sadly, the stock price returned to its downward trend, eventually going below $1.20/share in early 2018. At this point I had decided I was going to just hold on to them “forever”. However in late 2018 I received a bunch of legal documents stating that Snapfish was planning to acquire CafePress via a tender offer for $1.47/share. There was some jargon in it that I think stated I could lead a shareholder revolt etc. to try and block this, but once Snapfish had a majority stake they would not be anything I could do. So I did nothing and as I work on my taxes for this year, I’ll be claiming a $6 long-term capital loss for PRSS.