Thursday, March 17, 2016

The Best and Worst of LiveCode Troubleshooting

I am very behind in writing about my various LiveCode projects, particularly my Q Sort project. So I'll use this post to write about a few experiences I have had lately. Yes, this blog post is all about the art and science of troubleshooting. I'll start with a shining example, and then close with a problem that I remain unable to resolve. However, this problem has nudged me into a new direction for my Q Sort tool that really was inevitable, namely moving from an FTP approach to using text files to store data to the use of a mySQL database.

Troubleshooting Example 1: The Case of the Missing Data


In almost all of my field tests using my Q Sort tool, I had been experiencing an unusual problem of missing data. The problem was very spotty. The data from most responses were fine, but there would always be a handful (i.e. 2 or 3 out of 20 people) with missing data. Most of the time, only one data point would be missing, but it was possible that 2, 3, or even 4 data points could be missing. At first, I thought it might be some artifact of the FTP process, such as some data getting "lost in transmission," but that seemed like a weak and unlikely theory.

Also, another person who completed a Q sort - a doctoral student in my department - was also adamant that a statement she rated one way was subsequently rated a different way when she reviewed her data. No one else had ever noted this before, so I knew it was possible she was just mistaken or confused. However, she sounded very sure of herself, so I was careful to note her observation because if she was right, then the accuracy of all the Q sort data would be in question. (I now think she was right. The fix I explain here solves that problem too.)

It wasn't clear to me how to go about troubleshooting this problem, given the rareness of its occurrence. I had never experienced the problem myself in all of my testing. My first idea was to set aside an hour in my design studio course at the University of Georgia and have the students do several Q sorts in a row with the hope that the problem would appear in someone's data. Then, I could compare the data uploaded to the web server with the data saved to their local computer. However, I solved the problem on my own in a relatively short amount of time.

My Solution: Make All Data Visible


To help figure this out, I made a copy of the Q Sort tool just for troubleshooting. I turned off all of the FTP and other data storing commands and made visible the key hidden fields that collected and managed the data while the Q sort was in progress. As I played with doing a bunch of Q sorts, I discovered the problem.

Basically, here is what was happening. Two statements in adjacent slots would be appropriately "locked" into their slots. Then, the user would move one of these statements into the other slot. The just emptied slot would correctly then register "empty." But, if I then moved the other "locked in" statement into the now vacated slot, both slots would register that statement. The other consequence to this would be that if all other slots were filled, the "Submit" button would be activated, thus allowing the user to then quit and upload their data. This problem wouldn't occur, or would resolve itself if it had, if the person moved one of these statements back to the main area of the screen. So, the problem only occurred under these fairly rare situations.

To fix this, I added some code to the "on mouseUp" script in the button "statement template" to check for duplicate statement numbers in the field "slot contents." Even this was a little tricky as I had to make sure that the correct slot showed where the statement now resided. To do this, I first added this code to look for EVERY occurrence of the button number and replaced it with "empty":

    //First check for duplicate statement numbers in field "slot contents" (the cause of the missing data problem) - February 21, 2016  
    //I adapted this code from the button "Check for Duplicates" from the Q sort analysis tool  
    put the number of lines in field "slot contents" into L  
    repeat with i = 1 to L  
      put item 1 of line i of field "slot contents" into varName  
      if SN = varName then  
       put "empty" into line i of field "slot contents"  
      end if  
    end repeat  
   
The key was to put this code BEFORE this existing line of code (near at the end of the mouseUp script) because this line then puts the button's location into the correct slot:

put SN into item 1 of line varSlotNumber of field "slot contents"

In summary, if a duplicate was found the appropriate one would remain but the other would be replaced with "empty."

Improving the Usability


But, I wasn't finished. As I played with the program I could sense a usability problem. As I moved statements previously locked into a slot to an adjacent slot, it was often not obvious which statement was no longer "locked" into a slot. I decided the best thing to do would be to "snap" the unrated statement out of the "slot zone" to the original starting x screen coordinate, but leaving it at the current y screen coordinate. To do this, I adapted the script that already existed in the "To far left" button and added it to the custom function "checkForEmptySlots" on the card "sort":

    //First check for duplicate statement numbers in field "slot contents" (the cause of the missing data problem) - February 21, 2016  
    //I adapted this code from the button "Check for Duplicates" from the Q sort analysis tool  
    put the number of lines in field "slot contents" into L  
    repeat with i = 1 to L  
      put item 1 of line i of field "slot contents" into varName  
      if SN = varName then  
       put "empty" into line i of field "slot contents"  
      end if  
    end repeat  


A key idea was to put this script near the end of the function and right before other script that checked to see if all statements were accounted for. If all statements were accounted for, only then would the "Submit" button be activated.

Note this important line (line 7):

 if not intersect (graphic "statement background", button locStatementName) then next repeat  

This line is important because I only wanted to "snap" out of the way those statements that were in the "slot zone."

The result is now a very clear user interface that shows which statements are "locked" into place and which are not.

Troubleshooting Example 2: The Case of the Deleted Data


OK, great. I solved a thorny problem all on my own. Just as I was finishing my victory lap, complete with champagne, another recurring problem surfaced. This problem remains unresolved and really has me stumped: Data that I know were correctly FTPed to my web server have subsequently vanished. I really have no explanation for this. It has happened occasionally and rarely. The first few times it happened, I blamed myself for just not remembering deleting the data. This was a reasonable explanation because in my early field trials, I would occasionally wipe the text file clean on my server. However, the last time it happened, I know I did no such thing.

To be honest, I know I haven't been using the preferred LiveCode libURL commands, such as libURLftpUploadFile, for the data transfer (here is a link to a good tutorial). Instead, I've simply been using the simple "put" command in tandem with the URL function:

 put field "ftp scores"&return after URL varUploadSite  

However, I don't see how this is at all related to the problem given that I know the data were in fact saved to the web server. So, I remain stymied. Perhaps someone reading this blog post with more experience than I knows what to look for. If so, I hope they will contact me.

But, as I mentioned at the start of this blog post, my inability to solve this problem has persuaded me to abandon the FTP method altogether and instead use a mySQL database for all data storage. I knew I would eventually make the jump to using a real database, but there was a certain charm and elegance to just using simple text files for all data storage. Interestingly, I reread one of my own blog posts from last year to relearn how to do this titled "Desperately Seeking Middleware." I hope to finish this transition to mySQL in the next week or so.

Final Thoughts


These two examples are good reminders of how coding can bring the "thrill of victory" and the "agony of defeat." Just when I thought I was rather clever in figuring out one problem, another jumps up and bites me. No worries, though, as this is all part of the learning experience. One day, I know I'll figure out that deleted data problem, or bump into someone who can help me.


No comments:

Post a Comment