2007-09-26 10:52 UTC A low-bandwidth, high-latency, high-cost, and unreliable data channel
I like food, and I'm not really good at the creative art of cooking (though I'm a fine sous-chef), so I eat out at restaurants a lot. I usually pay by credit card. In the US, waiters have a minimum wage below the normal minimum wage, and thus you always have to tip, and so you never pay what the bill says (and I usually tip well, unless the service or food was appalling, even outside the US).
The net effect of this is that you basically get to decide how much you pay. Indeed, credit card bills at restaurants have a space where you fill in how much you want to pay.
I don't like doing arithmetic, especially not of the kind "$85.47 * 1.17", and so I just approximate. $85.47 is about $90, 15% of $90 is about 15, round to down to cancel out the earlier approximations gives about $100. So I pay $100.00 and go on my merry way.
One day I looked at my bank statement and it was something like:
POS Trans ZIBIBBO PALO ALTO CAUS | $76.00 |
POS Trans CHEESECAKE PALO ALTO CAUS | $40.00 |
POS Trans OUTBACK #0514 CUPERTINO CAUS | $210.00 |
POS Trans BROOKFIELD'S REST #2 SACRAMENTO CAUS | $34.00 |
Look at all those zero cents... there are data bits there, lying unused! It struck me that with every single restaurant transaction I could set the cents field to some number under my control, thus allowing me to communicate with myself at a later date!
This would be really useful as a way of sending ratings information back to myself, so that I could later review the restaurants online or otherwise keep track of where I would want to go back to or where I would want to avoid (since I eat out a lot, restaurants somewhat blend together in my memory).
We can set any number from 0 to 99. In binary, that's 0b0000000 to 0b1100011. In other words, we have seven bits to play with, except that if both of the high bits are set, then we lose bits 3, 4, and 5.
There are five things I wanted to be able to communicate. The first was the number of guests, so that I can divide the price by how many people I was paying for, to determine the price-per-person. The second was the rating, whether I should go back or not. The last three were whether the restaurant had wifi, whether they were suitable for vegetarians (Carey is vegetarian), and whether they had drinks I liked (I don't drink addictive drinks, drinks containing mind-altering drugs, carbonated drinks, and drinks containing high fructose corn syrup, which basically excludes almost anything you can buy in the US in many cheap restaurants, and even some fancy ones).
If we consider the rating to be a four-state flag, with values "avoid", "ok", "good", "awesome", and if we limit ourselves to being able to specify 0, 1, 2, or "more than 2" guests (in addition to me), and if we establish that if we want to avoid the place in future then it really doesn't matter whether the restaurant had Internet, a vegetarian selection, or good drinks, then we can neatly fit this into our contstrained not-quite-7-bit bitfield like this:
64 | 32 | 16 | 8 | 4 | 2 | 1 |
r | d | v | i | g |
...where:
- r
-
The rating, according to the following scale:
0 awesome 32 good 64 ok 96 avoid (and ensure d, v, and i are set to 0) - d
-
Whether drinks are good or not (set means they are good)
- v
-
Whether a vegetarian selection is available (set means there are vegetarian options)
- i
-
Whether free wifi Internet access is available (set means wifi is available)
- g
-
How many guests were paid for in the transaction:
0 just me 1 me and one guests 2 me and two guests 3 me and three or more guests
I did this, and used it for a while. I quickly discovered that something was wrong. The numbers in my bank statement made no sense, for example dinners with more than 2 guests at locations where I knew that I had been with just one person.
I changed to a new scheme. Instead of encoding data in the cents field, I instead just store the last two digits of the dollar amount into the cents field. A checksum, if you will. So if it cost around $34 with tip, then I put $34.34, or if it cost $122, then I put $122.22. I do this reliably now, on all restaurant transactions.
What I've found is a shocking number of restaurants don't charge me what I write. For a while I thought I just had bad handwriting, but I then went out of my way to write very clear numbers and that didn't help. For example, Zibibbo's in Palo Alto. I remember very clearly writing $77.77, but was charged $76.95. That's not the original amount without tip (which was probably closer to $65), it's not what I wrote, what the heck is it? On the other hand, the other time I went, they charged me $865.65, exactly what I wrote. A cafe in Monterey (Portola Cafe) charged me $18.28. Either they charged me ¢10 too much, or they gave me a $10 discount. The Melting Pot, San Jose, charged me $70.54. Where did the .54 come from? Why not take the remaining ¢16? Pasta Pomodoro did the same trick as Portola, charging me $37.47. But two months before that, they charged me $34.31, which is probably ¢3 less than I wrote. Why am I getting overcharged sometimes and undercharged others? In Hawaii, the majority of restaurants ignored the tip altogether, just charging me the original amount regardless of what I wrote. Are people in Hawaii so relaxed that they don't need the extra money from tips?
My theory is that it is because I don't write an explicit tip, I just give the total. Maybe restaurants need the tip as well as the total, and so to save time they just work out a round dollar tip that is close to what I wrote, and charge me that. My next step, to test this theory, is to start always writing the actual tip amount in.