<?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>KevFoo &#187; programming</title>
	<atom:link href="http://blog.kevfoo.com/index.php/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.kevfoo.com</link>
	<description>The weblog of a Chicago based .Net and iPhone developer.</description>
	<lastBuildDate>Wed, 26 May 2010 13:33:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Chatsworth: A Google talk group chat bot</title>
		<link>http://blog.kevfoo.com/index.php/2009/01/chatsworth-a-google-talk-group-chat-bot/</link>
		<comments>http://blog.kevfoo.com/index.php/2009/01/chatsworth-a-google-talk-group-chat-bot/#comments</comments>
		<pubDate>Mon, 26 Jan 2009 06:36:01 +0000</pubDate>
		<dc:creator>Kevin McMahon</dc:creator>
				<category><![CDATA[chatsworth]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[open source]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Chat Bot]]></category>
		<category><![CDATA[Chat Bots]]></category>
		<category><![CDATA[Chat Logs]]></category>
		<category><![CDATA[Chat Room]]></category>
		<category><![CDATA[Conversations]]></category>
		<category><![CDATA[Google]]></category>
		<category><![CDATA[Google Group]]></category>
		<category><![CDATA[Google Talk]]></category>
		<category><![CDATA[Gtalk]]></category>
		<category><![CDATA[Home Server]]></category>
		<category><![CDATA[Immediate Future]]></category>
		<category><![CDATA[Jabber]]></category>
		<category><![CDATA[Java Source]]></category>
		<category><![CDATA[Loose Ends]]></category>
		<category><![CDATA[Pitfall]]></category>
		<category><![CDATA[Talk Group]]></category>
		<category><![CDATA[Unit Tests]]></category>
		<category><![CDATA[Uptime]]></category>
		<category><![CDATA[Windows Service]]></category>

		<guid isPermaLink="false">http://blog.kevfoo.com/index.php/2009/01/chatsworth-a-google-talk-group-chat-bot/</guid>
		<description><![CDATA[For the past year and a half, I’ve been using PartyChat to participate in multi-user chats with friends.&#160; PartyChat essentially provides IRC type functional via GTalk and has been a great way to have on going conversations throughout the day while avoiding 100+ email threads.
The only pitfall PartyChat has to do with stability.&#160; PartyChat is [...]]]></description>
			<content:encoded><![CDATA[<p>For the past year and a half, I’ve been using <a href="http://techwalla.googlepages.com/" target="_blank">PartyChat</a> to participate in multi-user chats with friends.&#160; PartyChat essentially provides IRC type functional via <a href="http://talk.google.com" target="_blank">GTalk</a> and has been a great way to have on going conversations throughout the day while avoiding 100+ email threads.</p>
<p>The only pitfall PartyChat has to do with stability.&#160; PartyChat is a free service used by a large number of people, and it is run off the project creator’s computer in his apartment.&#160; I do not know exactly why the service goes down intermittently, but the recipe of home server plus lots of users cannot be helping.&#160; While it stinks that PartyChat isn’t always up, I understand I have no right to demand or expect 100% uptime, so I decided to do something about it.&#160; I leveraged some of the knowledge I picked up about XMPP, the protocol that Jabber and GTalk use, from another project and wrote a simple group chat bot called <a href="http://code.google.com/p/chatsworth" target="_blank">Chatsworth</a> to improve the availability of group chat that my friends and I use and depend on.</p>
<p>Chatsworth is a windows service written in C# that provides basic chat room functionality.&#160; It does not have all the features that PartyChat has, but it does offer people the ability to setup and manage their own chat bots.&#160; Additionally, if you are concerned about having all your chat logs being available not just to Google but also to the people running the PartyChat servers, then Chatsworth is the group chat provider for you.&#160; Chatsworth is fully functional but still immature and under development.&#160; I plan to add some additional features, take care of a few loose ends and provide more unit tests in the immediate future.</p>
<p>Admittedly I could’ve just downloaded the PartyChat java source, compiled it, and ran it on my own set of servers, but where is the fun in that?&#160; I figured rolling my own chat bot would give me the opportunity to do more than address some of the availability issues I was having.&#160; Starting up Chatsworth provides me a non-trivial project that I can use to explore different software development concepts and techniques as well as get some code and design samples out on the web.&#160; So if you’re in the market for group chat in GTalk, give <a href="http://code.google.com/p/chatsworth" target="_blank">Chatsworth</a> a try.&#160; I am looking forward to building this project out further and would love to hear any feedback.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kevfoo.com/index.php/2009/01/chatsworth-a-google-talk-group-chat-bot/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Crunching some NFL Stats with F#</title>
		<link>http://blog.kevfoo.com/index.php/2009/01/crunching-some-nfl-stats-with-f/</link>
		<comments>http://blog.kevfoo.com/index.php/2009/01/crunching-some-nfl-stats-with-f/#comments</comments>
		<pubDate>Sat, 10 Jan 2009 16:51:44 +0000</pubDate>
		<dc:creator>Kevin McMahon</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Berri]]></category>
		<category><![CDATA[Bolognese]]></category>
		<category><![CDATA[C World]]></category>
		<category><![CDATA[Couple Chapters]]></category>
		<category><![CDATA[Csv File]]></category>
		<category><![CDATA[Don Syme]]></category>
		<category><![CDATA[Football Stats]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[Interactive Window]]></category>
		<category><![CDATA[Java World]]></category>
		<category><![CDATA[Linq]]></category>
		<category><![CDATA[Nfl Stats]]></category>
		<category><![CDATA[Problem Domain]]></category>
		<category><![CDATA[Qb Rating]]></category>
		<category><![CDATA[Qb Stats]]></category>
		<category><![CDATA[Stat]]></category>
		<category><![CDATA[Turnovers]]></category>
		<category><![CDATA[Wages]]></category>

		<guid isPermaLink="false">http://blog.kevfoo.com/?p=24</guid>
		<description><![CDATA[To explore functional programming, I’ve decided to return to a familiar problem domain, football stats. I used this domain a couple years ago when I was in the process of making the transition from the Unix-based OS/Java world to the Microsoft/C# world. I am the type of person that learns better by doing than studying, [...]]]></description>
			<content:encoded><![CDATA[<p>To explore functional programming, I’ve decided to return to a familiar problem domain, football stats. I used this domain a couple years ago when I was in the process of making the transition from the Unix-based OS/Java world to the Microsoft/C# world. I am the type of person that learns better by doing than studying, so I’m going to try and jump in and cobble something together to start the learning process. I’ve watched the PDC presentation by <a href="http://blogs.msdn.com/lucabol/" target="_blank">Luca Bolognese</a>, and I’ve read through the first couple chapters of <a href="http://blogs.msdn.com/dsyme/" target="_blank">Don Syme’s</a> <em>Expert F#</em>, so consider me armed with an F# Interactive window and dangerous.</p>
<p>The first stat that I plan to look at is the <a href="http://dberri.wordpress.com/2007/09/09/a-new-qb-score/" target="_blank">QB Score Stat</a> as outlined by Berri, et al. in <a href="http://www.amazon.com/gp/product/0804752877?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0804752877" target="_blank"><em>Wages of Wins</em></a>.&#160; The stat is much easier to calculate than the traditional QB Rating used by the NFL, and if you read the link and/or book, you’ll see that it correlates much better to wins and points than QB rating. For our purposes, I’ll just outline the formula here but I do recommend checking out the links for more info.</p>
<p align="center">QB Score = Total Yards &#8211; 3 * Plays &#8211; 30 * Turnovers</p>
<p align="left">I got the <a href="http://sports.yahoo.com/nfl/stats/byposition?pos=QB&amp;conference=NFL&amp;year=season_2008&amp;timeframe=All&amp;sort=626&amp;old_category=QB" target="_blank">2008 QB stats</a> from Yahoo, dumped them into Excel and then saved them off into CSV.&#160; This can be done programmatically fairly easily with <a href="http://www.codeplex.com/htmlagilitypack" target="_blank">HtmlAgilityPack</a> and Linq to Xml but I’ll save that for another post.&#160; I’ve provided a copy of the stats in CSV <a href="http://www.kevfoo.com/files/QB_Stats_2008.csv" target="_blank">here</a>.</p>
<p>So to get started here is what we have to do in order to calculate the raw QB score and the QB score per play for all the NFL QB’s:</p>
<ol>
<li>Read in the CSV file </li>
<li>Grab the relevant stats for our calculation </li>
<li>Calculate the QB score per play for each QB </li>
<li>Return the QB name and the score. </li>
</ol>
<p>I’ll tackle this step by step and we can verify our results via the F# Interactive window.</p>
<p>To read in the file we can leverage the .Net System.IO library. The call pattern to read a file into memory is identical to what you would see in C# or VB and is pretty straight forward.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;#light    &amp;lt;br /&amp;gt;open System.IO    &amp;lt;br /&amp;gt;let filePath = &amp;amp;quot;D:\code\data\QB_Stats_2008.csv&amp;amp;quot;    &amp;lt;br /&amp;gt;let stream = new FileStream(filePath, FileMode.Open)    &amp;lt;br /&amp;gt;let reader = new StreamReader(stream)    &amp;lt;br /&amp;gt;let csv = reader.ReadToEnd()    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Here is the output of the F# interaction window.   <br /><em>val filePath : string</em>
<p>val stream : System.IO.FileStream</p>
<p>val reader : System.IO.StreamReader</p>
<p>val csv : string</p>
</p>
<p>As we can see from the output, &#8216;csv&#8217; is string that holds the contents of the QB stats file. Since we know that the file is is a CSV file, we can break it down into its individual elements like so:</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let stats =    &amp;lt;br /&amp;gt;csv.Split([|'\n'|])    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.skip 1    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map(fun line -&amp;amp;gt; line.Split([|','|]))    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map(fun values -&amp;amp;gt;    &amp;lt;br /&amp;gt;string values.[0], // qb name    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[5]), // att    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[7]), // pass yds    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[11]), // int    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[12]), // rushes    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[13]), // rush yds    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[17]), // sacks    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[20])) // fumbles lost    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Since &#8216;csv&#8217; is a string, we can use the Split method to chunk the string up into individual lines using the &#8216;\n&#8217; character as our split token.&#160; Once split into individual lines, the pipeline operator on line 3 further processes each line.&#160; Sequences in F# can be thought of as IEnumerables from C# and come with some nice baked-in methods to help with processing. Our QB stats CSV file has as its first line a key to the data. We&#8217;ll need to skip that first line before we get to process the real data, and to do so we&#8217;ll use one of those nice baked-in methods (Seq.skip) to do so.</p>
<p>Line 4 further deconstructs the csv file into the individual comma delimited values tokenizing each line. After the lines have been tokenized the individual values can be read. Here I&#8217;ve created a tuple to hold each lines values. The tokenized values have been collected in a tuple that holds 8 values.&#160; The mapping of the values is specified by the comments.</p>
<p>Here is the output of the F# interaction window after step 2:</p>
<p><em>val stats : seq </em></p>
<p>After step two we have a sequence of tuples that have only the stats and information that we care about. The next step now becomes calculating the QB score. The calculation of the score requires three sub-steps, so let us revise the outline we laid out earlier to include them.</p>
<ol>
<li>Read in the CSV file </li>
<li>Grab the relevant stats for our calculation </li>
<li>Calculate the QB score per play for each QB
<ol>
<li><strong><em>Create the formula function </em></strong></li>
<li><strong><em>Compute the components of the formula </em></strong></li>
<li><strong><em>Create the desired output</em></strong> </li>
</ol>
</li>
<li>Return the QB name and the score </li>
</ol>
<p>Let&#8217;s tackle the first sub-step and codify the formula now and see what we&#8217;ll need to provide from the data we just acquired.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let qbcalc (plays,yards,turnovers) = yards - 3 * plays - 30 * turnovers    &amp;lt;br /&amp;gt;</pre>
</p>
<p>This line of code creates a function called qbcalc that takes in a tuple composed of the plays, yards, and turnovers components of the formula.</p>
<p>If we run the qbcalc function through the interactive window we get:</p>
<p><em>val qbcalc : int * int * int -&gt; int</em></p>
<p>The end result of this is the raw QB score. The arithmetic operations in F# are similar to most languages, so the formula is a straight forward expression without any surprises. Since we know plays, yards and turnovers are all integer values, we could further constrain the types of values that the tuple is composed of, but F#’s type inference already does this for us, so it is not needed. When the compiler analyzed this code, it was able to ascertain from the operations and the integers used that the plays, yards and turnover values were of type int and automatically created the int constraints.</p>
<p>The next step is to compute the individual values of plays, yards, and turnovers. Before we start, I just want to note that I am sure there is a slicker, more concise way to do this, but this is my first go at this, so pardon the mess.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let names = stats |&amp;amp;gt; Seq.map(fun(name,_,_,_,_,_,_,_) -&amp;amp;gt; name)    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Here we start to perform operations on the stats sequence we captured from the CSV file. The basic structure of what I am doing here is grabbing the specific values of the components I am looking to either aggregate (names) or calculate (plays, yards, and turnovers) from the sequence and mapping them to a new sequence. Here is an example of how to create the plays sequence.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let plays = stats |&amp;amp;gt; Seq.map(fun(_,att,_,_,rush,_,sacks,_) -&amp;amp;gt; att+rush+sacks)    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Here the stats sequence is pushed through the pipeline operator ( |&gt; ) which allows you to chain functions in a sequence. This is happens because, as pointed out in <a href="http://www.amazon.com/gp/product/1590598504?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590598504">Expert F#</a>, the pipeline operator is just function application in reverse. This can be expressed like so:</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let (|&amp;amp;gt;) x f = f x     &amp;lt;br /&amp;gt;</pre>
</p>
<p>So in our case when we have the following:</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;stats |&amp;amp;gt; Seq.map (fun(_,att,_,_,rush,_,sacks,_) -&amp;amp;gt; att+rush+sacks)    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Chaining the stats sequence with the the Seq.map function will apply the function we’ve defined in the parenthesis to each element in the stats sequence and return a new sequence with the results of the function.&#160; The function we have defined has a signature that matches the 8 value tuples that compose the stats sequence. Since only a few values are needed to be computed for the various values, ‘_’ can be assigned to the values in the parameter definition and more meaningful names can be given to the values we care about. On the right hand side of the -&gt; (a symbol that represents a function), we do the simple adding of the values. Again the results of this function are collected in a new sequence that is returned from the Seq.map call.</p>
<p>After all the individual components of the QB score formula have been computed, we’re left with a bunch of individual sequence values that need to be reconstructed into something that we can pass to the the qbcalc function. The calculation function is defined as taking a tuple composed of a play, yard, and turnover values, so we need to utilize another method that Seq provides called zip.</p>
<p>Here is the code that crunches the individual components.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;let getStats =    &amp;lt;br /&amp;gt;let stats = loadQBStats    &amp;lt;br /&amp;gt;let names = stats |&amp;amp;gt; Seq.map(fun(name,_,_,_,_,_,_,_) -&amp;amp;gt; name)    &amp;lt;br /&amp;gt;let plays = stats |&amp;amp;gt; Seq.map(fun(_,att,_,_,rush,_,sacks,_) -&amp;amp;gt; att+rush+sacks)    &amp;lt;br /&amp;gt;let yards = stats |&amp;amp;gt; Seq.map(fun(_,_,passyd,_,_,rushyd,_,_) -&amp;amp;gt; passyd + rushyd)    &amp;lt;br /&amp;gt;let turnovers = stats |&amp;amp;gt; Seq.map( fun(_,_,_,int,_,_,_,fum) -&amp;amp;gt; int+fum)    &amp;lt;br /&amp;gt;Seq.zip3 plays yards turnovers |&amp;amp;gt; Seq.zip names    &amp;lt;br /&amp;gt;</pre>
</p>
<p>The final step to complete is to apply the qbcalc function to each play, yard and turnover tuple, and zipping up the resulting sequence with the names sequence rounds out steps and completes our task. The values were balled up into tuples in previous steps, so a lot of what is left to do is unpacking what we need to do the actual calculation and then reassemble to the output. The unpacking of the tuples are done with the fst and snd functions that are applied to the sequences. These methods return the fst, and the snd functions return the first and second elements of the tuples respectively. The last line of the doCalc function divides the raw QB score over the plays completing the calculation and then back pipes that sequence to be zipped up with the names. The zipped sequence gets returned, and at last we’ve calculated the QB score per play for the 2008 season. The last thing to note with the calculation is that in order to get better precision from the final result, the int values being divided need to be converted to a decimal. If the integers aren’t converted, then the results of the division operation will be rounded down, and we’ll lose precision on the calculation.</p>
<p>
<pre class="brush: fsharp;">    &amp;lt;br /&amp;gt;let doCalc =     &amp;lt;br /&amp;gt;let stats =    &amp;lt;br /&amp;gt;getStats    &amp;lt;br /&amp;gt;let names =    &amp;lt;br /&amp;gt;stats |&amp;amp;gt; Seq.map fst    &amp;lt;br /&amp;gt;let rawScore =    &amp;lt;br /&amp;gt;stats    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map snd    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map qbcalc    &amp;lt;br /&amp;gt;let plays =     &amp;lt;br /&amp;gt;stats    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map snd    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map (fun (plays,_,_) -&amp;amp;gt; plays)    &amp;lt;br /&amp;gt;let components =    &amp;lt;br /&amp;gt;Seq.zip rawScore plays     &amp;lt;br /&amp;gt;Seq.zip names &amp;amp;lt;| Seq.map(fun(x:int, y:int) -&amp;amp;gt; System.Convert.ToDecimal(x)/ System.Convert.ToDecimal(y)) components    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Below is the complete source listing of my first crack at doing something useful with F#. There are a couple things (the packing and repacking of the tuples, the CSV parsing) that scream “optimize me”. In my next F# post, I’ll refactor this code to slim it down and package it up so I can display these results graphically via C#.</p>
<p>
<pre class="brush: fsharp;">   &amp;lt;br /&amp;gt;#light    &amp;lt;br /&amp;gt;open System.IO&amp;lt;/p&amp;gt;  &amp;lt;p&amp;gt;let loadQBStats =   &amp;lt;br /&amp;gt;let filePath = &amp;amp;quot;D:\code\ProFootballDB\Data\QB_Stats_2008.csv&amp;amp;quot;    &amp;lt;br /&amp;gt;let stream = new FileStream(filePath, FileMode.Open)    &amp;lt;br /&amp;gt;let reader = new StreamReader(stream)    &amp;lt;br /&amp;gt;let csv = reader.ReadToEnd()&amp;lt;/p&amp;gt;  &amp;lt;p&amp;gt;let stats =   &amp;lt;br /&amp;gt;csv.Split([|'\n'|])    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.skip 1    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map(fun line -&amp;amp;gt; line.Split([|','|]))    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map(fun values -&amp;amp;gt;    &amp;lt;br /&amp;gt;string values.[0], // qb name    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[5]), // att    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[7]), // pass yds    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[11]), // int    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[12]), // rushes    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[13]), // rush yds    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[17]), // sacks    &amp;lt;br /&amp;gt;System.Int32.Parse(values.[20])) // fumbles lost    &amp;lt;br /&amp;gt;stats&amp;lt;/p&amp;gt;  &amp;lt;p&amp;gt;let qbcalc (plays,yards,turnovers) = yards - 3 * plays - 30 * turnovers&amp;lt;/p&amp;gt;  &amp;lt;p&amp;gt;let getStats =   &amp;lt;br /&amp;gt;let stats = loadQBStats    &amp;lt;br /&amp;gt;let names = stats |&amp;amp;gt; Seq.map(fun(name,_,_,_,_,_,_,_) -&amp;amp;gt; name)    &amp;lt;br /&amp;gt;let plays = stats |&amp;amp;gt; Seq.map(fun(_,att,_,_,rush,_,sacks,_) -&amp;amp;gt; att+rush+sacks)    &amp;lt;br /&amp;gt;let yards = stats |&amp;amp;gt; Seq.map(fun(_,_,passyd,_,_,rushyd,_,_) -&amp;amp;gt; passyd + rushyd)    &amp;lt;br /&amp;gt;let turnovers = stats |&amp;amp;gt; Seq.map( fun(_,_,_,int,_,_,_,fum) -&amp;amp;gt; int+fum)    &amp;lt;br /&amp;gt;Seq.zip3 plays yards turnovers |&amp;amp;gt; Seq.zip names&amp;lt;/p&amp;gt;  &amp;lt;p&amp;gt;let doCalc =    &amp;lt;br /&amp;gt;let stats =    &amp;lt;br /&amp;gt;getStats    &amp;lt;br /&amp;gt;let names =    &amp;lt;br /&amp;gt;stats |&amp;amp;gt; Seq.map fst    &amp;lt;br /&amp;gt;let rawScore =    &amp;lt;br /&amp;gt;stats    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map snd    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map qbcalc    &amp;lt;br /&amp;gt;let plays =     &amp;lt;br /&amp;gt;stats    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map snd    &amp;lt;br /&amp;gt;|&amp;amp;gt; Seq.map (fun (plays,_,_) -&amp;amp;gt; plays)    &amp;lt;br /&amp;gt;let components =    &amp;lt;br /&amp;gt;Seq.zip rawScore plays     &amp;lt;br /&amp;gt;Seq.zip names &amp;amp;lt;| Seq.map(fun(x:int, y:int) -&amp;amp;gt; System.Convert.ToDecimal(x)/ System.Convert.ToDecimal(y)) components    &amp;lt;br /&amp;gt;</pre>
</p>
<p>Useful links:</p>
<ul>
<li><a href="http://www.amazon.com/gp/product/1590598504?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=1590598504">Expert F# (Expert&#8217;s Voice in .Net)</a> </li>
<li><a title="http://msdn.microsoft.com/en-us/fsharp/default.aspx" href="http://msdn.microsoft.com/en-us/fsharp/default.aspx">Microsoft F# Developer Center</a> </li>
<li><a href="http://channel9.msdn.com/pdc2008/TL11/" target="_blank">PDC Video : Introduction to Microsoft F#</a> </li>
<li><a href="http://dberri.wordpress.com/2007/09/09/a-new-qb-score/" target="_blank">QB Score Stat</a> from <a href="http://www.amazon.com/gp/product/0804752877?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0804752877">Wages of Wins</a> </li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.kevfoo.com/index.php/2009/01/crunching-some-nfl-stats-with-f/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Best thing I&#8217;ve read all day</title>
		<link>http://blog.kevfoo.com/index.php/2009/01/best-thing-ive-read-all-day/</link>
		<comments>http://blog.kevfoo.com/index.php/2009/01/best-thing-ive-read-all-day/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 22:23:57 +0000</pubDate>
		<dc:creator>Kevin McMahon</dc:creator>
				<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://blog.kevfoo.com/index.php/2009/01/best-thing-ive-read-all-day/</guid>
		<description><![CDATA[“Most programmers think it is a sin to write code w/o comments, but it is a greater sin to write code that cannot be understood without them” – Paul Berry via Twitter
]]></description>
			<content:encoded><![CDATA[<p>“Most programmers think it is a sin to write code w/o comments, but it is a greater sin to write code that cannot be understood without them” – <a href="http://twitter.com/pjb3/status/1095852496" target="_blank">Paul Berry via Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kevfoo.com/index.php/2009/01/best-thing-ive-read-all-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exploring functional programming</title>
		<link>http://blog.kevfoo.com/index.php/2009/01/exploring-functional-programming/</link>
		<comments>http://blog.kevfoo.com/index.php/2009/01/exploring-functional-programming/#comments</comments>
		<pubDate>Sun, 04 Jan 2009 21:24:04 +0000</pubDate>
		<dc:creator>Kevin McMahon</dc:creator>
				<category><![CDATA[F#]]></category>
		<category><![CDATA[functional]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Bad Idea]]></category>
		<category><![CDATA[Blog]]></category>
		<category><![CDATA[Brain]]></category>
		<category><![CDATA[Buzz]]></category>
		<category><![CDATA[First Exposure]]></category>
		<category><![CDATA[Functional Languages]]></category>
		<category><![CDATA[Functional Programming]]></category>
		<category><![CDATA[Haskell]]></category>
		<category><![CDATA[Languages Class]]></category>
		<category><![CDATA[Masters]]></category>
		<category><![CDATA[New Language]]></category>
		<category><![CDATA[Ocaml]]></category>
		<category><![CDATA[Pragmatic Programmer]]></category>
		<category><![CDATA[Problem Domain]]></category>
		<category><![CDATA[Programming Languages]]></category>
		<category><![CDATA[Real World]]></category>
		<category><![CDATA[Sports]]></category>
		<category><![CDATA[Statistics]]></category>
		<category><![CDATA[Tomorrow Night]]></category>

		<guid isPermaLink="false">http://blog.kevfoo.com/index.php/2009/01/exploring-functional-programming/</guid>
		<description><![CDATA[I am trying to heed the Pragmatic Programmer’s advice to learn a new language each year and this year I figured it would not be a bad idea to look at functional languages.&#160; There is a lot of buzz and blog posts about functional programming going on right now so there should be plenty of [...]]]></description>
			<content:encoded><![CDATA[<p>I am trying to heed the <a href="http://www.amazon.com/gp/product/020161622X?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=020161622X" target="_blank">Pragmatic Programmer’s</a> advice to learn a new language each year and this year I figured it would not be a bad idea to look at functional languages.&#160; There is a lot of buzz and blog posts about functional programming going on right now so there should be plenty of fresh material and this won’t be my first exposure to functional programming.&#160; I’ll have to dust off some of my notes from the programming languages class I took during some of my masters work.</p>
<p>I am planning to follow along with the <a href="http://www.amazon.com/gp/product/0596514980?ie=UTF8&amp;tag=kev02-20&amp;linkCode=as2&amp;camp=1789&amp;creative=390957&amp;creativeASIN=0596514980" target="_blank">Real World Haskell</a> book club (which <a href="http://codebetter.com/blogs/matthew.podwysocki/archive/2009/01/04/ann-the-real-world-haskell-book-club-starts-1-5-2009.aspx" target="_blank">starts tomorrow</a> night) and also mess around with F# so I thankfully won’t have to rely on my one semester of <a href="http://www.ocaml-tutorial.org/" target="_blank">OCaml</a> to help me get going.&#160; As a fan of sports and statistics I’ll probably try and use that as my problem domain while exploring these languages.&#160; I am really looking forward to trying to wrap my mind around functional programming as it is so different than thinking about objects and should be a great <a href="http://www.neurobics.com/" target="_blank">“neurobic” activity</a> for the ol’ brain.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.kevfoo.com/index.php/2009/01/exploring-functional-programming/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
