• Email address is not valid
  • No message
500 / 500

In for a long spin

After completing an online beginner's Python course, I decided to finish it off with a self-imposed exam project. Not wanting it to be a complete waste of time, I took the opportunity to solve a personal annoyance of mine, namely picking Eurojackpot numbers. How could this not be worth my trouble?

It all began with the beginner’s course

My living revolves around branding and design, but I know a little bit about coding. Back around the break of the new millennium, when IE4 was the browser to be in, and iframes were not to be frowned upon, I was setting up pointless personal websites with laser green sci-fi fonts, remote control navigation bar with bevel invert on mouseover and all. I wrote the HTML myself and pieced together bits of JavaScript to get the mouse events working for the remote, which I had designed using the deadliest combo in the entire Web 1.0 era: Photoshop + Eye Candy.

It was good fun to tell the browser what to do, but I found it more intriguing to attempt to bend the layout to my command. Building websites was a design exercise for me, the first steps on my way to a career in graphic design. Programming, on the other hand, I considered to be a ballgame I couldn’t play even if I wanted to. An entirely different beast from web design and one that I didn’t dare to take on.

Being a big fan of video games at the time, plus the fact that ‘The Matrix’ had just dropped, coding could very well have been my first calling. But being in your early teens, in the pre-YouTube era, taking on a full-blown programming language simply looked insurmountable from where I sat (in my room, at my parents’ house). Just the JavaScript syntax alone would make my head spin.

Fast forward to 2022, where the world literally runs on code, learning how to program stuff would seem as sensible as learning how to cook from a survival standpoint. YouTube practically opened the door to the culinary arts for me. Accordingly, as the ‘Full Course for Beginners’ popped up in my feed, I decided to find out if YouTube once again could open a door — only this time to my long-lost haXXor ambitions.

A total write-off

I believe in the basics. All important achievements of mine have one thing in common: countless repetitions of fundamental steps preceded them. Only when the fundamentals have become thoughtless does it make sense to worry about greatness. And I get it. I’m as guilty as the next guy, most of the time I prefer to jump right in and be brilliant. But sometimes, the fastest way forward is just to sit down and read the manual.

My first question was which manual to read. I knew of multiple languages to choose from. Each with their own preferred use case, their own set of advantages and drawbacks, their own group of dedicated fanboys and their own degree of hiring demand. As I didn’t have any specific objective in mind at this point, other than to learn the basics of programming, I figured I’d pick the language that seemed the most approachable.

Python, a “less-debugging-more-development”-type of language, was exactly what I was looking for. The “Full Course for Beginners” from freeCodeCamp.org had 30+ million views on YouTube, so I looked no further and went all in. I decided from the beginning to type out every single lesson in the course in full. From variables to strings to lists to loops, I punched in every single character I saw being typed in the videos. The meaning behind this madness was of course for my fingers to soak up as much syntax as possible. However, after finishing a handful of lessons this way, it was my indifference that had become fully saturated.

Walk on my own ten fingers

Some people study to do a certain thing in a certain way. Other people study to be certain they can do the thing in any way. Given the choice, I prefer the latter approach. Repeating another person’s protocol rarely leads to a profound understanding. Most lessons arrive compressed as a ZIP file; you have to be able to unpack it in new environments and apply it in other contexts before you can begin to grasp its potential.

I wanted to get a good grip on this Python thing, so from there on out I decided that there could be no more typing along. Each lesson now had to be reimagined on the fly and applied to a new scenario. For example, on the topic of creating a student class with a set of grading properties I instead created a car class with properties to match. On the topic of using inheritance to alter the methods of one chef class from another I replaced the chefs with designers and had the methods depend on the type of designer class they belonged to. I.e. the industrial designer would shape a physical object with the “make_object” method, whereas the graphic designer would produce a logo with that same method, and so on.

The rest of the course I finished in this fashion and had a great time doing so, too. I can highly recommend it to anyone who contemplates coding in Python, or even in general. The course is easy to follow and covers a lot of ground, and it is as entertaining as it is informing throughout. My self-imposed obstruction did not transform it into anything more advanced than a beginner’s course, of course. But it did, however, help to point out how my newborn coding capabilities could escape the playground.

