This is beginning to take the form of a real (yet simple) application. I implemented the ability to save one’s work, which is going to be crucial in order for this tool to be useful. I am starting to see the light at the end of the tunnel with this project, which is both exciting and pre-emptively disappointing to think that I will soon put away this labor of love and let it stand on its own. In that case, the good news is that I’m not there yet.
As I started solving more of the message, I wanted to be able to save my work and come back to it. I was hoping to keep the solution to this as simple as possible. I had become quite comfortable working on the front end and achieving everything I needed to do with jQuery and CSS. All the DOM manipulation as one solves the message is done in jQuery. My initial approach was to first encode all the HTML in the element that contains the message (including the original message in digits, the letter options for each digit, the solved words, the cursor, and the select element and next button at the position in which they appear) to a string using the handy window.btoa method, which I just discovered. Then, I wanted to append that string to the URL after a hash and show it on screen for someone to copy or bookmark and come back to. Encoding the elements to a string worked, but appending that string to a hash or even logging it to the console either didn’t work or took about two minutes. I discovered that the string was over 600,000 characters long.
At this point, I was fretting about how to make that string shorter. I thought I might have to separate out the solved words and the position of the cursor and select element (all the things that the user manipulates) apart from the initial message. This would involve some fairly heavy parsing on both the saving and loading (from a saved message) ends.
One wrinkle I discovered when revisiting MySQL for the first time in a while is how much we as users of software take for granted what happens when one clicks “save”. We expect that action to create a new record if there isn’t one already, but if there is a record, we expect it to update that existing record. It is incredibly not-straightforward to do this in MySQL since there are two separate commands to achieve this: “Insert” and “Update”. One thing smooths this development process over quite a bit though is the “Insert… on Duplicate Key UPDATE…” method.
This part was pretty straightforward. I created a “load” button that took that 600,000+ character string from the database and decoded it back into HTML. For loading, I let the server do the heavy lifting for once – I did this in PHP using base64_decode.
The way I structured the data meant that the initial message and the user input were wrapped up in each other. This has implications for the future. If I discover a typo in the initial message and then fix it, this would invalidate any saved data. I thought about trying to separate it out, but this kind of bound relationship actually makes sense here. If the initial message originally said “43556”, and the user input contained “HELLO”, then I changed the initial message to “43574”, I would want to invalidate that user input. If I wanted to get fancy, I could be smart about which sections need to change and highlight those portions for the user to correct, but I’m not ready to get that fancy yet. This will just stress the importance of proofing the initial message that I input. I am considering crowdsourcing that proofreading to Mechanical Turk or the like since I can’t think of anyone I know who would be willing to subject him/herself to such drudgery as a favor.
I have perhaps an overly optimistic hope that there may be someone else as crazy as I am about figuring out what this message says. To that end, I set out to allow multiple users to save their own versions of their messages. This required authentication.
I didn’t want to deal with the security liability of storing people’s passwords, so I set up authentication using OpenID. I used the LightOpenID PHP library, which worked smoothly in the included example code and was straightforward enough to modify. For now, I am only using the authentication with Google. After authenticating, I am storing the user’s email address in a session variable and then using that as the “username” in the database if the person chooses to save or load.
Also, at the moment, there is a “load” button and a “save” button. This made sense when there was only one user, and these actions had to be explicit. However, now that there is authentication involved, it seems to make more sense to have “load” happen implicitly on login and remove the “load” button since it’s of no use after that initial load.
Based on the above, I plan to couple loading with login and couple clearing the saved message on logout so that the ability to view one’s stored message corresponds with being logged in.
If someone begins solving the message and then proceeds to register, I want to preserve the person’s work and then reload it once login is complete. This means implementing a lazy registration pattern. This would need to create a new database row to store the message if someone has input data and then clicks “log in”. Then after login is complete, it would associate the user’s email address with that row that was just created and reload the message from the database.
I need to create a “message saved” confirmation and perhaps a “logged out” confirmation as well.
And I still need to implement the ability to erase a word.