One of the most frustrating units for me to teach in my sophomore organic chemistry class is the coupling/j-value concept in the NMR chapter. Going through the tree diagrams, we can get to a place where we understand that 3 neighboring protons cause a quartet, but I’m not convinced they really understand why. It gets worse when we get to doublet of doublets. This really goes way over their head. So I delve deeper into the theory so it will become more clear, but the concept only becomes more muddy in their mind. So I go even deeper, really getting into the physics (a class many of them haven’t taken yet), and their eyes start to glaze over and I start to lose the class.

By the end of the unit, we all resign and the students end up ‘memorizing cases’ with little to no understanding of why. I hate ‘memorizing cases.’

So last week I had an epiphany on the drive to work. I was thinking about how to make the concept more clear. Given a proton with a chemical shift, the random up or down spin state of the neighboring proton influences the chemical shift of the observed proton and offsets the chemical shift by an equal value in the positive and negative direction. Total values… a binary up/down spin state… offset by equal amount. Coins!

Given a quarter with a ‘chemical shift’ value of $0.25, a flipped penny will either land heads up or tails (heads down). Say a heads up penny adds $0.01 to the total value, and a heads down penny subtracts $0.01 from the total value. Flipping the penny thousands of times and keeping a running tally of the occurrence of the total values will give a statistical 1:1 ratio of total value $0.24 or $0.26. Flipping two pennies thousands of times will give a statistical 1:2:1 ratio of total values $0.23, $0.25, or $0.27. The analogy is perfect! And if you flip a nickel instead of a penny, we can even draw an analogy to j-values!

I was really excited about my new teaching tool, and began thinking about how to implement it in the classroom. Do I just talk it through as a pure thought experiment? No, they’ll drone me out. I can bring in a penny for everyone and we can predict outcomes, flip, and discuss as a class. Then pair up and play again with two pennies and discuss. That would work, and be interactive. But the relationship to NMR may still be fuzzy. It’d be nice if they could run lots of simulations with lots of combinations of coins on their own time…

Now, I’ve been participating in Code Year by Codecademy since it started in January. It’s been awesome. The first module in Code Year was JavaScript, a language I didn’t know but had always wanted to learn. My dad taught me BASIC when I was a kid, and I taught myself html and CSS, but I never knew JavaScript. I’m still not an expert, but I can code my way around JavaScript fairly confidently now, thanks Codecademy and Code Year!

So, feeling cocky with my new JavaScript tools, I thought this would be an excellent playground for me to test my new coding ability. If you want the entire story about how I created the site, all the gory details are below the jump. Many of you will not care. But after working on it for a week straight, it’s finally ready to launch. Here’s the game. Feel free to play around and see what you think.

Play 5 times to earn a link to a page digging into the theory.

If you teach NMR, and if you want to use this in your class, feel free to! I haven’t tested this out with an actual class of students who have never seen coupling/j-value yet, so we’ll see how it lands when I launch it for real 🙂 Hopefully the days of not understanding coupling/j-value are over!

If you have any comments/suggestions/improvement, I’d love to hear them!

Here’s the story of how I coded the site, if you’re interested. If not, feel free to ignore 🙂

I wrote the code modularly, just like Codecademy’s exercises suggest. First, I wrote the js code to randomly ‘flip a penny’ and define the newPenny as ‘heads’ (0) or ‘tails’ (1). Then expanded it to take the random flip and change the value of the quarter by +1 or -1 the initialized totalValue (25). Then I stuck that method in a loop and had it run 10 trials.

(The CodeCademy JS lab was quite helpful in troubleshooting lots of my JS code throughout. w3schools.com was also invaluable)

