Helping Veterans Help Veterans (with maps)

Yesterday, I got an email recounting an amazing story from Jakob from the 2nd Battalion 7th Marines. He created a site for members of his unit to keep in touch after returning home from overseas.

2/7

Hey Patrick,

I really appreciate your map customizer. If you go to my website you can see that I used it to plot the location of the Marines from my unit. My unit, 2/7, has been especially burdened with suicides. We use the map to find each other for simple gatherings to have the same brotherhood we had in the past. But it has an even more important role. It allows me to find Marines in the area of a Marine in need. I thought you should know that your map customizer recently played a significant role in saving a good man’s life. One of our brothers was on the brink of suicide and we were able to find other Marines in his area in time to get him help. Thank you so much for what you made. We are very grateful.

Thanks you,
Jakob Willmann
2nd Battalion 7th Marines

This is a truly heartwarming story of people helping each other in their darkest hours. I’m thrilled that MapCustomizer was able to play a role in saving a life. Of course, it was the other Marine nearby that really saved that man; my site can’t take much credit here. Still, it is amazing to see the positive impact that the site has had. I get lots of emails from people thanking me for the site, saying that it makes their lives or jobs easier, but this is something else entirely.

It is also a somber reminder of how little we do in our country to take care of our returning service men and women. I’m glad that Jakob created this network of Marines for his Battalion, but we should do more to support them, as a society.

To find out more about the issues facing veterans as they return home, please check out the Verteranology podcast. If you want to help, please consider donating to the DAV or Fisher House.

To Jakob and all the other service men and women returning home: Thank you for your service to our country.

Posted in gmaps.kaeding.name | 1 Comment

How to get a low-numbered username for your kid in the SF public library online system

The San Francisco Public Library has a few special features for accounts for kids. Probably the most notable is that there are no overdue fines. Your kid can take out as many Curious George books as he can carry, and if he doesn’t finish them all by the due date (or they get misplaced under the couch), you don’t have to fret about it. I don’t know where the limits to this policy are, but I wouldn’t encourage abusing it—it is a nice thing they do to encourage a love of reading.

