26 May, 2014

D'Hondt results table for London MEP elections

There was just an election in the UK for the European Parliament (to elect MEPs), and it was interesting in the news because of the rise of one particular party, UKIP. The European elections use a proportional representation method, which UK general elections don't, so this doesn't mean that there will be a corresponding rise in UKIP members of parliament (at present, 0) at the next general election.

I voted in the London constituency, which has 8 MEPs elected in one ballot.

Wikipedia has a list of number of votes and number of MEPs elected, for each party.

Both the Green Party and UKIP got the same number of MEPs: 1 each. But their vote count was very different (371,133 for UKIP vs 196,419 for the Greens), and the liberal democrats, traditionally the third party in UK politics, got no seats at all.

I found myself playing with some "what-if" scenarios to better understand how the results came out.

The vote works like this: each elector chooses one choice on the ballot paper from a list of chosen parties - there were 17 parties on the paper, mostly small, fairly irrelevant ones.

The votes for each party are tallied, giving a vote count for each party.

Then, it is necessary to convert that vote count into a set of 8 MEPs that broadly reflects the proportion of votes. This is done here with the D'Hondt method which as an intermediate step needs a two-dimensional table. I'm going to omit the smaller parties here because they don't have an effect on my scenarios.

PartyCount /1/2/3/4/5/6/7/8/9/10/11/12
Labour806959806959 (1)403479 (3)268986 (5)201739 (7)161391 (11)13449311527910086989662806957335967246
Conservative495639495639 (2)247819 (6)165213 (10)1239099912782606708056195455071495634505841303
UKIP371133371133 (4)185566 (9)123711927837422661855530194639141237371133373930927
Green196419196419 (8)9820965473491043928332736280592455221824196411785616368
LibDem148013148013 (12)7400649337370032960224668211441850116445148011345512334

So the 8 seats were chosen as the top 8 "votes / seats" quotients. Those are coloured yellow in the table. I've also numbered the winning positions and the next 4 after that in order of "votes / seats".

So there's a difference there between the Greens and UKIP: UKIP was chosen 4th, with a solid block of votes to get its single seat. The greens were chosen last, and only just got a seat.

What do I mean by "only just"? Well, the next seat allocated if not for the Greens would have been a second UKIP seat (numbered 9 in the table) and to get that they would have needed 2 * 196419 = 392838 votes to beat the Greens: 21706 votes more than they actually got.

Or conversely, if the greens had got less than 185566 votes (so 10853 less than they really got), they would have taken 9th place, behind a 2nd UKIP seat taking the 8th seat. If that was the case, then the table would have looked like this:

PartyCount /1/2/3/4/5/6/7/8/9/10/11/12
Labour806959806959 (1)403479 (3)268986 (5)201739 (7)161391 (11)13449311527910086989662806957335967246
Conservative495639495639 (2)247819 (6)165213 (10)1239099912782606708056195455071495634505841303
UKIP371133371133 (4)185566 (8)123711927837422661855530194639141237371133373930927
Green185565185565 (9)9278261855463913711330927265092319520618185561686915463
LibDem148013148013 (12)7400649337370032960224668211441850116445148011345512334

Another thing that I think is interesting is just how badly the Lib Dems did. To get a seat, all other votes being equal, they'd have needed to get up to that 196419 to steal the 8th place off the Greens: that is 196419 - 148013 = 48406 more votes, 32% more than they actually got.

A different way of looking at that is considering if there were more than 8 seats, how many more seats would there need to be for the Lib Dems to get a seat to represent their proportion (about 6%) of the electorate?

The numbers in the first table above beyond 8 show that: the Lib Dems are 12th in line for a seat, after This table shows the 11 yellow coloured seats ahead of the lib dems, one more seat for each of Labour, the Conservatives, and UKIP.

PartyCount /1/2/3/4/5/6/7/8/9/10/11/12
Labour806959806959 (1)403479 (3)268986 (5)201739 (7)161391 (11)13449311527910086989662806957335967246
Conservative495639495639 (2)247819 (6)165213 (10)1239099912782606708056195455071495634505841303
UKIP371133371133 (4)185566 (9)123711927837422661855530194639141237371133373930927
Green196419196419 (8)9820965473491043928332736280592455221824196411785616368
LibDem148013148013 (12)7400649337370032960224668211441850116445148011345512334

So many election tea-leaves for staring into in this election!