Then I went to multiple pennies. I needed something to hold the spin state of several random pennies, so I made newPenny into an array equal to the number of pennies, and filled each index randomly with 0 or 1, then looped over the array and +1 or -1 the totalValue respectively. Based on the number of pennies, I created a chartData associative array of objects and looped through the known number of outcomes to create key:value pairs equal to the ‘value’ ($0.25), the ‘count’ (#outcomes), and a numerical ‘idTag’ (25). After each trial, I looped through this empty object until it found the index with the correct idTag, then increased the ‘count’ by 1. this filled the object with the statistical distribution of outcomes.

I included a method to print a results text that looped through the chartData associative array, checked if ‘count’ > 0, printed the ‘value’ and the ‘count,’ so flipping one penny would print a like like “Results: $0.24 – 4945, $0.26 – 5055” and didn’t print the values with count = 0. (This was later removed from final release)

Then I worked on the form to allow user input for the number of pennies. This wasn’t too hard. I also had buttons for flipping 1x or 10000x (These were removed from final release).

I thought about printing images of the heads or tails of each penny based on the final trial, or some silly ‘coin flipping’ animation while trials were computing, but ultimately decided against. Instead, on the flip I had it print the number of images of pennies given the number of pennies flipped.

The whole teaching point is lost if the page doesn’t make the column graph, as the distribution and the ratios are crucial to the concept. No joke, a few days after I started working on the site, Codecademy released a course on dynamically making a bar graph. I might have incorporated that, but I had already found amcharts, a site which provides JavaScript for creating graphs, and had already integrated it. So now the flip button ran the trials and graphed the output.

I was very frustrated at this point, because for whatever reason, the amcharts script only renders one graph per page load. I can hit the flip button as many times as I want, and the trials will run and the “results” line will print with the new results, but only the first graph rendered would remain on the screen, the script would only print one graph (even though I called the makeGraph method on each flip). So I built a reset button and disabled the Flip button after every flip to force a page refresh to clear the graph to allow for a new graph to be rendered. Kludge, but it worked; a new graph rendered after every reset.

Next was to incorporate the nickel. This is the hardest concept for students to grasp, and took me a while to figure out how to code. I couldn’t just have an array of 0s and 1s for the spin state of the coins, because I needed to know if the 0 corresponded to a penny or a nickel. So instead of creating an array of 0s and 1s for every trial, I created an associative array of objects with the first n indices reserved for the number of nickels [{value: 5, side: 1 or 0} and the last m indices reserved for the number of pennies {value: 1, side: 1 or 0}]. Then, when it looped through the array it increased or decreased the totalValue by the value of the ‘value’ key. Once I figured that out conceptually, the coding wasn’t really too bad.

Then I made a form input to change the number of flips so it wasn’t static at 1x or 10000x, but dynamically imputed by the user. and the basic framework was finished.

Then I css’ed it all to make it look pretty and added the Rules. This tweet of mine is illustrative of this process:

I knew I needed to check the input box to make sure they are integers. I know we’ve done this in Code Year, but couldn’t remember where (they should have a search feature!). I made my own code, but it looked clunky, so Google led me to someone who had the onKeyup code I ended up using. It made sure the value in the box is an integer within the defined parameters, throws the error if it’s not, disables the flip button, and selects the form field. And since it’s dynamically checking the value in the box, if it is indeed an integer, I have it call the updateCoins method to dynamically show how many coins we’re flipping.

So v1.0 was pretty much done at this point. When you flip, the results text is printed, the graph is rendered, the form input fields and the flip button are disabled, the reset button is selected, and text appears to prompt user to click reset to run another trial. On reset, the results text reset, the graph deleted, the form fields were enabled, and the reset text deleted.

I beta tested it with a few chemist friends. They hated the reset button (I did too). An unnecessary step (I agreed). Further, once you accept that you have to reset the page, doing so resets the form to the default values (0 nickels, 1 penny, 10000 flips). So If you want to increment through the different scenarios, you had to update every field every time.

Then I googled upon the sessionStorage object, which allowed me to store values locally, like a cookie, but not. It really took quite a while to get that to implement properly. This was about the time Codecademy was introducing us to jQuery in CodeYear. I was oscillating between a JavaScript body onload event and a jQuery $(document).ready event. But, for whatever reason, the .ready never worked for me. Console kept telling me $ was undefined (even though I was loading the jQuery script CodeYear provided in the first jQuery course). After lots of trial and error and intermediate logging to the console to test and debug, I finally got sessionStorage to work with the onload() event. So finally, the page remembered your values from before the page load. but you still had to reset each time.

Sent v2.0 off to my brother, who actually has a CS degree and works in the industry. He also hated the reset button… and wondered why I couldn’t just call the reset method as part of the flip onClick() event? DUH! So I quickly reorganized what happened when: store the appropriate values, then reload, then in the body onload() run the trials (if this isn’t the users first visit). This got rid of the reset button completely, as the graph isn’t rendered til after the reload, after the values are stored, and everything was great!

He also noticed the results text field and the variable number of flips wasn’t adding any value to the page. I dug around the amcharts documentation page to figure out how to display the value above the column, so I got rid of the results div and text. As for the #flips, since the ratio of the column heights is crucially important for the concept, in my playing around with it, I’d change the #flips such that the outermost columns had a count of 1000 (1000:1000, or 1000:2000:1000 or 1000:3000:3000:1000, etc). I noticed that the #flips to do this was related to the total #coins by a power of 2 (2^(total#coins)*1000), so I just replaced the #flips input field with this equation.

Another chemist friend suggested a theory page (If the theory was easy enough to describe succinctly, I wouldn’t need the game!) But being the perfectionist I am, I had to do it. So I did. It took a good day and a half to write all the copy and format all the divs. The link to the explanation page only appears after the user completed 5 rounds of the game, but the theory page can be found here.

Someone else suggested the concept might be reinforced better if we started with a dollar and centered all our values around $1.00 rather than $0.25. The code to do that would be really simple, but it would require a total redesign of the graphics on the game page and the explanation page, so that will have to wait until I have the momentum again to tackle this project again. i’m about out of momentum after over a complete week of working on the page nonstop.