Tuesday, October 2, 2018

Playing NPR's Sunday Puzzle: My First Successful Submission Thanks to LiveCode

I'm a big fan of National Public Radio (NPR) here in the United States. Every Sunday morning on Weekend Edition there is a segment called the Sunday Puzzle hosted by Will Shortz, the puzzle master. Will is a very famous puzzle guru (and ping pong player) who is probably best known for editing the New York Times crossword puzzle.

I'm usually in the kitchen cooking or doing the dishes when the Sunday Puzzle segment airs. Each week it features a "lucky listener" who Will challenges to solve some puzzles on air. Will then challenges all listeners with a weekly puzzle to be solved by Thursday. Will then randomly chooses one of the winning entries to join him on air the next Sunday. I'm really terrible at solving these puzzles. But, I just submitted my first correct answer to a recent puzzle. I solved it largely due to LiveCode.

Here's the puzzle, quoted from the show's transcript:

It comes from listener Jim Levering (ph) of San Antonio, Texas. Think of an affliction in five letters. Shift each letter three spaces later in the alphabet. For example, A would become D. B would become E, et cetera. And the result will be a prominent name in the Bible. Who is it? So again, an affliction in five letters. Shift each letter three spaces later in the alphabet. And the result will be a prominent name in the Bible. Who is it?

This seemed straightforward to me and I quickly determined it was easier to start with names from the Bible and work backwards. What constituted an affliction seemed too vague to me. The few names I thought of did not pan out. Interestingly, the first name I thought of was Judas. (You would think the first name I thought of was Jesus, given my Catholic school upbringing. But, I personally think Judas is one of the most interesting characters in the Bible.)

Following Will's directions above, here is what you get when you transpose Judas:

Judas > graxp

This is certainly not an affliction I'm aware of. After trying a few more names, I gave up and went on to other things. But, for some reason, this puzzle stuck with me over the next few days. Then, as I was falling asleep Wednesday night, it occurred to me that I could easily write a program in LiveCode to transpose every name in the Bible if I could find a web site listing all of the names. The next morning, I quickly found all the Bible names on the Internet (I forgot to write down the link) and wrote the following program in LiveCode.

Here's a screen shot of the app:

The names of the three fields, from left to right, are "alphabet," "names," and "afflictions."

Interestingly, I found one web site with male names and another with the female names. The female names listed the information in this format:

Abigail – mother of Amasa, Sister of David. I Chronicles 2:15-17[1]
Abigail – wife of the wicked Nabal, who became a wife of David after Nabal's death. I Samuel 25[2]
Abihail #1 – mother of Zuriel. (Zuriel was the chief of the house of Merari). Numbers 3:35[3]
Abihail #2 – wife of Abishur and mother of Ahban and Molid. I Chronicles[4]
Abishag – concubine of aged King David. I Kings[5]

But, this posed no problem as I knew I could easily extract just the first word in the line.  And, you might notice that some of the names in the screen shot have a comma in them. I needed to look for that and strip it out if found.

Here is the complete script in the button "Search:"

1:  on mouseup  
2:    put empty into field "total tries"  
3:    put the number of lines in field "names" into L  
4:    put the number of lines in field "alphabet"into A  
5:    put empty into field "affliction"  
6:    repeat with i = 1 to L // Check each word  
7:     put empty into varAffliction  
8:     put line i of field "names" into varLine  
9:     put the first word of varLine into varName  
10:     if the last character of varName is comma then delete the last character of varName  
11:     if the length of varName <> 5 then next repeat  
12:     repeat with j = 1 to 5 //check each letter of word  
13:       put char j of varName into varLetter  
14:       repeat with k = 1 to A // check the alphabet  
15:        if varLetter <> line k of field "alphabet" then next repeat // find the matching letter  
16:        put line k-3 of field "alphabet" into varNewLetter  
17:        if k = 1 then put line 24 of field "alphabet" into varNewLetter  
18:        if k = 2 then put line 25 of field "alphabet" into varNewLetter  
19:        if k = 3 then put line 26 of field "alphabet" into varNewLetter  
20:        put varNewLetter after varAffliction  
21:       end repeat // end check the alphabet  
22:     end repeat // end check each letter of word  
23:     put varName&comma&varAffliction&return after field "affliction"  
24:    end repeat // End check each word  
25:    put the number of lines in field "affliction" into field "total tries"  
26:  end mouseup  

Here are just a few choice explanations of key lines in the script:

There are three repeat loops:

  • Lines 6 to 24 repeat everything for each name found in field "names." 
  • Lines 12 to 22 work on each letter in the name, so this always repeats 5 times.
  • Lines 14-21 do the three letter transposing. 