In school you mostly focus on problems that already have a solution; at work you’re rarely completely sure what the problem even is.

Idea-oriented programming

There’s a big difference between going to school and going to work. In school you mostly focus on problems that already have a solution; at work you’re rarely completely sure what the problem even is. At least in my line of work. “The real problem” has become quite a legend. Probably because it is so hard to nail down and yet so easy to openly speculate on. And even if you manage to solve it, explaining what really did the trick often remains anyone’s best guess.

At this point in time though, in this cyber classroom setting, I knew exactly what the problem was: I needed to prove I could put what I’d learned to good use. So, my solution was to hit myself with an exam project which had to demonstrate my understanding of all the topics the course had covered. To put myself to the test I just needed an idea for a project, and I could think of no better catalyst for this than giving real problem solving a go.

Let the punishment fit the crime. No one is obliged beyond what he is able to do. The shoes should match the suit. Similarly, my choice of project had to be matched to my coding skills. I consulted my wife for consumer insights. I sought to understand which hurdles of daily life would have the potential to be removed by a piece of software. One hurdle — that each and every Friday stands between us and living large — is the Eurojackpot. Every week my better half asks me to pick some numbers, and each time I have no easy answers. Pulling numbers out of thin air persistently proves to be a problem. And as I came to think about it, I became increasingly convinced that this problem just might fit the bill of what my coding capacity would be able to deal with.

Prompting a response

If you’d ask me what characterizes a superb user experience, I’d say it’s one that offers an exceptional amount of tax-free return on user input. Ideally you’d want to provide the minimum amount of input it takes to achieve the exact outcome you’d expect. If the input required to return the expected outcome is too taxing, it’s no good. If a completely boiled-down input requirement produces an undesired outcome, it’s no good either. Bonding begins when a user is bestowed with the exact input/outcome balance they have been looking for. And if they can maintain the feeling of control and gain a sense of thrill throughout, it becomes downright spellbinding.

Meet the slot machine: The most stable earner in any casino; the most fed cash cow in the world of gambling. I would be hard-pressed to find a more tried and tested interaction mechanism. Hence, I stopped looking and started to think about how to replicate a one-armed bandit in pure text. Everything I had learned about coding was strictly terminal so far, not even a single mention of GUIs had been uttered yet. So, in order to create an interactive program inside the terminal I figured my slot machine had to play like an old Sierra adventure game, with typed commands only.

An earlier lesson in the course had covered how to construct a guessing game with while loops and user input. The while loop would keep looping over until you typed in the magic word or until you ran out of tries. From there it didn’t take a great leap of imagination to fathom how user input could trigger functions and how a single while loop could keep my program running until the desired lottery ticket had been spun up. I quickly fleshed out a couple of number-generating functions and a ticket printer, then I started building my while loop. A while later, I had effectively put together something that looked similar to a terminal session from a Fallout game. The obvious difference was, of course, that this thing would spit out Eurojackpot numbers.

Failing the alpha test cheerfully

Sometimes, you get so happy with yourself that it feels like you won the lottery. You achieve a goal you never expected could be achieved so easily. And despite being surprised, you now somehow think that it was self-evident. The feeling is so good that you sure as hell are not going to risk ruining it by second-guessing yourself. You did this, without a doubt. Someone will have to pry this achievement away from you before you’d let it go. This was how I felt after spending just one single afternoon to code my exam project — like an absolute haxxor. I wanted the feeling to last. That was probably why I decided to make my Mom and Dad the alpha testers.

I had already tested the program over and over myself. I was confident it worked exactly as intended. The alpha test was really a usability test, in my view. If my folks could come away with a Eurojackpot ticket from their first interaction with my program, I would have succeeded where countless UX designers have failed (most new digital experiences tend to overwhelm my parents). This time though, they breezed through the test and generated their first ticket without any trouble. “Enough said”, or so I thought. Right up to the moment my Dad snapped me back to reality by pointing out that my program was flawed at its core.

