Daily Learning Notes for July 26th, 2017

Today I woke up early again – 7am! – and I spent the day at my family’s house, alternating between spending time with my family and learning about the Firebase security rules API while working on my next social alarm clock app idea.

7:40am: Happy that I woke up early today, but sad that I still feel quite depressed and very uncertain of whether I’ll be able to force myself to work on anything today. For whatever reason, this “I can’t even” feeling has been very stubborn recently. I don’t even want to fight it anymore; I want to just give in and feel mopey and do nothing all day, accepting defeat while still hoping that I may feel better tomorrow.

Since my car may not be fixed by tonight, I cancelled the web dev study group while it’s still early. I spent a chunk of time messaging everyone individually just to make sure they got the update, because I’m never sure if people receive the Meetup emails. I even took a look at the Meetup API docs for a little while to see what I might be able to automate, but then I just felt overwhelmed again at the thought of figuring out how to use it while I feel so unmotivated and generally low on energy.

Anyway, here are some of the notes I had made yesterday about my social alarm clock app idea:

Notes on social alarm clock app

The goal: add another feature or two to my alarm clock app to help motivate myself to wake up early. (Short-term goal: I want to be able to join my friends for an early morning hike this Friday!)

Feature ideas and variations:

  1. Send a message on my Twitter account if I miss my target wakeup time – yay, public shaming!

  2. Allow anyone to write or record a message for me via a web app, which I would then read or listen to in the morning from within my alarm clock app – yay, positive reinforcement!

  3. Display a list of my wakeup times for tracking my progress and extra movitation thanks to some public accountability.

I think I’ll start with the second idea, because I’ve found that positive reinforcement is more powerful than negative reinforcement. (It would also be very easy to cheat and bypass the negative reinforcement altogether if I really wanted to.) The simplest version of the app that I can think of would be a web form that pushes messages into Firebase and displays them. But I still have some questions and details to work out!

Questions:

  • How can I give anyone write access to my Firebase app, but only allow them to add new entries to the database and not ovverride or delete anything?

  • If I wanted to stop myself from reading the messages beforehand (and only read them when my alarm goes off), how could I accomplish that with Firebase’s permissions system? Could I set a rule to only let users read messages during a certain time slot?

  • And if I wanted to let users record and upload audio, and then automatically play that audio with my alarm clock, how could I do that? How long would that take to figure out?

8:05am: While I still have a bit of willpower, I figured I can at least start on this idea. There’s no reason not to try for a few minutes. (Argh, but I do hate how I feel like I need to constantly negotiate with myself like this today!) OK… I’ll make a new Firebase app. I think I remember how to set that up. Oh yeah, I need a name for the app!

Notes on names for my social wakeup app prototype:

I decided to go with “Wake Up, Liz!” for the name, and I have an idea in mind for this first prototype that I’d like to send out to people to start collecting data right away: just a plain text box, the title, and a note that shows how many messages have been posted. So something like “5 messages have been written for Liz so far! She’ll have some extra motivation to wake up each day until Monday, August 30th!” And of course there should be a thank-you message when users submit something. I can share that out to people as soon as I figure out the permissions for reading from the database, which I’m thinking I’ll restrict to a time slot based on my wakeup time. I just need to resist the temptation to look at the raw data inside the database! Oh, here’s an idea: I could encrypt the data before submitting it to the database, and then decrypt it when it’s read from the database at the specified time slot. And the time slot rule should ideally be dynamic, based on another row of my database reserved for keeping a list of my wakeup goals. Hmm, this is adding up to quite a few more features than I realized! That’s what always happens. But the good news is that at least this is a good sign that I’m becoming interested in the project again, which hopefully can translate into motivation and taking action. I better write down these ideas as a list so I can review them more easily later!

