Sunday, September 6, 2015

Short Reprieve for my AECT LiveCode Workshop

I was notified by the AECT leadership that not enough people had registered for my proposed workshop on LiveCode at the upcoming AECT Conference in Indianapolis, November 3-7, 2015. Consequently, they were going to remove it from the AECT conference site. However, I reminded them that they had inadvertently left it off of the conference workshop web page, an error I caught only months later. They also remembered that I had full attendance the last few years. So, they have given my workshop a temporary reprieve and left it up on the conference site.

So, if anyone is going to attend the conference and you have an interest in learning about LiveCode and computer programming, please sign up for my workshop pronto - I don't know how much longer the AECT folks will give it.

Here are the details about the workshop:

Computer Programming for Mere Mortals Using LiveCode

Wednesday, November 4, 2015
9:00-Noon

Lloyd P. Rieber
The University of Georgia

Short Description

This workshop will demonstrate how to use the LiveCode programming language (http://livecode.com/ ) to create software programs that can be delivered in multiple formats, including native apps for the iPhone and the Android.  No prior knowledge about programming is needed. LiveCode uses a natural programming language based on HyperTalk (this was the language of Apple's HyperCard from several years ago).

Abstract

The purpose of this workshop is to introduce participants to the object-based programming language of LiveCode. LiveCode is used to create desktop, Internet, database, network, and mobile applications. Applications built with LiveCode are completely cross-platform. That means you can run any application you create on all major modern operating systems, including Windows, Linux, Unix and Mac OS. Applications can also run on mobile platforms, including Apple iOS and Android. LiveCode uses a natural programming language based on HyperTalk. (This was the language of Apple's HyperCard from several years ago. In fact, old HyperCard stacks can be opened and run in LiveCode with little or no revision to the original code.)

Two particular examples will be demonstrated. The first is an iPhone app called “Lunar Hotel Shuttle,” currently available through Apple’s App store. This app – completely designed and developed in LiveCode – is a space fantasy game where you control a special space shuttle as it lands on the moon. This game accurately simulates the physics principles of gravity, velocity, and acceleration. The second is a video analysis tool that allows users to identify video clips, then code them for analysis.

The workshop will use a project-based approach where participants build small-scale working games and simulations from scratch. These projects, along with videos, can be found at the workshop’s web site: http://www.nowhereroad.com/livecode/

In this half-day workshop, we will demonstrate the following skills and objectives:

Understanding the Structure of a LiveCode stack: Cards, Stacks, & Files
Using Media and Other External Resources
The Structure of a Script
Types of Handlers
LiveCode Messages and Events
Commands and Functions
Variables and Functions
Making Decisions: If…Then…Else
Configuring an iOS Application
Working with the Apple SDK
iOS-specific Engine Features: Mouse, multi-touch, and motion

Monday, July 20, 2015

Building the Permutation Test of Exact Inference with LiveCode

Yes, with a blog post title like that, I fully expect this post to go viral. I'm sure you'll be seeing me on CNN later this evening.

Ah, well, yes, the truth is that words like "permutation" and "inference" are hardly captivating stuff, unless you are into mathematics and statistics. Well, I'm into both, but in a "mere mortals" kind of way. I've been teaching a MOOC (massive open online course) for about two years now with the title "Statistics in Education for Mere Mortals." I love statistics, but I'm not a statistician or mathematician. Instead, I'm your typical educational researcher who has largely favored quantitative research methods and therefore I've become very acquainted with the practical use of statistics through my research. I've been on a mission for a number of years to bring more statistics into our graduate curriculum in instructional design and development.

Side note: I'm teaching this five-week MOOC right now and it is open and free to anyone. Click here for the enrollment page. We are two weeks into it, but it's a self-paced course, so you could easily catch up. In fact, several (very motivated) people have already finished it.

This summer I had the chance to teach a 3 credit version of this course for the University of Georgia. (Now I can honestly tell my wife - finally - that I got paid to teach this course.) I've had a blast.

As I prepared to teach the UGA course, I came across this very readable and provocative article by George Cobb:

Cobb, G. (2007). The introductory statistics course: A Ptolemaic Curriculum? Technology Innovations in Statistics Education, 1(1). Available Online: http://escholarship.org/uc/item/6hb3k0nz

Cobb argues that introductory statistics courses should abandon the teaching of the standard statistical tool for comparing the average scores for two different groups - the t test - in favor of something called the permutation test, which is a concept that has been around at least since the 1930s. This approach is only now practical due to the easy access to high-speed computers (such as the one you are reading this blog post on right now). The really cool thing is just how simple and straightforward the permutation test is:
  • You run an experiment comparing two groups. Let's use the example of one group of students (the treatment group) going through "Lloyd's Wonderous Statistics Tutorial" as compared to another group who get a standard statistics tutorial (the control group). Let's say there were 10 students in each group.
  • You record each of the student's scores on the final exam and compute the average for each group. Let's say that the treatment group's average was 34.4 and the control group's average was 27.9, for a difference of 6.5. Write 6.5 on the top of a piece of paper.
  • Next, you take all of the individual student scores - from both groups - and write each on a card. 
  • Shuffle the cards and then put 10 of the scores at random into one pile and the remaining 10 scores into a second pile. The first pile will be for the treatment and the second for the control.
  • You again compute the averages for the two groups and the difference between them. Write that difference score on that piece of paper on the next line under the 6.5.
  • Repeat this procedure a couple of thousand times.
  • How many times did 6.5 or greater come up? If the answer is less than 5% of the time, you have what is called a statistically significant difference, which basically just means that you don't think that the original 6.5 difference is due to mere chance. Instead, something else must account for the difference, which we'll conclude is the fact that "Lloyd's Wonderous Statistics Tutorial" is just so much better than the standard variety. By the way, the proportion of times that 6.5 or greater came up you is something called a probability, or p, value.
Even though this is a simple procedure, you can immediately see why the test wasn't embraced back in the 1930s - with only paper and pencil, no one wanted to do it! And, there is an even more accurate way of doing the test, namely to only use the permutations possible by dividing 20 scores into two groups of 10 (which, by the way, there are 184,756 different ways of grouping these numbers; check out this web site for a cool calculator). If you use only the unique permutation groupings as your scores in your overall calculation, your p value will be as exact as it gets, whereas the shuffling version has some error built into it. But, as long as you reshuffle a few thousand times, it's close enough.

Lloyd's Permutation Test App


OK, that's a long introduction to the fact that I built just such a Permutation Test app for demonstration purposes in my UGA course using LiveCode. Here's a screenshot of the app:




I used the top hat to symbolize the random shuffling. If you follow the blue columns from left to right, you'll see that this follows the step-by-step procedure describe above.

I made a video explaining the permutations test along with a demonstration of my app. But, if you just want to check out the app, fast forward to the 10:42 mark:



If you do fast forward, then you'll miss my favorite part, where I get to use my Pittsburgh Pirate baseball hat to do the reshuffling:


Wait, I think I Hear CNN Calling


Yes, just as I suspected, the phone is ringing. Gee, CNN couldn't even wait until after I published this blog post!


Sunday, July 19, 2015

Lloyd Emerges from His Teaching Fog

It's been quite awhile since my last posting - well over two months - but that doesn't mean I haven't been using LiveCode. In fact, I've made significant progress over the past two months on several LiveCode projects, including my Q Sort tool. I've been teaching two online courses for the University of Georgia this summer. Both began on June 4 and are now just wrapping up. These summer courses are short and intense, but I love teaching this way. I go into a wonderful kind "teaching fog." For me, a "teaching fog" is where I'm immersed in teaching to the point that almost every waking minute is spent thinking about my teaching.

But, back to LiveCode. I created several LiveCode projects as part of my summer teaching and I'm anxious to write about them in my blog. I'll do so by going backwards by sharing the last project I did and then sharing the others in reverse order. Some were big and some were really small. One little app I made that proved to be very useful took all of five minutes to create. But others were much more substantive and took quite of bit of time. One of the courses I taught was on educational software design and I introduced everyone to LiveCode. I created several more "LiveCode First Projects" for them and I'm pretty excited by how they turned out.

The first project I'll share - in a separate post coming later today or tomorrow - is an app I made for the second course I've been teaching for UGA. (I informally titled the course after my MOOC of the same name: "Statistics in Education for Mere Mortals.") The app is both a tool and demonstration of something called the Permutation Test of Exact Inference. Yes, I'm sure you can hardly wait.




Sunday, May 3, 2015

Lloyd's Q Sort Project: Importing Data from an Internet File

This is the first of several posts explaining how the first prototype of my Q Sort app works.

I think a good place to start is my design decision to store information about the Q Sort - both the Q Sort board and the Q Sort statements - in a text file stored on the Internet. The purpose of this decision was two-fold. First, I wanted to come up a simple file structure for dynamically defining and constructing the Q Sort activity. That is, when I started this project I knew I needed to design the app in such a way so as to allow for any text-based Q Sort to be constructed. (Quick aside: there is no inherent reason why Q Sort statements need to be textual. They could easily be pictures, sounds, or videos. But, I decided that I would focus my attention initially on text-based statements given that this is the dominant mode for the kinds of research and teaching needs I do.) I've used the approach of storing data that dynamically controls content of an app in a simple text file in other projects, most notably the project where I built a multiple-choice question app. It's a very useful and flexible approach, plus has the added charm of being very simple to do.

Here's a flowchart of the data download process that is used in this approach:


I used a background color of orange for the "pizza.txt" step and blue for the other steps to highlight the fact that the data is stored on the Internet (orange), then downloaded into the app (blue). In this post, we'll look at each of the first three steps of this process in more detail.

Data Stored in a Text File on the Internet


Let's begin by understanding the structure of the text file stored on the Internet. Here's the pizza example I used in my previous post:

Pizza
I am a big fan of eating pizza.
Most important,Least important
0,+2,#ccffcc,light green
1,+1,#ccffff,light blue
1,+1,#ccffff,light blue
2,0,#ffffcc,light yellow
2,0,#ffffcc,light yellow
2,0,#ffffcc,light yellow
3,-1,#ffcc66,light orange
3,-1,#ffcc66,light orange
4,-2,#ff9999,light red
#statements
The toppings are vegetarian.
The pizza is inexpensive.
The pizza has lots of cheese.
The crust is thick and chewy.
The pizza has lots of toppings.
The ingredients are grown locally.
The toppings include meat.
The crust is thin and crispy.
The pizza can be delivered to my home.

I realize your eyes are probably beginning to glaze over, but trust me, it's not nearly as complicated as it looks.

Line 1 is the title of the Q Sort activity.

Line 2 is a summary statement about the entire Q Sort activity. I don't use this statement yet in my prototype, so we can safely ignore it for now. But, as a very short explanation, just know that I'm thinking of ways to use a Q Sort activity as a teaching tool, not just a research tool. As a teaching tool, I think it would be a good idea to ask participants AFTER the Q Sort activity concludes to rate their opinion of this statement. I'll talk more about this later.

Line 3 includes the labels of the two poles of the rating scale, each separated by a comma. It was important to include this because the rating scale can vary tremendously. Typical examples would be "Most Agree-Least Agree" and "Most Important-Least Important," but the range of possibilities is endless. The point here is that this is an important dynamic element of a Q Sort.

The next group of lines define the elements of the Q Sort board, so let's consider them in some detail.

Defining the Elements of the Q Sort Board


Defining the elements of the Q Sort board is not complicated, but I admit that this the most obtuse part of the text file. There are four elements or items in each line, each separated by a comma. How one constructs it depends on the shape of the Q Sort Board. It's much easier to understand these lines if you visualize the board itself. So, here is a visual representation of the "Pizza Board" that was also included in my previous post:



Notice first that the scale ranges from -2 to +2 with 0 as the neutral spot. So, there are a total of five columns in the board. My design uses a linear representation of the board, with the rating progressively moving from right to left with an indentation to denote each rating notch. (Aside: we are accustomed to a Cartesian coordinate system where positive numbers are on the right and negative numbers are on the left.)

With that in mind, the first item in each line dictates the "indentation" of that rating element. A reminder that indentation goes from right to left, so 0 indicates no indentation, so this is reserved for the most "positive" rating element, or +2 in this case. Now, take a moment and work out in your mind how many "steps" are needed to move from +2 to -2. The answer is 4. Notice that there are two lines with a step of 1, then three lines with a step of 2, then two lines with a step of 3, and finally one line with a step of 4. Take a moment a see how this relates directly to the image of the Q Sort board above.

The Second Element of the Q Sort Board


The second element in each line (again delimited by the comma) is the rating scale itself which ranges from +2 to -2. This element is shown on each slot, preceded by the text "Rating: ".

The Third Element of the Q Sort Board


The third element in each line is the color of the slot. This is denoted using the common hexadecimal notation. I realize that this is not a very friendly way to represent color, but believe me, it really is a typical way to do it. Now, in fairness to LiveCode, you can also represent color using more descriptive terms, such as "yellow," or "red," or "green." But these denote a very small range of the color spectrum, so I thought it best to give the designer as many options as possible to define the color of a rating slot. Given that LiveCode allows for this approach, I thought it best to use it.

The Fourth Element of the Q Sort Board


The fourth element is completely optional - it's merely a description of the color. If you leave it off, nothing of consequence will result. Think of it as a "comment element." For me, I don't commit hexadecimal notation to memory, so I wanted to quickly be reminded of the colors I've chosen. You could comment on this or anything else you want.

Defining the Q Sort Statements


Notice that the next line begins with a hash tag, otherwise known as a pound sign - #. I decided to use this symbol as my "signal" that we are now going to define the information for the Q Sort statements. The LiveCode script looks for this symbol and when found, begins to interpret the lines that follow as those that define the Q Sort statements themselves.

There are no other elements that follow these Q Sort statements, so when the text file ends, this will trigger the end of the statements for the LiveCode script. The important thing to note here is that there is one line per statement.

Creating a Utility to Help People Construct the Q Sort Information


It has crossed my mind that it would be helpful if I take some time in the near future to build a little utility that helps would-be researchers or teachers using this Q Sort app - should it prove to be valuable - correctly build the text file. 

Transferring the Data Stored in a Text File on the Internet to the LiveCode App


Now that we have a better understanding of how the text file is constructed, let's take a look at the LiveCode script that also "interprets" the text file. All of the code is contained within the big yellow "Begin" button on the title card:





global varDownloadSite

on mouseUp
   //get URL for download site
   put field "qsortURLdownload" on card "administration" into varDownloadSite

   put empty into field "download" on card "resources"
   put URL varDownloadSite into field "download" on card "resources"
   
   if field "download" on card "resources" is empty then
      answer "There was an error downloading information. Please check your Internet connection." with "OK"
      exit mouseUp
   end if
   
   //Extract the data
   global varQTitle, varSummaryStatement, varRatingLabels
   
   put empty into field "board structure" on card "resources"
   put empty into field "statements" on card "resources"
   
   //field "download" on card "resources"
   //field "board structure" on card "resources"
   //field "statements" on card "resources"
   
   put line 1 of field "download" on card "resources" into varQTitle
   put line 2 of field "download" on card "resources" into varSummaryStatement
   put line 3 of field "download" on card "resources" into varRatingLabels
   
   put the number of lines in field "download" on card "resources" into L
   //look for # and put lines above into board structure field
   repeat with i = 4 to L
      if char 1 of line i of field "download" on card "resources" = "#" then 
         put line 4 to (i-1) of field "download" on card "resources" into field "board structure" on card "resources"
         exit repeat
      end if
   end repeat 
   
   //look for # again and put lines after into statements field
   repeat with i=4 to L
      if char 1 of line i of field "download" on card "resources" = "#" then 
         put line i+1 to L of field "download" on card "resources" into field "statements" on card "resources"
      end if
   end repeat
   
   //Done go to the sorting activity
   go to card "sort"
   

end mouseUp



Unfortunately, blogger doesn't allow for an easy way to reference lines in code, so I'll use a color-coding scheme where I'll toggle between red, blue, and orange. And, I won't even try to explain every single line of code. My goal is to give you the gist of what's going on here.

The first line in red goes and looks for the URL entered into the field "qsortURLdownload" on card "administration" into the global variable "varDownloadSite." Recall in the video that the card "administration" has two fields that contain the URLs for both the download of the Q Sort information detailed above and the URL to which the Q Sort data resulting from the participant's work is sent:



The next line shown in blue basically does a "copy and paste," taking the information found in the text file stored on the Internet (the URL of which is now stored in the variable "varDownloadSite") and puts it into the field "download" on the card "resources," a card hidden from view from the participant.

However, it's easy to anticipate that there might be a problem accessing this file, such as when there is not an Internet connection at the time the participants runs the file. So, the rest of these blue lines list code that will alert the participant to this problem. If this code is triggered, the line "exit mouseUp" is executed, which does just that - the button basically "quits" and no more of the script is executed.

The next lines shown in orange simply store lines 1-3 in three global variables that are used in various places in the app:

  • Line 1 is put into the variable "varQTitle"
  • Line 2 is put into the variable "varSummaryStatement" (though remember that the app doesn't yet use this)
  • Line 3 is put into the variable "varRatingLabels"

Data Separated for Q Sort Board and Statements


The next group of lines in red defines the structure and visual representation of the Q Sort board. I think the key thing here is that there is a repeat loop that continues until it finds that all-important hash tag "#". This sends the message "Whoa! Don't go any further" to the repeat loop. All of the lines the repeat loop finds is then put into the field "board structure" on the card "resources."

Defining the Q Sort Statements


The next set of blue lines denote the script that look for the Q Sort statements. Once again, the key here is hash tag "#" - the script starts at the top and works its way down until it finds the hash tag. Then, it takes all lines afterwards as the list of statements, with one line per statement. This information is put into the field "statements" on the card "resources."

So, What Do We End Up With?


Obviously, the card "resources" is rather important here, and I'm guilty of not telling you much about that card yet. This card is just that, an important resource for the app - it is used to store the information just teased out of the pizza.txt and sorted into the various Q sort components. So, let's take a look at that card:




There are three fields on this card. Going from left to right, they are "download," "board structure," and "statements," just as described above. Basically, this card just disentangles the information from the text file.

It's important to point out that I didn't have to store this information in fields on this card. Instead, I could have stored this information in global variables. But hey, I'm a very concrete kind of guy and I like being to actually "see" stuff like this. And, it obviously helps when I'm trying to explain this to others because I can actually show the card with the fields, which is much more tangible than variables.

Closing


This is a good place to stop. I hope you get the general idea of the approach I'm using here. This approach is good for any software application with dynamic elements, assuming the data structure is not too complicated. If it is, then using a bonafide database like mySQL would be the way to go. Next time we'll consider the scripts need to construct and present the Q Sort to the participant.









Monday, April 20, 2015

Creating a Q Sort with LiveCode

I'm currently attending the annual conference of the American Educational Research Association (AERA) in Chicago. One of my presentations was about "understanding university faculty perceptions about innovation in teaching and technology." A tall order, to say the least. My research colleagues (TJ Kopcha and Brandy Walker) and I used something called the Q methodology for the research project. The interesting part of this methodology is the use of an activity called a Q Sort to collect data. The cool thing about this activity is that people seem to find it an intriguing and fun thing to do. It is not a game, but it has some game-like qualities due to some of its intrinsic challenges. I have built an initial prototype of the Q Sort activity using LiveCode. Before I show that, let me provide some brief background about the Q Sort activity itself.

What is a Q Sort?


To explain how a Q Sort works, let's use an example that is near and dear to my heart - pizza. So, consider for a moment how much you like pizza. Think about how important certain kinds of toppings are to you. Are you a meat lover, a vegetarian, or are you someone who just wants as many toppings that will fit on top? Consider the cost of pizza. Are you a gourmet who doesn't care about cost, or someone on a budget who is always looking for those "2 for 1" deals.

OK, now imagine being asked to complete a survey about your pizza preferences. It's easy to imagine a typical survey that asks you to rate the importance of statements like "The crust is thick and chewy" using a scale from 1 (least important) to 5 (most important). Now, if you are a pizza lover, you might not think too much about the question and just answer "4" or "5" for any particular question.

In contrast, a Q Sort uses a special "game board" that resembles something like this:



All of the survey questions are then presented on separate cards, such as these:



The challenge in a Q Sort is that you have to move each statement card to one and only one slot on the Q Sort board. So, you are forced to choose which items are truly the most and least important to you, at least in comparison to the other items. That can be difficult, but in an intriguing sort of way. When you are done, you have a measure of your subjective point of view of pizza, at least as represented by the arrangement of these particular statements.

By the way, it is not a coincidence that the Q Sort board kind of looks like an inverted normal curve, that is, the classic bell curve (but upside down). This is actually an important part of the theory behind the Q Methodology, but we won't get into that here.

The Q Sort activity we used in our research had 33 statements, a rather typical number for a Q Sort, so it was much more involved and difficult for the participants to complete. Yet, they all seemed to enjoy the activity, with a few people reporting really liking it.

The Downside to Q Sorts


The biggest disadvantage of the Q Sort activity is that it is a bear to administer and score. You have to prepare a bunch of Q sorting boards and sets of cards. Participants have to accurately write down on their sorting board which statement is where before they hand it in. And then, you have the tedious task ahead of you of manually entering the data into a spreadsheet or statistical software package. This just cries out for an electronic version.

Creating a Q Sort Activity with LiveCode


Yes, it would be great to have an electronic version of the Q Sort activity. Several are available, the most notable is Q-Assessor. This looks like an excellent tool, at least as shown in a YouTube video demonstration of it. However, it is costly. They charge researchers $500 a month for a subscription to use it. We have not found any suitable free or low cost versions to use. Producing a fully supported electronic version is challenging because the limited amount of space available on a computer screen makes it very difficult to design the activity appropriately. Indeed, when completing the paper version participants typically need a large table surface available for laying out and sorting their statements. There is the possibility to redesign the activity so as to promote a multi-step Q sort procedure, which could easily allow 30-50 statements. Q-Assessor uses a two-step sorting procedure and it looks very effective. However, their design also requires that not all statements are fully visible to participants at the same time. They report that their design approach has been fully validated, but I think this remains an issue. I have certainly not solved this problem, but I recently had a design breakthrough that has helped tremendously. More about that shortly.

First, check out this brief video demonstration of the current prototype:


My Design Breakthrough


You will obviously notice in the video how different the Q Sort board is in my prototype from the example illustrated above. Here's a partial screen shot for those who did not watch the video:



This change in the visual layout of the board was my design breakthrough. At first, I had it stuck in my head that the gameboard had to be exactly like that used in the paper versions. Then, I was introducing the survey application Qualtrics to my doctoral students. If you have never used or seen Qualtrics, suffice it say that there are some very creative question types available. One of question types allows the user to sort a list of items using a drag and drop interface. This triggered the insight that I could use a more linear visual layout using indentations to represent the different rating levels. This visual design allows for a much more compact visual arrangement of the game board. One reason is that the game board slots become "docking locations" for the statements. This means that the slots don't have to be the same size as the statements. I was also able to use LiveCode to dynamically resize the statements based on their lengths. Doing so opens up yet more screen space. My early try-outs of this design convince me that this is the way to go for an electronic version.

But before I congratulate myself too much, let me quickly also point out that my prototype only currently allows for about 20 total statements, which is far below what would be needed for serious research using the Q methodology. Yet, I think I'm on the right track and may be able to squeeze out more space to allow for a few more statements. I may also try the multi-step approach in later versions, similar to that used in Q-Assessor.

Using a Web-Based Approach for Populating the Q Sort Activity and Collecting Data


As shown in the video, I designed the prototype in a very special way so as to facilitate the dynamic design and delivery of the Q Sort activity. I'll explain the details of this in a subsequent post. Suffice it to say that this approach allows for an unlimited number of Q Sorts to be designed using the same client software. For example, although designed as a research tool, I see some tremendous potential of the Q Sort activity as a teaching tool. A teacher could use the Q Sort activity throughout a course to engage students and provoke discussion and reflection. The topic of the Q Sort can be changed as often as one wishes just by changing the contents of the download URL entered into the software. To realize this potential, I still need to figure out an easy way to score the activity so as to make the results available more or less right away. I think there are some ways to do that without doing a full Q analysis. I'll be working on that.

Closing Thoughts


Yes, I am quite smitten with the Q Sort activity. One thing I like about it is that it promotes "mindfulness" in completing the activity. That is, you really have to think about what you value as you complete it. You can't just quickly click a bunch of 4s or 5s on a survey. You are fully engaged in activity as you complete it. The other thing, and this is not trivial, is again the fact that people seem to really enjoy doing it. I know I'm repeating myself, but I think it is because it has a game-like feeling about it. Also, I think the engaging, mindful nature of it is just naturally motivating. I also find the instructional potential of Q Sorts very, very exciting. I think a Q sort would be an excellent classroom activity leading to motivating and reflective discussions.

There is much more to explain and talk about here, but I hope this gives you a good sense of what a Q Sort is and the advantages of creating an electronic version. This project really needs a web-only delivered solution, so this will be a great candidate for exporting LiveCode to HTML5 when that feature becomes available in the (hopefully) not too distant future. On that note, I send my best wishes and vibes to the LiveCode team currently working on this.



Wednesday, April 8, 2015

Desperately Seeking Middleware: Connecting LiveCode to a mySQL Database with PHP

I think I have finally figured something out after about two years of false starts and false hopes. When I first started using LiveCode, one of the features that interested me most was its ability to connect to databases stored on Web servers. I quickly found the following tutorial which led me to believe that doing so would almost be child's play:

http://lessons.runrev.com/m/4071/l/7003-connecting-to-a-mysql-database

But, I quickly ran into a problem and submitted a request for help to the LiveCode's user forum. I quickly learned from other LiveCode users that this "easy way" to have LiveCode connect to a database was only possible if LiveCode has a "direct connection" to the database. However, for security reasons, few web servers allow direct connections. The solution was to use "middleware" code -- code that resides on the web server that acts as an intermediary between the database (stored also on the server) and my standalone LiveCode app (residing on my computer, my iPhone, etc.). I learned that I could write this middleware in PHP. Another approach I was encouraged to consider was installing a special version of LiveCode on the web server with special server functionality - called (not surprisingly) LiveCode Server - with which I could easily write this middleware. Unfortunately, the server and the database I wanted to connect to was administered by a commercial hosting company and so I did not have the ability to install LiveCode Server on it. Plus, I already had been working a little with PHP on other projects, so the PHP route seemed the way to go.

But, I really didn't have a firm conceptual understanding of what this middleware was supposed to do. Every now and then over the next two years I came back to this problem and each time I got stuck again. I usually chalked it up to just not doing a thorough enough search on Google or the LiveCode user forums. Finally, a few weeks ago, I redoubled my efforts and found a few intriguing leads. I also submitted a much more detailed and somewhat emotionally-laden request for help to the LiveCode user forum. Based on some very helpful replies, I realized that I was looking at the problem all wrong. As it turns out, I (more or less) knew all along how to solve this problem, but just didn't know it at the time. That realization opened the door for me to solve the problem.

So, the purpose of this blog post, and perhaps a few more to come, is to share what I've learned with some concrete examples, code and all. Put another way, the purpose of this post is to provide to others exactly what I needed two years ago.

But I must alert anyone who stumbles upon this posting that understanding the solution that follows requires not only some understanding of LiveCode, but at least a cursory understanding of PHP, a touch of SQL and HTML, and a very good understanding of how to set up and manage a mySQL database on a typical server installation (such as with the use of an interface such as phpMyAdmin).

Setting the Context: Imagine the World's Most Boring Game


I have created a very simple sample project to demonstrate how all this works. Imagine a game that generates a final score, except that we'll skip the game part and let users choose their own score. Next, imagine that you want the people playing your game to have the option to upload their score along with a user name of their choice. That way, we will have a record of all game scores tied to players. This would allow (later) the option to give a single user feedback on how well they are doing in relation to all other players. Similarly, although I don't do it here, it would also be straightforward to generate a list of the ten top high scores for the players to aim for. But, let's keep the task as simple as possible for right now.

So, yes, I created the world's most boring game for demonstration purposes here. Basically, you just enter whatever game score you would like along with a user name of your choice, then click a button to submit that information to be added to the database on the server. We'll also see how to retrieve and view all of the game scores and user names.

Assembling the Software Puzzle Pieces: mySQL Database, PHP, and LiveCode


To do this, you need to first create a database on the server. I'm using mySQL on a web site maintained by a commercial web hosting company. I created a simple database with just one table called "players." The table has the following columns:

  • ID_players
  • username
  • score_recent

Writing the LiveCode Scripts


Here is a screenshot of the boring game I built with LiveCode:



After entering your user name and game score -- in fields titled "username" and "score_recent" --  you click the button "Submit to the Game Center." Here is the script for this button:

on mouseUp
   put "username="&field "username" & "&score_recent="&field "score_recent" into varSendData
   post varSendData to URL "http://yourwebsite.com/gamecenter/insert_newscore.php"
   put it into varResults
   answer "Response from database:"&return&varResults
end mouseUp

The first line assembles a string containing the information the player entered into the two fields. Let's image that the person enter "Lloyd" for user name and "99" for the game score. The resulting string, put into the variable varSendData, would look like this:

"username=Lloyd&score_recent=99"

I used variable names that matched the column labels in my database, but that was not necessary.

This is information is then posted to the URL shown - obviously you would enter the URL of the PHP file on your web site. POST and GET are the two standard ways to send data to a URL. The GET method will attach the information to the end of the URL and hence will be visible in the user's browser (not recommended for sensitive information, such as passwords), whereas the POST method keeps the information hidden from view.

The PHP file "insert_newscore.php" takes that information and performs the database function of inserting the information into the database as a new record, then returns the message "Information entered into database." This message is put into the variable "varResults" which is displayed in a pop-up message.

OK, let's take a quick look at that PHP file.

Writing the PHP File "insert_newscore.php"


Here is the entire code for the PHP file "insert_newscore.php" that has been waiting on the web server:


<?php
//1. Create a database connection

# FileName="Connection_php_mysql.htm"
# Type="MYSQL"
# HTTP="true"
$hostname_connLivecode = "yourhostname";
$database_connLivecode = "demo_high_score";
$username_connLivecode = "yourusername";
$password_connLivecode = "yourpassword";
$connLivecode = mysql_pconnect($hostname_connLivecode, $username_connLivecode, $password_connLivecode) or trigger_error(mysql_error(),E_USER_ERROR);

//2. Perform database query

$username = $_POST["username"];
$score_recent = $_POST["score_recent"];

mysql_select_db($database_connLivecode, $connLivecode);
$query = "INSERT INTO players (";
$query .= " username, score_recent ";
$query .= ") VALUES (";
$query .= " '{$username}', '{$score_recent}'";
$query .= ")";

$result = mysql_query($query, $connLivecode) or die(mysql_error());

//3. Return feedback
echo "Information entered into database";
?>


This file is pure PHP. In fact, it is a single PHP code block. No HTML is included or needed. Adding HTML tags of any sort would just get in the way, as I'll explain later. The PHP code performs three steps. First, it establishes a database connection. You obviously need to enter your own hostname, database name, user name, and password for the database.

Second, it takes the two bits of information we posted (i.e. sent) to the page (shown in red) and puts each into PHP variables with the same names (again, not necessary, but a good habit to get into), followed by a SQL script to insert this information into the players table in the database.

Third, it returns the feedback "Information entered into database" to the LiveCode app using the PHP echo command (which I equate to a print-to-screen command). Indeed, if this PHP file were viewed in a browser at this moment, all you would see on the screen is the sentence "Information entered into database."

If you've never worked with PHP, please don't beat yourself for not understanding the syntax or command structure (and just be thankful that LiveCode isn't written this way). But, I do hope you can at least get the gist of what's going on here.

Using LiveCode to Trigger Database Queries


OK, what if I want to know all the games scores saved so far. The two buttons "Show All Users (sort by username)" and "Show All Users (no sort)" are used to initiate a process that will trigger the database to perform these queries then return this information from the database and put it in the field at the bottom of the card. The scripts for both buttons are identical except for one thing. Let's look at the script of the first button:

on mouseUp
   put empty into field "players"
   put URL "http://yourwebsite.com/gamecenter/show_all_scores_username.php" into varResults
   put varResults into field "players"
   if line 1 of field "players" is empty then delete line 1 of field "players" 

end mouseUp

The first line just empties out the field "players," which is the name of the field at the bottom of the card. The second line goes to the PHP file on the Internet and puts whatever it finds into the variable "varResults," which in turn is put into the field "players." (The last line is a hack -- for some reason, I get a blank line as the first line every time, so this just deletes it.)

The code for the other button is exactly the same, except that it goes to this URL:

http://yourwebsite.com/gamecenter/show_all_scores.php

OK, let's take a look at each of these two PHP files

Writing PHP Files to Query the Database and Return the Results to LiveCode


Here's the code for the PHP file "show_all_scores_username.php":

<?php
//1. Create a database connection
# FileName="Connection_php_mysql.htm"
# Type="MYSQL"
# HTTP="true"
$hostname_connLivecode = "yourhostname";
$database_connLivecode = "demo_high_score";
$username_connLivecode = "yourusername";
$password_connLivecode = "yourpassword";
$connLivecode = mysql_pconnect($hostname_connLivecode, $username_connLivecode, $password_connLivecode) or trigger_error(mysql_error(),E_USER_ERROR); 

//2. Perform database query

mysql_select_db($database_connLivecode, $connLivecode);
$query_rsUser = ("SELECT * FROM players ORDER BY username ASC");

$rsUser = mysql_query($query_rsUser, $connLivecode) or die(mysql_error());
$row_rsUser = mysql_fetch_assoc($rsUser);
$totalRows_rsUser = mysql_num_rows($rsUser);

if ($totalRows_rsUser > 0) {
    echo "#Data begins here"."\n";
if ($totalRows_rsUser == 0) {
    echo "no data found";


do {
  echo $row_rsUser['username'].",".$row_rsUser['score_recent']."\n";
   } while ($row_rsUser = mysql_fetch_assoc($rsUser)); 
  
?>



As you can see, this script has some similarities to that in the other PHP file. The main difference is the following SQL statement:

SELECT * FROM players ORDER BY username ASC

This says to select all of the records found in the table "players" and return and display them in alphabetical order of the column "username."

The other key command is the "do" command at the very end which also includes an "echo" command (show in red). This creates a loop where the database finds and shows each record in the database. The loop repeats for as many records in the database. As before, if we were to enter this URL in a browser, you would see the information appear on the screen. All LiveCode does is take this ouput and put it into the field "players."

It also merits pointing out that this PHP file does not need any input to work, so there is no need to POST or GET any information from the LiveCode file.

The script in the PHP file "show_all_scores.php" is identical except for the SQL statement:

SELECT * FROM players ORDER BY ID_players ASC

This just says to show the records in order of ID_players. ID_players is an integer that auto-increments by 1 every time a new record is created. It guarantees that every record will have a unique number assigned to it. Indeed, even if a record is deleted the number for that deleted record will not be reused. By ordering the output of the records by this number in ascending order, it will show the records in the order of which they were created.

Again, if you don't know PHP, then don't get stressed out over not understanding the ins and outs of every line. However, just to show that it really is just another programming language like LiveCode with the same sorts of functions and options, let's take a look at the line I highlighted above in red:

echo $row_rsUser['username'].",".$row_rsUser['score_recent']."\n";

Notice in the middle these characters: .",".

The period is the concatenation symbol in PHP, whereas we use the & symbol in LiveCode. So, I've merely joined the two variables with a comma in-between. Notice also at the end these characters: ."\n"

"Backslash n" is the PHP code for a line return, so I've simply concatenated this to the end of the string that is being "echoed" (printed to the screen). This ensures that each record in the database will be shown on a separate line.

So, let's imagine that this is the list of all scores in the database which gets returned to the LiveCode app:

#Data begins here
Mark,88
William,91
Lloyd,99

First, you might wonder why it starts with "#Data begins here." It's a little something I added. You will find this sentence in the script above. It's part of an if/then statement and is triggered only if there is data found in the database. Otherwise, the statement "no data found" is return." (I thought it would be a good idea to include the # sign, as I often use that symbol to aid in my list processing scripts because it's a unique and easy symbol to search for.)

Next comes the username and score for each record in the database separated by a comma, with each record on a new line. I decided to display it this way because this is a convenient form for LiveCode to handle given that the comma is the default itemDelimiter. So, item 1 of each line is the user name and item 2 of each line is the game score. If this were a "real" game, I would probably just keep the field hidden from view or alternatively store this list of data in a variable. Then I would display the information in a more friendly form to the user.

Why No HTML?


I'll bet you know some HTML and you are just dying to add a <p> here and a <br> there. Don't do it. The reason is that these tags will appear in their original text form in the field "player" along with the raw data, which is obviously something we don't want.

Short Summary of What I Learned


In the end, the PHP files above are really nothing special for LiveCode. If you were designing a Web site with a database backend, these are exactly the sort of pages you would be writing. Instead of having LiveCode send a user name with a game score, or asking for a list of scores to be shown, you would build an HTML page to do pretty much the same thing. That, in essence, was my conceptual breakthrough. I thought, incorrectly, that I needed to write a custom PHP script -- specialized for the needs of LiveCode -- that would allow LiveCode to "talk" to the database. This misconception blocked my ability to see the solution for two years.

Just so you know, I'm not convinced any of the above is the "best way" for LiveCode to communicate with a database, but it is definitely "one way" to do it. As always, I look forward to the more experienced LiveCode programmers out there to give feedback and guidance to me.

The best thing I can say is that I'm glad I persevered. I now have a whole new LiveCode world open to me.



Wednesday, March 18, 2015

March LiveCode Madness: Building a Clickable Bracket

For the first time ever, I have filled out my own bracket for the upcoming NCAA basketball tournament. For many people here in the USA, this is an important annual ritual. One's bracket simply predicts every winning team in every match-up in the six rounds of the tournament. The tournament starts with a field of 64 teams with half being eliminated after each of the first five rounds. The sixth round pits the two remaining teams in the championship game to crown the national champion. I'm finally participating at the encouragement of my brother, Bill, who happens to teach economics at Butler University in Indianapolis, Indiana. Bill is our family's sports historian with particular expertise in baseball. But this is basketball season and basketball is very big in Indiana. The significance of basketball in Indiana is depicted very well in the movie "Hoosiers." (Trivia: The final championship game in the movie was filmed at Butler Field House where the actual state high school championship game had long been played.)

Basketball is also very big at Butler University. Butler is probably the smallest school ever to appear in the NCAA championship game, having done so in both 2010 and 2011. Unfortunately, Butler lost both times. The loss in 2010 was quite dramatic with Butler, down two points, taking the last shot of the game. Alas, the ball bounced off the rim and Duke won 61-59. The University of Georgia is also playing in the tournament this year and it is conceivable that they could face Butler in the championship game. More on that later.

Like a lot of work places, Bill's colleagues at Butler run a little competition each year where you can enter your bracket. The person with the best prediction wins the competition. Bill enters every year and this year, again with Bill's encouragement, I'm participating too. Our other brother, Mark, is also participating.

To fill out my bracket, I found a PDF online at printyourbrackets.com. For those not familiar with what a bracket looks like, here is a quick snapshot:



I find the visual design very appealing. Teams from the midwest and west are on the left-hand side and teams from the east and south are on the right. You can easily see how teams are quickly whittled down until there is one national champion in the center-most box. But, to fill out this PDF, I had to do a whole lot of copying and pasting. The first version I sent to Bill had a serious copy and paste error, which I'm glad I caught soon after I sent my PDF to him. I had Wisconsin winning the game between Kentucky and Buffalo. (Wisconsin is good, but they are not that good.) I showed Wisconsin continuing to win in Kentucky's spot until the championship game, when Kentucky "reappeared." I fixed the PDF and sent my brother an updated version.

But, I found myself wishing that I had found a "clickable" version of the bracket online instead of a PDF. Then, I could have just clicked my way from team to team with each click quickly pasting in the name of my pick in the slot to the right or left. (It's likely there is such a clickable version out there, but I didn't find one in the few minutes I allocated to my search.)

So, I created a very simple and very incomplete version of a basketball bracket using LiveCode. And, I learned something new by creating this little project. In order for the "on mouseUp" handler to work within a field field, the text in the field has to be set to locked. This makes sense because otherwise every time you clicked in the field to type something into it -- such as the names of the basketball teams in round 1 of the tournament -- the on mouseUp handler would take over. But, to enter the first set of team names, the fields need to be unlocked. So, I needed to have an easy way to lock and unlock the text fields, or at least the text fields to the far left or right of the bracket.

I created two buttons - "Lockdown" and "Unlock" - that, well, lock and unlock the text fields. Now, in my little example, I only have 4 of the 64 teams represented. This results in a total of seven text fields (or three open brackets). If I had all 64 teams, that would require 126 text fields (with 62 open brackets). That's a lot of fields to lock or unlock. But, I learned a good trick while creating a previous project based on the fact that LiveCode automatically numbers all fields on a card. With that knowledge, I used the following script in the button "Lockdown" to lock all the fields on the card:

on mouseUp
   put the number of fields on this card into L
   repeat with i = 1 to L
      set the locktext of field i to true
      set the backgroundcolor of field i to red
   end repeat

end mouseUp

The first line just counts up the total number of fields on the card and puts this number into the local variable L.

Then, I create a loop that repeats L times, starting by putting 1 into the local variable i. The next line sets the locktext property of field i (that is, field 1 or field 2 or field 50, depending on what loop it is) to true, thus locking down the field. Each loop automatically adds one to i.

I also went ahead and set the backgroundcolor of locked fields to red. I thought it would be nice to use some color coding to signal to the user whether the fields were in a locked or unlocked state.

In the button "Unlock" I simply changed true to false in the "set the locktext" line. I also changed the background color to yellow. Here's a snapshot of the screen in the unlocked state:

[ Get the free LiveCode Community version. ]


Here's a snapshot of the screen after the fields have been locked down, thereby allowing the user to click on the fields to make selections, going from left to right:



I then added a script to each field that put a copy of whatever text is in that field to the next field to the right. Here's an example:

on mouseup
   put me into field "r2g1t1"

end mouseup

I labeled all the fields with a scheme that would be helpful if I later choose to continue building this project with a complete bracket. This scheme starts with the tournament round number, then the game number, then the team number. So, "r2g1t1" means round 2, game 1, team 1. Using this scheme, I think I could automate the script for the fields so that each would know what field to send their contents to. For now, I just hard coded the destination.

Looking Forward to the Day When LiveCode Exports to HTML5


As I write this, many of us are waiting anxiously for news on the RunRev company's efforts to enhance LiveCode to allow projects to be exported to HTML5. This project would be a perfect candidate for this feature because I could then embed this project within a web page. Then, I would have legions of basketball fans flocking to my clickable bracket maker site. As I understand it, exporting to HTML5 will essentially convert LiveCode scripts to Javascript. The company began the effort to add this feature to LiveCode about eight months ago with a timeline to completion of one year. So, I keep my fingers crossed everyday that the company will send out an announcement that this feature is finally ready.

One Last Bit of Basketball Trivia While Pondering Who Might Win This Year's College Championship


Here's a final piece of basketball trivia. As I understand it, dribbling evolved from a loophole in the original rules of basketball. The game was invented in the late 1800s by James Naismith, a Massachusetts teacher who wanted a safe, indoor game. The idea was to have players continually pass the ball to teammates to move the ball down the court with the goal of getting the ball into a peach basket mounted up high at the end of the opposing team's side of the court. It was against the rules to run while holding the ball. At some point, someone figured out that if you bounce the ball you are not technically holding it, so this was a way for the player to move about without breaking the rules. Ah, American ingenuity.

So, who do I predict will win the tournament this year? Yes, it is possible for my school - The University of Georgia - to meet my brother's school - Butler University - in the NCAA Basketball Championship game. But, even with the little I know about college basketball, I know the odds of this happening are very, very, small. So, despite the fact that I show above Butler beating Kentucky in round 4 of the tournament (also known as the "Elite 8"), I'm predicting Kentucky will go all the way this. But, then again, stranger things have happened.

Oh, one more thing ... what exactly is a hoosier, anyway?