Spamming for the Lord

April 3, 2013

The spammers are getting more creative. Just got this from Teresa Albert (teresa.albert503@yahoo.com)…

Hello dear,

With due respect and humility am writing you. Though i know this email will come to you as a surprise and i simply ask that you follow your heart before you respond to what i am about to say.

I have been informed by my Oncologist that I would not Last for the next two week due to an internal illness that has been going on for seven years. I have been down with Ovarian Cancer but what bothers me is my stroke. Due to my medical problem, i have decided to donate my life savings to the service of humanity, hence i am looking for someone of integrity who will help carry out my last wishes the way i will advise herein. I took this decision to contact you because I don’t want my husband’s wish to be wasted by unbelievers or someone not to be trusted.

I am not afraid of death hence I know where I am going. I know that I am going to be in the bosom of the Lord. Exodus 14 VS 14 says that the lord will fight my case and I shall hold my peace. Please let me know you can handle this evangelism so that i will provide you more information. Whoever that wants to serve the Lord must serve him in spirit and truth. Please always be prayerful all through your life. If you can handle this, get back to me immediately with your following contacts and detail informations.

Full name:
Address:
Phone Number:
Occupation:

Hope to hear from you.
Remain blessed in the name of the Lord,
From: Mrs. Teresa Albert

In short, “I’m about to die and don’t want to leave this world without first sending out some spam.”

Alfred Workflows

If you own a Mac and haven’t discovered Alfred 2 yet, well I’m sorry.  Combined with its PowerPack, it’s a formidable tool for doing things quickly on the Mac.  I’ve used QuickSilver and LaunchBar.  I held out for a long time as a staunch LaunchBar user, but recently made the switch to Alfred 2 and I’ve got it doing anything everything I need (and boy do I need a lot… I’m lazy and I’ll love keyboard shortcuts).  The only shortcoming with Alfred is its clipboard history, which is limited to text (no images… bummer).  LaunchBar does the clipboard history just right, so I map Alt+Cmd+K to LaunchBar’s clipboard history and I’m good to go.  Sure, LaunchBar is an expensive tool just for clipboard history, but I already owned it and why use Alfred’s crappy clipboard history when I have access to LaunchBar? 🙂

Anyway, I thought I’d share a few of my (now ~24) Alfred 2 workflows for anyone interested:

icon Arrows
Easily type arrow characters (↑, ↓, ←, →) using HTML entity names: uarr, darr, larr, and rarr.
IRC Cloud IRC Cloud
Open IRC Cloud in Chrome with irc.  If you’ve already got IRC Cloud in a tab, it doesn’t open it in a second tab.
icon OpenMRS
A workflow for OpenMRS developers with a few handy shortcuts.

  • op — launches the OpenMRS wiki
  • ot [ticket] — launches OpenMRS JIRA. Naming a ticket goes straight to that ticket; giving just a number will open the corresponding TRUNK ticket; leaving off the ticket just takes you to JIRA.
  • dev — opens the OpenMRS Developers Forum page
  • raf — types Rafał’s name properly into your editor (and into your clipboard in case you need it again)
  • paul – pastes “Paul is a dork” into your editor
icon Volume Controls
Provides some shortcuts for controlling your volume. You thought you were lazy? I know there are dedicated keys for this, but they’re way over there. Alfred shortcuts can be habituated (once learned, you just think and it happens) and don’t require your hands to leave the “home row” of the keyboard.

  • vl — volume low (about one “dot” of volume on the Mac)
  • vh — volume high (crank it up!)
  • mute ‐ guess what this does. 🙂

Auditing OpenMRS repos in GitHub

April 1, 2013

OpenMRS has some basic conventions for its repositories in GitHub (within the openmrs org).  Basically, we add four teams to every repo (owners, full committers, partial committers, and repo owners) and we disable wiki & issues on the repo (since we already have a place for wiki & issues).

It’s easy for these things to get overlooked as new repos are added to the org in GitHub, so I made a little Groovy script to manually audit the repos.  Nothing fancy and it doesn’t really warrant a repo of its own, but I want to get the code off my laptop… so I’m blogging it. 🙂

The output should look something like this:

$ groovy AuditOpenMRSRepos.groovy
OpenMRS org has 78 repos
Owners team has 78 repos, missing none
Full Committers team has 78 repos, missing none
Partial Committers team has 77 repos, missing none
Repo Owners team has 77 repos, missing none
wikis or issues (should be empty): []

Audit OpenMRS repos

#!/usr/bin/env groovy

import groovyx.net.http.RESTClient
import org.apache.http.*
import org.apache.http.protocol.*
import groovyx.net.http.*

@Grab(group='org.codehaus.groovy.modules.http-builder', module='http-builder', version='0.7.1')

def scriptDir = new File(getClass().protectionDomain.codeSource.location.path).parent
def token = new File("$scriptDir/github.token").text.trim()

// initialze a new builder and give a default URL
def github = new RESTClient( 'https://api.github.com' ).with {
  client.addRequestInterceptor(
    [process: { HttpRequest request, HttpContext context ->
        // using httpbuilders auth mechanism doesn't work, do it manually
        request.setHeader("Authorization", "token $token")
    }] as HttpRequestInterceptor
  )
  client.params.setIntParameter('http.connection.timeout', 5000)
  client.params.setIntParameter('http.socket.timeout', 5000)
  delegate
}

