Gambling on a lottery is a poor investment. By design, the bank profits, players lose. All things being equal, the smart choice is to abstain. You miss out on the 1 in 292,201,338 chance to hit the jackpot (unless you steal or find stray tickets, I guess), but you save $2 on each draw – no odds required. As Joshua puts it, the only winning move is not to play. But we don't exactly play to win; we play to not not win. [sic]
We ogle the prize. A eight- to nine-figure jackpot, occasionally exceeding one billion dollars. A life-changing amount of money. We long for change. Not playing is renouncing this possibility (unless, again, you happen upon an unattended ticket). Yes, the probability to get the right numbers is ridiculously small, but you have a chance. Partakers revel in this mysticism, bask in the dream. Get high on hope. Each week, an ordinary life may turn out to be extraordinary. Regularly buying tickets is a thrill, and an insurance of sorts. An insurance against the certainty to never win. A reason to go through the day. An escape.
But why do we yearn for such excessive wealth? Money is a mixed blessing at best, sometimes a curse. We tend to discount all the trouble associated with suddenly getting filthy rich (spoiled relationships, incessant requests, threats to personal safety, overindulgence, losing touch with reality, moral issues, depression or ennui...) and focus instead on the bright side: self-ownership. Freedom.
Considering the federal minimum wage in the United States ($7.25 per hour), unskilled labor is exploitative. On the other hand, educated masses struggle to pay off their huge student loans. Millennials' goal is not to save for retirement; their first ambition is to be "debt-free". Zero wealth, the bar is low... but they start at the bottom of a pit. They are money-hungry because they strive to redeem themselves. The fetters of debt keep modern-day galley slaves working the oars. Freedom is not free... Neither is education, nor healthcare, nor lodging, nor healthy food. Basic necessities have become a luxury.
At the same time, people demand more meaningful lives. They want to feel that they contribute to the betterment of mankind. Protect our environment. Make a difference. Sadly, meaning is in short supply. Too much human activity revolves around manufacturing and selling dispensable goods and services. Somehow, the falsehood that employment and economic growth matter has pervaded the minds. Machines eliminated most of the need for manpower, and what remains of the workforce concentrates in the tertiary sector, where busywork happens. Jobs often deprive people of their time, energy and soul. Hence the craving for change. Hence the lottery ticket.
The truth is, we don't need to put everyone to work. Only a fraction of the population. We should call for volunteers. Free and Open-Source Software proved that people who want to contribute do so for free. Citizens should receive an ample allowance to be free from want and free to choose their projects. Right. But that's not the world we live in today, so let's go back to the lottery.
I consider myself quite fortunate. My occupation, software developer, suits me. Programming compares to puzzle solving and riddle guesswork. If I were rich, I bet I would pursue the craft for the fun of it. This said, I could use an extra helping of freedom. I've started buying Powerball tickets on a regular basis. I pick numbers at random.
Twice a week, five white balls are drawn from a set of 69, plus a sixth, the "powerball", from a set of 26. For $2, you choose 5+1 numbers. A couple lucky guesses are worth a few bucks. With the correct five white balls (in any order) and powerball, you share the jackpot with the other winners. If nobody gets the six numbers right, the jackpot increases after the draw. A classic lottery. I disdainfully ignore the option called "power play", that adds $1 to the fare and multiplies the winnings... barring the jackpot.
![]() |
A Powerball ticket bought in Maryland. Not a winner. :( |
Besides the draw date, your beloved numbers, and mysterious pictograms, a ticket bears a large 25-character alphanumeric string titled "rewards points code". As the name suggests, a loyalty program allows you to collect rewards points with this code. You must claim them online. For the state of Maryland, the address is rewards.mdlottery.com, and for other states, I have no idea. The funny detail is that the number of points you get for each ticket is somewhat random. So what can you do with points? Trade them against useless items on the same website. Considering the retail value of these wares, the point-to-dollar change rate is crap. Alternatively, bid them on a virtual lottery. Yes. Quite the mise an abyme.
Sorry for this lengthy preamble. I come to the point now. The Freetinker showcases DIY projects. For starters, an attempt to streamline the chores of indulging in Powerball:
- Checking the numbers after each draw.
-
IRL: Locate a lottery retailer (usually inside convenience stores, gas stations, restaurants, bars, bowling alleys and grocery stores) and go for the terminal – the crimson cobble:
Mid-late Neolithic artifact, exceptionally preserved.
Pro(s):- If you win $600 or less, you can cash in right away.
- You get to go out and see people!
- If you win the jackpot, forget about anonymity.
- The machine is rather slow.
- There is often a line. If you have a bunch of tickets, people might hate you.
- You have to go out and see people.
- Online: mdlottery.com/games/powerball/winning-numbers/
Pro:- Pretty much everyone has Internet access at home, or in their pocket.
- You rely on a fallible human brain to ascertain whether you hold a winning ticket.
-
IRL: Locate a lottery retailer (usually inside convenience stores, gas stations, restaurants, bars, bowling alleys and grocery stores) and go for the terminal – the crimson cobble:
- Punching in the "rewards points code". This is totally optional, so the best optimization would be to simply disregard this step. Yet thrifty voices in my head urge me to collect points. Maryland Lottery's website is a pain to use, but there is no alternative. Or is there?
Maryland Lottery offers a free smartphone app, but it still does not feature the oft-requested ticket reader. With an other official app you can scan tickets, but only to claim the rewards points. Anyway, I don't even own a smartphone. Yes, I'm one of those guys. You can also receive the winning numbers by text message. You still have to verify them yourself... And heck, each incoming text costs me. I don't have a plan either.
Ideally, we would contrive a system that not only emulates a Maryland Lottery terminal, but also includes the functionality of automatically claiming the rewards points. One scan of the ticket, then we are done with everything, without waiting in line or waking our torpid neocortex. A lofty goal. But is it feasible? And how? Good questions.
Not only are the big ones twins, but they also contain all the data from the smaller one. A lot of redundancy here. So what do we have? Fields separated by semicolons. The first two are very short. Perhaps they form a version number. Useless. The third, of meaning unknown, also appears (minus the initial letter "S") in various places on the ticket. We recognize the fourth as our rewards points code, inexplicably prefixed with the letter "w". And, wait... That's all? Where are our numbers? How can the terminal tell whether we won without reading our numbers?
Here is an educated guess. When someone buys a lottery ticket, the cashier's machine connects to a centralized information system. A record is created, which holds the selected numbers, plus (maybe) ancillary notes such as the date, time, location, etc. An index is generated to uniquely identify this record. This index is sent back to the retailer, where it is printed on the ticket... as part of the QR-encoded data. So that's what the third field is about! When checking a ticket, the terminal decodes a QR code, transmits the index to the database via the network, then receives the numbers from the matching record. Maybe the remote server even takes care of the math and returns directly the gains. In any case, we don't know where the database is located, and even if we knew, it's very likely password protected. Without credentials, we simply cannot do the same as the terminal. Bummer.
Well, the numbers are printed on the ticket, after all. We could take a picture, then run an optical character recognition (OCR) program to extract them. I have tried. It does not work so well. On one hand, the software makes mistakes at times, and on the other hand, the print of the ticket is often of mediocre quality, so it's not helping. I know that it's possible to train the OCR to get better results... but it's never going to be perfect. I want to be absolutely sure that I did not win before I toss my ticket. At this point, I give up the idea of a machine reading the numbers. We will transcribe them manually.
The prize payout is a given. We also need to know which balls were drawn. Luckily, it's public information. It's all over the web... Now we can be picky. Since we want to automate the process, a source in a machine-readable format is the best. The text file at www.powerball.com/powerball/winnums-text.txt is as good as it gets: a table detailing two decades' worth of lottery results, steadfastly updated one hour after a draw. Nice.
We've defined all the pieces of our prospective system. Programming is the glue to bind them. Our program will prompt the user for their numbers, retrieve the drawn numbers, compare and output the gains, if any. For the hardware, any kind of computer with a keyboard, screen and Internet connection will do. For the software, I recommend a script language: Python. I've only started playing with it this year, but I'm fond of it. The documentation is not as helpful as Java's, and there is a weird split between versions 2.x and 3.x... No further complaints. Python comes with handy building blocks: we'll make use of the provided routines to read CSV files, to carry out operations on sets... Less on our plate, fewer lines of code required to make it happen. That's what you call powerful. In Python, the source code is interpreted (not compiled), so it doesn't matter whether your operating system is Linux, Windows or whatnot, as long as a Python interpreter is installed. This said, I use Linux and the first line of code below is Linux-specific. It's a hack to run a Python script just like a regular shell script. Note that for this to work, the script must be executed from a command-line interface, and its "execute" permission must be set.
The user is still involved in the process, so this solution is not automated enough. New approach: to reverse-engineer the website and figure out how to do without. An HTML form is meant to be used by humans. It relays the user input to some service. For the program meant to replace the soft machine, calling directly the target service is simpler. Let's find its URL. Read the HTML and JavaScript in the source of the web page. Audit the HTTP requests sent by the page. Browser extensions can help. Learn about the syntax of the command "curl." The man page will come in handy. It takes some trial and error too... Eventually, you should be able to log in and send a form without using a browser at all. You will eliminate the need for human intervention by writing a Bash script as follows:
Quick note about the hardware. We still need the usual computer, keyboard, monitor and Internet access, but also a peripheral to take pictures. I experimented with various models of webcams. The most convenient setup was to use the camera embedded above the screen of a laptop computer. To position the ticket quickly and reliably in front of the lens, I improvised a holder with reclaimed materials:
It works. At times. The construction is admittedly subpar; the plastic sheet bends out of shape until it loses its function. Above all, the concept itself is not satisfactory. The ticket stands so close to the lens that it must be lit from behind with a blinding USB lamp (not pictured). When it's slightly crumpled, the process fails. Even in perfect conditions, the image is often too blurry for the QR code to be readable. I switched to a flatbed scanner. Bulkier, but a much more pleasant experience:
Ideally, we would contrive a system that not only emulates a Maryland Lottery terminal, but also includes the functionality of automatically claiming the rewards points. One scan of the ticket, then we are done with everything, without waiting in line or waking our torpid neocortex. A lofty goal. But is it feasible? And how? Good questions.
Checking the Numbers
Let's reverse engineer the terminal a little. How does it read our numbers? As you can see on the animated picture above, it only scans the bottom of the ticket, where the maze-looking pictograms are. These are QR codes; similar to bar codes, but information is encoded in two dimensions instead of just one. We can already tell that the two bigger QR codes are identical. The smaller one looks different. A free application or an online service such as zxing.org will decode them for us:small one: V1;J0;S11094003818150447; big ones: V1;J0;S11094003818150447;w0P19B0QDQZK9G100N012RC5VB
Not only are the big ones twins, but they also contain all the data from the smaller one. A lot of redundancy here. So what do we have? Fields separated by semicolons. The first two are very short. Perhaps they form a version number. Useless. The third, of meaning unknown, also appears (minus the initial letter "S") in various places on the ticket. We recognize the fourth as our rewards points code, inexplicably prefixed with the letter "w". And, wait... That's all? Where are our numbers? How can the terminal tell whether we won without reading our numbers?
Here is an educated guess. When someone buys a lottery ticket, the cashier's machine connects to a centralized information system. A record is created, which holds the selected numbers, plus (maybe) ancillary notes such as the date, time, location, etc. An index is generated to uniquely identify this record. This index is sent back to the retailer, where it is printed on the ticket... as part of the QR-encoded data. So that's what the third field is about! When checking a ticket, the terminal decodes a QR code, transmits the index to the database via the network, then receives the numbers from the matching record. Maybe the remote server even takes care of the math and returns directly the gains. In any case, we don't know where the database is located, and even if we knew, it's very likely password protected. Without credentials, we simply cannot do the same as the terminal. Bummer.
Well, the numbers are printed on the ticket, after all. We could take a picture, then run an optical character recognition (OCR) program to extract them. I have tried. It does not work so well. On one hand, the software makes mistakes at times, and on the other hand, the print of the ticket is often of mediocre quality, so it's not helping. I know that it's possible to train the OCR to get better results... but it's never going to be perfect. I want to be absolutely sure that I did not win before I toss my ticket. At this point, I give up the idea of a machine reading the numbers. We will transcribe them manually.
The prize payout is a given. We also need to know which balls were drawn. Luckily, it's public information. It's all over the web... Now we can be picky. Since we want to automate the process, a source in a machine-readable format is the best. The text file at www.powerball.com/powerball/winnums-text.txt is as good as it gets: a table detailing two decades' worth of lottery results, steadfastly updated one hour after a draw. Nice.
We've defined all the pieces of our prospective system. Programming is the glue to bind them. Our program will prompt the user for their numbers, retrieve the drawn numbers, compare and output the gains, if any. For the hardware, any kind of computer with a keyboard, screen and Internet connection will do. For the software, I recommend a script language: Python. I've only started playing with it this year, but I'm fond of it. The documentation is not as helpful as Java's, and there is a weird split between versions 2.x and 3.x... No further complaints. Python comes with handy building blocks: we'll make use of the provided routines to read CSV files, to carry out operations on sets... Less on our plate, fewer lines of code required to make it happen. That's what you call powerful. In Python, the source code is interpreted (not compiled), so it doesn't matter whether your operating system is Linux, Windows or whatnot, as long as a Python interpreter is installed. This said, I use Linux and the first line of code below is Linux-specific. It's a hack to run a Python script just like a regular shell script. Note that for this to work, the script must be executed from a command-line interface, and its "execute" permission must be set.
Loyalty Program
Next challenge: to enter the rewards points code automatically. We already know how to extract it from the QR code. We still have to interface our system with the Maryland Lottery's to claim the points. Their website complicates the task by splitting the code into five parts. My initial idea was to mitigate the difficulty with a custom extension for Chrome. I wrote a helper tool to fill the fields, so that the user only has to paste once the whole code:![]() | |
When the user hits the Enter key, the fields are populated. |
The user is still involved in the process, so this solution is not automated enough. New approach: to reverse-engineer the website and figure out how to do without. An HTML form is meant to be used by humans. It relays the user input to some service. For the program meant to replace the soft machine, calling directly the target service is simpler. Let's find its URL. Read the HTML and JavaScript in the source of the web page. Audit the HTTP requests sent by the page. Browser extensions can help. Learn about the syntax of the command "curl." The man page will come in handy. It takes some trial and error too... Eventually, you should be able to log in and send a form without using a browser at all. You will eliminate the need for human intervention by writing a Bash script as follows:
Quick note about the hardware. We still need the usual computer, keyboard, monitor and Internet access, but also a peripheral to take pictures. I experimented with various models of webcams. The most convenient setup was to use the camera embedded above the screen of a laptop computer. To position the ticket quickly and reliably in front of the lens, I improvised a holder with reclaimed materials:
Introducing the ticket holder. |
The ticket holder in action. |
It works. At times. The construction is admittedly subpar; the plastic sheet bends out of shape until it loses its function. Above all, the concept itself is not satisfactory. The ticket stands so close to the lens that it must be lit from behind with a blinding USB lamp (not pictured). When it's slightly crumpled, the process fails. Even in perfect conditions, the image is often too blurry for the QR code to be readable. I switched to a flatbed scanner. Bulkier, but a much more pleasant experience:
Bad news, everyone!...
ReplyDeleteI've just read that robots are forbidden to access MD Lottery's website. According to their terms of use:
"You may not copy, transmit, modify, distribute, show in public or in private, modify or create any derivative works from the Content you find on Website unless Provider or Lottery or the licensor of either of them, depending on who owns the Content, expressly in writing authorizes you to do so. Without limiting the foregoing, you may not (i) direct link, inline link, deep link, or otherwise hyperlink any page of this Website other than the home page or (ii) page-scrape, robot, spider, hack, password mine or use any similar automatic or manual program or process to use the Website."
So, do not do it. I won't take down the whole article though, because the shell script does not work anymore. They added a CAPTCHA to the login page to make it more difficult (though not impossible) to use similar scripts.
Get the thai lottery result today from https://thailotterytips.info/
ReplyDelete