Feature list for version 1:

  • Create a simple web form with two plain text boxes (for name and message), the page title, a thank-you message that appears when a note is submitted, and a blurb like: “5 messages have been written for Liz so far! She’ll have some extra motivation to wake up each day until Monday, August 30th!”

  • When messages are submitted, encrypt them and then save them to a “messages” section of the database. Each message will have a message body, an optional name for who to thank, a timestamp for when it was submitted, and a Boolean field for tracking whether the message has been read or not.

  • Allow anyone to write new data to the messages part of the database, but only let people read from the database during a certain time slot. (For now, I’ll also let anyone update the “read” field of messages, only during that same time slot.)

  • Create a separate, unpublished web page for reading a single message from the database (in the order in which they were submitted) that decrypts the message and then marks the message as having been read, updating that entry in the database.

  • Create another row in my database for wakeup goals listed as timestamps, which nobody can read or write to. (I’ll just manually enter the timestamps myself for now.) Modify the database rules to use those timestamps for a dynamic time slot rule that defaults to say 7am if there isn’t an entry for the current day.

8:37am: Now I have a bunch of questions! I think I’ll start by learning about the Firebase database rules system. But first, it’s time to join my family for breakfast in the other room.

9:38am: OK, before I go for a walk or do something else to replenish my willpower, I can at least convince myself to work on this for a little bit. I’ll start by looking up how to set up the rules for Firebase. First question: how do I restrict read access based on the time of day? Is that possible?

9:50am: I found a good example on the Structuring Your Rules page in the Firebase docs. So first I added some sample data to my database, and now I should be able to test the rule using their predefined variable for the current timestamp.

10:00am: Cool, it works! Another important note: “You can capture portions of the path for a read or write by declaring capture variables with the $ prefix. This serves as a wild card, and stores the value of that key for use inside the rules declarations.” I also have a question: if I set rules for specific parts of the database, do I also need to write default rules for the rest? If I don’t, what does it default to? I’ll try testing that out…

10:09am: OK, it defaults to denying access for everything else. Good to know! Next question: how do I structure the rule I need to only allow read access to messages during a time slot based on my wakeup time? Let’s see… First, how about only allowing read access at a certain time of day? The tricky part is I need to parse the current timestamp to only look at the time, not the date. Huh, so it would actually be easier if I did this the dynamic way, because then I would be comparing one timestamp against another!

OK, I’ll set up my test data with my actual wakeup time goals for the next couple days. I got up by 7:30am yesterday, 7am today, and my goal is to be up before 6am on Friday… so tomorrow I guess I’ll aim to wake up at 6:30am. Yikes, that sounds scary! I hope I can stick to it. OK, let’s get this data into Firebase.

10:24am: I’m kind of stuck on this now! I’m not sure how to structure the wakeup goals in the database or how to know which timestamp to grab from the database to compare to the current time. Doing some more digging through the documentation for ideas…

10:39am: Dealing with dates in JavaScript is annoying. I can’t use a library like MomentJS within the Firebase rules either. My best bet might be to convert the timestamp into a date string using built-in date functions.

11:41am: Got distracted by some emails and messages on Slack and then talked to my Dad for a while. Now I completely forgot what I was doing! Let’s see… oh yeah, I was stuck on dealing with dates within Firebase. Now I’m starting to think that maybe it would be easier to do this with a hard-coded time of day. Something like this: "now.getHours() === 7 && now.getMinutes() > 0 && now.getMinutes() < 15"

I’ll test that out right now in the Firebase rules simulator thing… Oh right, but I don’t have a date object, I just have a timestamp! I wonder if I can create JavaScript variables right inside a rules declaration. Yup, I got an error: “Rule expressions may not contain multiple expressions.”

Well, I may have just discovered an important limitation of Firebase! Maybe for this use case, I would really just need to write my own server-side code. Hmm. But there must be a way! Doing a little research, I just found this thread about temporary variables in Firebase security rules, which points out: “The Firebase Security rules language doesn’t have support for custom variables. This indeed leads to lots of duplication between rules. The best solution is to write your rules in a higher-level language, that compiles into Firebase Security rules.” One example is Bolt, the Firebase team’s experimental rules compiler. But that all seems like overkill for this tiny app!

12:07pm: I figured if I can’t create variables or use multiple expressions, I should be able to create a new Date object each time like this: "new Date(now).getHours() === 7 && new Date(now).getMinutes() > 0 && new Date(now).getMinutes() < 15"

But I got the error “Unknown variable ‘Date’” so I guess the Firebase rules language is indeed quite limited! But I did find a cool mathematical workound in this StackOverflow thread: just do (now - (now % 86400000)) to get today’s timestamp at midnight, because there are 86,400,000 milliseconds in 24 hours. I don’t understand why that works, though!