As he explained, a Eurojackpot ticket consists of five draws from a single pool of numbers between 1 and 50 and two draws from another pool between 1 and 10 (now 12). The trouble was that my slot machine simply spat out seven random numbers, five of which were between 1 and 50 and two were between 1 and 10. While brimming with optimism, it had completely passed me by that no number could be represented more than once in each of the two number sets. How could I’ve missed this? My program was printing out pure gibberish. Humbled by this experience, I immediately headed back to the drawing board.

I struggled to get the results I wanted. No matter how I wrote the number generating function I could not eliminate the chance of rolling duplicate numbers. And just when I thought I had it sorted, adding in the hold function would brake it again. It was at this point I decided to look outside the curriculum and zoom in on the random module and its methods. The course had only covered the randint() method, so when I discovered the choice() method my eyes lit up with anticipation. Quickly, I was back in PyCharm writing out the program in the simplest possible form I could think of; a list of integers representing the number pool, a function that returns a random choice from the pool and then pops that number off the list (representing a draw) and a 2D list containing the 7 picks and a hold status for each (representing a ticket). I integrated the new code back into my while loop, and voila! My slot machine was finally running as it should. Little did I know that this little hiccup would turn out to be just the warm-up.

As I sat there, I did, however, begin to wonder how people would be able to run my program without the source code and a Python installation.

Interaction without an interpreter

When you sit down and start to code, you feel like there’s nothing you can’t accomplish; a sense of endless possibilities. As I sat there, I did, however, begin to wonder how people would be able to run my program without the source code and a Python installation.

Slowly, but surely, dark clouds washed over my optimistic outlook. The endless possibilities were gone, and the only future I could see was me spending countless of hours learning yet another language, framework, SDK or the like before anybody besides myself would have the chance to play my slot machine. Determined to see this through, I started to weigh my options.

As I saw it, I could go one of three ways: desktop application, web app or mobile app. The desktop route seemed a bit unwieldy. My vision was to be able to generate numbers as soon as my wife asked for them, whether that would be in the supermarket or at home, so needing a laptop to play would be a dealbreaker. Seeing my project through from the alpha test to the App Store would definitely had been a fun learning experience, but the prospect of a lengthy review process didn’t jive with my projected timeline, and learning and rewriting the slot machine in a new language did even less so. Realistically speaking, the only option left was the web app route, and so I went for it.

I was certain it was possible, just not quite sure how. “Google runs on Python”, “Spotify runs on Python” were two all-too-common phrases I’d heard again and again, but all the web hosting services I had ever dealt with only offered PHP or .NET. And hosting aside, the big question was how to actually use Python to run a website. Google explained that is was done through a web framework. My immediate follow-up question then became: which framework should I use? I was looking for plenty of support, thorough documentation and widespread adoption. Django was the obvious contender, and after skimming through a handful of video guides I was confident that I could make it work. So I whipped out a pip install, set up my virtual environment, and with masteringdjango.com loaded up in my browser I disappeared down my laptop for a couple of weeks.

Python is only part of the program

Back when I was on my way to graduating as a graphic designer, I faced a fork in the road; I had to specialize in either print design or web design. For me, it was a choice between a chance to stand out and a way to fit in. I saw print as the blank canvas for ideas — if you could think it, you could do it — whereas web design I saw as kind of a mould to be filled up, but never to be broken. Print was driven by design, whereas web design was driven by technology. Sure, you can argue that user interaction and a dynamic canvas leave the designer with more options, but once you take into account legacy support, browser differences, screen resolutions, device ratios, dark mode and SEO considerations — not to mention the nature and purpose of most commercial websites — your ‘safe zone’ is a whole lot smaller than the potential of the technology. I ended up choosing print specialization without a doubt in my mind. At this point in my project though, my only choice was to go web.

Somehow, new technology always seems to come with the expectation that switching to it will rid you of all the headaches you were experiencing with whatever technology you used before. At least I was positive that because I was writing my web app in Python — a language far beyond HTML(!) — the challenges of building a website that displays exactly as intended for all users would somehow be a thing of the past. Of course I was completely wrong. Python wants nothing to do with your front-end! It’s your silent partner, it only works behind the curtain. I was stuck with my two old friends HTML and CSS if I wanted to get this show on the road. And to make matters worse, cross-platform design was an even bigger challenge than in the old IE4 days with the plethora of new devices, pulling your code in every direction. Once again, my free evening hours were in grave danger.

