Saturday, April 20, 2013

511 labor contraction counter app

I coded up a little 511 app to help track the duration and period of labor contractions. Childbirth extends over several hours for most women, so the rule of thumb for a woman trying to decide when to head into the hospital (or whatever) is to wait until after contractions occur every 5 minutes averaging one minute in length for one hour - the "5-1-1" rule.

Anyway - the "5-1-1" rule was news to me when I learned about it watching this goofy video where the expecting parents were tracking contractions on a pad of paper. I thought, "why don't they track the contractions on their smart phone?". Such a genius!

I poked around looking for a 511 app, and didn't find one, so I decided to take it on as a project. After I started a friend mentioned that there is an iPhone app - doh! By then I was already committed to the project. There's one for Android now too - ugh.

Anyway - in addition to demonstrating my complete incompetence in web design, the app allowed me to play around with some "HTML5" tech that is pretty cool. I used YUI - which I like a lot. The app is wired with a manifest, so our poor pregnant woman can pull up the app even when she's offline, and an apple-touch icon, so she can "pin" the app to her start screen as a standalone app.

Unfortunately, I made some newb mistakes too. I designed the app to just maintain its state in memory - assuming that when a user starts having contractions, then she'll pull up the app, use it until she goes into full labor or not, and that's that. I expected a webapp launched from the start-screen would maintain its state if the user switched between apps - the same way a browser tab maintains its state if the user switches tabs. Bad assumption! It turns out that a pinned webapp loses its in-memory state whenever the user switches between apps - at least the iPhone behaves that way. I went back and added code to save and restore the apps state to local cache, but it would have been better if I had designed the code to work that way from the start.

The app could of course benefit from several improvements. First, I currently have the thing wired to save state to local cache after every UX event, because I couldn't figure out how to detect a "user is leaving this page" event, and only save then. I recently found this thread on stackoverflow that describes the "leaving page" event, so I'd like to give that a try.

I'd also like to wire-up the app to somehow auto-suggest that the user pin the app to her home screen, and make that easy to do (it's kind of a hassle in Android Chrome for example). I'm pretty sure some apps do that kind of thing, but it may be more trouble than I'm willing to go through - we'll see.

Anyway - I'm pretty happy with how the project came out - even though the woman I built it for didn't use it, because her water broke (doh!), but the baby came out healthy, so all's well that ends well. The source code is online under my dev-clone of my littleware mercurial repo on google code - mixed in with a bunch of other code I've been playing with. At some point I started making breaking changes to the littleware code, so I forked off to that clone, but still haven't merged back to the main repo - which is stupid, because nobody uses that code but me. Anyway - I need to clean up the repo, and probably setup a clone on github - which is where all the cool kids track code these days, but I'll save that project for another day ...

Tuesday, April 16, 2013

paging s3 listObjects as a scala stream

One of Scala's fun features is its lazy list Stream class. I guess for a Haskell programmer a lazy list is not a big deal, but it's cool for the rest of us java, ruby, python, javascript, C#, ... programmers.

Anyway - I plan to host some web content on S3, so I've been writing some scala code using S3's java API to automate some tasks. One of the patterns S3 employs is to "page" large result sets, and scala streams provide a natural way to load the pages on demand - something like this:

      lazy val s3Listing:Stream[s3.model.ObjectListing] = 
          s3Client.listObjects( 
            new s3.model.ListObjectsRequest( folder.getHost, queryFolderPath, null, "/", null ) 
          ) #:: s3Listing.takeWhile( _.isTruncated ).map( (part) => s3Client.listNextBatchOfObjects( part ) )

Pretty cool, but, unfortunately, Stream has some quirk where its flatMap method can easily overflow the stack. For example - the following code for assembling the directories in a file system explodes:

          lazy val folderStream:Stream[jio.File] = new java.io.File( folder.path.getPath ).getCanonicalFile #:: 
            folderStream.flatMap( (d) => { d.listFiles().filter( (sd) => sd.isDirectory ) } )

We can construct a stream, and avoid calling flatMap with a recursive method that manages its own stack.

          def depthFirst( stack:List[jio.File] ):Stream[jio.File] = {
            stack match {
              case head :: tail => {
                  head #:: depthFirst( tail ++ head.listFiles.filter( _.isDirectory ) )
              }
              case Nil => Stream.empty
            }
          }

          depthFirst( List( root ) )