You can get the Haskell code on GitHub that produced the above tables, if you want to fiddle yourself.

01 May, 2014

paytag wristband

A year or so ago, one of my credit cards sent me a PayTag: a sticker with the contactless payment bits of a regular credit card, but without the other stuff (contact chip, embossed number, etc).

Their stated usecase was for sticking on your phone, as a sort-of low tech upgrade for phones which don't have NFC.

I didn't find that use case particularly compelling, and aside from comedy ideas like putting it inside a fairy-wand, I've been waiting for a use.

A few days ago I made it into a payment wristband. My right-hand wrist has loads of bracelets on it already, and I took one of those, some plastic packaging and some superglue and made a payment wristband.

I was a little wary at deploying this in use at first. My initial test was deliberately in a stationer's shop which had unattended self-checkout terminals. (I've used that same branch for RFID fun as a teenager in the past, where I had a anti-shoplifting coil in my pocket and set the alarms off every weekend). For 75p I ended up with a new card case and a successful initial test.

Next I went to Waitrose to buy my groceries. I was wary here because the daytime staff are angry dinner ladies who have confiscated stuff off me in the past(!). They didn't seem to bat an eyelid at me waving my jacket arm at their payment terminal.

Thirdly I went to buy coffee. This was more awkward. Their payment terminal was stuff under a shelf and looked like it was probably quite awkward to use even with a regular contactless card. The dude was a bit confused at me putting my empty hand towards him and waving.

My final test was in a pub. The contactless user experience is a bit different in most pubs: they use hand-held terminals and usually you hand over your card, they notice it is contactless and then use that. So I had to work around that a bit. I handed over my regular payment card and when he noticed it was contactless and went to swipe I drunkenly shouted "WAIT! LET ME USE MY WRIST!" which he did. At that point the card reader decided it needed to do dialup verification so there was a tense few seconds where I hoped I didn't look like a knob. But it worked.

I'm surprised at how unsurprised staff are at seeing this. I need to figure out the right way to start a contactless payment in a hand-held reader environment. I'm looking forward to being able to use this on the London Underground ticket gates later in the year too...

later: someone sent me this article about a contactless payment suit.

26 February, 2014

Haskell numbers

I just put the (still being worked on) slides for a talk in a few hours that I'm doing at the London Haskell User Group, on the subject of "Numbers".

09 February, 2014

Range-weighted average-score voting at battle of the bands.

Went to a "Battle of the Bands" contest. It was in a bar and the audience got to vote. Everyone was given cards numbered 1 point, 3 points and 5 points. Voting happened after each band played. We'd all gone to see a friend of a friend so the obvious strategy was to vote 5 for that band, and not vote for the others.

Turned out they did the voting differently here: they computed the average score rather than the total score. In a fixed audience, both average and total would produce the same ranking. But in this situation the audience changed. Battle of the bands is really "who has the most friends?" and people turn up only to see and vote for their friend.

So normally you'd vote 5 points for your band, and ignore all the others (who might be playing when you haven't even arrived yet or after you've left) and that would be equivalent to voting 0.

Using an average vote penalises you for this, though: your absence didn't count as a zero vote because you weren't in the total vote tally. To downvote a band that isn't your friends, you have to be physically present.

That seemed a neat way for the bar to make you stay and drink more beer.

20 October, 2013

xkcd 320 compliant watchface for Pebble watch

I released my xkcd 320 compliant watchface for the Pebble e-ink watch: xkcd320-1.1.pbw

It looks like this:

And the source code is here on github.

17 October, 2013

libpebble on debian

Getting my pebble talking to my linux laptop took a while - mostly because I didn't know much about the linux bluetooth stack.

I'm running all this as root. I might eventually figure out how to do it as a normal user.

Can we see the pebble at all? This doesn't always show the pebble to me - i think because its not waiting long enough for the pebble to be active on bluetooth.

# hcitool scan
Scanning ...
        00:18:2F:CC:EC:A9       Pebble ECA9

In one window:

# bluez-simple-agent
Agent registered

In another window:

# l2ping 00:18:2f:cc:ec:a9
Ping: 00:18:2f:cc:ec:a9 from E0:06:E6:BA:33:AB (data size 44) ...
44 bytes from 00:18:2f:cc:ec:a9 id 0 time 8.54ms
Send failed: Connection reset by peer
It gives that connect reset message every time I try this ping... but carry on anyway.
# rfcomm bind 0 00:18:2f:cc:ec:a9
next:
./p.py --pebble_id ECA9 ping
will make the pebble buzz and show a ping message on screen.