def getNext(response) {
  def next = null
  for (link in response.getHeaders('Link')?.value[0]?.split(',')) {
    def matcher = link =~ /< (.*)\?page=(\d+)>; rel="next"/
    if (matcher.matches()) {
      next = [url:matcher[0][1], page:matcher[0][2]]
    }
  }
  next
}

def fromGithub = { path ->
  def resp = github.get(path: path, headers:['User-Agent':'Groovy'])
  def data = resp.data
  def next = getNext(resp)
  while (next) {
    resp = github.get(path: next.url, query:[page: next.page], headers:['User-Agent':'Groovy'])
    data += resp.data
    next = getNext(resp)
  }
  data
}

def addRepoToTeam = { repo, team ->
  def resp = github.put(path: "/teams/$team.id/repos/openmrs/$repo.name",
  	headers:['User-Agent':'Groovy'])
}

def editRepo = { repo ->
  def body = """{"name":"$repo.name", "has_issues":false, "has_wiki":false}"""
  def resp = github.patch(path: "/repos/openmrs/$repo.name", body: body, 
    requestContentType:ContentType.URLENC, headers:['User-Agent':'Groovy'])
}

repos = fromGithub('/orgs/openmrs/repos')
teams = fromGithub('/orgs/openmrs/teams').findAll{ it.name != 'Transfer Team' && it.name != 'Release-test' }
println "OpenMRS org has ${repos.size()} repos"
for (team in teams) {
  teamRepoNames = fromGithub("/teams/$team.id/repos").collect{ it.name }
  missing = repos.findAll{ !(it.name in teamRepoNames) && it.name != 'openmrs-core' }
  print "$team.name team has ${teamRepoNames.size()} repos, "
  println missing.size() > 0 ? "missing from these: ${missing.collect{it.name}}" : "missing none"
  for (repo in missing) {
    print "fixing..."
    addRepoToTeam(repo, team)
    println "done."
  }
}

wikisOrIssues = repos.findAll{ it.has_wiki || it.has_issues }
println "wikis or issues (should be empty): ${wikisOrIssues.collect{it.name}}"
for (repo in wikisOrIssues) {
  print "fixing..."
  editRepo(repo)
  println "done."
}

One-Eyed Pinky Trick

March 23, 2013

Have you ever seen a harvest moon?

Harvest Moon

Have you ever wondered why the moon looked so big?  Is it some sort of refraction of the atmosphere?  Actually, it’s just an optical illusion.  It’s time for the One-Eyed Pinky Trick!

Pinky

  1. Extend your arm toward the moon.
  2. Stick your pinky (smallest finger) straight up and hold it right next to the moon.
  3. Close one eye.

Notice anything different?

That’s right, the moon is smaller.  Don’t believe me?  Try it.  It works on the sun too (just don’t stare at the sun, ok?).

How does this work?  Here’s my theory…

Poof!  Optical Illusion busted thanks to the One-Eyed Pinky Trick!

OpenMRS Licensing

OpenMRS

Background

In the process of upgrading the software license for OpenMRS, it seems like a good time to review how we got here and why we’re changing our license.  Here’s a brief history of OpenMRS Licensing…

OpenMRS Public License 1.0

Ok.  Let’s stop here for a second.  At this point, in 2007, OpenMRS transforms from a shared, unlicensed, pile of code within a public Subversion repository into officially licensed open-source software.  So, what is this OpenMRS Public License and where did it come from?  With the help of local lawyers, we hired a lawyer with expertise in open source licensing and described our goals:

  • Keep the platform openly available… forever, but avoid being so copyleft as to scare away commercial interests – i.e., a key goal of the platform is to enable local capacity.
  • Provide indemnity for medico-legal issues.
  • Allow modules to be licensed separately.
  • Require anyone changing the core platform to share those changes, while leaving open the possibility for an exception iff an entity seeking an exception offers something in exchange that the community deems worthy (e.g., BigCo wants to commercialize an adapted version of OpenMRS as a closed product, but is willing to offer resources for a dozen dedicated FTEs to the open-source effort in perpetuity, and jumps through enough hoops to satisfy the OpenMRS community)

The lawyer took these goals, reviewed the available open source licenses at the time, and suggested the Mozilla Public License 1.1 with a few tweaks to fit our specific needs.  So, we created the OpenMRS Public License 1.0 as a slightly modified version of MPL 1.1 and applied it to all of our code.

Living with OPL 1.0

OpenMRS Public License 2.0 Mozilla Public License 2.0 + Disclaimer

In 2013, with some hard work by Paul and help from OSI, Luis Villa, and some other lawyers, we discover that the Mozilla Public License 2.0 with a disclaimer could meet all of our needs, so we proposed the idea to the community.  Overall, people in the community are pleased to see us adopting an OSI-approved license.

OSI LogoOkay, OpenMRS on an OSI-approved license… at last.  That’s cool.  But why Mozilla Public License 2.0 (MPL 2.0)?

 