Here is an explanation of other key lines:

  • Line 9 puts the first word of the line into varName.
  • Line 10 looks to see if there is a comma as the last character. If there is, it deletes it. 
  • Line 11 checks to see if the length of the name is five characters. If it is not, the rest of the code is aborted and the next name in the list is chosen.
  • Line 16 is the transposing engine - once the matching letter is found in field "alphabet," it finds the letter that is three spots ahead of it.
  • Lines 17-19 are hacks. I got lazy - I hadn't had my first cup of coffee yet - and just manually figured out which letter went with a, b, and c.
  • Line 20 builds the newly transposed word.
  • Line 23 puts the Bible name and the transposed word, with a comma in-between, in a new line in the field "affliction."
After clicking the button "Search," it takes LiveCode a few seconds to process the 1964 lines in field "names." Again, I didn't know exactly what affliction I might find, but I figured I could scan the list easily to find one (or more). Here's a screen shot showing the correct answer:

I missed it the first time I scanned the list of 409 matches. But, I found it on the second pass:

Herod > ebola

I was one of 1100 people who submitted the correct answer. Thankfully, I was not chosen as the "lucky listener" to appear on next Sunday's show.

Wednesday, March 21, 2018

Using LiveCode as Pseudocode for Coding in PHP

In previous posts I've commented occasionally about integrating my LiveCode apps with HTML, PHP, and mySQL. I wish all programming environments were patterned after LiveCode. But, alas, they are not. Too bad because I've been programming in LiveCode long enough that I actually think in LiveCode. I need to get much more proficient in PHP and it dawned on me recently that I could leverage my LiveCode skills to do so. My idea is to first build a working prototype of functions or procedures I need to program in PHP with LiveCode. The idea being that I can work out the hard part - the logic - much more easily in LiveCode, then "convert" that logic to PHP code.

The idea of just creating an algorithm in everyday language is often just called pseudocode. The code doesn't actually work in any programming language, but it allows you to get to the heart of the logic without getting bogged down in syntax or rules. I have come to naturally write out my logic with LiveCode so these algorithms not only act as pseudocode, they are also work when plugged into LiveCode.

Here's a very simple example of some PHP code I wrote recently that took all of 10 seconds to write out first in LiveCode:

 if varDatabaseColumn is empty then put "Nothing entered." into varDatabaseColumn  
 put varDatabaseColumn&return after field "text"  

Stated in English: If the variable containing the information from the column (or record) downloaded from the database does not contain any information, then enter the phrase "Nothing entered." into that variable. Then, display or print that value on the screen with a line return after it.