Now run as many p.py commands as you like.

At some point when I did this previously, it got a persistent pairing with the pebble - I have no idea where in my hacking around the persistent pairing happened as at one stage I had to do it for every interaction...

14 October, 2013

list monad character to html entity encoding

This isn't particularly fancy, but it struck me as interesting from the "trying to abstract more" perspective.

Given a string with some funny characters in them, change the characters into HTML entities.

Here's a puffing-out function that given a character c :: Char returns a string (a list of characters, [Char]) for it to be replaced with. In the default case, the returned list contains only the original character.

generalPuffer c = case c of 
  c | ord c == 163 -> "£"
  c | ord c == 174 -> "®"
  c | ord c == 153 -> "™"
  c | ord c == 188 -> "¼"
  c | ord c > 128 -> error $ "unknown high character code " ++ (show $ ord c) ++ " encountered."
  c -> [c]

So how to use this? concatMap will handle this, and that was my first implementation (after fusing map and concat in my head).

concatMap f "£1 Shop™"
but concatMap is monadic bind, restricted to the list monad...

So equivalently you could write:

"£1 Shop™" >>= f
or
f =<< "£1 Shop™"
or
 do { l <- "£1 Shop™" ; c l }

08 September, 2013

BST

I wired in a rugby MSF clock into my raspberry pi, and wrote my own software to interface it to NTP.

Unfortunately I wrote it in winter when they were transmitting approximately GMT. Now its summer time and so they are transmitting British Summer Time not GMT; this is indicated by a bit in the time message. That I ignored. Oops.

Bed time project today was to add that in. Now I've got my stratum 1 server back.

28 August, 2013

certificate transparency

I went to a certificate transparency hack day at google london.

Dodgy x509 host certs really annoy me - they were a hassle when I worked on globus where we pretty much have out free host certs without any checking, to anyone who asked.

An achievable goal seemed to be to get a nagios plugin to check for certificates issued against a given hostname. I sort of have that working, with both OK/CRITICAL and a graph:

For now, the plugin is looking for certificates with the substring google in the subject name - there are plenty of such certificates in the log

When new certificates are discovered, they count as suspicious: they appear in red on the graph and the nagios notification system sends me an email. When an administrator (i.e. me) approves of the certs (by running an appropriate script), they turn into OK certificates and go green on the graph.

The underlying python code I'm using has a terribly slow ASN.1 parser, and so is only getting through a few hundred of the 2 million certs in the log every minute (see the blue line on the graph) - in a few days time hopefully it will have caught up. At least gives a pretty graph over time. In real life I'd expect a much smaller number of green certificates and hardly any/zero red certificates, as a flat line over time.

My original intention was to use this for matching domain names, but someone pointed out that it could be used to matching eg. trademark names anywhere in a certificate for some anti-phising detection.

Plenty of flaws:

  • doesn't check certificate alternate names (subjAltName)
  • doesn't check domain names at all
  • doesn't check consistency of data coming from the log server
  • doesn't deal with multiple log servers
  • doesn't deal with multiple domain name probes efficiently (eg by caching or sharing download/ASN.1 decoding between domain names) - this is perhaps better implemented by using Nagios's passive plugin interface where a monitor could push interesting results (for various domains) into Nagios, rather than the present active/polling style (whichI chose because its easy to do)
  • doesn't deal with unknown certificate extensions (at the moment, it ignores them which I think is sometimes the wrong behaviour - if the extension is one that authorises the use of new names (such as subjAltName does...)
  • its fairly synchonous which is a bad thing for nagios probes - spending 2 days to verify the initial log is not good for a probe that should take less than 10s

27 August, 2013

Timesort

Standing at bar. Older gentleman comments how when he gets new missed calls appearing way down the missed calls list. conversation continues. After a while comments that SMSes also appear way down the list. Eventually I jokingly comment "is your clock set wrong?" to while he replies "yes- is that what's causing it?"

Mostly I find that interesting because it seems an unbelievably obvious problem if you've grown up immersed in computers, but isn't if you have different abstractions: post doesn't stack up on your doormat in the order of the clocks in your house; it stacks up in the order that normal time flows.