<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" >
	<channel>
		<title>jarv.org</title>
		<atom:link href="http://jarv.org/feed/" rel="self" type="application/rss+xml" />
		<link>http://jarv.org</link>
		<description>blog and projects</description>
		<lastBuildDate>Sat, 18 Feb 2012 20:52:49 +0000</lastBuildDate>
		<language>en</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
		<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
			<title>Automating Drupal 7 Installs Using Drush and Install Profiles</title>
			<link>http://jarv.org/2012/02/automating-drupal-7-installs-using-drush-and-install-profiles/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=automating-drupal-7-installs-using-drush-and-install-profiles</link>
			<comments>http://jarv.org/2012/02/automating-drupal-7-installs-using-drush-and-install-profiles/#comments</comments>
			<pubDate>Sat, 18 Feb 2012 20:47:42 +0000</pubDate>
			<dc:creator>jarv</dc:creator>
			<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://jarv.org/?p=1187</guid>
			<description><![CDATA[Recently I needed to install Drupal 7 non-interactively on a Linux Server running a typical LAMP software stack. There is a lot of information out there already for this type of installation but nothing concise for what I needed to do. &#160;Hopefully by adding this one to the pile it will help someone else who [...]]]></description>
			<content:encoded><![CDATA[<p>Recently I needed to install Drupal 7 non-interactively on a Linux Server running a typical LAMP software stack. There is a lot of information out there already for this type of installation but nothing concise for what I needed to do. &#160;Hopefully by adding this one to the pile it will help someone else who went through a similar exercise, if you found it useful <a title="About" href="http://jarv.org/about/">please let me know</a>!</p><p><strong>What you get after installation with this custom install profile</strong>:</p><ul><li>Drupal 7 core</li><li>Core + selected module(s) installed and enabled</li><li>A custom user role and user name passed in on the command-line</li></ul><p><strong>Server Setup</strong>:</p><p>For a testing sandbox it will be easiest to use a Linux box or VM that has the following installed:</p><ul><li>Apache or lighttp w/ php and sqlite</li><li>php w/ sqlite</li><li>Drush v5.x</li></ul><p>Use your OS&#8217;s packaging system to install the webserver with php and database support.</p><p>Make sure you drush is version 5.x, to install it using php pear:</p><pre class="brush: plain; title: ; notranslate">pear channel-discover pear.drush.org pear install drush/drush</pre><p>Or see <a href="http://drupal.org/project/drush">http://drupal.org/project/drush</a></p><h2>Drush Make</h2><p>The command &#8220;drush make&#8221; will read a makefile that has some directives to tell drush where to fetch the core, modules and themes. Here is the drush makefile that we will use that installs the core plus the <a href="http://drupal.org/project/role_delegation">Role Delegation</a> module.</p><pre class="brush: plain; title: ; notranslate">; Core Drupal ; ------------- core = 7.x api = 2 projects[drupal][version] = 7 ; Modules ; ------------- projects[role_delegation][subdir] = contrib</pre><p>You can tell drush where to fetch the drupal core and the module but in this case it will get it from drupal.org. There are more powerful things you can do with the makefile, <a href="http://drupal.org/project/drush_make">see the docs for more info</a>.</p><p>To use this makefile and Drush to install Drupal into a web directory:</p><pre class="brush: plain; title: ; notranslate">drush make /path/to/makefile /path/to/install/dir</pre><p>This will download and explode the Drupal core and the module into a directory which will then allow you to run the install wizard by pointing a browser to it. What you most likely want however is to automatically install Drupal and get everything set up in one shot. If all you want to do is install the core and an admin user then you can stop reading here; use the <em>drupal site-install</em> command which has command-line arguments for the basic options.</p><p>Read on if you want to learn how to make additional customizations.</p><h2>Drupal Install Profiles</h2><p>The <em>standard</em> install profile is the default one that is used for a vanilla Drupal core installation. Using that profile as a starting point you can start making customizations like adding modules to the default list and you can add your own install steps. This example will create an additional user and permission role called &#8220;Content Creator.&#8221; This user will have the abilities to create new article content and some admin abilities like changing themes.</p><p>Copy the standard profile into a new one called <em>my_profile</em></p><pre class="brush: plain; title: ; notranslate">cd /path/to/install/dir cp -r profiles/standard profiles/my_profile</pre><p>In the &#8220;my_profile&#8221; directory, rename all references to the name &#8220;standard&#8221; to &#8220;my_profile.&#8221;</p><h3>my_profile.info</h3><p>The info file has key=value pairs that informs the profile which modules will be activated, add the &#8220;role_delegation&#8221; module to the list. This is necessary to activate the module on install.</p><pre class="brush: plain; title: ; notranslate">... dependencies[] = role_delegation</pre><h3>my_profile.profile</h3><p>This file can be customized to add additional install steps. We are going to add a step to ask for a username and password for an additional user who will be given the custom &#8220;content creater&#8221; user role. Add the following php code to the end of <em>my_profile.profile</em>.</p><pre class="brush: php; title: ; notranslate">... /** * Implements hook_install_tasks(). */ function my_profile_install_tasks() {$tasks = array(); // Add a page allowing the user to specify a &quot;content creator&quot; user $tasks['my_profile_cc_form'] = array( 'display_name' =&gt; st('Content creator username'), 'type' =&gt; 'form', ); return $tasks; }/** * Task callback: returns the form allowing the user to add * a &quot;content creator&quot; user */ function my_profile_cc_form() {drupal_set_title(st('Content Creator Username')); $form['cc_uid'] = array( '#type' =&gt; 'textfield', '#title' =&gt; st('Username for Content Creator:'), '#description' =&gt; st('Enter the content creator userid'), ); $form['cc_email'] = array( '#type' =&gt; 'textfield', '#title' =&gt; st('Email for Content Creator:'), '#description' =&gt; st('Enter the content creator email'), ); $form['cc_pass'] = array( '#type' =&gt; 'textfield', '#title' =&gt; st('Password for Content Creator:'), '#description' =&gt; st('Enter the content creator password in both fields'), ); $form['actions'] = array('#type' =&gt; 'actions'); $form['actions']['submit'] = array( '#type' =&gt; 'submit', '#value' =&gt; st('Create content creator role and user'), '#weight' =&gt; 15, ); return $form; }/** * Submit callback: creates the &quot;content creator&quot; role and user */ function my_profile_cc_form_submit(&amp;$form, &amp;$form_state) {$uid = $form_state['values']['cc_uid']; $email = $form_state['values']['cc_email']; $pass = $form_state['values']['cc_pass']; // Create a role for &quot;content managers&quot; $c_role = new stdClass(); $c_role-&gt;name = 'content manager'; user_role_save($c_role); // additional permissions beyond what the authenticated // user receives user_role_grant_permissions($c_role-&gt;rid, array( 'assign content manager role', 'create article content', 'edit own article content', 'delete own article content', 'create page content', 'edit own page content', 'delete own page content', 'administer themes', )); $cc_user = array ('name' =&gt; $pass, 'pass' =&gt; $pass, 'roles' =&gt; array($c_role-&gt;rid =&gt; $c_role-&gt;rid), 'mail' =&gt; $email, 'status' =&gt; 1, # status: active ); $user = user_save(NULL, $cc_user); }</pre><ul><li><strong>my_profile_install_tasks()</strong> &#8211; adds the additional install task</li><li><strong>my_profile_cc_form()</strong> &#8211; specifies the custom form to get user input</li><li><strong>my_profile_cc_form_submit()</strong> &#8211; runs when the form is submitted, creates a custom role with limited permissions and creates the user with this role assigned.</li></ul><h3>my_profile.install</h3><p>This file has php code that will run on installation, it sets up the basic views, sets the theme, etc. This can be changed or extended in whatever way you want but for this example we will stick with the standard setup.</p><p>Once this profile is created it will be available as a new option on the install wizard:</p><p style="text-align: center;"><a href="http://jarv.org/wp-content/uploads/2012/02/select_profile.png"><img class="aligncenter wp-image-1193" title="select_profile" src="http://jarv.org/wp-content/uploads/2012/02/select_profile.png" alt="" width="487" height="381" /></a></p><p>And the new custom screen to create the &#8220;content creator&#8221; user:</p><p style="text-align: center;"><a href="http://jarv.org/wp-content/uploads/2012/02/content_creator.png"><img class="aligncenter wp-image-1194" title="content_creator" src="http://jarv.org/wp-content/uploads/2012/02/content_creator.png" alt="" width="604" height="378" /></a></p><p>There are many different form elements and attributes that you can read about in the <a href="http://api.drupal.org/api/drupal/developer!topics!forms_api_reference.html/7">Drupal form api documentation</a>. For this example it would probably be better to use a <em>password_confirm</em> text input for the password but since the goal is to automate it from the commandline it doesn&#8217;t really matter.</p><h2>Automating everything from the command-line</h2><p>Now that the profile is customized instead of running through the wizard it would be nice to input everything from the command-line. To do this the <em>drush site-install</em> gives you the option of passing form parameters into the command line.</p><p>Here is what you would do to automate everything from the command-line where shell variables correspond to the &#8220;CC&#8221; (content creator) user information and admin account info.</p><pre class="brush: plain; title: ; notranslate">(create the makefile) drush make /path/to/makefile /path/to/install/dir (create the new profile) cd /path/to/install/dir drush -y site-install --clean-url=0 --db-url=sqlite:sites/default/files/db.sqlite --account-name=$ADMIN_USER --account-pass=$ADMIN_PASS --account-mail=$ADMIN_MAIL --site-mail=$SITE_MAIL my_profile my_profile_cc_form.cc_uid=$CC_USER my_profile_cc_form.cc_email=$CC_MAIL my_profile_cc_form.cc_pass=$CC_PASS</pre><p>&#8220;my_profile_cc_form&#8221; is the name of the form for the custom &#8220;Content Creator&#8221; install step and cc_uid, cc_email, and cc_pass are the parameters that entered. When that command completes you will have a fully functional site with a custom user and role.</p><p>If you something isn&#8217;t working for you I have put all of the above into<a href="https://github.com/jarv/shell-script-for-a-custom-drupal-install/blob/master/create_site.sh"> a standalone shell script</a>, simply install drush and and change the variable assignments at the top to suite your needs.</p>]]></content:encoded>
			<wfw:commentRss>http://jarv.org/2012/02/automating-drupal-7-installs-using-drush-and-install-profiles/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>A Text Analysis of Supreme Court Oral Arguments</title>
			<link>http://jarv.org/2012/02/a-text-analysis-of-supreme-court-oral-arguments/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=a-text-analysis-of-supreme-court-oral-arguments</link>
			<comments>http://jarv.org/2012/02/a-text-analysis-of-supreme-court-oral-arguments/#comments</comments>
			<pubDate>Sun, 05 Feb 2012 21:56:28 +0000</pubDate>
			<dc:creator>jarv</dc:creator>
			<category><![CDATA[Uncategorized]]></category>
			<guid isPermaLink="false">http://jarv.org/?p=1004</guid>
			<description><![CDATA[Transcripts of the Sitting Justices This post takes a look at supreme court transcripts as corpus for natural language processing. Lately I&#8217;ve been playing around with the nltk python module and I thought this might be an interesting data set (given that I&#8217;m also an avid follower of SCOTUS). Supreme Court transcripts are made available [...]]]></description>
			<content:encoded><![CDATA[<h1>Transcripts of the Sitting Justices</h1><p>This post takes a look at supreme court transcripts as corpus for natural language processing. Lately I&#8217;ve been playing around with the <a href="http://nltk.org">nltk python module</a> and I thought this might be an interesting data set (given that I&#8217;m also an avid follower of SCOTUS). </p><table style="border-spacing: 0px;"><tbody><tr><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/thomas1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/alito1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/scalia1.jpg" alt="" width="100" height="100" /></td></tr><tr><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/breyer1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/roberts1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/kennedy1.jpg" alt="" width="100" height="100" /></td></tr><tr><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/sotomayor1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/kagan1.jpg" alt="" width="100" height="100" /></td><td><img style="margin: 0px; border: 0px; padding: 0px;" title="thomas" src="http://jarv.org/wp-content/uploads/2012/02/ginsberg1.jpg" alt="" width="100" height="100" /></td></tr></tbody></table><p>Supreme Court transcripts are made available by <a href="http://www.supremecourt.gov/oral_arguments/argument_transcripts.aspx">supremecourt.gov</a> and can be downloaded in PDF form. Extracting data from the PDFs is not an exact science since the format varies a bit. I can get a majority of the cases broken up by speaker for what is available for download. The script does its best to compensate for transcription errors, typos, etc. Nothing is perfect though so it&#8217;s only useful to look at this data in the aggregate.</p><p>Click <a href="https://github.com/jarv/scotus-nltk/blob/master/by_name.tar.bz2">here</a> for transcripts by person organized by name, or here for organized by <a href="https://github.com/jarv/scotus-nltk/blob/master/by_case.tar.bz2">case</a>.</p><h2>Stats from all available transcript data</h2><table><tr><th></th><th>statements</th><th>sentences</th><th>words</th><th>stopwords</th><th>unique words</th></tr><tr><td>JUSTICE_ROBERTS</td><td>10338</td><td>21925</td><td>127500</td><td>167153</td><td>8683</td></tr><tr><td>JUSTICE_ALITO</td><td>3042</td><td>6706</td><td>51472</td><td>70438</td><td>5897</td></tr><tr><td>JUSTICE_SCALIA</td><td>11870</td><td>27347</td><td>149102</td><td>220758</td><td>9239</td></tr><tr><td>JUSTICE_THOMAS</td><td>8</td><td>19</td><td>114</td><td>169</td><td>86</td></tr><tr><td>JUSTICE_KENNEDY</td><td>6081</td><td>12686</td><td>76322</td><td>113082</td><td>7125</td></tr><tr><td>JUSTICE_BREYER</td><td>9105</td><td>31739</td><td>181260</td><td>276786</td><td>9202</td></tr><tr><td>JUSTICE_GINSBURG</td><td>7336</td><td>17898</td><td>118725</td><td>169126</td><td>8740</td></tr><tr><td>JUSTICE_KAGAN</td><td>912</td><td>2222</td><td>17048</td><td>22474</td><td>3026</td></tr><tr><td>JUSTICE_SOTOMAYOR</td><td>3263</td><td>7145</td><td>43937</td><td>63213</td><td>5277</td></tr><tr><td>other speakers</td><td>59531</td><td>185848</td><td>1552665</td><td>1952296</td><td>21500</td></tr></table><p><em>&#8220;Other speakers&#8221; are petitioners and respondents (not justices)</em><br /><em>&#8220;stopwords&#8221; are high frequency words like the, to, also, etc.</em><br /><em>&#8220;words&#8221;, &#8220;unique words&#8221; do not include &#8220;stopwords&#8221;</em></p><h2>Stats from 500 randomly selected statements</h2><table><tr><th></th><th>sentences</th><th>words</th><th>stopwords</th><th>unique words</th></tr><tr><td>JUSTICE_ROBERTS</td><td>1061</td><td>6971</td><td>7900</td><td>1952</td></tr><tr><td>JUSTICE_ALITO</td><td>1086</td><td>9563</td><td>11618</td><td>2443</td></tr><tr><td>JUSTICE_SCALIA</td><td>1146</td><td>7435</td><td>9354</td><td>1989</td></tr><tr><td>JUSTICE_KENNEDY</td><td>1045</td><td>7508</td><td>9239</td><td>2121</td></tr><tr><td>JUSTICE_BREYER</td><td>1729</td><td>11315</td><td>14582</td><td>2329</td></tr><tr><td>JUSTICE_GINSBURG</td><td>1206</td><td>9298</td><td>11493</td><td>2483</td></tr><tr><td>JUSTICE_KAGAN</td><td>1245</td><td>10867</td><td>12727</td><td>2250</td></tr><tr><td>JUSTICE_SOTOMAYOR</td><td>1150</td><td>8189</td><td>10051</td><td>2170</td></tr><tr><td>other speakers</td><td>1484</td><td>13256</td><td>15047</td><td>3178</td></tr></table><p><em>Justice Thomas is not included in the above data set because there are only 8 statements from him in the generated corpus</em><br /><em>&#8220;Other speakers&#8221; are petitioners and respondents (not justices)</em><br /><em>&#8220;stopwords&#8221; are high frequency words like the, to, also, etc.</em><br /><em>&#8220;words&#8221;, &#8220;unique words&#8221; do not include &#8220;stopwords&#8221;</em></p><div id="easyChartDiv59028001" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv59028001_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv59028001_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv59028001_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv59028001", {"type":"horizbar","width":200,"height":"90","title":"num words \/ sentences from 500 random transcript statements","minaxis":"","groupnames":"Supreme Court Justices","groupcolors":"2E2EFE","valuenames":"Roberts, Alito, Scalia, Kennedy, Breyer, Ginsburg, Kagan, Sotomayor, Other Speakers","group1values":"6.57,8.81,6.49,7.18,6.54,7.71,8.73,7.12,8.93","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>Linguistic diversity is a coarse measure of a varied vocabulary. The chart below displays the total number of unique words divided by the total number of words. </p><div id="easyChartDiv2da58002" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv2da58002_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv2da58002_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv2da58002_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv2da58002", {"type":"horizbar","width":200,"height":"90","title":"Linguistic diversity from 500 random transcript statements","minaxis":"","groupnames":"Supreme Court Justices","groupcolors":"2E2EFE","valuenames":"Roberts, Alito, Scalia, Kennedy, Breyer, Ginsburg, Kagan, Sotomayor, Other Speakers","group1values":"0.28,0.26,0.27,0.28,0.21,0.27,0.21,0.26,0.24","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>Nothing too interesting or surprising here. Justices may use less words in their sentences for a variety of reasons. This data isn&#8217;t normalized to factor out introductions or interruptions. Nevertheless the trend appears to be that Justice Kagan and Alito&#8217;s sentence lengths are longer than the others and about equal to the petitioners and respondents.</p><h3>Long words in the oral transcripts</h3><p>18 or 19 letters is the typical length for the longest words (that are in the dictionary) used by the various speakers. This includes non-sitting justices where the data was available.</p><ul><li>Justice Alito &#8211; (18) <em>misrepresentation</em></li><li>Justice Thomas &#8211; (16) <em>unconstitutional</em></li><li>Justice Kagan &#8211; (18) <em>misrepresentations</em></li><li>Justice Rehnquist &#8211; (18) <em>telecommunications</em></li><li>Justice Sotomayor &#8211; (18) <em>unconstitutionally</em></li><li>Justice Ginsberg &#8211; (18) <em>misrepresentations</em> / <em>telecommunications</em> / <em>disproportionately</em></li><li>Justice Scalia &#8211; (19) <em>unconstitutionality</em></li><li>Justice Breyer &#8211; (18) <em>representativeness</em> / <em>telecommunications</em> / <em>disproportionately</em> / <em>unconstitutionally</em><li>Other speakers &#8211; (19) <em>counterintelligence</em> / <em>unconstitutionality</em> / <em>extraterritoriality</em></li></ul><h2>Sentiment Analysis</h2><p>Sentiment analysis can yield interesting results for corpus data though in this case there is not very good training material. One of the standard data-sets used for this are movie reviews, widely available and with clear negative and positive denotations. For more information about sentiment analysis there is some good information <a href="http://text-processing.com/demo/sentiment/">here</a> and in <a href="http://streamhacker.com/2010/05/10/text-classification-sentiment-analysis-naive-bayes-classifier/">these</a> <a href="http://streamhacker.com/2010/06/16/text-classification-sentiment-analysis-eliminate-low-information-features/">two</a> articles. Applying this to oral arguments? Well let&#8217;s leave it as just one way to look at this data..</p><p><div id="easyChartDiv456d8003" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv456d8003_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv456d8003_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv456d8003_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv456d8003", {"type":"horizbar","width":200,"height":"100","title":"Sentiment analysis from 500 random statements","minaxis":"","groupnames":"pos, neg","groupcolors":"0000FF,FE2E2E","valuenames":"Roberts, Alito, Scalia, Kennedy, Breyer, Ginsburg, Kagan, Sotomayor, Other Speakers","group1values":"230,248,213,229,208,269,248,254,324","group2values":"270,252,287,271,292,231,252,246,176","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><br /><em>Justice Thomas is not included in the above data set because there are only 8 statements from him in the corpus</em><br /><em>&#8220;Other speakers&#8221; are petitioners and respondents (not justices)</em></p><p>Once the sentiment engine is trained, each statement registers as either positive or negative based on the words that match closest to the language in positive and negative movie reviews.</p><p>I&#8217;m sure the error of margin is high and without training data for similar text I would hesitate to draw any conclusions. One that I might make from this is that petitioner and respondents tend to use more positive language than the judges on the bench. If that is a valid hypothesis this data certainly seems to validate it.</p><h2>Laugh lines in the oral transcripts</h2><p>Note: there are venturesome academic papers like  <a href="http://commlawreview.org/Archives/CLRv10i2/The%20Function%20of%20Laughter%20at%20the%20U.S.%20Supreme%20Court%20CLR%20v10i2.pdf">this one</a> from the <a title="Communication Law Review" href="http://www.commlawreview.org/SSCAs_Communication_Law_Review/Welcome.html">Communication Law Review</a> that address laughter in the SCOTUS courtroom. I make no attempt to go into that depth here though my results more or less agree with previous studies on this topic.</p><p>It&#8217;s not uncommon to get laughter after a statement from the bench, this is denoated in the transcripts as either <em>[laughter]</em> or <em>(laughter)</em>. This chart displays the total number of laughter lines by sitting Judge</p><div id="easyChartDiv52258004" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv52258004_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv52258004_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv52258004_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv52258004", {"type":"horizbar","width":200,"height":"100","title":"Number of Laughter Lines in the Oral Transcripts","minaxis":"","groupnames":"Supreme Court Justices","groupcolors":"0070C0,FFFF00,FF0000,00CC00,A3A3A3,007070,00FFFF,CC7000,00CC70,CC0070,7000CC,A370CC","valuenames":"Roberts, Alito, Scalia, Kennedy, Breyer, Ginsburg, Kagan, Sotomayor","group1values":"162,24,490,84,319,21,11,5","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>As usual Thomas is excluded for generally not speaking when he sits on the bench.<br />Here is the same data but instead of the total number of <em>[Laughter]</em> lines it divides it by the number of statements for each justice.</p><div id="easyChartDiv58d88005" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv58d88005_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv58d88005_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv58d88005_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv58d88005", {"type":"horizbar","width":200,"height":"100","title":"Laughter Lines \/ Number of Spoken Lines","minaxis":"","groupnames":"Supreme Court Justices","groupcolors":"0070C0,FFFF00,FF0000,00CC00,A3A3A3,007070,00FFFF,CC7000,00CC70,CC0070,7000CC,A370CC","valuenames":"Roberts, Alito, Scalia, Kennedy, Breyer, Ginsburg, Kagan, Sotomayor","group1values":".016,.008,.041,.014,.045,.002,.002,.002","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>Justice Breyer appears to be funnier by this measure.</p><h1>Additional Notes</h1><p>Unfortunately it&#8217;s impossible to cleanly extract the argument data from PDFs. Older transcripts have the Justice&#8217;s remarks labeled as &#8220;QUESTION&#8221;; without specific name references the data had to be discarded. Some transcripts have the Justice&#8217;s name spelled incorrectly, for example: <em>JUST SCALIA</em> or <em>JUDGE SCALIA</em></p><p>Here is an example of where there is wrong attribution:</p><pre class="brush: bash; title: ; notranslate">MR. LANDAU: JUSTICE O'CONNOR: Your Honor, that is not -And I think it is conceivable that the Florida court was correct that you could draw the line some way and say contracts that are void should be handled differently.</pre><p>For this reason don&#8217;t take these results too seriously though hopefully the errors are down in the noise (I have no desire to go through and correct them).</p><p>The pdfs were parsed and the data was generated with two crufty python script, they are <a href="https://github.com/jarv/scotus-nltk">on my github</a> if you want to look at this data yourself. If you make any improvements please let me know!</p>]]></content:encoded>
									<wfw:commentRss>http://jarv.org/2012/02/a-text-analysis-of-supreme-court-oral-arguments/feed/</wfw:commentRss>
									<slash:comments>0</slash:comments>
								</item>
								<item>
									<title>Popular names from ssh break in attempts</title>
									<link>http://jarv.org/2012/02/popular-names-from-ssh-break-in-attempts/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=popular-names-from-ssh-break-in-attempts</link>
									<comments>http://jarv.org/2012/02/popular-names-from-ssh-break-in-attempts/#comments</comments>
									<pubDate>Wed, 01 Feb 2012 22:40:15 +0000</pubDate>
									<dc:creator>jarv</dc:creator>
									<category><![CDATA[Uncategorized]]></category>
									<guid isPermaLink="false">http://jarv.org/?p=1050</guid>
									<description><![CDATA[Lately I noticed that there were more than the usual amount of ssh invalid logins on a machine I manage. For kicks here is data from a script that extracts some name statistics from auth logs. These stats are compared to the male and female names contained in one of the nltk corpora. Below is [...]]]></description>
									<content:encoded><![CDATA[<p>Lately I noticed that there were more than the usual amount of ssh invalid logins on a machine I manage. For kicks here is data from a script that extracts some name statistics from auth logs. These stats are compared to the male and female names contained in one of the <a href="http://www.nltk.org/">nltk</a> corpora.<br />Below is data collected over the month of January, 2012 using authlog as my input. Over the course of a month there were over 125,000 invalid ssh attempts. </p><ul><li><strong>Total number of male name login attempts</strong>: 17,804</li><li><strong>Unique male names</strong>: 1,565</li><li><strong>Logest male names</strong>:&#160;christopher, bartholomew, constantine</li></ul><div id="easyChartDiv6f978006" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv6f978006_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv6f978006_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv6f978006_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv6f978006", {"type":"horizbar","width":200,"height":"120","title":"Male names by occurrence (top 1%)","minaxis":"","groupnames":"male names - percentage of total","groupcolors":"2E2EFE","valuenames":"michael, victor, shell, angel, adrian, adam, david, dan, robert, cyrus, john, web, alex, temp, billy","group1values":"0.44, 0.47, 0.48, 0.48, 0.48, 0.49, 0.54, 0.58, 0.59, 0.62, 0.63, 0.7, 0.99, 1.21, 1.67","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><ul><li><strong>Total number of female name login attempts</strong>: 22,483</li><li><strong>Unique female names</strong>: 2,217</li><li><strong>Logest female names</strong>:&#160;alexandrina, constantine</li></ul><div id="easyChartDiv70de8007" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv70de8007_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv70de8007_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv70de8007_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv70de8007", {"type":"horizbar","width":200,"height":"130","title":"Female names by occurrence (top 1%)","minaxis":"","groupnames":"female names - percentage of total","groupcolors":"FE2EC8","valuenames":"susan, caroline, ann, cecilia, clara, anna, chris, denise, claudia, sharon, daniel, frank, diane, kim, victoria, sarah, shell, angel, adrian, amanda, alex, billy","group1values":"0.26, 0.26, 0.26, 0.26, 0.27, 0.27, 0.27, 0.28, 0.28, 0.28, 0.28, 0.29, 0.29, 0.33, 0.34, 0.34, 0.38, 0.38, 0.38, 0.56, 0.79, 1.33","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>&#8220;billy&#8221; wins the prize; the corpus for &#8220;names&#8221; has it as both male and female. Also the corpus has &#8220;temp&#8221; as a male name which appears in the top 1% for obvious reasons.</p><p>What about all logins? For these we will just look at the top 0.1%.</p><ul><li><strong>Total number of login attempts</strong>: 125,588</li><li><strong>Unique logins</strong>: 35,627</li><li><strong>Longest login nam</strong>e:&#160;fidelu142muiesteaua8642jet184</li></ul><div id="easyChartDiv71718008" style='width:100%;' style='text-align:center;' align='center'><!-- Easy Chart Builder by dyerware --><img id="easyChartDiv71718008_img" style='text-align:center;float:center;' alt='dyerware.com' title='' align='center' border='0' /><br/><br/><INPUT type='button' value='Show/Hide Table Data' onclick='wpEasyChartToggle("easyChartDiv71718008_data");' style='text-align:center;' align='center' ><br/><div class='easyChartBuilder' id="easyChartDiv71718008_data" style='text-align:center;display:none;' align='center'></div></div><script type="text/javascript">//<![CDATA[ wpEasyChart.wpNewChart("easyChartDiv71718008", {"type":"horizbar","width":200,"height":200,"title":"All logins by occurrence (top 0.1%)","minaxis":"","groupnames":"all logins - percentage of total","groupcolors":"0070C0,FFFF00,FF0000,00CC00,A3A3A3,007070,00FFFF,CC7000,00CC70,CC0070,7000CC,A370CC","valuenames":"administrator, postmaster, students, test2, postfix, smtp, alex, www, webmaster, r00t, toor, test1, operator, temp, info, student, apache, geronimo, germany, testing, italy, billy, ts, tester, guest, server, testuser, adm, user, ftp, postgres, nagios, oracle, admin, test","group1values":"0.11, 0.11, 0.12, 0.13, 0.13, 0.13, 0.14, 0.14, 0.15, 0.15, 0.16, 0.16, 0.16, 0.17, 0.18, 0.22, 0.22, 0.23, 0.23, 0.23, 0.23, 0.24, 0.27, 0.27, 0.33, 0.34, 0.34, 0.34, 0.38, 0.4, 0.41, 0.45, 0.45, 0.71, 1.01","group2values":"0,0,0","group3values":"0,0,0","group4values":"0,0,0","group5values":"0,0,0","group6values":"0,0,0","group7values":"0,0,0","group8values":"0,0,0","group9values":"0,0,0","group10values":"0,0,0","group11values":"0,0,0","group12values":"0,0,0","group1markers":"","group2markers":"","group3markers":"","group4markers":"","group5markers":"","group6markers":"","group7markers":"","group8markers":"","group9markers":"","group10markers":"","group11markers":"","group12markers":"","markercolor":"FFFF00","imagealtattr":"dyerware.com","imagetitleattr":"","hidechartdata":false,"chartcolor":"FFFFFF","chartfadecolor":"DDDDDD","datatablecss":"hentry easyChartDataTable","imgstyle":"text-align:center;float:center;","watermark":"","watermarkvert":"","watermarkcolor":"A0BAE9","currency":"","precision":"","grid":false,"axis":"both"}); //]]&gt;</script><p>&nbsp;</p><p>Conclusion: if you name your kid <em>billy</em> or <em>test</em> make sure he uses certificate authentication.</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2012/02/popular-names-from-ssh-break-in-attempts/feed/</wfw:commentRss>
												<slash:comments>0</slash:comments>
											</item>
											<item>
												<title>Amazing Musical Giftbox</title>
												<link>http://jarv.org/2012/01/amazing-musical-giftbox/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=amazing-musical-giftbox</link>
												<comments>http://jarv.org/2012/01/amazing-musical-giftbox/#comments</comments>
												<pubDate>Tue, 24 Jan 2012 18:25:20 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=1037</guid>
												<description><![CDATA[I received mail from Piotr Zimnowlodzki last week who showed me this cool hack using the PlayTune library and my midi converter script to play &#8220;Can you feel the love tonight&#8221; an attiny. Much better than the cheap greeting card hack, amazing craftmanship!]]></description>
												<content:encoded><![CDATA[<p>I received mail from Piotr Zimnowlodzki last week who showed me this cool hack using the <a href="https://github.com/jarv/PlayTune">PlayTune library</a> and my <a href="https://github.com/jarv/PlayTune/blob/master/bin/xml2h.py">midi converter script</a> to play &#8220;Can you feel the love tonight&#8221; an attiny. Much better than the <a title="Custom musical greeting card for less than $5" href="http://jarv.org/2011/11/custom-musical-greeting-card-for-less-than-5/">cheap greeting card hack</a>, amazing craftmanship!</p><p><script type='text/javascript' src='http://jarv.org/wp-content/plugins/hana-flv-player/flowplayer3/example/flowplayer-3.2.6.min.js'></script><div ><div id='hana_flv_flow3_1' style='display:block;width:400px;height:330px;' title=""></div></div><script type='text/javascript'>flowplayer('hana_flv_flow3_1', { src: 'http://jarv.org/wp-content/plugins/hana-flv-player/flowplayer3/flowplayer-3.2.7.swf', wmode: 'transparent' }, {clip: {url: '/flv/giftbox_480x360.flv', scaling: 'scale', autoPlay: false, autoBuffering: true , onFinish : function () { this.seek(0); }} });</script></p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2012/01/amazing-musical-giftbox/feed/</wfw:commentRss>
												<slash:comments>0</slash:comments>
											</item>
											<item>
												<title>Musical Ms. Pacman Candy Tin Hack</title>
												<link>http://jarv.org/2011/12/musical-ms-pacman-candy-tin-hack/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=musical-ms-pacman-candy-tin-hack</link>
												<comments>http://jarv.org/2011/12/musical-ms-pacman-candy-tin-hack/#comments</comments>
												<pubDate>Sun, 04 Dec 2011 19:53:25 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=954</guid>
												<description><![CDATA[Here is another weekend hack that plays around with my midi to AVR conversion script and library. With xmas fast approaching I thought it would be fun to convert a pacman candy tin to an xmas ornament and have it play music. Below is the result, pressing a button on the tin will cycle through [...]]]></description>
												<content:encoded><![CDATA[<p>Here is another weekend hack that plays around with my <a href="https://github.com/jarv/PlayTune">midi to AVR conversion script and library</a>. With xmas fast approaching I thought it would be fun to convert a pacman candy tin to an xmas ornament and have it play music. Below is the result, pressing a button on the tin will cycle through three Ms. Pacman songs converted from midi files found online.</p><p><iframe width="500" height="375" src="http://www.youtube.com/embed/hyWlVr72n1M?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></p><h1>Construction</h1><p>Once I had the circuit working on a breadboard it was just a matter of finding a prototype board that fit and some ugly soldering to glue it all together. In my case I had these parts lying around (including the tin) but if you wanted to buy everything it would cost between $5-$10.</p><ul><ul><ul><li><a href="https://www.google.com/search?q=pacman+ghost+candy+tin">PacMan ghost candy tin</a></li><li>Prototype Board</li><li>A couple stand-offs and screws</li><li>Two 1k potentiometers</li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=AST-030C0MR-Rvirtualkey66500000virtualkey665-AST-030C0MR-R">Piezzo Speaker</a></li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=HU2032-LFvirtualkey61410000virtualkey614-HU2032-LF">Batter holder</a></li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=CR2032_PANASONICvirtualkey65800000virtualkey658-CR2032">Coin cell battery</a></li><li>DIP socket</li><li><a href="http://www.mouser.com/ProductDetail/Atmel/ATtiny85-20PU/?qs=sGAEpiMZZMvu0Nwh4cA1wUVlLgw9m2DP8LpB74D%2fcic%3d">ATTINY85 Microcontroller</a>(8k of flash, internal clock @ 8MHz)</li><li>Push-button switch</li></ul></ul></ul><p><a href="http://jarv.org/wp-content/uploads/2011/12/IMAG0034.jpg"><img class="aligncenter size-large wp-image-957" title="IMAG0034" src="http://jarv.org/wp-content/uploads/2011/12/IMAG0034-1024x612.jpg" alt="" width="590" height="352" /></a></p><h3>Other materials..</h3><ul><ul><ul><li>AVR SPI programmer or an <a href="http://hlt.media.mit.edu/?p=1229">Arduino to program the attiny</a></li><li>A drill with a decent bit to cut through the tin</li><li><a href="http://musescore.org/">Musescore</a> sequencing software (free)</li><li>Soldering iron, wires, a free afternoon, etc.</li></ul></ul></ul><p><a href="http://jarv.org/wp-content/uploads/2011/12/circuit1.png"><img class="aligncenter size-full wp-image-995" title="circuit" src="http://jarv.org/wp-content/uploads/2011/12/circuit1.png" alt="" width="398" height="236" /></a></p><p><a href="http://jarv.org/wp-content/uploads/2011/12/IMAG0042.jpg"><img class="aligncenter size-large wp-image-961" title="IMAG0042" src="http://jarv.org/wp-content/uploads/2011/12/IMAG0042-1024x612.jpg" alt="" width="590" height="352" /></a></p><p>The circuit is only slightly more complicated than the <a title="Custom musical greeting card for less than $5" href="http://jarv.org/2011/11/custom-musical-greeting-card-for-less-than-5/">musical greeting card</a>. Two 1K potentiometers are used to mix the two square waves into one speaker. The push switch is connected to the external interrupt pin which is set low when pressed. On the prototype board the switch is wired on the opposite side of the circuit so that the speaker faces down when placed in the candy tin. This makes it louder by drilling holes in the back piece (see below). Standoffs are used to prop up the non-speaker side of the circuit.</p><p><a href="http://jarv.org/wp-content/uploads/2011/12/IMAG0039.jpg"><img class="aligncenter size-large wp-image-962" title="IMAG0039" src="http://jarv.org/wp-content/uploads/2011/12/IMAG0039-1024x612.jpg" alt="" width="590" height="352" /></a></p><p>Nothing is needed to hold the the circuit board in the tin since the button keeps it in place and there isn&#8217;t a lot of extra room when it is put together.</p><h2>Software</h2><p>(for more on the <a href="https://github.com/jarv/PlayTune">PlayTune library</a> see my <a title="Arduino music from a midi file" href="http://jarv.org/2011/11/arduino-music-from-a-midi-file/">earlier post</a> on using the PlayTune library with an Arduino)</p><p>Like the musical greeting card we will use the PlayTune library to play the melody and the xml2h.py to handle the musical conversion. The conversion takes a single track and converts it into two byte arrays of pitches and delays. The pitch values are a function of clock frequency and the prescaler.</p><p>The total size of the program ends up being around 2k so there is plenty of room to add more songs if you are inclined.</p><p>I used three midi files for the songs and loaded them into <a href="http://musescore.org/">musescore</a>. In the application it was necessary to transpose it an octave, other than that there wasn&#8217;t much else to do since these songs are already two-tracks which is exactly what we want for the attiny.</p><p>After saving the midi file as a MusicXML file a header file is created for each song. These header files are what the PlayTune library uses for tone and delay values.</p><p><a href="http://jarv.org/wp-content/uploads/2011/12/xml2h-thechase.png"><img class="aligncenter size-full wp-image-963" title="xml2h-thechase" src="http://jarv.org/wp-content/uploads/2011/12/xml2h-thechase.png" alt="" width="655" height="400" /></a></p><p>The prescale values scale the frequency of the clock by a power of 2. Ideally you want the lowest value given in the list though TIMER0 only supports values of 1024, 256, 64 and 8 so for the first part &#8220;64&#8243; is chosen.<br />For TIMER1 (part2) the lowest number can be selected to give the highest timer resolution. The reason this is important is because the frequency of the square waves generated on the two microcontroller pins are only an approximation of the note frequency. Higher frequency == greater timer resolution == better pitch accuracy.</p><p>The AVR is immediatly put into power-down sleep mode. When an external level change on the INT0 pin is detected (button press) the ISR routine will run which will play one of the three tunes.</p><pre class="brush: cpp; title: ; notranslate">#include &lt;avr/io.h&gt; #include &lt;avr/pgmspace.h&gt; #include &lt;avr/interrupt.h&gt; #include &lt;avr/sleep.h&gt; #include &lt;util/delay.h&gt; #include &lt;avr/interrupt.h&gt; #include &quot;playtune.h&quot; #include &quot;songs/mspacman-acti-they-meet-attiny.h&quot; #include &quot;songs/mspacman-game-start-attiny.h&quot; #include &quot;songs/mspacman-actii-the-chase-attiny.h&quot; int main(void) {// setup interrupt GIMSK |= (1&lt;&lt;INT0); // INT0 enabled for interrupts while(1) {set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); }return(0); }volatile uint8_t tune = 0; ISR (INT0_vect) {PlayTune theymeet0(0,MSPACMAN_ACTI_THEY_MEET0); PlayTune theymeet1(1,MSPACMAN_ACTI_THEY_MEET1); PlayTune gamestart0(0,MSPACMAN_GAME_START0); PlayTune gamestart1(1,MSPACMAN_GAME_START1); PlayTune thechase0(0,MSPACMAN_ACTII_THE_CHASE0); PlayTune thechase1(1,MSPACMAN_ACTII_THE_CHASE1); switch(tune) {case 1: while ( theymeet0.isPlaying() || theymeet1.isPlaying() ) { theymeet0.playNote(); theymeet1.playNote(); _delay_ms(65); }break; case 2: while ( gamestart0.isPlaying() || gamestart1.isPlaying() ) { gamestart0.playNote(); gamestart1.playNote(); _delay_ms(15); }break; case 3: while ( thechase0.isPlaying() || thechase1.isPlaying() ) { thechase0.playNote(); thechase1.playNote(); _delay_ms(65); }break; }if (tune == 3) {tune = 1; } else {tune++; }}</pre>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/12/musical-ms-pacman-candy-tin-hack/feed/</wfw:commentRss>
												<slash:comments>0</slash:comments>
											</item>
											<item>
												<title>Picked up on lifehacker/hackaday</title>
												<link>http://jarv.org/2011/11/picked-up-on-lifehackerhackaday/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=picked-up-on-lifehackerhackaday</link>
												<comments>http://jarv.org/2011/11/picked-up-on-lifehackerhackaday/#comments</comments>
												<pubDate>Tue, 22 Nov 2011 22:13:27 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=944</guid>
												<description><![CDATA[Usually that number is closer to zero :)]]></description>
												<content:encoded><![CDATA[<p><a href="http://jarv.org/wp-content/uploads/2011/11/analytics1.png"><img class="aligncenter size-large wp-image-945" title="analytics1" src="http://jarv.org/wp-content/uploads/2011/11/analytics1-1024x605.png" alt="" width="590" height="348" /></a></p><p>Usually that number is closer to zero :)</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/11/picked-up-on-lifehackerhackaday/feed/</wfw:commentRss>
												<slash:comments>0</slash:comments>
											</item>
											<item>
												<title>Custom musical greeting card for less than $5</title>
												<link>http://jarv.org/2011/11/custom-musical-greeting-card-for-less-than-5/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=custom-musical-greeting-card-for-less-than-5</link>
												<comments>http://jarv.org/2011/11/custom-musical-greeting-card-for-less-than-5/#comments</comments>
												<pubDate>Sun, 20 Nov 2011 23:03:26 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=676</guid>
												<description><![CDATA[After playing around this week translating midi tracks into songs that the Arduino can play I thought that would it be interesting to see how cheap I could make a musical greeting card. &#160;These days you can pick up one at the store for about $5 that plays sampled music. If one or two part [...]]]></description>
												<content:encoded><![CDATA[<p>After <a title="Arduino music from a midi file" href="http://jarv.org/2011/11/arduino-music-from-a-midi-file/">playing around this week</a> translating midi tracks into songs that the Arduino can play I thought that would it be interesting to see how cheap I could make a musical greeting card. &#160;These days you can pick up one at the store for about $5 that plays sampled music. If one or two part square wave tones are good enough it&#8217;s doable to make one for about the same price.</p><p>Other applications? Maybe a &#8220;musical throwy&#8221;, It&#8217;s almost cheap enough :)</p><p>Here is &#8220;You&#8217;ve got a friend in me&#8221; played on an attiny85 and two speakers converted from a midi version of the song:</p><p><iframe width="250" height="188" src="http://www.youtube.com/embed/gntKQZFomi8?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe><br /><span class="Apple-style-span" style="font-size: 20px; font-weight: bold;">Materials</span></p><ul><li><a href="http://www.mouser.com/ProductDetail/Atmel/ATtiny85-20PU/?qs=sGAEpiMZZMvu0Nwh4cA1wUVlLgw9m2DP8LpB74D%2fcic%3d">Attiny85</a> &#8211; Thru-hole, no frills AVR running at 8MHz&#160;$1.62</li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=7BB-27-4L0virtualkey64800000virtualkey81-7BB-27-4L0">Piezzo speaker(s)</a> &#8211; I had some of these lying around $1.62/ea</li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=HU2032-LFvirtualkey61410000virtualkey614-HU2032-LF">Battery holder</a>&#160;- Plastic, thru-hole. &#160;$1.06</li><li><a href="http://www.mouser.com/Search/ProductDetail.aspx?R=CR2032_PANASONICvirtualkey65800000virtualkey658-CR2032">Coin cell battery</a> &#8211; You can probably find cheaper ones. &#160;$0.50</li></ul><p>Total: $4.80 (cheaper than Hallmark)</p><p>(I&#8217;m going to use two speakers for mine bringing the cost up to $6.42)</p><p><a href="http://jarv.org/wp-content/uploads/2011/11/IMAG0028.jpg"><img class="alignnone size-large wp-image-920" title="IMAG0028" src="http://jarv.org/wp-content/uploads/2011/11/IMAG0028-1024x612.jpg" alt="" width="472" height="282" /></a></p><h2>Other misc materials</h2><ul><li>Programmer for the attiny85 (<a href="http://hlt.media.mit.edu/?p=1229">you can use an Arduino if you have one</a>)</li><li>Soldering iron, solder, wires, etc</li><li>Greeting card?</li></ul><h2>Construction</h2><p><a href="http://jarv.org/wp-content/uploads/2011/11/gc1.jpg"><img class="alignleft size-medium wp-image-922" title="gc1" src="http://jarv.org/wp-content/uploads/2011/11/gc1-300x295.jpg" alt="" width="240" height="236" /></a><a href="http://jarv.org/wp-content/uploads/2011/11/gc2.jpg"><img class="alignleft size-medium wp-image-921" title="gc2" src="http://jarv.org/wp-content/uploads/2011/11/gc2-300x295.jpg" alt="" width="240" height="236" /></a></p><hr /><p>There are only 6 connections to solder, 5 if you tie black speaker wires together. &#160;I set all pins that are not being used to low to be used as ground connections. &#160;I would avoid connecting anything to the pin right beneath your +3V connection to avoid shorts.</p><p>Using a poor-man&#8217;s paper switch to complete the connection for the battery the tune only plays once and stops (the AVR is put into power-down mode after the song finishes). &#160;There is plenty more that could be done here including using more pins for LEDs, etc.</p><p>It would also be possible to mix the two outputs into one speaker with some resistors, this was easier though.</p><h2>Creating the music</h2><p>There are many places to find midi tracks, the challenge is finding one that will work for one or two parts. &#160;With <a href="http://musescore.org/">Musescore</a> you can merge multiple parts together if they don&#8217;t overlap. &#160;This example I&#8217;ll use <a href="http://jarv.org/files/gotafriend.mid">&#8220;You&#8217;ve got a friend in me&#8221;</a>, the Disney ToyStory theme-song.</p><p>First thing to do is to clean it up in musescore, copy the &#8220;<a href="https://github.com/jarv/PlayTune/blob/master/musescore/zapchords.js">zap chords</a>&#8221; plugin into your Musescore plugin directory.</p><div id="attachment_903" class="wp-caption alignnone" style="width: 514px"><img class="size-full wp-image-903 " title="gotafriend1" src="http://jarv.org/wp-content/uploads/2011/11/gotafriend1.png" alt="" width="504" height="386" /><p class="wp-caption-text">Loading the midi file in Musescore</p></div><p>After removing the chords, transposing it, increasing some note lengths in the second part and cleaning it up:</p><div id="attachment_907" class="wp-caption alignnone" style="width: 512px"><a href="http://jarv.org/wp-content/uploads/2011/11/gotafriend3.png"><img class="size-full wp-image-907 " title="gotafriend3" src="http://jarv.org/wp-content/uploads/2011/11/gotafriend3.png" alt="" width="502" height="386" /></a><p class="wp-caption-text">After running chord-zap and some transposing</p></div><p>Looks pretty, right? Now it needs to converted into something that the Attiny85 AVR chip can read.<br />To do that we will use the <a href="https://github.com/jarv/PlayTune/blob/master/bin/xml2h.py">xml2h.py</a> script to create a header file for the PlayTune library.</p><p><a href="http://jarv.org/wp-content/uploads/2011/11/gotafriend.png"><img class="size-full wp-image-915 alignnone" title="gotafriend" src="http://jarv.org/wp-content/uploads/2011/11/gotafriend.png" alt="" width="524" height="238" /></a></p><p>Unlike running this for the Arduino in the <a title="Arduino music from a midi file" href="http://jarv.org/2011/11/arduino-music-from-a-midi-file/">last post</a> we select a clock frequency of 8MHz.</p><h3>Selecting Prescaler Values</h3><p>Prescaler values of 2,4,16,32,128,512 are ONLY valid for the attiny85 TIMER1</p><p>The attiny85 has two timers each with their own prescaler value. &#160;The prescaler value is an integer clock modifier that will divide the clockspeed (in our case 8MHz) so the timer runs slower. &#160;On one hand this allows us to play lower frequencies, on the other it does not give us as much resolution resulting in less precise frequencies for the tones. &#160;In general you want to select the lowest pre-scaler value that is shown in the list that the timer supports.</p><p>For the attiny85 TIMER0 supports 1,8,64,256,1024. &#160;TIMER1 supports 1,8,16,32,64,128,256,512,1024,2048,4096</p><p>For the arduino atmega chips you should <strong>only use</strong> prescale values of 1,8,64,256,1024.</p><h2>Software</h2><p>Here is the code that plays the song using the <a href="https://github.com/jarv/PlayTune">PlayTune library</a>, you can see more details about it <a title="Arduino music from a midi file" href="http://jarv.org/2011/11/arduino-music-from-a-midi-file/">here</a>.</p><pre class="brush: cpp; title: ; notranslate">#include &lt;avr/io.h&gt; #include &lt;avr/pgmspace.h&gt; #include &lt;avr/interrupt.h&gt; #include &lt;avr/sleep.h&gt; #include &lt;util/delay.h&gt; #include &quot;playtune.h&quot; #include &quot;songs/gotafriend.h&quot; int main(void) {// set everything low that we aren't using DDRB |= (1&lt;&lt;PB2) | (1&lt;&lt;PB4) | (1&lt;&lt;PB3) | (1&lt;&lt;PB5); PORTB &amp;= ~(1&lt;&lt;PB2) | ~(1&lt;&lt;PB4) | ~(1&lt;&lt;PB3) | ~(1&lt;&lt;PB5); PlayTune p0(0,PART0); PlayTune p1(1,PART1); while ( p0.isPlaying() || p1.isPlaying() ) { p0.playNote(); p1.playNote(); _delay_ms(70); }set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); return(0); }</pre><p>After the song is finished the Attiny85 will be put to sleep in low-power mode.</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/11/custom-musical-greeting-card-for-less-than-5/feed/</wfw:commentRss>
												<slash:comments>23</slash:comments>
												<enclosure url="http://jarv.org/files/gotafriend.mid" length="0" type="audio/midi" />
											</item>
											<item>
												<title>Arduino music from a midi file</title>
												<link>http://jarv.org/2011/11/arduino-music-from-a-midi-file/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=arduino-music-from-a-midi-file</link>
												<comments>http://jarv.org/2011/11/arduino-music-from-a-midi-file/#comments</comments>
												<pubDate>Sat, 19 Nov 2011 16:32:13 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=674</guid>
												<description><![CDATA[Recently I wrote an Arduino / AVR lib and python script so that I could take three parts from a midi file and playing them simultaneously using the three Arduino timers. There are already plenty of other ways to&#160;generating tones using an Arduino. &#160; You can play music from a midi input&#160;there is a&#160;library for [...]]]></description>
												<content:encoded><![CDATA[<p>Recently I wrote an <a href="https://github.com/jarv/PlayTune">Arduino / AVR lib and python script </a>so that I could take three parts from a midi file and playing them simultaneously using the three Arduino timers.</p><p>There are already plenty of other ways to&#160;generating tones using an Arduino. &#160; You can play music from a <a href="http://arduino.cc/en/Tutorial/Midi">midi input</a>&#160;there is a&#160;<a href="http://www.arduino.cc/playground/Code/PCMAudio">library</a> for playing PCM audio and <a href="http://sealedabstract.com/code/bassdll-an-arduino-piezo-music-library/">similar projects</a> for playing music&#160;using all three Arduino timers simultaneously. I&#8217;ve also <a title="Singing Marioman" href="http://jarv.org/2009/05/singing-marioman/">played</a> <a title="Blinking motion sensor / Mario Brothers Candy Tin" href="http://jarv.org/2009/09/usb-powered-blinking-ir-motion-sensor-mounted-in-a-mario-brothers-candy-tin/">around</a> with AVR sound generation before in previous posts.</p><p><em>Note: if you just want to use the pre-generated header files in the songs/ directory you can download the lib and hook up your Arduino to a speaker to play tunes..</em></p><p><span class="Apple-style-span" style="font-size: 20px; font-weight: bold;">What you need to get started</span></p><ul><li>Arduino (or an atmega328, atmega168)</li><li>A speaker and some potentiometers to mix the inputs.</li><li>A midi file you want to convert</li><li>Python and the <a href="http://www.crummy.com/software/BeautifulSoup/">beautifulsoup</a> library for parsing xml</li><li>Sequencing software like the <a href="http://musescore.org/en/download">Musescore</a> (free) &#160;that will also convert the midi file to musicxml</li><li>&#8220;xml2h.py&#8221; which parses a musicxml file and generates a header file with notes and delays for the arduino</li><li>PlayTune library that will play the song on the atmega for any tune for up to three tracks simultaneously.</li></ul><h2>The result..</h2><table style="width: 500px;"><tbody><tr><td><iframe width="250" height="188" src="http://www.youtube.com/embed/bCZo2XlGI3k?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></td><td><iframe width="250" height="188" src="http://www.youtube.com/embed/S8czbvo_hF8?fs=1&#038;feature=oembed" frameborder="0" allowfullscreen></iframe></td></tr></tbody></table><p><span class="Apple-style-span" style="font-size: 20px; font-weight: bold;">How music is generated using an Arduino</span></p><p>On the Arduino and in general on the atmega168 and 328 there are 3 timers that operate independently of each other in hardware. &#160; The timers count up (starting at 0) to either 255 or 65535 and reset to zero. &#160;When these timers are put into &#8220;CTC&#8221; (clear on timer compare) a pin is toggled every time the counter matches a specific value called the &#8220;match value&#8221;. The speed of the timer depends on two things, one is the speed of the clock ( for the Arduino this is 16MHz ) and a clock prescaler. The &#8220;prescaler&#8221; is an integer that can be set that will slow down the timer by a factor of 1024, 256, 64, or 8. Once the timer is setup in CTC mode and a match value is specified there will be square wave generated on a pin at a frequency proportional to how frequently the timer hits the match value.</p><p><a href="http://jarv.org/files/midi-avr/arduino_all_piano_tones.html"><img class="size-medium wp-image-809 alignleft" title="tones" src="http://jarv.org/wp-content/uploads/2011/11/tones-300x233.png" alt="" width="300" height="233" /></a></p><p><a href="http://jarv.org/files/midi-avr/arduino_all_piano_tones.html">Here are the match values</a> that correspond to different pre-scalers and their corresponding piano notes at 16MHz. (This is from <a href="http://jarv.org/files/midi-avr/arduino_all_piano_tones.ods">a spreadsheet</a> I made which comes in handy especially when dealing with different clock frequencies)</p><p>Let&#8217;s start making music..</p><hr /><h2>Using the PlayTune library</h2><p>Copy <a href="https://raw.github.com/jarv/PlayTune/master/playtune.cpp">playtune.cpp</a> and <a href="https://raw.github.com/jarv/PlayTune/master/playtune.h">playtune.h</a> to a &#8220;PlayTune&#8221; directory in the libraries folder of your Arduino install. &#160;Once it&#8217;s copied there you should see it in the &#8220;import library&#8221; list under &#8220;Sketch&#8221;.</p><p>To initialize PlayTune pass into the constructor what timer you want to use, what prescaler, a list of match values and a list of corresponding delays.</p><ul><li>&#8220;isPlaying()&#8221; lets us know if there are still notes left to play for the part. When it&#8217;s finished it will reset back to the beginning.</li><li>&#8220;playNote()&#8221; will iterate over the note list, playing the tone that corresponds to the match value or a rest if zero.</li></ul><p>By default the PlayTune lib will play a scale from middle C to tenor C if you just pass in the timer you want to use.</p><p>In this example we will play the scale on all three timers simultaneously.<br />(connect your speaker to pins 6,9 and 11)</p><pre class="brush: cpp; title: ; notranslate">#include #include void setup(void) {PlayTune p0(0); PlayTune p1(1); PlayTune p2(2); while (p0.isPlaying() || p1.isPlaying() || p2.isPlaying() ) { p0.playNote(); p1.playNote(); p2.playNote(); _delay_ms(500); }} void loop(void) {}</pre><p><em>Note that the _delay_ms(500) function requires the additional include of util/delay.h.</em></p><p><strong>Do not use the Arduino &#8220;delay()&#8221; function! </strong>It will cause problems because it uses TIMER0 which is being used by the lib for generating the tone.</p><p>So that was fun (but boring).. Now on to creating some more interesting music&#8230;</p><h2>Midi, musescore and xml2h.py</h2><p>Musescore is a wonderful free sequencing tool. Using that you can open midi files, adjust them, and convert them to musicxml.</p><p>&#8220;xml2h.py&#8221; is a script I wrote that takes a musicxml file and generates an header file that tracks two arrays for up to 3 parts, one for note values and another for delays (rests are note values equal to zero)</p><p>The conversion from midi to arduino tones is a bit of a hack :/<br />xml2h.py will do its best to:</p><ul><li>pick the best prescaler</li><li>ignore chords</li><li>combine voices if it can</li><li>handle tied notes</li></ul><p>I&#8217;ll walk through a video game theme as an example (it works well since the songs are simple). There are a number of sites out there with video game midi files most of them look like they were designed in 1997. Below I&#8217;ll use the <a href="http://jarv.org/files/midi-avr/smb1-Theme.mid">Super Mario Brothers theme</a>. In this score there are 4 parts, we will convert the first three to play on the Arduino.</p><div id="attachment_857" class="wp-caption aligncenter" style="width: 603px"><a href="http://jarv.org/wp-content/uploads/2011/11/smb.png"><img class="size-full wp-image-857 " title="smb" src="http://jarv.org/wp-content/uploads/2011/11/smb.png" alt="" width="593" height="352" /></a><p class="wp-caption-text">SMB theme in Musescore</p></div><p>There are some limitations to keep in mind for the midi conversion:</p><ul><li>If notes span multiple clefs then you there will probably be too large a range for the resolution of the timer, not many (simple) songs have this problem though.</li><li>When you convert you will need to select between 1-3 parts to be played simultaneously.</li><li>Chords will be ignored by the xml2h.py script.</li><li>If there are more than voice on a part the script will try to merge them together.</li></ul><p>I wrote a plugin called &#8220;<a href="https://github.com/jarv/PlayTune/raw/master/musescore/zapchords.js">chord zapper</a>&#8221; for musescore that will (attempt to) remove all the chords. Copy this to the musescore plugin folder, select all, run the plugin to get rid of all the chords if you want to get a better sense of how the song will sound when converted. Whether or not you remove chords the &#8220;xml2h.py&#8221; script will ignore them, taking the top note in the chord if there are any.</p><div id="attachment_819" class="wp-caption aligncenter" style="width: 310px"><a href="http://jarv.org/wp-content/uploads/2011/11/zapchords.png"><img class="size-medium wp-image-819 " title="zapchords" src="http://jarv.org/wp-content/uploads/2011/11/zapchords-300x240.png" alt="" width="300" height="240" /></a><p class="wp-caption-text">zapping all the chords (optional)</p></div><p><a href="http://jarv.org/wp-content/uploads/2011/11/zelda_ow.png"><br /></a></p><p>When you are satisfied save the midi file save it as a &#8220;MusicXML&#8221; file and run it through xml2h.py.<br />The script takes the xml plus the name of the header file you want to write out.</p><p>For example:</p><p style="text-align: center;"><a href="http://jarv.org/wp-content/uploads/2011/11/smb1.png"><img class="aligncenter size-full wp-image-879" title="smb" src="http://jarv.org/wp-content/uploads/2011/11/smb1.png" alt="" width="524" height="280" /></a></p><p>Pick the clock frequency. This defaults to 16MHz which is what you want for the Arduino<br />Pick the part you wish to process (part0 corresponds to the top clef in the midi file)<br />Pick the prescaler, the script will give you a subset of prescalers, you should select the lowest one that is supported. (see note on prescalers below)</p><p>If it finishes without error you will end up with a header file that contains some arrays and macros for passing them into the PlayTune constructor.</p><p><a href="https://raw.github.com/jarv/PlayTune/master/songs/smb.h">Here is what the resulting header looks like</a>, the macros for PART1, PART2, PART3 are used in the sketch below:</p><pre class="brush: cpp; title: ; notranslate">#include #include #include void setup(void) {PlayTune p0(0,PART0); PlayTune p1(1,PART1); PlayTune p2(2,PART2); while (p0.isPlaying() || p1.isPlaying() || p2.isPlaying() ) { p0.playNote(); p1.playNote(); p2.playNote(); _delay_ms(50); }} void loop(void) {}</pre><h2><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">Assuming you are converting two parts and the first part will be using Timer0 and the second part Timer1 pick the lowest value from the two sets that show up in the prescaler selection.</span></h2><p>The only difference between this sketch and the last one is the additional include for the &#8220;smb.h&#8221; header file, the addition of the PART# macros used in the PlayTune constructors and a smaller delay.</p><p>The value of the delay will determine the tempo of the song and corresponds to the delay between each tick in the MusicXML file or the shortest note. &#160;Usually this is either 1/32 or 1/64.</p><p><span class="Apple-style-span" style="font-size: 13px; font-weight: normal;">If you have questions about the lib or if you create more songs <a title="About" href="http://jarv.org/about/">let me know</a>and I will add them to collection.</span></p><h2>Selecting Prescalers</h2><p>In general you want to select a low value for a prescaler to give you the highest resolution (to match the pitch of the song as close as possible).<br />The two timers on the attiny support different prescalers though so you need to be aware of what timer you are using (0 or 1) and what prescalers it supports.</p><p><strong>Timer0</strong> supports: &#160;1024, 256, 64, 8<br /><strong>Timer1</strong> supports: 1024,512,256,128,64,32,16,8</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/11/arduino-music-from-a-midi-file/feed/</wfw:commentRss>
												<slash:comments>10</slash:comments>
												<enclosure url="http://jarv.org/files/midi-avr/smb1-Theme.mid" length="10498" type="audio/midi" />
											</item>
											<item>
												<title>Building the AVR toolchain on Linux</title>
												<link>http://jarv.org/2011/11/avr-development-on-linux/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=avr-development-on-linux</link>
												<comments>http://jarv.org/2011/11/avr-development-on-linux/#comments</comments>
												<pubDate>Wed, 16 Nov 2011 14:42:54 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=304</guid>
												<description><![CDATA[Since I recently needed to rebuild my environment I&#8217;m going take notes as I go for anyone else going through the same pain. There are a few other guides out there already for this, I&#8217;ll just add this one to the pile. This assumes you want to program an AVR microcontroller with gcc and use [...]]]></description>
												<content:encoded><![CDATA[<p>Since I recently needed to rebuild my environment I&#8217;m going take notes as I go for anyone else going through the same pain.</p><p>There are a few other guides out there already for this, I&#8217;ll just add this one to the pile. This assumes you want to program an AVR microcontroller with gcc and use something like the USBtiny or another programmer that AVRDude supports.</p><p>Everything you need will be installed in your home directory.</p><p>I&#8217;ll be building this on a debian box so I&#8217;ll assume you have apt to prime your build environment. No reason why the same can&#8217;t be done using another distro.</p><h1>Installing the avr toolchain</h1><pre class="brush: plain; title: ; notranslate">mkdir ~/src # for everything sudo apt-get install build-essential texinfo # for avrdude sudo apt-get install flex byacc libusb-dev # for gdb sudo apt-get install libncurses5-dev # for simulavrxx sudo apt-get install tcl-dev cvs autoconf \libtool swig g++ zlib1g-dev texlive-base</pre><h2>Setup search paths</h2><pre class="brush: plain; title: ; notranslate">export PATH=$HOME/bin:$PATH export C_INCLUDE_PATH=$HOME/include export LIBRARY_PATH=$HOME/lib export LD_LIBRARY_PATH=$HOME/lib</pre><p><strong>IMPORTANT</strong>: <em>If you have other versions of gmp and mpfr installed and you don&#8217;t set these variables you will certainly run into issues. </em></p><h2>Compile and install binutils</h2><p>Download the latest version of bintools:<br /><a href="http://ftp.gnu.org/gnu/binutils/?C=M;O=D">http://ftp.gnu.org/gnu/binutils/?C=M;O=D</a></p><pre class="brush: plain; title: ; notranslate">cd ~/src wget http://ftp.gnu.org/gnu/binutils/binutils-2.19.1a.tar.bz2 tar jxvf binutils-2.19.1a.tar.bz2 cd binutils-2.19.1/ ./configure --prefix=$HOME --target=avr \--enable-install-libbfd --disable-werror make &amp;&amp; make install</pre><h2>Compile and install gmp/mpfr/mpc</h2><p>Download the latest gmp/mpfr/mpc from</p><p><a href="ftp://gcc.gnu.org/pub/gcc/infrastructure/">ftp://gcc.gnu.org/pub/gcc/infrastructure/</a></p><pre class="brush: plain; title: ; notranslate">cd ~/src wget ftp://gcc.gnu.org/pub/gcc/infrastructure/gmp-4.3.2.tar.bz2 tar jxvf gmp-4.3.2.tar.bz2 cd gmp-4.3.2/ ./configure --prefix=$HOME make &amp;&amp; make install cd ~/src wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpfr-2.4.2.tar.bz2 tar jxvf mpfr-2.4.2.tar.bz2 ./configure --prefix=$HOME make &amp;&amp; make install cd ~/src wget ftp://gcc.gnu.org/pub/gcc/infrastructure/mpc-0.8.1.tar.gz tar zxvf mpc-0.8.1.tar.gz cd mpc-0.8.1 ./configure --prefix=$HOME make &amp;&amp; make install</pre><h2>Compile and install gcc</h2><p>Grab the latest GCC source from<br /><a href="ftp://ftp.gnu.org/gnu/gcc">ftp://ftp.gnu.org/gnu/gcc</a></p><p><em><br /></em></p><pre class="brush: plain; title: ; notranslate">wget ftp://ftp.gnu.org/gnu/gcc/gcc-4.3.6/gcc-4.3.6.tar.gz tar zxvf gcc-core-4.3.6.tar.bz2 mkdir gcc-4.3.6/build cd gcc-4.3.6/build ../configure --target=avr --prefix=$HOME \--disable-nsl --enable-languages=c,c++ \--disable-libssp make &amp;&amp; make install</pre><h2>Compile and install avr-libc</h2><p>Grab the latest avr-libc from</p><p><em><a href="http://download.savannah.gnu.org/releases/avr-libc/">http://download.savannah.gnu.org/releases/avr-libc/</a></em></p><p><em>I downloaded the latest out of CVS since there was a bug in 1.7.1.</em></p><pre class="brush: plain; title: ; notranslate">cd ~/src wget \http://download.savannah.gnu.org/releases/avr-libc/avr-libc-1.7.2rc2252.tar.bz2 tar jxvf avr-libc-1.7.2rc2252.tar.bz2 mkdir avr-libc-1.7.2rc2252/build cd avr-libc-1.7.2rc2252/build export CC=avr-gcc ../configure --build=`../config.guess` --host=avr --prefix=$HOME make &amp;&amp; make install</pre><h2>Compile and install avrdude</h2><p>Grab the latest avrdude from</p><p><a href="http://nongnu.askapache.com/avrdude/">http://nongnu.askapache.com/avrdude/</a></p><pre class="brush: plain; title: ; notranslate">cd ~/src wget http://nongnu.askapache.com/avrdude/avrdude-5.10.tar.gz tar zxvf avrdude-5.10.tar.gz cd avrdude-5.10 export CC=gcc ./configure --prefix=$HOME make &amp;&amp; make install</pre><h2>Compile and install gdb</h2><p>Grab the latest gdb from</p><p><a href="http://ftp.gnu.org/gnu/gdb/">http://ftp.gnu.org/gnu/gdb/</a></p><pre class="brush: plain; title: ; notranslate">cd ~/src wget http://ftp.gnu.org/gnu/gdb/gdb-7.3.1.tar.bz2 tar jxvf gdb-7.3.1.tar.bz2 cd gdb-7.3.1/ export CC=gcc ./configure --target=avr --prefix=$HOME \--disable-werror make &amp;&amp; make install</pre><h2>Compile and install SimulAVR</h2><p>Grab the latest SimulAVR from</p><p><a href="http://savannah.nongnu.org/projects/simulavr/">http://savannah.nongnu.org/projects/simulavr/</a></p><pre class="brush: plain; title: ; notranslate">cd ~/src git clone git://git.savannah.nongnu.org/simulavr.git cd simulavr ./bootstrap ./configure --prefix=$HOME --with-bfd=$HOME make &amp;&amp; make install</pre><h1>Makefile template</h1><p>Now that all of the tools are installed you will need to put together a makefile. The path of least resistance is to use a <a href="http://electrons.psychogenic.com/modules/arms/view.php?w=art&amp;idx=8&amp;page=2">template</a>, modify it to suite your needs and go. Happy Coding!</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/11/avr-development-on-linux/feed/</wfw:commentRss>
												<slash:comments>0</slash:comments>
											</item>
											<item>
												<title>Django 1.3 / JQuery tutorial &#8211; Making a flashcard game (Part 4)</title>
												<link>http://jarv.org/2011/10/django-jquery-tutorial-part4/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=django-jquery-tutorial-part4</link>
												<comments>http://jarv.org/2011/10/django-jquery-tutorial-part4/#comments</comments>
												<pubDate>Fri, 14 Oct 2011 02:23:58 +0000</pubDate>
												<dc:creator>jarv</dc:creator>
												<category><![CDATA[Uncategorized]]></category>
												<guid isPermaLink="false">http://jarv.org/?p=525</guid>
												<description><![CDATA[So far we&#8217;ve discussed setting up Django, defining models and views and setting up templates. The last part of this tutorial will cover JQuery/javascript used to dynamically generate questions and answers, and to control the game flow using AJAX calls. All of the custom javascript for the site is contained in a single js file [...]]]></description>
												<content:encoded><![CDATA[<p>So far we&#8217;ve discussed <a href="http://jarv.org/2011/10/django-jquery-tutorial-part1/" title="Django 1.3 / JQuery tutorial - Making a flashcard game (Part 1)">setting up Django</a>, <a href="http://jarv.org/2011/10/django-jquery-tutorial-part2/" title="Django 1.3 / JQuery tutorial - Making a flashcard game (Part 2)">defining models and views</a> and <a href="http://jarv.org/2011/10/django-jquery-tutorial-part3/" title="Django 1.3 / JQuery tutorial - Making a flashcard game (Part 3)">setting up templates</a>.<br />The last part of this tutorial will cover JQuery/javascript used to dynamically generate questions and answers, and to control the game flow using AJAX calls.</p><p>All of the custom javascript for the site is contained in a single js file that is loaded as a Django template. The reason for loading it as a template rather than as a static file is so that we can reference the STATIC_PREFIX location for static files as well as some other template goodies like dynamically referencing URLs. If we ever change where our static files are stored or decide on a different URL naming scheme they will be updated in the javascript dynamically.</p><h1>JQuery Introduction</h1><p>JQuery is a javascript library that that helps with some of the cross-browser compatibility issues that are common when writing javascript. It also handles the visual effects on the page and provides AJAX request methods for dynamic updates.</p><p>The js file for the JQuery and JQuery-UI libraries need to be included in the base template after it is copied to the static file directory. The UI library is an extension of the base JQuery library and is used specifically for the &#8220;puff&#8221; animation that happens when you select an answer.</p><p><a href="https://github.com/jarv/wordconfuse/blob/master/templates/base.html">wordconfuse/templates/base.html</a>:</p><pre class="brush: xml; title: ; notranslate">&lt;script src=&quot;{{ STATIC_PREFIX }}js/jquery-1.5.1.min.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt; &lt;script src=&quot;{{ STATIC_PREFIX }}js/jquery-ui-1.8.9.custom.min.js&quot; type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;&lt;/script&gt;</pre><p>There are a number of JQuery functions that are used in the app:</p><ul><li><a href="http://api.jquery.com/jQuery.each/">jQuery.each()</a> &#8211; used to iterate through a collection of objects</li><li><a href="http://api.jquery.com/jQuery.ajax/">jQuery.ajax</a> &#8211; for all AJAX posts and requests made to the server</li><li><a href="http://api.jquery.com/fadeOut/">fadeout</a> / <a href="http://api.jquery.com/fadeIn/">fadein</a> / <a href="http://api.jquery.com/show/">show</a> / <a href="http://api.jquery.com/hide/">hide</a> &#8211; used for all the fade-in and fade-out animation and to hide and show the various game screens</li><li><a href="http://docs.jquery.com/UI/Effects/Puff">puff</a> &#8211; UI effect when a definition is clicked</li><li><a href="http://api.jquery.com/click/">click</a> &#8211; setup click handlers for buttons and links</li><li><a href="http://api.jquery.com/html/">html</a> &#8211; dynamically update html on the page</li><li><a href="http://api.jquery.com/animate/">animate</a> &#8211; used to move the correct definition after selection</li></ul><p>Some javascript built-ins are used to handle the delays and timer for the game:</p><ul><li> <a href="https://developer.mozilla.org/en/DOM/window.setTimeout">setTimout</a> &#8211; Used to add delays between events on the screen</li><li> <a href="https://developer.mozilla.org/en/DOM/window.setInterval">setInterval</a> &#8211; Called once per turn to update the countdown timer and so we know when the player has run out of time.</li><li> <a href="https://developer.mozilla.org/en/DOM/window.clearInterval">clearInterval</a> &#8211; Stops the counter setup by setInterval and is called multiple times both when the player runs out of time and when when he clicks one of the answers. </li></ul><h2>Some general javascript/JQuery tips</h2><p>If you are coming to javascript/jquery from other languages there are a couple things that are essential to before jumping in.</p><ul><li><strong>javascript uses function level scoping, not block level scoping</strong></p><p>How many derps does this (awful) code print to the console?</p><pre class="brush: java; title: ; notranslate">for (var i=0; i&lt;10; i++) {for (var i=0; i&lt;10; i++) {console.log(i + &quot;derp&quot;); }}</pre><p>If you guessed &#8220;10 derps&#8221;, you are correct. The variable &#8220;i&#8221; in both loops share the same scope. Don&#8217;t re-use variable (object) names inside a function. Objects in a function share the same namespace.</li><li><strong>JQuery calls are asynchronous most of the time</strong></p><p>It&#8217;s a common pattern in JQuery to fade something out, update content, and fade it back in.<br />Say the content we want to fade out and fade in is between the following div tag:</p><pre class="brush: xml; title: ; notranslate">&lt;div class=&quot;foo&quot;&gt; ... &lt;/div&gt;</pre><p>An intuitive procedural approach to doing this might be:</p><pre class="brush: java; title: ; notranslate">$(&quot;.foo&quot;).fadeOut('slow'); $(&quot;.foo&quot;).fadeIn('slow'); $(&quot;.foo&quot;).html('herp derp');</pre><p>Calls are asynchronous so our &#8220;foo&#8221; div will be fading out, fading in, and herp derp&#8217;ing all at the same time! That&#8217;s probably not what you want.  </p><p>Instead, you should do this:</p><pre class="brush: java; title: ; notranslate">$(&quot;.foo&quot;).fadeOut('slow', function() {$(&quot;.foo&quot;).fadeIn('slow', function() {$(&quot;.foo&quot;).html('herp derp'); }}</pre><p>By using these closures as callbacks to the fade functions we can be sure that everything is executed in the proper order.</li></ul><p>Another common pattern is to display some text, wait X number of seconds and then do something else. There isn&#8217;t a sleep() function in javascript otherwise we would be blocking the execution such that the browser would stop responding to updates. Use the <a href="https://developer.mozilla.org/en/DOM/window.setTimeout">setTimeout()</a> function which takes a function reference as a callback. You will see this in the WordConfusion javascript code whenever a delay is needed in the game.</p><pre class="brush: java; title: ; notranslate">$(&quot;.foo&quot;).html(&quot;herp&quot;); setTimeout(derp, 500); function derp() {$(&quot;.foo&quot;).html(&quot;derp&quot;); }</pre><h1> The code for WordConfusion </h1><h2> Page loading, the spash screen </h2><p>The function passed in to the jquery <a href="http://api.jquery.com/ready/">$(document).ready()</a> function will execute code when the browser makes a new request to document root.</p><pre class="brush: java; title: ; notranslate">var gameover = { ... }var high_scores = { ... }var game = { ... }$(document).ready(function() {if (typeof console == &quot;undefined&quot;) {console = { log: function() {} }; }// on the main page load we show the splash screen // and register start and highscores for clicks $('.new').click( function() {$('.splash').fadeOut( '1000', function() {game.startGame(); }); }); $('.highscores').click( function() {$('.splash').fadeOut( '1000', function() {high_scores.showscores(); }); }); $('.splash').fadeIn('500'); });</pre><p>The first thing that&#8217;s being done on the load is to make sure console logging is off if there isn&#8217;t a console connected. Next we set up two click handlers for highscores and starting a new game. Finally, the last line in the fades in the spash screen giving the user the option of starting a new game or viewing the highscores. At this point code execution stops and waits for the user to click one of the buttons.</p><p>Above the code <strong>$(document).ready()</strong> are the objects that hold the code for the game logic, these objects for <strong>gameover</strong>, <strong>high_scores</strong> and <strong>game</strong> and are the only ones in the global namespace. The rest of this tutorial will talk about each of these objects and the code in them for handling the screens and game logic.</p><h2>Displaying the highscore screen</h2><p>Displaying the highscore table will be the simplest code path so it&#8217;s probably a good place to start. When the user clicks the high_score button the showscores() function will run.</p><pre class="brush: java; title: ; notranslate">var high_scores = { showscores: function() {$.ajax({ url: '{% url hs %}', cache: 'false', dataType: 'html', async: 'false', success: function(data) {$('.hs').show(); $('.hs-content').html(data); $('.playagain').click(function() {$('.hs').fadeOut('slow', function() {game.startGame(); }); }); }, error: function() {console.log(&quot;ERROR: hs&quot;); }, }); }}</pre><p>First notable thing in this javascript code is some Django syntax. The <strong>{% url hs %}</strong> is Django template syntax for the URL corresponding to the highscore view. If the URL corresponding to that view ever changes the javascript will be updated dynamically.</p><p>The showscores() function executes a <a href="http://api.jquery.com/jQuery.ajax/">jquery ajax call</a> which sends a get request from the browser (without re-loading the full page). The results of this request are put in the <strong>data</strong> variable which is displayed between the div tags that have the &#8220;hs-content&#8221; class by <strong>$(&#8216;.hs-content&#8217;).html(data)</strong>.<br />Remember the div tags with the &#8220;hs-content&#8221; class is in the  <a ref="https://github.com/jarv/wordconfuse/blob/master/templates/index.html">index.html</a> template described in <a href="http://jarv.org/2011/10/django-jquery-tutorial-part3/" title="Django 1.3 / JQuery tutorial - Making a flashcard game (Part 3)">part 3</a> of the tutorial.</p><pre class="brush: xml; title: ; notranslate">&lt;div class=&quot;hs-content&quot;&gt; ... &lt;/div&gt; ^ the html returned by the &quot;hs&quot; view will be inserted here</pre><h2>Displaying the main game screen</h2><h3>Setting up the game </h3><pre class="brush: java; title: ; notranslate">var game = { ... ROUNDS: 10, ANSWERS: 4, TURNTIME: 9, startGame: function() {this.s=null; //setInterval (for the countdown timer) this.turn=1; // turn count this.sec_left=null; // number of seconds left for the countdown timer this.wd= null; // current word group in quiz this.count=0; // number of correct answers this.submitted = true; // setup click handlers for answers $('.ab').each( function() {$(this).click( game.answer_click ); }); // grab the word list $.ajax({ url: '{% url get_words %}', cache: 'false', dataType: 'json', async: 'false', success: function(data) {game.wl = data; // preload images jQuery.each(game.wl, function(index,value) {var objImage = new Image(); objImage.src ='{{STATIC_PREFIX}}img/words/'+value['q']+'.png'; if (index == game.wl.length - 1) {// last image has loaded game.new_turn(); }}); }, error: function() {console.log(&quot;ERROR: get_words&quot;); }, }); }, ...</pre><p>The startgame function sets up the game. When a new game starts some variables that are local to the game object are created. The names should be self explanatory but the following deserve some additional explanation:</p><ul><li><strong>sec_left</strong> &#8211; Within the game object this will keep track of the total number of seconds left per turn, currently this is configured to count 9 seconds.</li><li><strong>wd</strong> &#8211; When a request is made to get a new list of words by hitting the <a href="http://wordconfusion.com/get_words">get_words URL</a> this variable will contain the current word information as the game iterates through the list.</li><li><strong>count</strong> &#8211; This will track the total number of correct answers which is posted to the server when the game is over.</li><li><strong>submitted</strong> &#8211; This variable that is global to the game object will be set to true as soon as an answer is selected or when there is no more time left for the current turn. This is so that the code can make sure the user doesn&#8217;t submit an answer twice. After an answer is clicked or time has run out it will be set back to False when the next word and definitions are shown</li></ul><p>After some variables that are global to the game object are initialized, click handlers are setup for the answers.</p><pre class="brush: java; title: ; notranslate">$('.ab').each( function() {$(this).click( game.answer_click ); });</pre><p>For every div block in the index.html template that has the &#8220;.ab&#8221; class, a click will execute code referenced by <strong>game.answer_click</strong>.</p><p>The last setup task is to fetch the word data and put it into the <strong>wl</strong> variable which is global to the game object. Once the data is fetched the code iterates through the <strong>wl</strong> object and caches all the images so they are displayed in a timely manner as the game runs. When the last image is cached the code in game.newturn is called to begin the game.</p><h3>Starting the Game </h3><pre class="brush: java; title: ; notranslate">new_turn: function() {$('.nt').hide(); clearInterval(game.s); if (game.turn &gt; game.ROUNDS) {console.log('game over'); $('#a0').unbind(); $('#a1').unbind(); $('#a2').unbind(); $('#a3').unbind(); game_over.showscreen(); } else {$('.game-questions').fadeOut( 'slow', function() {$('.game-info').html('Turn ' + game.turn + ' / 10'); game.wd = game.wl[game.turn-1]; time = game.unix_time(); game.sec_left = game.TURNTIME; $('.ct').html(game.sec_left); game.s = setInterval( function() {if (game.sec_left &lt;= 1) {if (game.submitted) {return false; } else {game.submitted = true; }clearInterval(game.s); // stop the countdown timer $('.nt').css({ 'backgroundImage': 'url(&quot;{{STATIC_PREFIX}}img/outoftime.png&quot;)', }); $('.nt').fadeIn('slow',function() {game.show_answer(); }); } else {game.sec_left = game.TURNTIME - (game.unix_time() - time); if (game.sec_left &gt;= 1) {// just to be paranoid.. $('.ct').html(game.sec_left); }} }, 1000); $('.qb').html('&lt;img src=&quot;{{STATIC_PREFIX}}img/words/' + game.wd['q'] + '.png&quot; /&gt;'); // reset the answer board $('.ab').each( function() {$(this).removeAttr(&quot;style&quot;); }); for (var j=0; j&lt;game.ANSWERS; j++) {$('div#a' + j + ' .answer').html('&lt;p&gt;' + game.wd['a'][j] + '&lt;/p&gt;'); }$('.game-questions').fadeIn( 'slow', function() {$('.game').fadeIn('500'); // for the first time game.submitted = false; // finally we allow clicks }); game.turn++; }); }}, unix_time: function() {return Math.floor(new Date().getTime() / 1000); }, }</pre><p>The new_turn function is called 10 times, once for every turn. If there are still rounds left in the game it will update the board with the definition, answers and set up a timer for the turn. If there are no rounds left it will end the game and call the show_screen function in the game_over object.</p><p>When a new game is started a few things are done:</p><ul><li>The <strong> game.wd = game.wl[game.turn-1];</strong> takes the list of word data that was fetched earlier from the <a href="http://wordconfusion.com/get_words">URL get_words</a> and puts it in the <strong>wd</strong> object which will be used for the current turn.</li><li><strong>game.s = setInterval( function() {&#8230;},1000 )</strong> will execute code every second to update the countdown timer and check to see if there is any time left. One important thing to note in this code is that it uses the system clock, and doesn&#8217;t rely on setInterval for the time. This is a more accurate way to track of time on the browser since if the browser is busying doing other things the function may not run precisely every wall-clock second</li><li>After the interval is set the board needs to be updated with the words and definitions for the current turn data in the <strong>wd</strong> object. Iterating through the question boxes for the words and the answer boxes for the definitions the appropriate images and text are faded in so that the user can select an answer.</li></ul><h3>Clicking on an answer</h3><pre class="brush: java; title: ; notranslate">answer_click: function () {if (game.submitted) {return false; } else {game.submitted = true; }// check to see if the word is correct id = $(this).attr('id'); if (id == 'a' + game.wd['s']) {clearInterval(game.s); // stop the countdown timer game.count++; // increase the correct answer count $(this).css({ 'opacity' : '.6', 'background' : '#3366cc', }); $('.nt').css({ 'backgroundImage': 'url(&quot;{{STATIC_PREFIX}}img/goodjob.png&quot;)', }); $('.nt').fadeIn('slow',function() {setTimeout(game.show_answer, 300); }); } else {$('.nt').css({ 'backgroundImage': 'url(&quot;{{STATIC_PREFIX}}img/wronganswer.png&quot;)', }); $('.nt').fadeIn('slow',function() {setTimeout(game.show_answer, 300); }); }},</pre><p>This is the code that is executed (via the click handler that was setup in startGame) when a player clicks on a defintion. The first if-else in this function is an important check to make sure that an answer wasn&#8217;t already clicked. If it was then we just return from it without doing anything.</p><p>The rest of this function checks the answer that was clicked against the answer that was read in from the get_words data. If it matches a &#8220;good job&#8221; is displayed on the screen and the show_answer function is called after about 300ms. If it doesn&#8217;t match a &#8220;wrong answer&#8221; is displayed and the show_answer function is also called. If the answer is correct the variable <strong>count</strong> (global to the game object) is incremented by 1. This keeps track of the number of correct answers. </p><h3>Ending the turn, showing the correct answer</h3><pre class="brush: java; title: ; notranslate">show_answer: function () {clearInterval(game.s); // stop the countdown timer // reset opacity $('.ab').each( function() {$(this).removeAttr(&quot;style&quot;); }); var wrong_answers = []; for (var cnt=0; cnt &lt; game.ANSWERS; cnt++) {if (cnt != game.wd['s']) {wrong_answers.push(cnt); }} jQuery.each(wrong_answers, function(index,value) {$('#a' + value).hide(&quot;puff&quot;,{},'1000', function() {if (index==wrong_answers.length-1) {//last wrong answer has faded out, //now move the correct one var pos0 = $('#a' + game.wd['s']).position(); // change the style $('#a' + game.wd['s']).css({ position: 'absolute', top: pos0.top, }).animate( {top: 160, left: 135, }, 500,function() {setTimeout(game.new_turn,900); }); }}); }); },</pre><p>At end of every turn this function is called to clear out the wrong answers (whether or not the player clicked the correct one) and display the correct one. After the wrong answers are cleared using the <a href="http://docs.jquery.com/UI/Effects/Puff">JQuery UI &#8220;puff&#8221; effect</a> and the correct answer is moved to the center using the <a href="http://api.jquery.com/animate/">JQuery animate effect</a>. The new_turn function will be called again after 900ms to setup the board for the next word and definitions.  </p><h3>GameOver</h3><p>There are two functions for the game_over object, one for posting the data to the game_over url and another for setting up the click handlers for when a new highscore is created. Starting with the showscreen function:</p><pre class="brush: java; title: ; notranslate">var game_over = { ... showscreen: function() {$('.game').fadeOut('slow', function() {$.ajax({ url: &quot;{% url gameover %}&quot;, data: {'count': game.count }, type: 'post', async: 'false', success: function(data) {$('.gameover').show(); $('.gameover').html(data); game_over.button_events(); }, error: function () {console.log(&quot;ERROR: gameover&quot;); }, }); }); }, ...</pre><p>After the main game board fades out using the <a href="http://api.jquery.com/fadeOut/">JQuery fadeout function</a> an AJAX request is sent to the gameover URL containing post data for the number of words that were answered correctly. The request to the gameover URL will return html giving the player his score, the current highscores and a option to submit his name if he rates the high score table.<br />Once the html is displayed between the div tags in index.html with the &#8220;gameover&#8221; class, button_events() is called to set upt the click handlers for playing a new game and submitting a highscore.</p><pre class="brush: java; title: ; notranslate">button_events: function() {$('.playagain').click(function() {console.log(&quot;restarting game&quot;); $('.gameover').fadeOut('slow', function() {game.startGame(); }); }); $('.hs_submit').click(function() {console.log(&quot;hs_submit clicked&quot;); // simple length check before they // submit var username = $('#id_username').val(); if (username.length &gt; 20 || username.length &lt; 3) {console.log(&quot;invalid username: &quot; + username.length); $('.error').html( 'Please use a username between 3 and 10 characters'); } else {console.log(&quot;submitting newhs&quot;) $('.error').html(); $.ajax({ url: &quot;{% url new_hs %}&quot;, data: {'username':username}, type: 'post', async: 'false', success: function(data) {console.log(&quot;fading out&quot;); $('.newhs').fadeOut('slow', function() {$('.hs-content').html(data); }); }, error: function() {}, }); }}); }</pre><p>If the player clicks the link with the &#8220;playagain&#8221; class he will start over with a new game.  </p><p>The other handler is for the submit button for a new high score with the &#8220;hs_submit&#8221; class. This will only show up if the score is high enough to be on the highscore table and is determined by the server when it sends the html back using the <a href="https://github.com/jarv/wordconfuse/blob/master/templates/gameover.html">gameover</a> template.</p><p>There is a small amount of client side javascript checking here to make sure the user submits a name between 3 and 20 characters.  </p><pre class="brush: java; title: ; notranslate">if (username.length &gt; 20 || username.length &lt; 3) {console.log(&quot;invalid username: &quot; + username.length); $('.error').html( 'Please use a username between 3 and 10 characters'); }</pre><p>The client-side check is just a convenience for a coarse validation. <strong> It is never safe to rely on javascript validation since it can easily be bypassed by the browser.</strong><br />After the username is submitted an updated highscore screen is returned from the &#8220;new_hs&#8221; URL that will be updated with the player&#8217;s name.</p><h1>Summary</h1><p>That covers all of the javascript for the screens and game logic for WordConfusion. I hope you found this tutorial valuable if you have any questions, suggestions, or find errors please feel free to <a href="http://jarv.org/about/" title="About">send me mail</a> or write in the comments below. Good luck!</p>]]></content:encoded>
												<wfw:commentRss>http://jarv.org/2011/10/django-jquery-tutorial-part4/feed/</wfw:commentRss>
												<slash:comments>4</slash:comments>
											</item>
										</channel>
									</rss>