Another interesting aspect of the children’s accounts is that they prompt you to create a username to use the online portal (used for checking your account, reserving books through inter-library loan, checking out ebooks, etc). For adults, they let you choose your own username, but for kids, you have to choose a color and an animal. (I’m guessing this is to prevent using personal information, like a real name, which can get particularly dicey when the website operator knows the user is a child.

So, you have to choose a color from one dropdown, and an animal from another, and the system concatenates them together and adds a number to come up with a unique username:

2015-04-04 at 5.35 PM

It seems that the number chosen by the system is the lowest number that is not already in use for that color/animal pair. Color/animal pairs that I would expect people to choose frequently (such as ‘red ant’ or ‘black cat’) have high numbers, while weirder color/animal pairs (like ‘orange louse’) have lower numbers. (I’m not sure how big of a system this is, it might be for all libraries in California, since I wouldn’t expect there to be that many kids in San Francisco choosing these usernames. But maybe they have all the kids in the elementary schools go through this, or something. Or maybe I just underestimate the number of kids in this city.)

So, obviously, this leads to a game to find a unique color/animal pair. Who really wants to be the 5,408th ‘red ant’?

It turns out there is a web service powering this username lookup running at:

https://sfpl.bibliocommons.com/user/generate_username.json?color=COLOR&animal=ANIMAL

For instance:

$ curl 'https://sfpl.bibliocommons.com/user/generate_username.json?color=red&animal=ant'
{"success":true,"user_name":"red_ant_5408","messages":[],"logged_in":false}

So, we just need to enumerate all of the color/animal pairs, hit that web service, and look for ones that have a low number. By manually exploring on the library web site, I knew that some pairs had the number ‘2’, so I wrote a script to print all pairs with a 2 or less:

import requests

def check_username(color, animal):
  url = "https://sfpl.bibliocommons.com/user/generate_username.json?color={}&animal={}".format(color, animal)
  req = requests.get(url)
  resp = req.json()
  name = resp.get('user_name')
  if name:
    return int(name.replace('{}_{}_'.format(color, animal), ''))
  else:
    print "No username from url: ", url
    return None

colors = ["red", "green", "blue", "yellow", "taupe", "mauve", "burgundy", "violet", "maroon", "orange", "indigo", "navy", "olive", "brown", "black", "white"]
animals = ["alligator","ant","antelope","ape","baboon","badger","bat","bear","beaver","bee","beetle","bird","bison","buffalo","butterfly","buzzard","camel","cat","cattle","chamois","cheetah","chicken","cobra","cockroach","cormorant","coyote","crab","crane","crocodile","crow","deer","dog","dogfish","dolphin","donkey","dove","duck","eagle","eel","elephant","elk","falcon","ferret","finch","fish","flamingo","fox","frog","gazelle","gerbil","giraffe","goat","goldfinch","goose","gorilla","guanaco","gull","hamster","hare","hawk","heron","hippo","hog","hornet","horse","human","hummingbird","hyena","jackal","jaguar","jay","jellyfish","kangaroo","ladybug","lark","leopard","lion","llama","lobster","louse","magpie","mallard","manatee","mink","mole","monkey","moose","mosquito","mouse","mule","nightingale","ostrich","otter","owl","ox","oyster","panda","panther","parrot","partridge","peafowl","pelican","penguin","pheasant","pig","pigeon","polecat","pony","porcupine","quail","rabbit","raccoon","rail","ram","rat","raven","reindeer","rhino","rook","seastar","pineped","shark","sheep","skunk","snake","snipe","sparrow","spider","squirrel","swallow","swan","tiger","toad","turkey","turtle","weasel","whale","wildfowl","wolf","wombat","worm","wren","yak","zebra","zebu"]


for c in colors:
  for a in animals:
    num = check_username(c, a)
    if num is not None and num < 3:
      print c, a, num

It turns out that there were a few pairs that returned a zero! (There is one fewer now 🙂 ) There are also a few ‘1’s and ‘2’s left.

Posted in Uncategorized | Tagged , , , , , | Leave a comment

How to display the date on the OS X lock screen

Today, my wife asked if I could have the lock screen on my OS X workstation at home display the date, so she could easily see the date, without logging in. This is the screen that is shown when you are logged in, but the screensaver is locked. By default, it displays the logged-in user’s desktop background, the time, battery status, and a login box. This should be a simple problem to solve, right?

It turns out, I’m not the only one with this question. The accepted answer on that post suggested using a 3rd-party application to dynamically change the wallpaper, to include the time and date. While that might work, it seemed like overkill to solve such a simple problem, and I’m worried about the performance impact this application might have (though it is probably minimal).

The other suggestion on that page seemed to be geared toward displaying the time in 24-hour format, rather than including the date, and in any case, it didn’t work for me (on Mac OS 10.9.5).

In my research, though, I discovered that you can include a static text message on the lock screen. This can be configured using the UI by going to System PreferencesSecurity & PrivacyShow a message when the screen is locked.. It turns out, you can also set this message using the terminal:

sudo defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "Hello World!"

This is great, but this message is static. There is no magical code you can include in the message to display the date.

So, the solution I came up with is to create a cron task to update the message every day. This is a bit of a hack, but it doesn’t involve installing any 3rd-party code, and it has no performance implication.

To get the current date as a string, I ran the following command:

$ date '+%B %d, %Y'
February 08, 2015

Because the command to update the lock screen text needs to be run with sudo, you need to add an entry in root‘s crontab:

$ sudo crontab -e

I wanted to update the message every day at midnight, so the full crontab entry I used was:

0 0 * * * defaults write /Library/Preferences/com.apple.loginwindow LoginwindowText "The date is `date '+%B %d, %Y'`"

Hope someone else finds that useful!

Posted in Uncategorized | Tagged , , | Leave a comment

MapCustomizer.com Launches

I have been meaning to overhaul my site that allows you to plot multiple points on Google maps for a long time now, and I am happy to announce that MapCustomizer.com is the result!

2014-05-25 at 2.23 PM 2x

There are a number of new features that people have been asking for, including:

  • It should continue to work, even if the site is busy. In the old site, when things got busy, it would exceed the quota for geocoding addresses with the Google Maps API. In the new site, the geocoding is restructured so this shouldn’t happen. It is still possible for things to slow down if you are creating a large map (and pasting in lots of addresses), but it won’t slow things down for other users.
  • Edit/delete your own maps You can optionally create an account with the new site, and manage maps that you create. You can edit them after creating them, or delete them. Even if you don’t create an account, you can still edit maps that you create, as long as you are still using the same computer and web browser that you used to create them.

    2014-05-25 at 2.44 PM 2x

  • Numbered location markers A lot of people were asking for this. The list of locations shows numbered markers that correspond to the numbered markers on the map. You can print the map out, and still see which location is which.
    2014-05-25 at 2.30 PM 2x
  • General UI improvements I never put too much effort into making the old site look nice, and it showed :). The new site is a lot nicer, in my humble opinion. This leads into…
  • Full-screen map Once the map is created, it takes up almost the full browser window, leaving a little bit of space for the location list.