Here is the PHP code I eventually wrote:

 if (empty($row_rsUser['rating_statement'])) {  
      echo "Nothing entered."."\n";  
 } else {  
      echo $row_rsUser['rating_statement']."\n";  

The LiveCode and PHP code aren't exactly equivalent in that I didn't actually need to use an if-then-else construction with LiveCode. But, just writing out what needed to happen in simple logic led me to the right PHP construction. What took me 10 seconds in LiveCode took about an hour in PHP because I am not fluent in PHP. I had to relearn that a period is used as the concatenation symbol. I had to relearn that /n is used to trigger a return (i.e. new line) on the screen. I had to relearn that a dollar sign is used to connote a variable. And so on.

Interestingly, in PHP there are several functions that address the idea of "emptiness" in a variable:
  • empty($var)
  • isset($var)
  • is_null($var)
Long story short, the empty command address the two situations that matched my need: Is the string just empty (nothing in it), or does it contain the value of NULL? I'm not prepared to explain the difference between nothing and NULL, other than to say that NULL is actually a value that can be entered into a database record. So, yes, that took some time to learn too.

I have several other immediate PHP programming jobs that are much more sophisticated. I will again start with building a working version with LiveCode as a way to figure out the logic, then "convert" that logic into PHP code.

I think it will be a long time before I start to think in PHP.

Saturday, March 17, 2018

Lloyd's Q Sort Tool is Now a Viable Option for Q Researchers

It is going on three years since I began creating a digital Q sort tool. Over the past few weeks, I've been on a very "deep dive" into this project thanks to having a research leave this semester - my first leave of any kind in 30 years. My goals this semester have been to finalize the app's initial development, create a web site for other teachers to use my tool at no cost, do a lot of reading about Q methodology, write about its development, and submit a grant proposal for some modest funding to keep the work going.

The three readers of this blog know that I actually released beta version 1.0 back in August. I used the term "beta" because this was a preliminary and cautious release. Anyone interested in getting an instructor account to use my tool needed my approval. It's not that I was expecting thousands of people to start using it, but I deliberately wanted to keep the number of users very small in order to have them help to spot problems and bugs, while also suggesting ideas for further development. As an unfunded project with me as chief designer,  programmer, web developer, statistician, PR department, and marketer, there are likely to be a lot of as yet undetected errors. I didn't want too many people cursing my name from afar as the errors were revealed.

As it turned out, very few instructors have signed up to be users, which has been disappointing, even though I've made three presentations about this project since the release of version 1.0, including one at the annual conference of the Association for Educational Communications and Technology (AECT) in November and another at the Conference on Higher Education Pedagogy (CHEP) at Virginia Tech in February. I've also sent out two announcements about my app to the Q-Method listserv run out of Kent State University. I actually had quite a few inquiries from the Q-Method folks, but only about whether my app could be used for research projects. I explained that my main goal and purpose in developing the app has been for instructional, not research, applications. These folks wished me well, but obviously had little interest other than the app's potential for conducting Q methodology research.

Time For Me to Sit Up and Pay Attention

So, for the last month or so I've started to rethink the goals of my Q sort project with an eye toward expanding it to include the needs of Q researchers. Obviously, that is the group who has shown the most interest and encouragement. So I decided to go for the best of both worlds by making my Q sort tool viable for Q researchers and people like me who want to tap the power of Q for enhancing instruction. To that end, I've made some important updates to the tool, many in just the past week (thanks to this being spring break here at the University of Georgia). This set of revisions mark an important milestone in the ideation and iterations of the design, especially as I write a draft design article about this project for presentation at the upcoming AERA conference in New York.

Here is a short summary of those updates.

Easy Exporting of the Data into Q Analysis Statistical Tools

Even though I was careful to make the raw data of a Q sort completed with my app readily accessible to a researcher, it was, well, really raw. With the help of one of my doctoral students, Tong Li, I added an export option in the instructor version of my app. This option now makes it very easy to export the data to the popular Q analysis applications, such as PQMethod an Ken-Q. I've become a big fan of the Ken-Q Analysis Tool, mainly because it's a web site, not a standalone app (and it's free), so I made a quick video on how to export data from my app into it:

I don't try to explain anything about the analysis, but only to demonstrate to a Q researcher how easy it is to export the data.

Two Other Features that Q Researchers Have Asked About, and One They Didn't

Embedded End-of-Q Sort Survey

Q researchers have repeatedly asked about whether my app can conduct and collect some survey data after the Q sort has been completed. Asking the user to explain their high and low sort choices along with any other comments that help to explain their thinking is a typical procedure in Q methodology. My response has been no, but also that it shouldn't be a big deal to collect these data through other means, such as through a Qualtrics survey. But, I also know that having the user jump out to yet another application at the critical moment when they are asked to do the hard work of reflection runs a huge risk of the user just quitting. So, I've now made asking three open-ended questions a feature in my app as well, along with giving the researcher control over the wording of the three questions. Given my hunch that instructors who use my Q sort tool for teaching will not want to ask these three questions, this feature can be turned off when the Q sort definition is created.

Making the Summary Survey Question Optional

Interestingly, another feature of my app that I've included from the very beginning is one that Q researchers don't like. After a user completes the Q sort, my app asks them a simple summary survey question in the style of a Likert question. For example, after completing a Q sort about ice cream, the user is asked to rate the statement "I like ice cream." from strongly agree to strongly disagree. Asking a question like this has been very important and useful in using Q sorts for instruction because it lets a class know how the entire group feels about the topic in a single data point. This helps to start the conversation. Well, Q researchers really don't seem to like this. Even though I explain that this question comes after the Q sort and therefore doesn't interfere to invalidate the Q data, they just don't want to ask a question of this sort. So, I've now made the asking of this summary survey question optional when a Q sort definition is created.

Creating these two features - and the option to use or not use either in a Q sort - have extended my understanding of how to have a standalone app created with LiveCode communicate with a mySQL database. Indeed, a great deal of my work over the past week has been exclusively on the mySQL database and the PHP code on the web site I created months ago to support the tool.

Kiosk Mode

Interestingly, one of my colleagues who is interested in using my Q sort tool in her teaching matter of factly mentioned how she planned on setting up a computer or two in a corner of her classroom for students to complete the Q sort at some point during the class. The reason is that she didn't expect students to bring a laptop with them for downloading the app. I thought this was a great idea, but it quickly dawned on me as she walked away that this wasn't possible because my app doesn't allow someone to complete a Q sort a second time, except for practice without any data being submitted to the database. I solved this problem by adding a feature to the instructor version of my app that I call Kiosk mode. As the name suggests, you can run my app like a kiosk on a dedicated computer somewhere and have lots of people come by to complete the Q sort. There is the risk of one person completing a Q sort multiple times, so it will be up to the instructor (or researcher) to police this. And, given that this feature is only available in the instructor version of the app, there is no chance some "rogue participant" could use the regular version of the app to stuff the ballot box.

Immediate Next Step: Lots of Testing

Any time a new version is rolled out, there is a good chance that bugs and errors remain. Testing is a time-consuming endeavor and, as I already mentioned, my time is divided between all of the roles needed on the project. So, before I release the version of the app with all of the updates discussed here, I'll first be turning my attention over the week or so to the mundane task of creating lots of sample Q sorts while playing the role of both interested and uninterested participant, all in the mission of uncovering the bugs. If anyone wants to join me, just let me know.

Eventual Next Step: Posting a Note to the ITFORUM Listserv

One place I haven't disseminated information about my Q sort project is the ITFORUM listserv. This listserv remains one of the best ways to communicate to professors, researchers, designers, and students in the field of learning, design, and technology (aka instructional technology). I'm not sure why I've been hesitating. I think one reason is that I wanted the app to be very solid before announcing it there. But, time may be almost ripe to post something to the ITFORUM listserv, especially because it might spur a few people in my field to seriously consider using Q sorts in their teaching or Q methodology in their research.

Sunday, February 4, 2018

I Thank All Those Responsible for Creating LiveCode's Data Grid Object

I have known about LiveCode's data grid object for a long time. I explored it briefly soon after I started learning LiveCode and recognized immediately how useful it would be. But, I found that learning to use it would require some time and so I waited for a project that needed it. Well, that time has finally come. Now that I've learned the fundamentals of a data grid, I am so grateful that someone, or some team, took the time to create it.

Why I Needed a Data Grid

A data grid is simply a way to present data in a table-style format, similar to a table in Word or an Excel spreadsheet. (You can also display data in a label-style format.) Let me explain why I needed it. In my Q sort tool I provide a report to users that lists how related their Q sort results are to each and every other person who did the sort. This relationship is expressed by a correlation coefficient ranging from +1 to -1 where +1 is a perfect, positive correlation and -1 is a perfect negative correlation. Perfect correlations never happen in the social sciences - at least I've never seen one. Instead one gets a number somewhere in-between. A strong positive number indicates that the two people's sorts share a statistical relationship in the same direction. That is, their Q sorts indicate a shared point of view. They are of like minds. A strong negative number also indicates a statistical relationship, but in the opposite direction. To use the example of ice cream flavors, two people who seem to like or dislike the same flavors would have a strong positive correlation number, whereas two people who have very different tastes would have a strong negative number: "I love chocolate, but I hate pistachio." "Really? I hate chocolate but love pistachio."

Up to now, I've been displaying these data to the user within a simple, hard to read - and ugly - text field:

Ugliness aside, I've also found that some people misinterpret the data mainly because they don't necessarily see the all important comma in the right column in-between the person's name and the correlation. The zig zagging right edge of the data also makes it tough to read. I also have many non-US people who grew up using the comma instead of the period as the decimal point. This causes further confusion.

In contrast, a data grid allows the same data to be displayed in a clearer, neatly arranged, table-style format:

So, How Does a Data Grid Work?

A data grid is actually a group of interrelated LiveCode objects all tied together with special scripts unique to a data grid. For example, each cell in a data grid is actually a text field. To get all of the individual fields to work together requires a family of specialized scripts that have been programmed into the data grid object. I again thank the person or people who took the time many years ago to create the data grid object and for including a complete set of specialized commands and functions to control it using scripts.

I have only scratched the surface of the capabilities of a data grid so far in my Q sort tool. I learned about the fundamentals of a data grid by going through much of the following LiveCode tutorial:

I highly recommend this tutorial to anyone who is about to use data grids for the first time with the caveat that you will need some time and patience. It's not difficult, but there are a lot of nonintuitive details to master. I also recommend creating some "toy projects" at first so you can play around with the data grid and the associated scripts before trying to plug a data grid into one of your real projects. The frustration for me was that I have finally come to "think in LiveCode" but the data grid scripts weren't following my grasp of the LiveCode language. It was kind of like traveling to another part of the country where everyone speaks a different dialect with a very strong accent. You know they're speaking English, but you're just not sure what the person said.

Examples of a Few Key Scripts

First, it's easy to populate a data grid manually using the property inspector. However, I needed to learn how to populate it with scripts. The first script I learned wasn't very hard - you just need to use a comma to delineate between cells on a row, then add a line return at the end of the row. This example comes straight from the tutorial:

1:  on mouseUp   
2:     ## Create tab delimited data.   
3:     ## Note that first line has name of columns.   
4:     ## Providing names tells Data Grid how to map   
5:     ## data to appropriate columns.    
6:     put "Live" & tab & "Code" & cr & \   
7:           "ALABAMA" & tab & "AL" & cr & \   
8:           "ALASKA" & tab & "AK" into theText   
9:     ## Let Data Grid know that first line has column names   
10:     put true into firstLineContainsColumnNames   
11:     set the dgText [ firstLineContainsColumnNames ] of group "DataGrid 1" to theText   
12:   end mouseUp   

Line 11, the line that actually puts the data into the data grid, is really the only line of script that I didn't already know. If this were just a regular ol' text field, the script would have been this:

put theText into field "myData"

Let's consider how to sort data, first in a in a regular text field where each line has some comma delimited text, such as the name of a country followed by its capital (e.g. USA, Washington DC). This script sorts the entire field by the name of the country:

sort field "list" ascending by item 1 of each

To sort instead by the capital, we just change it to item 2:

sort lines of field "list" ascending by item 2 of each

Obviously, we can swap "ascending" with "descending" to reverse the sorting direction.

Here is the sort command for a data grid:

set the dgProps["sort by column"] of group "DataGrid" to "City"

Again, not a script one can conjure up with just an ordinary knowledge of LiveCode.

Another great thing about data grids is that they have sorting built into them. The user just needs to click on the header in either column to toggle the direction of the sort.

But, There's So Much More

I needed more functionality, such as clicking on a person's name and showing the correlation coefficients just for that person. I'll cut to the chase and show the entire script:

1:  global varComparisonSummaryDG, varAllComparisonsDG, varOneGroupOnlyDG  
2:  on mouseDown pMouseBtnNo  
3:    set the itemDelimiter to tab  
4:    dgMouseDown pMouseBtnNo  
5:    //Gets the number of the row clicked on  
6:    put the dgHilitedLines of me into L  
7:    //Gets the value of a column in a particular row  
8:    put GetDataOfLine(L, "Name") into varName  
9:    put varName into line 2 of field "comparison label"  
10:    //show field "one group only"  
11:    // put empty into field "one group onlyDG"  
12:    put empty into varOneGroupOnlyDG  
13:    set the dgData of group "One Group OnlyDG" to empty  
14:    put the number of lines of varAllComparisonsDG into M  
15:    repeat with i=1 to M  
16:     if line i of varAllComparisonsDG = varName then   
17:       repeat with j=i to M //after name is found, look for the next empty line  
18:        if item 1 of line j of varAllComparisonsDG is "SUM" then exit repeat  
19:       end repeat  
20:       put line i+1 to j-1 of varAllComparisonsDG into varOneGroupOnlyDG  
21:       set the dgText [ false ] of group "One Group OnlyDG" to varOneGroupOnlyDG  
22:       exit repeat  
23:     end if  
24:    end repeat  
25:    set the itemDelimiter to comma  
26:  end mouseDown  

Even as I look at this code now, a few days after I wrote it, I find it challenging to remember what all is going on. But here are the basics:

  • Line 6 puts the number of the line just clicked into the variable L.
  • Line 8 puts the data in the column "Name" into the variable varName.
  • Line 9 just puts the person's name in a label field near the top of the screen to make it clearer who is the person being compared.
  • The global variable varAllComparisonsDG contains all of the comparison data. Lines 15-24 systematically looks through all of this data to find the person's name. Once found, it notes where in the variable the data for this person is found in line numbers. (A variable holds data in a way that is similar to a field.)
  • Line 20 puts this data into a variable named varOneGroupOnlyDG
  • Line 21 puts the data in variable varOneGroupOnlyDG into the second data grid shown on the screen on the right.

And yes, there is so much more. A good place to browse is this web page showing all of the data grid properties. 

So I end this post with yet another shout out to those responsible for creating the data grid and making it available as a built-in tool for LiveCode. I don't know what I would have done without it.

Lloyd's LiveCode Blog Is No Longer MIA

Yes, it may have appeared that I've been "missing in action" when it comes to me writing about learning LiveCode. But, I want to assure all my readers - both of them - that my Learning LiveCode blog is alive and well. I haven't posted much lately mainly because I've been involved in deep dives of two very different LiveCode projects.

The first is a project that has some modest funding support in the area of agricultural education. For reasons mainly of confidentiality I've not written anything about that project despite spending an enormous amount of time on it over the past year or so. But, I think I'll be able to start writing about it soon. It's actually a very cool project and I've come up with an interesting prototype that the team likes and appears to be getting good reviews during the first field trials.

The second project has simply been doing some heavy duty tweaking of my Q sort tool. The tool itself remains fundamentally the same as when I wrote about it back in August. However, some of these tweaks have been fairly significant, such as switching to LiveCode's data grid object, also known as a table field. My next post will be about learning how to use a data grid. And, some new options are planned that I look forward to sharing here.

So, thanks for being patient and thanks for all those cards and letters asking where I've been. (Sorry, that last bit was a lie, but it felt good writing it.)

Friday, August 18, 2017

Lloyd's Q Sort Tool: Version 1.0 Just Released

I've been very derelict in providing updates on my project to create a digital tool to allow instructors to use Q sorts in their teaching. I suppose my only excuse is that I've been focused these past three months on actually doing the design work and coding to make it all possible. Well, I'm happy to announce that version 1.0 of the my app - Lloyd's Q Sort Tool - is now available. [Cue the dropping of balloons and confetti.]

Part of the task has been the monumental effort to also create a web portal for instructors to use. Although I had designed the mySQL database carefully over a year ago to allow for instructor accounts, I had never actually created anything more than a crude administrator interface for me to do the behinds-the-scene database tasks to support the field tests I have been running. And yes, this was a very ugly site. So, I've been working on developing an attractive and (hopefully) intuitive web portal for instructors while also making the final revisions of the app. Oh yeah, I was also teaching two courses for the University of Georgia this summer at the same time.

But, I am now ready to make instructor accounts available on a very limited basis. [Cue the triumphant horns.] It is really only the beta of version 1.0 that has been released because I feel it is necessary to do much field testing of the app before I'm confident that I have finally reached a true version 1.0. If you are one of the few who read this blog and one of the very few who might be interested in using Q sorts in your instruction, please feel free to go to my Q sort project's web site to request an account:


Of course, if you are not an instructor, but would like to check out how my Q sort tool works, I invite you to download the app and try one of the public Q sorts I've included on my web site.

Here is a video demonstration of how the app works:

Summary of the Most Significant Revisions to the App

I need to provide separate blog postings to spotlight and explain each of the big revisions to the app, but here is a quick summary of the most significant. Some of these represent true breakthroughs in my design.

Breaking Through the 20 Statement Limit

For the first two years of the project, my design limited all Q sorts to no more than about 20 statements. Although this proved sufficient for all of my field tests, I knew that this limitation had to be overcome at some point. So, this past spring I mounted a design effort to find another approach. The solution came in the form of dynamically collapsing and expanding statements as they were sorted on the grid. This allowed me to switch to a more standard design of the Q sort board which resembled an inverted normal curve. I did keep the sideways orientation to the format of this board, which helped to leave the majority of the screen open for the statements. However, this approach triggered other user experience challenges and it was only through feedback from people who participated in some critical field tests that I was able to find a way for this to work.

Creating a Sorting Sandbox to Encourage Initial Grouping of Statements

It is standard practice within Q methodology to ask participants to first group all statements into three general piles: most agree, least agree, and neutral. Although my first prototypes advised people to do this, it never really worked well given the way the screen was organized. I found a way to persuade users to do this preliminary grouping which provided a solution to the limited screen space. Along the way, I think I found a unique design approach to doing a preliminary grouping. I added three long strips at the top of the screen, marked respectively as high, neutral, and low. Participants are advised to take each statement and do a "gut sorting" of it into one of these three groups. The unique design is that the placement of each statement, from left to right, on each of the three strips, gives a priority ranking to the statements in that strip. I have never seen this added dimension in any of the Q sort designs - paper or digital - that have been developed. I then added a 1-click option for participants to move the statements in any of the three strips into the main area of the screen in an expanded form and in the same order in which they appeared in the strip. The important thing to note about this strategy is that the initial grouping effectively removes all of the statements from the main area of the screen, thus opening this space for the statements to appear when when the 1-click option is used. In this way, the limited screen space is effectively used even if a large number of total statements is used in the Q sort. I also programmed an auto-magnify feature to immediately show the full statement when the participant mouses over any of the statement numbers in the sandbox.

Auto-Numbering of the Statements

I also programmed the list of statements to be auto-numbered. This provides a secondary cue to which statement is which. I combined this with the option to have a pop-up window to list all of the statements. Furthermore, this list can be copied to the clipboard for pasting in another application, such as a word processing document, to allow the participant easy access to all of the statements along with the statement number. This helps participants to cross-reference statements to their numbers.

Improving and Extending the Q Sort Analysis

I made a key decision about a year ago to put the analysis directly into the app itself. Before then, the analysis was done with a separate app I built meant just for the instructor.  This decision put the analysis data directly in the hands of students with real-time access to the data. That is, the student could check to see how many responses had been submitted and run an analysis on the responses submitted so far.

More recently, I extended the analysis by adopting a method very much aligned with Q methodology. Although I have long had an analysis option called "Are You Like Me?" which was based on difference scores calculated between each pairs of people who completed the Q sort, this never proved to be an effective means of getting people to engage with each other. This summer I programmed this option to also provide correlation coefficients along with noting which were statistically significant. Although I have yet to field test this revision, I'm optimistic that it will make people more likely to both talk to those who share their views and talk to those people who do not.

Overview of the Instructor Web Portal

Creating the instructor web portal was a challenge, not so much in terms of programming it, but in designing it to sufficiently explain how everything works to an instructor who has never met me or has never heard of a Q sort. Fortunately, the instructors to whom I've already given our accounts are people who heard me speak at various conferences about this project and asked permission to use the app in their teaching. I had to kindly tell them that the project was not yet "ready for prime time" and that I could not yet honor their requests. But, I added their names to a list of interested folks.

I provide some extensive guidance to instructors on how to use the site. I also created the following video demonstration:

The Difference Between Q Sort Definitions and Q Sort Activities

There are some key concepts that, if not well understood, will make everything else confusing for instructors. The main one is probably the difference between a Q sort definition and Q sort activities. I won't give the long answer here, but the difference has allowed me to take a smart approach to creating Q sorts in a way that should save instructors lots of time. In short, one first creates a definition of a Q sort that contains almost all of the information about the Q sort. Then, one creates one or more activities that are linked, or bound, to that one definition. In this way, one use and reuse a Q sort definition dozens or even hundreds of time without have to go through the time-consuming task of creating yet another Q sort.

Next Steps for the Project

It's been almost two and a half years since I first wrote about my decision to create a digital version of  a Q sort in April 2015. After hundreds of hours of coding and more than a dozen field tests, it feels so good to finally put this project "out there." Yes, I have built it, but will anyone come. To be honest, I only want a small number to request an instructor account so that I can identify and fix errors and problems which are inevitably present.  My hope is that eventually at least a small community of instructors will form who are interested in exploring ways to capitalize on students' subjective perspectives in teaching. I have charted an initial strategy for their use, but I know there are many other creative approaches yet to be identified.

I look forward to seeing how the project unfolds. I plan on presenting this project at upcoming conferences, beginning with the small (but wonderful) IDD@UGA conference on August 19, 2017. But, I will be presenting this project at the upcoming conference of the Association for Educational Communications and Technology (AECT) in Jacksonville, Florida in October. I also have submitted a proposal to present the project at the American Educational Research Association (AERA) in New York in April 2018. I also intend to submit a proposal to the Conference on Higher Education Pedagogy (CHEP) held each February 2018 at Virginia Tech to provide an update of the project.

I have spent a lot of time on this project. I hope it proves to be useful to teachers, instructors, and trainers.

Monday, July 10, 2017

The "Any 3 for 15" Game and the Courage to Start Over

I'm again teaching two courses for the University of Georgia this summer. One is a design course and recently we were talking about accessibility. I've tried to broaden my students' understanding of accessibility. I want them to see accessibility more as a design paradigm rather than a set of mandated technical requirements. That is, instead of seeing accessibility as nuisance for a designer, I want them to see accessibility as an opportunity to improve their designs.

One little activity I've used over the years is a cool little game that demonstrates the power of representation, namely that the way a concept, principle, or procedure is represented can dramatically alter the ease of learning it.

The rules of the game are simple. There are two players and each takes turn picking a number from 1 to 9. Once a number is chosen, it is unavailable to be chosen again. The player with the first hand with any three numbers that equal 15 is the winner. It's a surprisingly challenging game to play. As we play it, people begin to have the feeling that they've played the game before. There is a big reveal at the end. It turns out that this little game is really just tic-tac-toe (also known as naughts and crosses), but in mathematical form. The game is fully revealed when the numbers are shown in this pattern:

This is commonly known as a magic square. Notice how any row, column, or diagonal adds up to 15. Obviously, adults don't play tic-tac-toe any more because once you know the secret to choosing the center square, there is no way you can lose. However, even after the big reveal, the math version of the game is still a challenge to player. The two versions of the game have exactly the same rules, but the representation of each is dramatically different. My hope is that students will take this point to heart and try to find the best representation for their designs.

Creating a Version of the Game with LiveCode

I've had groups play this game for years using PowerPoint. I would just stay in edit mode and manually move the numbers around as the game is played. However, it occurred to me a few hours before class that I could create a quick version in LiveCode that would be easier to manage. Forty-five minutes later, I had a nice working version of the game. I still had to mentally keep checking to see if one of the players had three numbers that added up to 15. After class I thought it be great to program LiveCode to do this checking. Well, that began a design saga that took me over a week to complete.

Identifying All Unique Groups of Three Numbers

The algorithm needs to check all possible combinations of three numbers in the player's hand after each turn. I saw a couple of way to handle this problem. One way is to use a well-known formula to determine the total number of possible combinations, then turn LiveCode loose spitting out random combinations until all of the unique ones were found. Here's the formula:

r is the number of numbers in a given combination, which is always 3 in this case.

n is the total number of numbers in the list, which is the number of numbers a player has drawn up that point.

Obviously, the player has to have at least three numbers before you start calculating. And, the most numbers a player will have is 5 given that the players take turns drawing numbers. The formula above indicates there are only a total of 10 unique combinations of three numbers in a list of 5 numbers. (Order of the numbers obviously does not matter.)

A better strategy - and the one I selected - was to figure out the algorithm first, mapping it out step by step on paper. It's pretty simple:

Take five numbers: 1, 2, 3, 4, 5

The pattern of combinations can be determined as follows:


Yep, there are 10 of them. Do you see the pattern? There are three loops here corresponding to each digit in a row. Believe me, it is very easy to get totally confused in trying to troubleshoot a problem with an algorithm having three interwoven loops - it's like trying to balance three spinning plates on sticks. Once you focus on one, the others are prone to fall.

I spent about two hours on a Sunday afternoon working on this without success. I came back to the problem that evening, only to find myself thoroughly confused. So, I started over.

On the Reluctance to Start Over

I had about three hours invested in an approach that was not working. At times, it appeared I was tantalizingly close, just to have the algorithm fall apart again. The idea of starting over after having invested so much time is a tough pill to swallow. And yes, I think it does take some courage to admit defeat and start from scratch.

I turned to a favorite strategy where I build a new "toy app" from scratch that focuses solely on this one problem. In this virtual sandbox, I find I can focus better on a thorny problem. It really helps to start with a blank canvas and not have all of the other stuff from the bigger project jumbling around in your head. It was a busy week, so it was only Wednesday when I got round to doing this.

Unfortunately, my second approach yielded the same confounding results. And I again decided I needed to start over. Fortunately, all of the code this time was contained in a single button in a very simple stack, so I just moved that button off to the side and made a new button. I worked on this Friday night and some of Saturday. And, I again got myself into a brain splitting knot.

Fourth Time's a Charm

I again decided to start over. Although I had basically the right idea behind the loops, my approach to ending one loop and starting the next was flawed. The week's efforts convinced me that I needed to focus on the most concrete representation of the problem I could muster. So, instead of working with ever growing looping lists within variables, I used fields as containers. This gave me a visual form to seeing how the algorithm worked, not unlike the tic-tac-toe example.

I don't think I can sufficiently or succinctly explain my solution here, but suffice it to say it was a joyous moment when my program finally worked.

The lesson to take away here is sometimes the wisest way to solve a problem is to abandon an approach -- regardless of the amount of time already invested in it -- and start over.  Knowing when to throw in the towel is tricky, but I guess that's where the wisdom comes in.

Play the "Any 3 for 15" Game

(Alert! Depending on your Internet speed, this can take a full minute to download.)

And yes, the game title definitely needs work. Right now, it sounds like a selfish version of the Three Musketeers motto (i.e. "All for one and one for all").

A Final Note: Computing Factorials with LiveCode

I mentioned that I flirted with the idea first of using the formula above as my starting point for my solution to this problem. I spent about 15 minutes trying to program LiveCode to compute the factorial of a given number. I would have eventually figured it out, but fortunately,I stopped and did a google search and found a very elegant solution:

The example comes from this web page:


To quote from that page:

"A function can call itself. The following example calls itself to compute the factorial of an integer:"

 function factorial theNumber  
 if theNumber <= 1 then return 1  
 else return theNumber * factorial(theNumber -1)  
 end factorial  

My solution would have been quite convoluted in comparison. And, I learned something new about LiveCode as a result.