See our license at http://openmrs.org/license.

 

Preach Open Source; when necessary, mention code.

March 19, 2013

I was recently reminded of the quote that so often is (mis)attributed to St. Francis of Assisi:

Preach often; when necessary, use words.

Without getting religious, I believe and hope OpenMRS follows this dictum: spend more time & effort improving health in resource poor environments than we spend talking about it.  And, for OpenMRS, we choose to do our work openly.  Why?  Because “Open Source” is not so much about sharing code as it is about sharing experiences, teaching & learning from each other, and embracing collaboration & open methodologies… in short, open behavior.  It took a while to learn that distinction.  Now when I hear people fussing over code, it feels petty.  One of the most important lessons that I’ve learned from the OpenMRS Community:

The value is not in the code; it’s in the people.

We could switch to a completely different programming language or a new shiny platform could (and likely will) come along some day that’s far better than what we’ve done.  All of our precious code will fade away.  That’s fine.  As long as we have our people.  Are you running a development shop?  Have you calculated how much you’ve invested in your “product” and found yourself thinking about the code?  Wrong.  Your investment is in people.  Give me the choice between good code and a good coder and I will take the coder 100 times out of 100.  In the end, code is just a tool… property.  And property can be replaced.  Love your coders.  Treat them well and invest in them.  Life will be good.  And while you’re doing that, consider working openly.

IRCCloud ftw!

March 12, 2013

I recently discovered IRCCloud and it has brought me back to IRC.  I no longer have to worry about opening or maintaing a client or an IRC bot.  I can check into IRC on my own terms and easily catch up on what I’ve missed (even days of history) with little effort.  Perfect!

But it gets better.  After a day or so playing around with IRCCloud, I hopped into the feedback channel to give some props to the IRCCloud team and ask some questions.  I had noticed that I couldn’t page up/down through the history using the keyboard.  Look what happened:

IRCCloud continuous delivery

From feature request to deployment in under 4 hours… now that is continuous delivery!  Well done, IRCCloud!!!

IRCloud is still in a beta phase.  You can sign up, but it might be a while before you get an invite.  If you’re looking for an invite to IRCCloud Beta, let me know and I may be able to send you one.

The growing OpenMRS Development Glossary

January 4, 2013

As we work to organize & improve the development work we are doing for OpenMRS, we’re starting to use (and sometimes misuse) a growing list of terminology. I thought I’d dump them out here (to get them out of my head, to be able to come back & look at them, and maybe to get comments from folks on what we’ve got wrong).  Many of these are drawn from our (growing) experience with agile methodology.  Since I’m not taking the time to look up “official” definitions, I’m sure these are imprecise and I wouldn’t be surprised to learn that we’re doing what others were doing 10 years ago. 🙂

What gets done:

How it gets done:

Who does the work:

Thoughts or comments are welcome.

Partial checkout with Subversion

June 6, 2012

I wanted to check out OpenMRS trunk and a couple branches from the subversion repository within the same local copy so that I could apply a set of changes to trunk and backport it to a couple prior versions in a single commit. Typically, when you check out a directory, you get everything underneath. But OpenMRS trunk and the branches I wanted are only a few of the bazillion folders and files underneath http://svn.openmrs.org/openmrs/. Checking out all of those folders would take a long time, place an unnecessary tax on the OpenMRS repository, and end up transferring a bazillion files that I didn’t need. While it’s not obvious, there is a way to do this with Subversion.  The answer is in Subversions sparse directories feature. Thank you, stackoverflow! Here’s how I checked out only a subset of folders (trunk and a couple branches) from subversion:

$ svn co --depth empty http://svn.openmrs.org/openmrs
$ svn update --set-depth infinity openmrs/trunk
$ svn update --set-depth empty openmrs/branches
$ svn update --set-depth infinity openmrs/branches/1.8.x
$ svn update --set-depth infinity openmrs/branches/1.9.x

What are the first 10 consecutive digits of e that form a prime number?

January 22, 2012

After seeing some sample Google Interview Questions that included this question, I couldn’t resist the challenge…

def bigE() {
  BigDecimal e = new BigDecimal(1.0G)
  BigDecimal temp = new BigDecimal(1.0G)
  for (int i in 1..100) {
    temp *= i
    e += new BigDecimal("1")
         .divide(temp, new java.math.MathContext(10000))
  }
  return e.toString()
}

def isPrime(long n) {
  if (n < 2) return false
  if (n == 2 || n == 3) return true
  if (n%2 == 0 || n%3 == 0) return false
  long sqrtN = (long)Math.sqrt(n)+1
  for (long i=6L; i < sqrtN; i += 6) {
    if (n%(i-1) == 0 || n%(i+1) == 0) return false
  }
  return true
}

def firstPrimeBySize(n) {
  String e = bigE()
  for (int i in 2..e.size()-n) {
    String chunk = e.substring(i,i+n)
    if (isPrime(new BigDecimal(chunk).toLong())) {
      return "$chunk at position $i"
    }
  }
}

assert firstPrimeBySize(10) == "7427466391 at position 100"