If you go to the old homepage, you will be automatically redirected to the new site, or you can just go directly here:

MapCustomizer.com

If you are curious about the technology behind the new site, it is written in Scala using the Play Framework. MongoDB provides the persistence layer, and I am using WebJars with RequireJS, and the relevant sbt-web plugins to build everything. It was a great experience to play with WebJars and sbt-web (I am already proficient in Scala, Play, and MongoDB).

As with the old site, it is supported by ads and Paypal contributions. It operates on a value-for-value model: If you find that the site provides you with a value, please consider paying for that value.

Posted in gmaps.kaeding.name | Tagged , , , | 133 Comments

sbt-git-stamp released

I finally published a simple sbt plugin: sbt-git-stamp, which I had written long ago, and every now and then, someone would find the code and ask about it.

This is a little project I created in 20% time at work, and it enables you to include some basic information about the state of the Git repository when the artifact was built, so you never have to wonder where an artifact came from. The information recorded is:

  • Head revision
  • Branch name
  • Whether or not there were uncommitted changes
  • Build date

This info is recorded in the MANIFEST.MF file, like so (the highlighted entries are from the plugin):

Manifest-Version: 1.0
Implementation-Vendor: My-Company
Implementation-Title: My Project
Implementation-Version: 0.1
Implementation-Vendor-Id: My-Company
Specification-Vendor: My-Company
Git-Repo-Is-Clean: false
Git-Branch: gitstamp
Specification-Title: My Company
Git-Build-Date: 2013-04-26T17:22:58.538-07:00
Specification-Version: 0.1
Git-Head-Rev: b0d5a67d59dc7c0133aecce2e2ceb18fc8d23597

Installation instructions and more are on Bitbucket.

Posted in Uncategorized | Tagged , , | Leave a comment

Injecting connection information into Typesafe Slick at the last possible point

Often when designing a database-driven application, you will want flexibility as to which database you want to connect to. You will certainly want different databases for production, test, and development environments. You might even want different database engines for different environments. For example, you might use an H2 database in your local development environment, and Postgres in test and production. Or perhaps you are writing an application that will be used in many environments, and you need to support Postgres, MySQL, DB2, Oracle, etc. The usual answer to this problem is dependency injection, and while there are frameworks for this, in many cases, you can accomplish these goals using just the language features of Scala.

Most tutorials (that I have found, anyway) for using Typesafe Slick assume that you are picking one database engine and sticking with it. You need to import implicits specific to the driver you are using. You can easily specify different connection URIs at runtime, but you need to commit to a driver throughout your application.

Here, I will present an alternative that allows you to specify your driver in one place, and have various classes of your database interface code all agnostic to the particular driver you are using. There is no runtime switching of the driver, and (almost) everything is type checked at compile time.

