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 , , , | 6 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 computers | 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 computers | 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

FIBS: Functional interface for Interactive Brokers for Scala

Announcing a small side project I have been hacking on: a Scala wrapper library for the Interactive Brokers TWS API.  The TWS API uses a message-passing design, where you pass a message asking for a quote, for instance, and then you get a series of messages back, making up that quote.  It is up to you to keep track of which response messages are referring which quote request, and the whole thing involves a lot of mutable state.

I, however, wanted to write an application staying as functionally pure as possible, with little or no shared mutable state, which could process many quotes at once.  I wanted to do this using my favorite functional language du jour, Scala/scalaz.

So, I created FIBS, which is a terrible backronym that I am claiming stands for Functional interface for Interactive Brokers for Scala.  It is in its infancy, and currently only supports the following operations:

  • Realtime Stock Quotes
  • Historical Stock Quotes

There is much, much more in the API to flesh out.  One of the other things I don’t like in the TWS API is that it is up to you to know which parameters are appropriate for the request you are making.  (For example, only certain order parameters make sense for a given order type.)  So, I want to enforce this logic with the type system.  You, as the consumer fo my API, should never pass a null value because that parameter makes no sense in the context of what you are doing.  The type system should enforce this.

Instead of waiting for various pieces of information to return, you will get a Promise or a Stream, or some other monad to allow you to move forward with your code while IB is doing its thing.

So, I am making progress on the API slowly, as I need it for my application.  I wanted to make it public to see if anyone else was interested.  I could also use some domain expertise in knowing exactly what parameters are appropriate, when.  My experience as a quant is strictly amateur.

Check it out on Bitbucket!

Posted in computers | Tagged , , , , | 3 Comments

Building Inline Comments for Pull Requests and Commits

(or, what I did over summer vacation)

For the last few months, I have been working with the Bitbucket team at Atlassian.  I switched over to this team at the beginning of the summer to help build a new inline commenting feature on pull requests and commit pages, to help make the tool more useful for code reviews in a team.

It was a great project, and I wrote up a story of how we built inline comments for pull requests and commits over at the Bitbucket blog.  Check it out!

Posted in Uncategorized | Leave a comment

Proof that Netflix is the only thing holding the USPS afloat

"Netflix Only" chute at the post office

Posted in Uncategorized | Leave a comment