You really don’t know how dumb you really are. You have to learn how dumb you are; it takes practice.

I had some serious catching up to do if I wanted to end up with a modern, mobile-friendly, arcade-style web interface for my slot machine. So, back to the fundamentals I went, binge-watching just about every tutorial I could find on the subject. Div, position, padding, margin, @media, grid, rem, em, forms, flex, min, max — the basic the better. I was seeking to understand the behavior of all these elements in detail so I could proceed systematically, slowly scaffolding the page layout while making sure that everything worked as intended. In my early web design days I would welcome happy accidents, but on this site they were banned. To make it all the way to a published website without any rage quitting along the way, I had to be confident enough to troubleshoot when things would start to break, which I was sure they would with each bit of introduced complexity. Slowly, and surprisingly surely, my lottery ball grid started to come alive. And to my amazement, it proved to be fully responsive at any screen resolution I could test it in. “Awesome”, I thought. “Let’s wrap this baby up!”.

Stack of trouble

You really don’t know how dumb you really are. You have to learn how dumb you are; it takes practice. Only one assumption at the time will your own stupidity reveal its true depth – and it can be scary deep. Perhaps if I’d already known what I was about to find out, I wouldn’t have dared to dive headfirst into this project to begin with. But at this point though, I just couldn’t believe I could go wrong. I had coded a slot machine in a language I had just started to learn, I had learned enough about a foreign web framework to adapt my program to run within it, and to top that off, I had whipped the whole thing into a delightful mobile-friendly website just from watching a couple of YouTube guides. The hard work was over; it was time to put the sprinkles on it. Or so I thought. By sprinkles I mean hooking up all the buttons and switches controlling the program, which I was sure I could accomplish without any hassle (having Django at my command and all). But I was wrong, again.

Once the hubris-induced blindness had dissipated, I could see the challenge ahead of me. My brief history as a developer was already repeating itself, as I once again was faced with the necessity of learning a new language in order to finish the project. And this time, it was none other than my old nemesis — JavaScript! This foul language had rung my bell before, and was now about to send me down for the count. I was already exhausted, and long overdue on my worst-case timeline. Starting to learn JavaScript from scratch would set me back no less than a month. It would be just as big a commitment as doing the whole Python course, and I just wanted to finish this thing. Sadly, there was no way around it, so I needed to find a faster way through it.

Throughout my web tutorial binge, I would occasionally hear about JQuery: a JavaScript library that offers mainstay JS functions for only a fraction of the code. Needless to say, this was not the time to be too proud to dig around in the documentation, and thus, I went in searching for something useful. With my eyes wide open, I tried to imagine how I could set up my views in Django to work with whatever I could find. The .click() function, the .load() method and the .toggleClass() method caught my attention. With .click() I could make buttons functional, with .load() I could interact with my program via URLs, and with .toggleClass() I could potentially reflect the state of the program visually. Or at least, that was the idea. Whether or not I could make it all work seamlessly, I wasn’t sure, but I decided there and then that now was the time to find out.

From that point and on, I have no clear recollection of the path I took to see this project through. What started as a systematic approach turned into a complete frenzy. I was making so many stops at stackoverflow.com that I didn’t know if I was coming or going. I would encounter one problem and try to solve it, and then two more would pop up, over and over again. Until one day, suddenly, all the problems were behind me — I had arrived.

Take it for a spin

eurojackslot.com is finally up and running, and has already been subject to a few updates since its inception. When it first launched, it was all cookie based, as that was the only way I could imagine doing state management at the time. I later learned about sessions in Django, and have since scrubbed the cookie-based approach entirely. Also, the first week after launch, Eurojackpot changed its range of star numbers from 1-10 to 1-12. Luckily, that was an easy fix. Only a single value in a range() function needed adjusting. As I became more familiar with best practices, I continuously went back over the program to optimize functions and switch methods for all the sloppy parts I had first put together.

The short of the long is: it’s finally done. I probably forgot to mention a thing or two, but I think I’ve said plenty already. Go ahead and take it for a spin, just for the fun of it.