Schema Definition

The Slick docs start with selecting a database driver before doing anything else:

// Use H2Driver to connect to an H2 database
import scala.slick.driver.H2Driver.simple._

But of course, we don’t want to do that. So, here is a schema definition class that only assumes that we will be using some kind of scala.slick.driver.JdbcDriver:

import slick.driver._
class Tables(val profile: JdbcProfile) {
  import profile.simple._
  
  def ddl: profile.SchemaDescription = names.ddl

  class PersonTable(tag: Tag) extends Table[(Long, String)](tag, "person") {
    def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
    def name = column[String]("name")
    
    def * = (id, name)
  }
  val names = TableQuery[PersonTable]
}

Note that this gets the implicits from the JdbcProfile that is passed in. This allows us to pass in the profile when we know what it is, but we don’t have to worry about it here.

DAO layer

Next, lets add some DAO code that uses this new table:

class PersonDao(t: Tables) {
  import t.profile.simple._
  def makePerson(name: String)(implicit sess: Session): Long =
    (t.names returning t.names.map(_.id)) += (-1, name)
}

Again, we just import the implicits needed for the Slick DSL from the profile that was given to the schema definition.

Finally, we bind the database driver

Up until now, we have been agnostic as to which database driver we use. At some point, though, you need to choose one. Here is a simple Main class that does that with a hardcoded value. You can imagine some logic that reads a config file, or some other mechanism to do this, though.

import slick.driver._

object Main extends App {
  import scala.slick.driver.H2Driver.simple._
  import slick.driver.H2Driver.profile
  val db = Database.forURL("jdbc:h2:db", driver="org.h2.Driver")
  db.withSession { implicit s => 
    val foo = new PersonDao(new Tables(profile))
    println(foo.makePerson("george"))
    println(foo.makePerson("sally"))
    println(foo.makePerson("becky"))
    println(foo.makePerson("barry"))
  }
}

Only lines 4-6 in the above snippet commit us to a specific database. They could be swapped out for a different driver, with a different profile, and a different connection string, and our schema definition and DAO code could remain unchanged.

While coming up with this, I did find one case where the compiler got confused, and I needed to cast something, though. This was while adding a function to recreate the DDL:

  db.withSession { implicit s => 
    val ddl: profile.SchemaDescription = new Tables(profile).ddl.asInstanceOf[profile.SchemaDescription]
    import profile.Implicit._
    ddl.drop
    ddl.create 
  }

From looking at the code, you can tell that the Tables.ddl object should be of the type profile.SchemaDescription (for whatever type profile you are passing in), but the cast was necessary to make the compiler happy.

Caveats to this approach

  • You are stuck with the lowest common denominator. Some features may compile, but then fail at runtime if you use a feature that one driver doesn’t support. Likewise, if one driver presents a non-standard feature, you may not be able to use it.
  • Be sure to run your test suite (at least the part that exercises your db interface) against all drivers you intend to support. If your database functions prove to behave identically whether run on an H2 in-memory database or a real Postgres DB, you can then test the rest of your code (that just calls your db interface layer) against the H2 in-memory db, and possibly achieve faster test runs.
Posted in Uncategorized | Tagged , , | Leave a comment

33 is the Magic Number…

Photo courtesy of Flickr user schoeband

On the No Agenda Show, there is the theory that the number ’33’ is inserted into news stories as code.  No one is sure what the code means, though.  In some contexts, it seems to mean that the rest of the news story is bogative, or maybe it means ‘mission accomplished’, or it is just a flag to alert people in-the-know to take heed.

In any case, I created a little site to track instances of such numbers in the news.  Introducing: 33IsTheMagicNumber.com.

Subscribe to the feeds if you want to be kept abreast of any possible coded stories!

This was a fun little project to get more familiar with Heroku, Play 2.1, and Reactive Mongo.  I even worked a little bit of Shapeless HLists in there, for good measure.

Posted in Uncategorized | Leave a comment