12:16pm: Time for a break to take care of a couple emails and then maybe have lunch.

5:09pm: Back again! After lunch I showed my dad how to do some basic multi-layer image editing in Paint.NET, talked through that modular arithmetic example after I figured it out, played cards (apparently the game is called Thousand, not Thousands), and fixed a couple small things on a website I had worked on ages ago for USC. I guess the whole day went by already! But now I’m back.

As for that math problem, just like I thought, it was very straightforwrd. The key that I forgot about before is that Unix timestamps start at midnight and then wrap around from there! So every 24 hours (or 86,400,000 milliseconds), we’re back at midnight. So dividing by that modulus gives us however long it’s been since midnight of the current day, and then subtracting that offset from the current timestamp gives us the actual timstamp for midnight of the current day.

Combining those two formulas gives me a pretty simple formula to check if the current time is within 15 minutes of my wakeup goal time: "now > ( (now - (now % 86400000)) + (nextWakeupGoalTimestamp.val() % 86400000) ) && now < (nextWakeupGoalTimestamp.val() + 900000)"

I checked it with some fake numbers and it is indeed working! Hurray! But how do I access the next wakeup goal timestamp from my list of those timestamps? Or should I have another section in my database that just stores the timestamp of the next wakeup goal for easier access? Meh, I feel like I need another short break.

6:00pm: Just kidding, I didn’t take a break. I was reading random stuff in the Firebase docs and reviewing examples of other rules. I found this handy trick: ".write": "!data.exists() && newData.exists()" lets users create a new database entry if it doesn’t already exist without being able to modify or delete the entry! I need that. Adding more validation rules for my messages now… Nice! This works very nicely for controlling write access! This finally makes some sense.

6:12pm: I know that saving the next wakeup goal timestamp to its own section of the database will work, but how would I keep it up to date without entering it in manually each time (since I want this first version to work without any authentication)? I have a more convoluted idea, but I don’t know if that’ll work either, so I’ll just assume for now that nobody will hack my web app. (Famous last words, right? Haha.) Then I can just automatically update that piece of data every time I update each wakeup goal to switch its status from null to success or fail.

7:03pm: Time flies when you’re reading the docs and experimenting! I also just (re)learned an important lesson: save your changes immediately and don’t ever rely on a web app to save stuff for you! I just lost all my validation rules because I forgot that the Firebase console doesn’t save them automatically. Oops. Also, I don’t know why I never just read over the Firebase Database Security Rules API – it’s way more complete than their other guides! And by that I mean it is complete, haha.

7:24pm: After more testing and refining, I think I’m happy with my database rules! Yay! I figured this would be the hardest part of this project, or at least it would involve the most unknowns, so it feels great to see that everything should be downhill from here! Plus I learned something new – something I had been intimidated by before and had procrastinated on! So that’s a nice little milestone. I’m going to go take a break now and maybe go for a walk or eat something.

Wrapping up: I went for a short walk, answered some more emails and messages, played piano for all of three minutes (just long enough to see how much I forgot after not practicing for a few months), and did some beginner algebra problems on Khan Academy. I also watched this talk from last year’s GitHub Universe conference: Tips & Tricks: Gotta Git Them All. I learned about a couple new tricks, but I’ll have to watch it again sometime.

Gathering string

  • Project idea: make another little web/mobile app that tracks how many “I can’t even!” feelings I have throughout each day and how many times I’m able to convert them into “Actually, I can!” feelings. Plus it would be interesting to see a list of the activities I try each time to stabilize my mood, identifying which ones seem to work the best.

  • Really curious about (and inspired by) this workshop taught by Andy Balaam: Write Your Own Programming Language! I definitely want to watch some of his talks and look through his code there sometime.

  • I also want to check out the free and open-source learn-to-code game Rabbit Escape, also made by Andy Balaam.

  • Watch this talk next: Pains & Gains: Five Short Stories (GitHub Universe 2016)

  • Project ideas for podcasts: a podcast where meetup organizers interview each other, or one specifically for Girl Develop It and/or Women Who Code! Also, the “rabbit hole” podcast idea where a couple of friends share their journey exploring a new topic together! Also also, a Learn Teach Code podcast focusing on blurring the line between learning and teaching! (I’m sure I have plenty of other ideas too, but that’s enough for right now.)