<?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>No, I am better than that!</title>
	<atom:link href="http://rickosborne.org/blog/index.php/feed/" rel="self" type="application/rss+xml" />
	<link>http://rickosborne.org/blog</link>
	<description>Striving to subdue the mediocrity.</description>
	<lastBuildDate>Fri, 27 Aug 2010 04:18:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>HTML5 in-browser SQL database storage</title>
		<link>http://rickosborne.org/blog/index.php/2010/03/31/html5-in-browser-sql-database-storage/</link>
		<comments>http://rickosborne.org/blog/index.php/2010/03/31/html5-in-browser-sql-database-storage/#comments</comments>
		<pubDate>Thu, 01 Apr 2010 04:28:20 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[api]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[sqlite]]></category>
		<category><![CDATA[storage]]></category>

		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1213</guid>
		<description><![CDATA[I&#8217;ve been working on a new presentation to add to my Advanced Database Structures course: HTML5 Storage. It covers both the Web Storage and Web Database APIs. The former is a key-value store most likely to be used like beefed-up cookies or for form data persistence. The latter one is the more interesting of the [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been working on a new presentation to add to my <em>Advanced Database Structures</em> course: <em>HTML5 Storage</em>.  It covers both the <a href="http://www.w3.org/TR/webstorage/">Web Storage</a> and <a href="http://www.w3.org/TR/webdatabase/">Web Database</a> APIs.  The former is a key-value store most likely to be used like beefed-up cookies or for form data persistence.  The latter one is the more interesting of the two.</p>
<p>The Web SQL Database API is the logical progression from Google Gears: a programmatic way of accessing a SQL database that&#8217;s built into your web browser.  The current crop of browsers also have this all nice and sandboxed, so we shouldn&#8217;t end up suffering from some of the cross-site data access issues that were a worry in the previous generation.</p>
<p>So far, I think the best user-space access to the databases has to go to Safari.  You can get at them in the <em>Security</em> tab of the <em>Preferences</em> window:</p>
<p class="noindent"><img src="/blog/wp-content/uploads/2010/03/sudoku-db-win1.png" alt="" title="Database list in Safari preferences" width="456" height="171" class="aligncenter size-full wp-image-1222 noindent" /></p>
<p>But, even better than that, the Developer tools have an actual browser and query console&mdash;with smart SQL tab-completion!</p>
<p class="noindent"><img src="/blog/wp-content/uploads/2010/03/sudoku-db-console.png" alt="" title="sudoku-db-console" width="549" height="400" class="aligncenter size-full wp-image-1220 noindent" /></p>
<p>(I didn&#8217;t do anything magic to hide that <kbd>rs_hints</kbd> object&mdash;it&#8217;s a view.  I guess the Safari browser doesn&#8217;t show views.)</p>
<p>All of the current browser implementations use <a href="http://www.sqlite.org/">SQLite</a> as their storage engine.  SQLite has robust SQL support&mdash;it&#8217;s not meant to be a data warehouse, but it&#8217;ll probably do pretty much anything you&#8217;d think was sane to do inside a web browser.  I&#8217;ve successfully been able to use views, unions, several types of joins, indexes, and primary and foreign keys.</p>
<p>I&#8217;ve whipped up a quick app that shows off some of the technology: <a href="http://rickosborne.org/html5-dbstorage-sudoku/">Sudoku + HTML5</a>.  The storage layer for the app is done using the SQL engine, as is the business logic (game rules) of the Sudoku game itself.  The presentation layer is, of course, done in JavaScript using the HTML5 <kbd>canvas</kbd> API.  I&#8217;ve tested it in Safari, Opera, and Chrome.  Firefox, as of 3.5, does not yet support the SQL Database API.  I don&#8217;t have access to Internet Explorer to test it, but 8 shouldn&#8217;t work due to the use of the <kbd>canvas</kbd> element.</p>
<p class="noindent"><a href="/blog/wp-content/uploads/2010/03/sudoku-html5.png"><img src="/blog/wp-content/uploads/2010/03/sudoku-html5-300x181.png" alt="" title="Sudoku implemented with the HTML5 SQL Database Storage API" width="300" height="181" class="aligncenter size-medium wp-image-1217 noindent" border="0" /></a></p>
<p>Here&#8217;s a really quick overview of the Web SQL Database API:</p>
<pre class="javascript">var DB_NAME    = "ricko-sudoku";
var DB_VERSION = "1.0";
var DB_TITLE   = "Rick O's SQL Sudoku";
var DB_BYTES   = 500000;
var db = window.openDatabase(DB_NAME, DB_VERSION, DB_TITLE, DB_BYTES);</pre>
<p>The first part is very straightforward: I define a few constants and make the <kbd>openDatabase</kbd> call.  I&#8217;m using the constants to illustrate the variable placement&mdash;your app may just use literals in the function call.</p>
<p>The <kbd>openDatabase</kbd> call takes one additional optional argument that I have elided: a function callback.  If the database needs to be created, this being the first time you&#8217;ve ever tried to open this database, the extra function will be called.  The theory is that you could write all of your table creation and other DDL queries in this callback.  However, since SQLite supports the <kbd>IF EXISTS</kbd> syntax, I find it easier to run my schema setups immediately no matter if it&#8217;s the first time or not.</p>
<p>Before we run any queries, though, it would be helpful to have debugging functions for when our queries go pear-shaped:</p>
<pre class="javascript">function sqlFail(err) { alert("SQL failed: " + err.message); }
function txFail(err) { alert("TX failed: " + err.message); }</pre>
<p>Again, nothing tricky here: we&#8217;ll use these functions as callback error handler in future queries.  For illustrative purposes, we could also have a logger for when our queries succeed:</p>
<pre class="javascript">function sqlWin(tx, response) { console.log("SQL succeeded: " + response.rows.length + " rows."); }
function txWin(tx) { console.log("TX succeeded."); }</pre>
<p>A little trickier, but we&#8217;ll go into more detail on result sets in a bit.  On with the database setup:</p>
<pre class="javascript">db.transaction( function(tx) {
    var queryParams = [];
    tx.executeSql(
        "CREATE TABLE IF NOT EXISTS animals (id INT NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR(20) NOT NULL UNIQUE);",
        queryParams,
        sqlWin,
        sqlFail
    );
}, txFail, txWin);</pre>
<p>Again, I&#8217;m a little verbose and heavy with the variables for illustrative purposes&mdash;you&#8217;d use a literal <kbd>[]</kbd> instead of a <kbd>queryParams</kbd> local variable.  Inside of a <kbd>transaction</kbd> function, your queries are executed atomically and serially, but also <strong>asynchronously</strong> so be careful&mdash;hence all of the callback functions.  The <kbd>transaction</kbd> function even has optional failure/success callbacks of its own, but again be careful: they&#8217;re in the opposite order of the query functions.</p>
<p>If we insert a row, we can get back the ID of an autogenerated number:</p>
<pre class="javascript">db.transaction( function(tx) {
    var animalName = "Cheetah";
    tx.executeSql("INSERT INTO animals (name) VALUES (?);",
        [ animalName ],
        function(tx, results) {
            var animalId     = results.insertId;
            var animalsAdded = results.rowsAffected;
            // for this simple insert, we should only see 1 row
        },
        sqlFail
    );
});</pre>
<p>Using <kbd>SELECT</kbd> queries is just as easy:</p>
<pre class="javascript">db.readTransaction( function(tx) {
    var animalName = "%Lion%";
    tx.executeSql("SELECT id, name FROM animals WHERE (name LIKE ?);",
        [ animalName ],
        function(tx, results) {
            for(var i = 0; i &lt; results.rows.length; i++) {
                var row = results.rows.item(i);
                console.log("Animal[" + row.id + "] = " + row.name);
            } // for i
        },
        sqlFail
});</pre>
<p>Still nothing too tricky here.  Query parameters work just like you&#8217;d expect: replace the parameter with a question mark in the query, then pass it in the array afterward.  The callback here iterates over the records, each of which is a simple object with column names for keys, and prints them on the debugging console.</p>
<p>There&#8217;s not much more to it than that&mdash;it&#8217;s surprisingly easy for something designed by committee!</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/index.php/2010/03/31/html5-in-browser-sql-database-storage/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Running Gargoyle: Step 2</title>
		<link>http://rickosborne.org/blog/index.php/2010/03/16/running-gargoyle-step-2/</link>
		<comments>http://rickosborne.org/blog/index.php/2010/03/16/running-gargoyle-step-2/#comments</comments>
		<pubDate>Wed, 17 Mar 2010 04:36:11 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Fitness]]></category>

		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1203</guid>
		<description><![CDATA[There was an Adidas booth at the runner&#8217;s expo for the Gate River Run last weekend. In the booth, they were demonstrating their new tech: miCoach. The gist of this collection of devices is this: via a foot pod and heartrate monitor, the central device sits between your MP3 player and earphones and tells you [...]]]></description>
			<content:encoded><![CDATA[<p><img src="/blog/wp-content/uploads/2010/03/adidas-micoach.jpg" alt="" title="Adidas miCoach" width="180" height="180" align="right" /></p>
<p>There was an Adidas booth at the runner&#8217;s expo for the Gate River Run last weekend.  In the booth, they were demonstrating their new tech: <a href="http://www.adidas.com/us/micoach/">miCoach</a>.  The gist of this collection of devices is this: via a foot pod and heartrate monitor, the central device sits between your MP3 player and earphones and tells you if you&#8217;re working at your target intensity.  You can still hear your music and use your own MP3 player, but you&#8217;ve got a coach with a mute button.  The workouts can be programmed in detail: mix any number of minutes at a number of intensity ranges (easy blue to maximum-effort red).</p>
<p align="center"><img src="/blog/wp-content/uploads/2010/03/micoach-workout.jpg" alt="" title="Adidas miCoach Workout" width="509" height="288" /></p>
<p>I&#8217;ve been on the fence about migrating from <a href="/blog/index.php/2009/02/09/technojoggery/">my Nike+</a> to something with a bit more functionality.  I love my Nike+ and consider myself one of its original fanboys, but &#8230; the fact is that Nike pioneered the tech, then left it to founder.  They upgraded the website and made an iPhone app, but the iPod app is essentially the same original version.  There&#8217;s still no real workout management tool beyond &ldquo;create a run of a given distance or time&rdquo;.  As I start to get more technical in my runs, adjusting speed and intensity, the Nike+ is beginning to show its cracks.</p>
<p>Not that everything about the miCoach is better than the Nike+.  The revamped Nike+ website, for example, has a few more social features&mdash;challenges, etc.  It&#8217;s not exactly <a href="http://www.dailymile.com/">DailyMile</a>, but it&#8217;s not horrible.  The miCoach site isn&#8217;t much more than a data sink and management tool.  Adidas says that social aspects will be forthcoming, but we&#8217;ll see.</p>
<p align="center"><img src="/blog/wp-content/uploads/2010/03/micoach-home.jpg" alt="" title="Adidas miCoach User Home" width="509" height="291" class="aligncenter size-full wp-image-1206" /></p>
<p>I looked into a Garmin ForeRunner, as the Virtual Partner tech is very sexy: a little digital avatar telling me if I&#8217;m on pace, above, or below.  It&#8217;s similar to what the miCoach does, and I imagine the two sets of features will continue to converge.  That the new ForeRunners also have heartrate monitors is another great selling point.</p>
<p>But then there&#8217;s the cost.  We&#8217;re talking $400, easy.  Not exactly an impulse buy.</p>
<p>So we&#8217;re back to my original point: the Adidas miCoach.  This is the Baby Bear in this Goldilocks story.  It&#8217;s got a decent price point at $140, all in.  It&#8217;s engineered to work with your existing MP3 player.  It doesn&#8217;t have GPS.  Instead of a Virtual Partner, it&#8217;s got a voice in your ear telling you to speed up or slow down.  And, of course, you&#8217;ll look like a <a href="http://en.wikipedia.org/wiki/Snow_Crash">gargoyle</a>: heartrate monitor, foot pod, miCoach, iPod with controller watch, and earphones.</p>
<p>But I am nothing if not a data junkie.  Hopefully, I&#8217;ll be able to crack open and mine the data from the miCoach as easily as I can the Nike+.</p>
<p>So I bought one.  It arrives tomorrow night.  We&#8217;ll see how it goes.</p>
<hr/>
<p><strong>Update:</strong> Holy tiny technology, Batman!  Here&#8217;s a picture of the miCoach pacer and iPod nano in the palm of my hand.  It&#8217;s much smaller than I had thought it would be.</p>
<p align="center"><a href="/blog/wp-content/uploads/2010/03/miCoach-nano.jpg"><img src="/blog/wp-content/uploads/2010/03/miCoach-nano-300x225.jpg" alt="" title="miCoach-nano" width="300" height="225" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/index.php/2010/03/16/running-gargoyle-step-2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data Mining the 2010 Gate River Run 15K results</title>
		<link>http://rickosborne.org/blog/index.php/2010/03/15/data-mining-the-2010-gate-river-run-15k-results/</link>
		<comments>http://rickosborne.org/blog/index.php/2010/03/15/data-mining-the-2010-gate-river-run-15k-results/#comments</comments>
		<pubDate>Mon, 15 Mar 2010 18:12:26 +0000</pubDate>
		<dc:creator>Rick Osborne</dc:creator>
				<category><![CDATA[Fitness]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[data mining]]></category>
		<category><![CDATA[running]]></category>

		<guid isPermaLink="false">http://rickosborne.org/blog/?p=1198</guid>
		<description><![CDATA[Random facts learned by data mining the 2010 Gate River Run 15K results: Fastest Father-Son Team: Robert and Harrison Gordon, coming in with a 1:03:15 chip time. Fastest Father-Daughter Team: Greg Lawrence and Amy Eller, coming in with a 1:08:52 chip time. Fastest Husband-Wife Team: Scott and Laura Flint, coming in with a 1:15:02 chip [...]]]></description>
			<content:encoded><![CDATA[<p>Random facts learned by data mining the 2010 Gate River Run 15K results:</p>
<ul>
<li><strong>Fastest Father-Son Team</strong>: Robert and Harrison Gordon, coming in with a 1:03:15 chip time.</li>
<li><strong>Fastest Father-Daughter Team</strong>: Greg Lawrence and Amy Eller, coming in with a 1:08:52 chip time.</li>
<li><strong>Fastest Husband-Wife Team</strong>: Scott and Laura Flint, coming in with a 1:15:02 chip time.</li>
<li><strong>Best Spirit of Cooperation</strong>: Kara Mathias and Manny Gutierrez, a Gator and a &#8216;Nole, running the entire race together and finishing in just under 66 minutes.</li>
<li><strong>Most Supportive Running Group</strong>: Dominic, William, Tim, Jamie, and Brian from Ponte Vedra, FL, coming in at a chip time of 1:46:48.</li>
<li><strong>The Family That Runs Together Stays Together</strong>: The Gobold family of Jacksonville&mdash;Chris and Lesa, with children Jena and Tyler, and friends Christopher and Mary&mdash;staying together and finishing in 2:23:30.</li>
</ul>
<p>I am truly impressed how many husband and wife teams were seeded.  That&#8217;s absolutely awesome.  (And that they can match eachother&#8217;s pace the entire race!)</p>
<p>Despite an enormous number of Father-Son and Husband-Wife teams, Mother-Daughter teams seemed to be thin on the ground.  My best guess?  Jessica and Anna of Jacksonville, FL with a finish time of 1:18:21.  Finding them is harder, because the surnames may not be the same.  The age difference helps, but isn&#8217;t a guarantee.  (Woe unto me if I call out a mother-daughter pair only to be wrong!  And I&#8217;m nowhere near stupid enough to try Father-Daughter or Mother-Son pairs!)</p>
<p>Someone named Nicole Norris of Roswell, GA kept pace with my buddy and I throughout the entire race, crossing each split marker within 3-4 seconds of us each time.  Nicole: we were the guys in the red shirt and hat and yellow shirt (mustard, not the greenish of the official race shirts).  Sorry we didn&#8217;t say hello!</p>
]]></content:encoded>
			<wfw:commentRss>http://rickosborne.org/blog/index.php/2010/03/15/data-mining-the-2010-gate-river-run-15k-results/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
