<?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>Eric Conner</title>
	<atom:link href="http://ericwconner.com/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://ericwconner.com</link>
	<description>Just another WordPress site</description>
	<lastBuildDate>Wed, 21 Sep 2011 18:07:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>The Not Coke Machine</title>
		<link>http://ericwconner.com/?p=513</link>
		<comments>http://ericwconner.com/?p=513#comments</comments>
		<pubDate>Wed, 21 Sep 2011 18:02:51 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=513</guid>
		<description><![CDATA[The Not Coke Machine is an ethernet enabled kegerator that uses a flow sensor and arduino to send real time updates to a server displaying how much beer is being poured from the keg. Checkout my full write up of the process.]]></description>
			<content:encoded><![CDATA[<p><a href="http://raunk.com/">The Not Coke Machine</a> is an ethernet enabled kegerator that uses a flow sensor and arduino to send real time updates to a server displaying how much beer is being poured from the keg.  Checkout my <a href="http://ericwconner.com/?p=470">full write up of the process</a>.</p>
<p style="text-align: center;"><img class="alignnone" title="NotCokeMachine" src="http://ericwconner.com/images/notcokem.png" alt="" width="400" /></p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=513</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Raunk</title>
		<link>http://ericwconner.com/?p=508</link>
		<comments>http://ericwconner.com/?p=508#comments</comments>
		<pubDate>Wed, 21 Sep 2011 17:59:31 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=508</guid>
		<description><![CDATA[Raunk is a website that allows you to rate anything and see best of lists. The first iteration of the site was built in the Summer of 2011 with Jeremy Keeshin, David Kravitz, Daniel Smith and Zach Galant. I worked on a number of things including the list creation process, the notifications system, system administration, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://raunk.com/">Raunk</a> is a website that allows you to rate anything and see best of lists.  The first iteration of the site was built in the Summer of 2011 with Jeremy Keeshin, David Kravitz, Daniel Smith and Zach Galant.  I worked on a number of things including the list creation process, the notifications system, system administration, background processing and search, static images, and rating items.</p>
<p style="text-align: center;"><img class="alignnone" title="Raunk" src="http://ericwconner.com/images/raunk.png" alt="" width="400" /></p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=508</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The Not Coke Machine</title>
		<link>http://ericwconner.com/?p=470</link>
		<comments>http://ericwconner.com/?p=470#comments</comments>
		<pubDate>Tue, 20 Sep 2011 22:24:24 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=470</guid>
		<description><![CDATA[The Not Coke Machine is the product of a realization that a mini-fridge provides little benefit beyond a store for cold, cheap beer. It is an ethernet enabled kegerator with a built in flow meter that monitors how much beer has been poured through the tap. It also shows in real time how much beer [...]]]></description>
			<content:encoded><![CDATA[<p>The Not Coke Machine is the product of a realization that a mini-fridge provides little benefit beyond a store for cold, cheap beer.  It is an ethernet enabled kegerator with a built in flow meter that monitors how much beer has been poured through the tap.  It also shows in real time how much beer is being poured as it is poured.  Brohemia.  (or would this be Brogeneering?)</p>
<h2>How It Works</h2>
<p>The CO2 tank in a kegerator keeps the keg pressurized so that the beer can keep for a longer period of time than if you were just using a hand pump.  The CO2 also provides the push so that when you open the tap, beer flows automatically without needing any pumping.  So, if you insert a flow sensor in the beer line, you can monitor every pour of beer through the tap and keep track of how much is left in the keg.</p>
<p>A small turbine provides the monitoring in a flow sensor.  As liquid passes through the sensor the turbine spins and outputs an electrical signal that can be monitored using a microcontroller, the Arduino.  The Arduino has attachments that allow it to be networked so that when a reading occurs a request can be sent to a server to record that reading.</p>
<h2>Building the Kegerator</h2>
<p>The first step in this whole ordeal was building the kegerator.  Parts needed:</p>
<ul>
<li>5lb CO2 Tank</li>
<li>CO2 Regulator</li>
<li>5/8-inch CO2 Tube</li>
<li>Keg Tap</li>
<li>3/8-inch Beer line</li>
<li>4 x 1/2-inch or less hose clamps</li>
<li>Keg faucet</li>
<li>Keg tap</li>
</ul>
<h3>Making it Fit in the Fridge</h3>
<p>I went about this in kind of a roundabout, and admittedly stupid, way.  I didn&#8217;t properly measure the mini-fridge before hand and just kind of assumed that I would be able to fit a pony keg in it.  A pony keg is half the size of a full keg, but has the same diameter.  Both are about 17 inches wide and the pony keg is half the height of a normal keg.  I measured my fridge from the outside, saw that it was about 20 inches across and assumed that it would be fine so I bought <a href="">this kegerator conversion kit</a>.  </p>
<p>Well, it turns out that the inner dimensions are much less than the outer.  It&#8217;s about 17 inches exactly across on the inside, but three things really burst my bubble once I considered the inner dimensions (after already buying the conversion kit).  First the temperature control was on the right-hand wall:</p>
<p><img alt="" src="http://notcokem.com/media/images/blog/before.jpg" title="Temperature Control" class="alignnone" width="500" /></p>
<p>and it turns out that instead of being ambiently cooled, the fridge is cooled internally from the freezer compartment.  The freezer compartment shelf is actually what provides all the cooling:</p>
<p><img src="http://img469.imageshack.us/img469/4108/xv6vvvkskysjtz46qfrnuusud2.jpg" /></p>
<p>Through it flows the coolant that is recycled by the fridge&#8217;s motor.  This design is exactly why the freezer comparment always collects frost..and..is frozen.  It&#8217;s the coldest part of the fridge so you can&#8217;t get rid of that shelf.  Third, the motor in the back at the bottom subtracts some of the internal volume of the fridge..that&#8217;s why there&#8217;s only a small drawer at the bottom.</p>
<p>Kegs come in a variety of dimensions so I thought I might be able to find one that would work with all these variables.  The pony keg is just a little too wide and I didn&#8217;t want to deal with trying to move and rewire the temperature control.  A 5-gallon keg has a smaller diameter (only about 9 inches) but is much taller, rising to between 23 to 26 inches.  So the pony keg wouldn&#8217;t fit because of the temperature control and the five gallon keg wouldn&#8217;t fit because of the freezer compartment.  The tap needed to extend up into that shelving area where the freezer was. </p>
<p>I figured I wasn&#8217;t the first to try converting a mini-fridge of that size so I got on the Googles and found this video:<br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/gnKJ8cHcuKg" frameborder="0" allowfullscreen></iframe></p>
<p>I followed his guide pretty closely and was able to bend the freezer compartment down in the same way:</p>
<p><img width="500" src="http://notcokem.com/media/images/blog/bent_freezer_shelf.jpg" /></p>
<p>This was one of the more difficult pieces of the project because I had to be very careful not to force the main coolant line too much.  Apparently it&#8217;s very easy to crack that line and it will totally ruin the fridge if you do.  A pair of pliers and a flathead screw driver were enough to bend it down though.  The fridge makes some funky noises now, but it&#8217;s been running fine for a few days so I guess it worked.</p>
<p>I also removed the door shelving in the same way shown in the video,</p>
<p><img src="http://notcokem.com/media/images/blog/door_removed.jpg" width="500" /></p>
<p>With the shelf bent and the door shelving gone, I had enough space to fit the keg and CO2 tank inside so I went about filling the CO2 and getting the lines connected.</p>
<h3>Connecting and Testing the Kegerator</h3>
<p>I knew I needed to fill my CO2 tank, but the only experience I had had with it up to that point was in playing paintball.  I had always gotten my paintball tank filled at Sports Authority so I got my 5lb tank (which is significantly larger than any paintball tank) and lugged it over to the store.  It turns out that Sports Authority does not have enough pressure to fill a tank of that size.  The guy looked at me like I was crazy when I asked so I left the store and went back to the Googles to figure out where I could get the tank filled.</p>
<p><img src="http://mountainhomebrew.com/ProductImages/homebrewingequipment/draftequipment/995.jpg" /></p>
<p>Welding supplies were my answer.  It turns out you can take these big tanks to welding supply companies and trade the empty tank for a full one and just pay about $20 for the CO2.  I found <a href="http://www.madcogases.com/">Madco</a> and took my tank over and had a full one in about 10 minutes.  The guy was really friendly and taught me that the thread on any gas tank actually determines what kind of gas is inside.  So he could tell it was pure CO2 just by the type of fitting on the outside of the tank and that all CO2 regulators would fit those threads (God I wish programmers could be that consistent..everything would be compatible!).</p>
<p>Once I had the full CO2 tank I decided that I needed to get a keg.  Everything I read online about kegging beer mentioned the use of so called cornelius (corny) kegs &#8212; 5 gallon soda kegs that have a special kind of tap.  I actually found nothing contrary to this while I was researching so I wrongly assumed that all 5 gallon kegs were these corny kegs.  This assumption would come back to bite me later, but for now I just assumed that I could get a corny keg and use it to test the kegerator.</p>
<p><center><br />
<img src="http://www.winemakingsuperstore.com/easy_beer/images/corneliuskeg.jpg" /><br />
</center></p>
<p>I went to a local home brew supply store and bought a corny keg and the fittings needed to hook it up in the kegerator.  The corny keg and taps and CO2 tank all fit in the fridge so I was happy with that so I decided to go about mounting the faucet.</p>
<p>To do this all you really need to do is saw a hole in the fridge (easier said than done).  My dad had given me a drill while I was home so I had that covered and just needed to get a hole saw of the right diameter.  I went to home depot and picked up a carbon hole saw which was cheaper than the alternative metal saw rated for drilling through metal.  The fridge door was metal though.  Doh.. well I tried it anyway and the saw was able to get through the door with lots of forcing and expletives.  Now I&#8217;m just not sure it&#8217;s going to be able to get through anything else.  Oh well, it was only a couple dollars so no big deal.</p>
<p><img src="http://notcokem.com/media/images/blog/faucet.jpg" width="500" /></p>
<p>Alright so my tap was mounted and it was time to test the lines.  I filled the corny keg with water and tapped it and was able to get water flowing through.  Figuring this was good enough, I decided to hook in the flow sensor.</p>
<h2>Arduino and the Flow Meter</h2>
<p>I first needed to make sure I could read from the flow sensor using the Arduino so I setup a test where I could pour water in a measuring cup through the line, have it run through the sensor, and come out into a bottle.  The code monitoring the flow could then be easily and repeatedly debugged.</p>
<p><img src="http://notcokem.com/media/images/blog/testing_setup.jpg" width="500" /></p>
<p>The flow sensor turbine spins as liquid flows through it.  Each time it spins, a change in its magnetic field causes an electrical pulse that, when wired to the arduino, can be detected with software running on the microcontroller.  The number of pulses is proportional to the amount of liquid that passes through the tube and, with some math, you can find the volume of liquid passing through.  I followed <a href="http://www.seeedstudio.com/forum/viewtopic.php?f=4&#038;t=989">this guide</a> on reading the liquid flow rate using the arduino.  </p>
<p><img src="http://notcokem.com/media/images/blog/extending_wires.jpg" width="500" /></p>
<h3>Networking the Arduino</h3>
<p>The next step was to get the Arduino networked so the data could be saved somewhere meaningful.  To do this I used the Arduino ethernet shield, which comes with some great libraries for TCP connections.  All Arduinos operate with a simple loop function that runs over and over which can be made to listen for events.  At this point I was using that loop to monitor the flow so I just needed to add some code that would send a request to a server when the flow was detected to be greater than 0.  </p>
<p><img src="http://notcokem.com/media/images/blog/arduino_sensor.jpg" width="500" /></p>
<p>When you connect to a web server using a browser, you almost always establish a keep-alive connection.  This type of connection tells the machine that you&#8217;re likely going to keep requesting pages so it should stay open to avoid the latency of having to reconnect.  This connection also comes with a timeout where the connection will close if no pages are requested within some interval.</p>
<p>Since the sensor needed to have fairly good request resolution (i.e. make a lot of requests in a short period of time) I decided to use a keep alive connection.  Every iteration of the arduino loop looks to see if the connection has closed, and if so, it reopens the connection so that when there is flow in the sensor it can be sent to the server.</p>
<p>When the sensor detects flow, a request telling the server the number of pulses in the last one second period is sent to the server.  If this request is subsequent to a previous request within 2 seconds, then the requests together are identified as part of one pour and the recorded number of pulses can be used to incrementally show how much liquid has been poured.  </p>
<p>Here&#8217;s the code running on the arduino:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">/*
This sketch monitors a flow sensor and sends any readings greater
than 0 to a server.
&nbsp;
 Circuit:
 * Ethernet shield attached to pins 10, 11, 12, 13
 * Flow sensor attached to pin 2
&nbsp;
 Written by Eric Conner
&nbsp;
 Adapted from code by
 David A. Mellis
 Charles Gantt - http://www.seeedstudio.com/forum/viewtopic.php?f=4&amp;t=989&amp;p=3632
 */</span>
&nbsp;
<span style="color: #339933;">#include &lt;SPI.h&gt;</span>
<span style="color: #339933;">#include &lt;Ethernet.h&gt;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Enter a MAC address and IP address for your controller below.</span>
<span style="color: #666666; font-style: italic;">// The IP address will be dependent on your local network:</span>
byte mac<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> 0xXX<span style="color: #339933;">,</span> 0xXX<span style="color: #339933;">,</span> 0xXX<span style="color: #339933;">,</span> 0xXX<span style="color: #339933;">,</span> 0xXX<span style="color: #339933;">,</span> 0xXX <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
byte ip<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000dd;">192</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">168</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">10</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
byte server<span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#123;</span> <span style="color: #0000dd;">50</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">19</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">92</span><span style="color: #339933;">,</span> <span style="color: #0000dd;">1</span> <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">// notcokem</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Initialize the Ethernet client library</span>
<span style="color: #666666; font-style: italic;">// with the IP address and port of the server</span>
<span style="color: #666666; font-style: italic;">// that you want to connect to (port 80 is default for HTTP):</span>
Client client<span style="color: #009900;">&#40;</span>server<span style="color: #339933;">,</span> <span style="color: #0000dd;">80</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">volatile</span> <span style="color: #993333;">int</span> NbTopsFan<span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//measuring the rising edges of the signal</span>
<span style="color: #993333;">int</span> Calc<span style="color: #339933;">;</span>
<span style="color: #993333;">int</span> hallsensor <span style="color: #339933;">=</span> <span style="color: #0000dd;">2</span><span style="color: #339933;">;</span>    <span style="color: #666666; font-style: italic;">//The pin location of the sensor</span>
&nbsp;
<span style="color: #993333;">void</span> rpm <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>     <span style="color: #666666; font-style: italic;">//This is the function that the interupt calls</span>
<span style="color: #009900;">&#123;</span>
  NbTopsFan<span style="color: #339933;">++;</span>  <span style="color: #666666; font-style: italic;">//This function measures the rising and falling edge of the hall effect sensors signal</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #993333;">void</span> setup<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
  <span style="color: #666666; font-style: italic;">// start the Ethernet connection:</span>
  Ethernet.<span style="color: #202020;">begin</span><span style="color: #009900;">&#40;</span>mac<span style="color: #339933;">,</span> ip<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  delay<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
&nbsp;
  pinMode<span style="color: #009900;">&#40;</span>hallsensor<span style="color: #339933;">,</span> INPUT<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//initializes digital pin 2 as an input</span>
  Serial.<span style="color: #202020;">begin</span><span style="color: #009900;">&#40;</span><span style="color: #0000dd;">9600</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//This is the setup function where the serial port is initialised,</span>
  attachInterrupt<span style="color: #009900;">&#40;</span><span style="color: #0000dd;">0</span><span style="color: #339933;">,</span> rpm<span style="color: #339933;">,</span> RISING<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//and the interrupt is attached</span>
&nbsp;
  <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span>client.<span style="color: #202020;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;connected&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span> <span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #666666; font-style: italic;">// kf you didn't get a connection to the server:</span>
    Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;connection failed&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #993333;">void</span> loop<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
<span style="color: #009900;">&#123;</span>
  NbTopsFan <span style="color: #339933;">=</span> <span style="color: #0000dd;">0</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//Set NbTops to 0 ready for calculations</span>
  sei<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">//Enables interrupts</span>
  delay <span style="color: #009900;">&#40;</span><span style="color: #0000dd;">1000</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">//Wait 1 second</span>
  cli<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">//Disable interrupts</span>
  Calc <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span>NbTopsFan <span style="color: #339933;">/</span> <span style="color:#800080;">7.5</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//(Pulse frequency x 60) / 7.5Q, = flow rate in L/hour</span>
  Serial.<span style="color: #202020;">print</span> <span style="color: #009900;">&#40;</span>Calc<span style="color: #339933;">,</span> DEC<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//Prints the number calculated above</span>
  Serial.<span style="color: #202020;">print</span> <span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot; L/hour<span style="color: #000099; font-weight: bold;">\r</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> <span style="color: #666666; font-style: italic;">//Prints &quot;L/hour&quot; and returns a  new line</span>
&nbsp;
  <span style="color: #666666; font-style: italic;">// consume any data on the connection</span>
  <span style="color: #b1b100;">while</span><span style="color: #009900;">&#40;</span>client.<span style="color: #202020;">available</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    <span style="color: #993333;">char</span> c <span style="color: #339933;">=</span> client.<span style="color: #202020;">read</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Serial.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span>client.<span style="color: #202020;">connected</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
      client.<span style="color: #202020;">stop</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Not connected...&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>client.<span style="color: #202020;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Reconnected to server.&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
      <span style="color: #009900;">&#125;</span>
   <span style="color: #009900;">&#125;</span>
&nbsp;
  <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span>NbTopsFan <span style="color: #339933;">&gt;</span> <span style="color: #0000dd;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;MAKING REQUEST!&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    Serial.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span>NbTopsFan<span style="color: #339933;">,</span> DEC<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #666666; font-style: italic;">// Make a HTTP request:</span>
    client.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;GET /flow?freq=&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    client.<span style="color: #202020;">print</span><span style="color: #009900;">&#40;</span>NbTopsFan<span style="color: #339933;">,</span> DEC<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    client.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot; HTTP/1.1&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    client.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Host: notcokem.com&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    client.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Connection: keep-alive&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    client.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;Cache-Control: max-age=0&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>       
    client.<span style="color: #202020;">println</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
  <span style="color: #009900;">&#125;</span></pre></div></div>

<p>Yea, it&#8217;s a GET request with side effects.  And anyone can post to that URL.  Meh..it&#8217;s a kegerator I don&#8217;t care much about security.  Also, for what it&#8217;s worth, I&#8217;m using Django on Amazon&#8217;s EC2 (just in case i need to scale my keg up, ya know ;-P) on the backend.</p>
<p>At this point the keg was basically setup (only using water) so I made a video showing some of the basics:<br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/TNqSf0u7gps" frameborder="0" allowfullscreen></iframe></p>
<h2>Making it Realtime</h2>
<p>The final thing I wanted it to be able to do was show, in real time, how much was being poured as it was poured.  Here&#8217;s the finished product:<br />
<iframe width="420" height="315" src="http://www.youtube.com/embed/xk1NpttwKvw" frameborder="0" allowfullscreen></iframe></p>
<p>This real time push uses a technology called comet.  If you use twitter, comet is used when you&#8217;re browsing tweets and you see the notification &#8220;23 new tweets&#8221; or whatever without refreshing the page.  Those tweets occurred, in real time, since you started browsing.  Twitter is able to push a notification to you that more tweets have been posted.</p>
<p>To accomplish this, I used an event driven server that interfaces well with Django called Orbited and the Stomp protocol for the socket connections that handle the real time back-and-forth.  Every connection to a website uses what&#8217;s called a socket.  You can think of a socket like a mailbox.  You put a letter in at one end and it comes out the other.  To accomplish real time interaction, multiple mail boxes (sockets) are used so that one can receive any new data.  </p>
<p>Here is a bit of the code that handles the real time push if you are curious:</p>
<p>On the server side,</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">conn = stomp.<span style="color: black;">Connection</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
conn.<span style="color: black;">start</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
conn.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
conn.<span style="color: black;">subscribe</span><span style="color: black;">&#40;</span>destination=<span style="color: #483d8b;">'/pours'</span>, ack=<span style="color: #483d8b;">'auto'</span><span style="color: black;">&#41;</span>
...
<span style="color: black;">pourjson</span> = json.<span style="color: black;">dumps</span><span style="color: black;">&#40;</span><span style="color: black;">&#123;</span><span style="color: #483d8b;">'pk'</span>: cur_pour.<span style="color: black;">pk</span>, <span style="color: #483d8b;">'size'</span>: cur_pour.<span style="color: black;">size</span><span style="color: black;">&#125;</span><span style="color: black;">&#41;</span>
conn.<span style="color: black;">send</span><span style="color: black;">&#40;</span>pourjson, destination=<span style="color: #483d8b;">'/pours'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>On the client,</p>

<div class="wp_syntax"><div class="code"><pre class="javascript" style="font-family:monospace;">&nbsp;
$<span style="color: #009900;">&#40;</span>document<span style="color: #009900;">&#41;</span>.<span style="color: #660066;">ready</span><span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
    stomp <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">new</span> STOMPClient<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	<span style="color: #003366; font-weight: bold;">var</span> pourTimeout<span style="color: #339933;">;</span>
&nbsp;
    stomp.<span style="color: #660066;">onopen</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//console.log(&quot;opening stomp client&quot;);</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #660066;">onclose</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>c<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #006600; font-style: italic;">//alert('Lost Connection, Code: ' + c);</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #000066;">onerror</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>error<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Error: &quot;</span> <span style="color: #339933;">+</span> error<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #660066;">onerrorframe</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>frame<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">alert</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Error: &quot;</span> <span style="color: #339933;">+</span> frame.<span style="color: #660066;">body</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #660066;">onconnectedframe</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        console.<span style="color: #660066;">log</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;Connected. Subscribing&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #006600; font-style: italic;">//alert(&quot;subscribing&quot;);</span>
&nbsp;
        stomp.<span style="color: #660066;">subscribe</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;/pours&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #660066;">onmessageframe</span> <span style="color: #339933;">=</span> <span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span>frame<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>
        <span style="color: #003366; font-weight: bold;">var</span> curPour <span style="color: #339933;">=</span> $.<span style="color: #660066;">parseJSON</span><span style="color: #009900;">&#40;</span>frame.<span style="color: #660066;">body</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	$<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#messages&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&lt;h1&gt;Pouring...&quot;</span> <span style="color: #339933;">+</span> curPour.<span style="color: #660066;">size</span> <span style="color: #339933;">+</span> <span style="color: #3366CC;">&quot;&lt;/h1&gt;&quot;</span><span style="color: #009900;">&#41;</span>
&nbsp;
	<span style="color: #006600; font-style: italic;">// clear the previous timeout..we are still pouring</span>
	clearTimeout<span style="color: #009900;">&#40;</span>pourTimeout<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	pourTimeout <span style="color: #339933;">=</span> setTimeout<span style="color: #009900;">&#40;</span><span style="color: #003366; font-weight: bold;">function</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span> 
	    $<span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;#messages&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #660066;">html</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">&quot;&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
	<span style="color: #009900;">&#125;</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">3000</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#125;</span><span style="color: #339933;">;</span>
    stomp.<span style="color: #660066;">connect</span><span style="color: #009900;">&#40;</span><span style="color: #3366CC;">'localhost'</span><span style="color: #339933;">,</span> <span style="color: #CC0000;">61613</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Alright.. so at this point the kegerator poured, updates were recorded, and everything seemed great.  So I went out at got a keg of Blue Moon to test it with.</p>
<h2>Woe the Corny Keg</h2>
<p>Remember earlier how I said all my research suggested a corny keg is what I would get?  Well I was wrong.  It turns out that breweries sell 5 gallon kegs with the normal, standard type of keg tap you&#8217;d expect.  Corny kegs use a completely different system so my taps were all wrong.  Luckily the tap wasn&#8217;t too hard to replace.</p>
<h2>Woe the Foam</h2>
<p>Kegs are finicky and the amount of foam in beer is all about temperature and pressure.  Foam is just CO2 gas and while the beer is under pressure you&#8217;d like most of that CO2 to stay in solution.  That is, you want it dissolved in the beer.  If you have pockets of CO2 in your keg and lines then you end up with foam everywhere.  As temperature is reduced, less pressure is needed to keep the right amount of CO2 in solution.  You therefore need the pressure and temperature of the keg to be balanced and the beer line needs to be at the same temperature as the keg.</p>
<p>I had a lot of problems with foam (and am still having some).  The first culprit was that my CO2 line wasn&#8217;t screwed on all the way.  I found that out when I got up this morning and half of the tank was gone (a full tank should last for at least five or more kegs).  I also lowered the temperature and have been playing with the pressure (and wasting a lot of beer&#8230;).  It&#8217;s pretty good now, but not the best it could be.</p>
<h2>That&#8217;s It.  That&#8217;s All.</h2>
<p>All in all it was a really fun project.  The next step is probably to add a temperature monitor.  I&#8217;ll get there eventually.  Check it out at <a href="http://notcokem.com/">http://notcokem.com/</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=470</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Migrating an EC2 Image between AWS Availability Regions</title>
		<link>http://ericwconner.com/?p=425</link>
		<comments>http://ericwconner.com/?p=425#comments</comments>
		<pubDate>Fri, 05 Aug 2011 22:42:23 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Amazon AWS]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=425</guid>
		<description><![CDATA[Yesterday I got to experience the joy of migrating an ec2 image from the us-east region to the us-west region on ec2. The best way to do this was to migrate the images through S3. You&#8217;ll find some guides about using rsync and copying everything over through ssh, but I think those were written before [...]]]></description>
			<content:encoded><![CDATA[<p>Yesterday I got to experience the joy of migrating an ec2 image from the us-east region to the us-west region on ec2.  The best way to do this was to migrate the images through S3.  You&#8217;ll find some guides about using rsync and copying everything over through ssh, but I think those were written before AWS introduced ec2-bundle-vol and ec2-migrate-image.</p>
<p>Here are the steps we&#8217;ll go through to migrate the image:</p>
<ol>
<li>Create and attach new volume to store bundled image</li>
<li>Bundle the current running volume into the newly attached volume</li>
<li>Upload bundle to S3 in source region</li>
<li>Migrate bundle to S3 in destination region</li>
<li>Register instance in destination region</li>
<li>Launch instance in destination region</li>
</ol>
<p><br/></p>
<h2>Preparation</h2>
<p>You&#8217;ll need a running instance of your AMI to do this, so launch one if you do not have one up.  The next thing to check is to make sure the ec2 command line tools are installed on your instance (they should be there by default).  Try the command,</p>
<pre class="shell">
> ec2-bundle-vol --help
</pre>
<p>to be sure.</p>
<p>You&#8217;ll also need the private key and certificate files for your AWS account on the server so that you can issue admin commands using the ec2 command line tools.  These have to be regenerated each time you want to download them, so be sure to save them the first time you generate them.  They can be found by going to My Account &#8211;> Security Credentials and clicking the X.509 Certificates tab under the Access Credentials heading.</p>
<p>Go ahead and upload these to your running instance:</p>
<pre class="shell">
> scp -i mykey.pem pk-<em>xxxx</em>.pem ubuntu@ec2-xxx-xxx-xxx-xxx.compute.amazonaws.com:
> scp -i mykey.pem cert-<em>xxxx</em>.pem ubuntu@ec2-xxx-xxx-xxx-xxx.compute.amazonaws.com:
</pre>
<p><br/></p>
<h2>Create and attach new volume</h2>
<p>Cool.  Now that everything is prepared for the migration, let&#8217;s create and attach a new volume to hold our bundled volume.  Go ahead and create an empty volume and be sure to specify the same availability zone as the one in which your instance is running,<br />
<a href="http://ericwconner.com/wp-content/uploads/2011/08/create_volume.png"><img src="http://ericwconner.com/wp-content/uploads/2011/08/create_volume-300x124.png" alt="" title="create_volume" class="alignnone size-medium wp-image-441" /></a><br />
The max size of the bundle will be 10GiB so just be sure that you leave enough space for the bundled volume.</p>
<p>Next attach it to the running instance of the image,<br />
<a href="http://ericwconner.com/wp-content/uploads/2011/08/attach_volume.png"><img src="http://ericwconner.com/wp-content/uploads/2011/08/attach_volume-300x156.png" alt="" title="attach_volume" class="alignnone size-medium wp-image-440" /></a></p>
<p>Now we need to determine where the newly attached image was added.  The comment in red tells us that our linux kernel may rename our device so it won&#8217;t be at /dev/sdg necessarily.  SSH into the instance and type the command,</p>
<pre class="shell">
> cat /proc/partitions
 202        1    8388608 xvda1
 202       80   12582912 xvdf
</pre>
<p>Ok, so it was attached then at /dev/xdvf.  Let&#8217;s mount the new volume:</p>
<ol>
<li>
Create the filesystem on the partition</p>
<pre class="shell">
> sudo mkfs -t ext3 /dev/xvdf
</pre>
</li>
<li>
Create a mount point for the new volume,</p>
<pre class="shell">
> sudo mkdir /mnt/backup
</pre>
</li>
<li>
Mount the new volume</p>
<pre class="shell">
> sudo mount /dev/xvdf /mnt/backup
</pre>
<li>
Check that everything worked,</p>
<pre class="shell">
> df
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/xvda1             8256952   5048364   2789160  65% /
none                    295996       112    295884   1% /dev
none                    303236         0    303236   0% /dev/shm
none                    303236        48    303188   1% /var/run
none                    303236         0    303236   0% /var/lock
/dev/xvdf             12385456    161908  11594404   2% /mnt/backup
</pre>
</li>
</ol>
<p>Perfect.  We&#8217;ve mounted a new partition to store our bundled volume.<br />
<br/></p>
<h2>Bundle Current Volume</h2>
<p>Before bundling the volume, check on the architecture as we&#8217;ll need to provide this to the bundle-vol command.</p>
<pre class="shell">
> uname -a
(...etc...) x86_64 x86_64 x86_64 GNU/Linux
</pre>
<p>Ok, now we just need to issue the ec2-bundle-vol command, (the -u option is your amazon aws account number)</p>
<pre class="shell">
> sudo ec2-bundle-vol -d /mnt/backup -k pk-xxxx.pem -u xxxx-xxxx-xxxx -c cert-xxx.pem
Please specify a value for arch [x86_64]:
</pre>
<p>If the default architecture value is correct, go ahead and hit return.  You&#8217;ll see output about the initialization of the bundling process which will take quite awhile to complete.<br />
<br/></p>
<h2>Uploading the Bundle to S3</h2>
<p>The next step is to transfer the bundle to S3 so that it can be migrated.  In this step you&#8217;ll need your aws access key and secret which can be found under Account &#8211;> Security Credentials.  By default, the ec2-bundle-vol command creates a manifest file describing the image named image.manifest.xml in /mnt/backup.  We&#8217;ll need this filename for the next command,</p>
<pre class="shell">
> ec2-upload-bundle -b my-us-standard-bucket -m /mnt/backup/image.manifest.xml -a access_key_id -s secret_key
</pre>
<p>All of the parts that were just created by bundling the volume will be uploaded to S3.  In the meantime, figure out the region location you&#8217;d like to transfer the image to,</p>
<pre class="shell">
> ec2-describe-regions -C cert-xxxx.pem -K pk-xxxx.pem
REGION     eu-west-1          ec2.eu-west-1.amazonaws.com
REGION     us-east-1          ec2.us-east-1.amazonaws.com
REGION     ap-northeast-1     ec2.ap-northeast-1.amazonaws.com
REGION     us-west-1          ec2.us-west-1.amazonaws.com
REGION     ap-southeast-1     ec2.ap-southeast-1.amazonaws.com
</pre>
<p>In this tutorial, we&#8217;ll use us-west-1.</p>
<h2>Migrate Bundle to S3 Bucket in Destination Region</h2>
<p>Now that the bundle has been uploaded to S3 in your source region, ensure that you have a bucket in S3 in your destination region to receive the image.  I&#8217;ll call mine my-us-norcal-bucket.  Now, all we need to do is migrate the image from the source bucket to the destination bucket,</p>
<pre class="shell">
> ec2-migrate-image -K pk-xxxx.pem -C cert-xxxx.pem -o access_key_id -w secret_key --bucket my-us-standard-bucket --destination-bucket my-us-norcal-bucket --manifest image.manifest.xml --location us-west-1
Downloading manifest image.manifest.xml from my-us-standard-bucket... OK
Copying 'image.part.000' to 'my-us-standard-bucket/image.part.000'... OK
Copying 'image.part.001' to 'my-us-standard-bucket/image.part.001'... OK
Copying 'image.part.002' to 'my-us-standard-bucket/image.part.002'... OK
...
</pre>
<p><br/></p>
<h2>Register image in the destination region</h2>
<p>Finally we just need to register the image:</p>
<pre class="shell">
> ec2-register -K pk-xxxx.pem -C cert-xxxx.pem --region us-west-1 my-us-norcal-bucket/image.manifest.xml --name myimage
</pre>
<p>That&#8217;s it.  That&#8217;s all.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=425</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Markov Chains and PageRank</title>
		<link>http://ericwconner.com/?p=382</link>
		<comments>http://ericwconner.com/?p=382#comments</comments>
		<pubDate>Wed, 18 May 2011 17:29:35 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=382</guid>
		<description><![CDATA[Introduction Most modern search engines operate on a three step process, User types in a query Engine locates all pages matching that query in its index The results are ordered in a useful way and returned to the user [1] The Google search engine’s main improvement over others was a novel method for ranking these [...]]]></description>
			<content:encoded><![CDATA[<h2>Introduction</h2>
<p>Most modern search engines operate on a three step process,</p>
<ol>
<li>User types in a query</li>
<li>Engine locates all pages matching that query in its index</li>
<li>The results are ordered in a useful way and returned to the user [1]</li>
</ol>
<p>The Google search engine’s main improvement over others was a novel method for ranking these results called PageRank. Consider a page <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> which has hyperlinks to some set of pages <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e9e6aae1d6fbe06d063527536b71ff3a.png" title="F_u" style="vertical-align:-20%;" class="tex" alt="F_u" />. Brin and Page considered each outgoing link from <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> to a page in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e9e6aae1d6fbe06d063527536b71ff3a.png" title="F_u" style="vertical-align:-20%;" class="tex" alt="F_u" /> as a recommendation by page <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> for a page in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e9e6aae1d6fbe06d063527536b71ff3a.png" title="F_u" style="vertical-align:-20%;" class="tex" alt="F_u" /> (or as a citation of the page in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e9e6aae1d6fbe06d063527536b71ff3a.png" title="F_u" style="vertical-align:-20%;" class="tex" alt="F_u" /> by page <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" />). Presumably authors of important pages on a topic would only link to other important pages [2].</p>
<p>Every page on the internet has a set of forward links, <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e9e6aae1d6fbe06d063527536b71ff3a.png" title="F_u" style="vertical-align:-20%;" class="tex" alt="F_u" />, and a set of back links, <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_60924c42e2286cb8b2c6f1c565f56b97.png" title="B_u" style="vertical-align:-20%;" class="tex" alt="B_u" />. Forward links are those pages to which the page links and back links are the set of pages which link to <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" />. The figure below illustrates this relationship.</p>
<p><center><a href="http://ericwconner.com/wp-content/uploads/2011/04/figure1.png"></a><a href="http://ericwconner.com/wp-content/uploads/2011/04/figure1.png"><img class="alignnone size-full wp-image-384" title="figure1" src="http://ericwconner.com/wp-content/uploads/2011/04/figure1.png" alt="" width="500" height="278" /></a></center></p>
<h2>Original Definition of PageRank</h2>
<p>The first version of PageRank described by Brin and Page in their seminal 1998 paper is a recursive relationship in which the rank of <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" />, <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_5271e6a361cb01a9eb21793bd5eef14c.png" title="R(u)" style="vertical-align:-20%;" class="tex" alt="R(u)" />, is calculated based on each of the pages <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_0eef60d6c8cf58fd2d6a7f5b43e675fb.png" title="v" style="vertical-align:-20%;" class="tex" alt="v" /> in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_60924c42e2286cb8b2c6f1c565f56b97.png" title="B_u" style="vertical-align:-20%;" class="tex" alt="B_u" />,</p>
<p style="text-align: center;"><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_e084dc09048cc25f1e87eea666907017.png" title="R(u) = c \sum_{v\in B_u}\frac{R(v)}{N_v}" style="vertical-align:-20%;" class="tex" alt="R(u) = c \sum_{v\in B_u}\frac{R(v)}{N_v}" /></p>
<p>where <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_6dcc941faa1a95355588d1eb9ed841f0.png" title="N_v = |F_v|" style="vertical-align:-20%;" class="tex" alt="N_v = |F_v|" />, the number of forward links from <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_0eef60d6c8cf58fd2d6a7f5b43e675fb.png" title="v" style="vertical-align:-20%;" class="tex" alt="v" /> and the constant <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_8390854cea1afc6c349c4c26b8bebb3c.png" title="c" style="vertical-align:-20%;" class="tex" alt="c" /> is a normalizing factor so that the total rank of all web pages is constant. In this way, the rank of <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> depends on the importance of as well as the number of pages recommended by each page in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" />’s set of back links. Therefore, the page <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> will gain a lot of importance from an important page in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_60924c42e2286cb8b2c6f1c565f56b97.png" title="B_u" style="vertical-align:-20%;" class="tex" alt="B_u" /> which has just a few outward links. Conversely, a page with many forward links that isn’t very important will not contribute much to <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" />’s rank. This ingenious definition prevents page authors from gaming the algorithm since a page’s importance depends on the network of all of its recommendations [2].</p>
<p>There are two problems with this simple definition. First, it is unclear how to distribute the weight of pages that are dead ends and, second, it is possible for certain loops in the graph to become rank sinks. As an example, imagine that two pages form a loop consisting of one forward link from each page to the other. Then, during an iterative calculation of the PageRank, the loop will accumulate weight since it has no outbound edges.</p>
<p><center><a href="http://ericwconner.com/wp-content/uploads/2011/04/rank_sink.png"><img class="size-full wp-image-386 aligncenter" title="rank_sink" src="http://ericwconner.com/wp-content/uploads/2011/04/rank_sink.png" alt="" width="292" height="80" /></a></center></p>
<p style="text-align: left;">To overcome this problem, in their original formulation, Brin and Page define a source of rank E, a vector over pages on the internet, which is usually initialized as a uniform probability distribution over the number of pages (e.g. each entry <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_871447c1d447ad4c1444bc1ff200039c.png" title="E(i) = frac{1}{|E|}" style="vertical-align:-20%;" class="tex" alt="E(i) = frac{1}{|E|}" />).<br />
The resultant formula then becomes,</p>
<p style="text-align: center;"><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_920a9a7675a37b00386fdee44099592c.png" title="R(u) = c \sum_{v \in B_u} \frac{R(v)}{N_v} + cE(u)" style="vertical-align:-20%;" class="tex" alt="R(u) = c \sum_{v \in B_u} \frac{R(v)}{N_v} + cE(u)" /></p>
<p style="text-align: left;">such that <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_8390854cea1afc6c349c4c26b8bebb3c.png" title="c" style="vertical-align:-20%;" class="tex" alt="c" /> is maximized and the sum of all entries in <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_d59ee023c548da3ba1c4da9988982bc9.png" title="R" style="vertical-align:-20%;" class="tex" alt="R" /> is 1. Intuitively, the vector <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_9e021374aed36323cad429d5234ddd96.png" title="E" style="vertical-align:-20%;" class="tex" alt="E" /> represents the probability that instead of going from <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_154feb24ee1ebba02e30354c6171c524.png" title="u" style="vertical-align:-20%;" class="tex" alt="u" /> to <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_0eef60d6c8cf58fd2d6a7f5b43e675fb.png" title="v" style="vertical-align:-20%;" class="tex" alt="v" />, we jump to a random page on the internet [2].</p>
<h2>Markov Chain Interpretation of PageRank</h2>
<p>The vector <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_9e021374aed36323cad429d5234ddd96.png" title="E" style="vertical-align:-20%;" class="tex" alt="E" /> also points to another way to interpret the PageRank formulation. Imagine a web surfer who starts from a random page and clicks a link at random on each new page he or she encounters. This random clicking can be modeled by a Markov chain whose states, <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_36949f2f78187b18025ac6ce48760f8e.png" title="i = 1,\dots,N" style="vertical-align:-20%;" class="tex" alt="i = 1,\dots,N" /> are pages where the probability of going from state <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_17205bd7356afc72c6e1cad22749dbb0.png" title="j" style="vertical-align:-20%;" class="tex" alt="j" /> to state <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_b2d5fbf99790e9a8f89f51d876bf7d45.png" title="i" style="vertical-align:-20%;" class="tex" alt="i" /> is given by,</p>
<p><center><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_f091949a2de318cbfa7a95e27fbffe58.png" title="p_{j,i} = \frac{1}{N_j}  \text{ if j links to i}" style="vertical-align:-20%;" class="tex" alt="p_{j,i} = \frac{1}{N_j}  \text{ if j links to i}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_528fe679baefd35bd6522725d565fa3c.png" title="p_{j,i} = 0 \text{ otherwise}" style="vertical-align:-20%;" class="tex" alt="p_{j,i} = 0 \text{ otherwise}" /><br />
</center></p>
<p>The PageRank of page u is then defined by the stationary distribution of this random walk. We gauge the importance of a page by determining the probability of finding the random surfer on that page at any given time.</p>
<p>To handle rank sinks, we introduce a restart state <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_84c31e1de3b1512853c20177f7f9bcf9.png" title="i = 0" style="vertical-align:-20%;" class="tex" alt="i = 0" /> and some parameter <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_a07424e1b964b5a44e36e13c98909b75.png" title="r" style="vertical-align:-20%;" class="tex" alt="r" />. Modify the random walk so that, instead of following links, the surfer moves to the restart state with probability <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_bdf92b0500ff4a603a5169058db40a64.png" title="p_{i,0} = (1-r)" style="vertical-align:-20%;" class="tex" alt="p_{i,0} = (1-r)" />. The probability of going from state <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_f4624c18e0a94f269add90954dab1329.png" title="0" style="vertical-align:-20%;" class="tex" alt="0" /> to state <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_b2d5fbf99790e9a8f89f51d876bf7d45.png" title="i" style="vertical-align:-20%;" class="tex" alt="i" /> is then <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_f2e2da78ab2aa36d422105e0266fa5c3.png" title="p_{0,i} = r" style="vertical-align:-20%;" class="tex" alt="p_{0,i} = r" /> since we have a fixed probability <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_cf7714cc486ad0d93a8d0cd52c474708.png" title="1-r" style="vertical-align:-20%;" class="tex" alt="1-r" /> of remaining in the restart state. Introducing this restart state ensures that the Markov chain is irreducible and aperiodic since any state can be reached from the restart state. Intuitively, this state corresponds to a random surfer who periodically gets bored and jumps to a URL at random on the web [5].</p>
<p>To handle dead ends, we assume that any page which has no forward links instead links to every page on the internet. Assuming this structure ensures that the page’s weight will be distributed evenly over all pages on the web and allow the walk to continue [5].</p>
<p>Now, since the chain is irreducible, aperiodic, and has a finite number of states, there exists a stationary distribution <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_21c5d4dae643fc6cbf465626aa1965b4.png" title="\pi" style="vertical-align:-20%;" class="tex" alt="\pi" /> on the chain that satisfies the following two equations,</p>
<p style="text-align: center;"><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_d928978edc21127308e8d54765d00575.png" title="\pi_i = \sum_{j = 0}^{N} \pi_j p_{j,i}" style="vertical-align:-20%;" class="tex" alt="\pi_i = \sum_{j = 0}^{N} \pi_j p_{j,i}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_a4daf54ada6f6fa9be8e187f61b599e4.png" title="\sum_{i = 0}^{N} \pi_i = 1" style="vertical-align:-20%;" class="tex" alt="\sum_{i = 0}^{N} \pi_i = 1" /></p>
<p>Expanding this using the Markov chain we set up,</p>
<p style="text-align: center;">
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_b5edf9ce263bc550f681099b1ee9450c.png" title="\pi_0 = \sum_{j = 0}^{N} \pi_j p_{j,0} = (1-r) \sum_{j = 0}^{N} \pi_j = (1-r)" style="vertical-align:-20%;" class="tex" alt="\pi_0 = \sum_{j = 0}^{N} \pi_j p_{j,0} = (1-r) \sum_{j = 0}^{N} \pi_j = (1-r)" /><br />
and, for <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_815165995cdb0f4b518b3dfe41d43860.png" title="\pi_i" style="vertical-align:-20%;" class="tex" alt="\pi_i" />,<br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_8ea2f1a1126bd752f6634ab7747dcf10.png" title="\pi_i = \pi_0 p_{0,i} + \sum_{j=1}^N \pi_j p_{j,i}" style="vertical-align:-20%;" class="tex" alt="\pi_i = \pi_0 p_{0,i} + \sum_{j=1}^N \pi_j p_{j,i}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_505a831f8124514c5a86b064b6036fa3.png" title="= (1-r) * \frac{r}{N} + r\sum_{j \in B_i} \pi_j p_{j,i}" style="vertical-align:-20%;" class="tex" alt="= (1-r) * \frac{r}{N} + r\sum_{j \in B_i} \pi_j p_{j,i}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_d750b765985175af199130ddcbdd8a2e.png" title="= (1-r) * \frac{r}{N} + r\sum_{j \in B_i} \pi_j \frac{1}{N_j}" style="vertical-align:-20%;" class="tex" alt="= (1-r) * \frac{r}{N} + r\sum_{j \in B_i} \pi_j \frac{1}{N_j}" />
</p>
<p>Divide both sides by r,</p>
<p style="text-align: center;"><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_ec71667c8d3e680d46aa625462d2d360.png" title="\frac{\pi_i}{r} = \frac{1-r}{N} + \sum_{j \in B_i} \frac{\pi_j}{r} \frac{r}{N_j}" style="vertical-align:-20%;" class="tex" alt="\frac{\pi_i}{r} = \frac{1-r}{N} + \sum_{j \in B_i} \frac{\pi_j}{r} \frac{r}{N_j}" /></p>
<p>Now, let the page rank <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_5798944b3243586b95ae3ba155cb0834.png" title="R(i) = \frac{\pi_i}{r}" style="vertical-align:-20%;" class="tex" alt="R(i) = \frac{\pi_i}{r}" /></p>
<p style="text-align: center;"><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_7020a9448eac594bbe91d4917f79849b.png" title="R(i) = \frac{1-r}{N} + \sum_{j \in B_i} R(j) \frac{r}{N_j}" style="vertical-align:-20%;" class="tex" alt="R(i) = \frac{1-r}{N} + \sum_{j \in B_i} R(j) \frac{r}{N_j}" /></p>
<p>Hence, our Markov chain approximates the original formulation of the PageRank algorithm when E is chosen to be uniform over all web pages. The rank is proportional to the stationary distribution of the chain [5].</p>
<h2>A Simple Example</h2>
<p>Consider a network consisting of 3 pages A, B, and C such that A and B are linked to C which is a dead end. Here we can see that the random surfer will end up in state C and be stuck there. The stationary probability <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_869304a74235cfee173557f95ad2056b.png" title="\pi_C" style="vertical-align:-20%;" class="tex" alt="\pi_C" /> would thus be 1 while that of A and B would be 0 as state C had accumulated all of the weight. Also, if there were an additional rank sink (such as a loop) then weight would accumulate there as well.</p>
<p style="text-align: center;">
<a href="http://ericwconner.com/wp-content/uploads/2011/04/automaton.png"><img class="alignnone size-full wp-image-388" title="automaton" src="http://ericwconner.com/wp-content/uploads/2011/04/automaton.png" alt="" width="294" height="152" /></a>
</p>
<p>To remedy this, we introduce the restart state D as well as two green edges which transform C from a dead end into a universal linker. The random surfer model assumes that C, which was a dead end, instead links to every page in the network so that its weight will be distributed fairly among those pages.</p>
<p style="text-align: center;">
<a href="http://ericwconner.com/wp-content/uploads/2011/04/automaton_extra_state.png"><img class="alignnone size-medium wp-image-385" title="automaton_extra_state" src="http://ericwconner.com/wp-content/uploads/2011/04/automaton_extra_state-300x218.png" alt="" width="300" height="218" /></a>
</p>
<p>In this example, we let the parameter r = 0.85, which is the value widely thought to be used at Google, so that, with probability (1 − r) = 0.15, the random walk goes to the restart state D. Otherwise, with probability r = 0.85, the random walk continues along an outgoing edge from the current page.  We get a system of equations for the ranks of the pages,</p>
<p style="text-align: center;">
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_148bf3ae0a60c33ac0afd728073186a4.png" title="R(A) = \frac{1 - 0.85}{3} + 0.85 * \frac{R(C)}{2}" style="vertical-align:-20%;" class="tex" alt="R(A) = \frac{1 - 0.85}{3} + 0.85 * \frac{R(C)}{2}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_a1a6aefa88e0698afebc1c607ba87ff0.png" title="R(B) = \frac{1 - 0.85}{3} + 0.85 * \frac{R(C)}{2}" style="vertical-align:-20%;" class="tex" alt="R(B) = \frac{1 - 0.85}{3} + 0.85 * \frac{R(C)}{2}" /><br />
<img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_96db9ce57a0f0ff03e27e653bba0c0f7.png" title="R(C) = \frac{1 - 0.85}{3} + 0.85(R(A) + R(B))" style="vertical-align:-20%;" class="tex" alt="R(C) = \frac{1 - 0.85}{3} + 0.85(R(A) + R(B))" />
</p>
<p>and we get R(A) = R(B) = 0.29 and R(C) = 0.42, which sum to 1 and which make intuitive sense. Since both A and B link to page C, it makes sense that page C should have double the weight of both A and B.</p>
<h2>Calculating PageRank</h2>
<p>For larger and larger numbers of pages it is not straightforward to setup and solve a system of equations for the rankings. Performing Gaussian elimination with millions of variables would take eons, even for a very fast computer [1]. Instead, define the matrix P so that the ij entry is <img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_af7794eb0db2d071e5a3b187ee01cc22.png" title="frac{1}{n_j}" style="vertical-align:-20%;" class="tex" alt="frac{1}{n_j}" /> if page j has a link to page i and 0 otherwise. We can then define a vector over the rankings which satisfies the equation,</p>
<p><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_63e2b169f3404b4324830e43685af33b.png" title="{\bf v} = P{\bf v}" style="vertical-align:-20%;" class="tex" alt="{\bf v} = P{\bf v}" /></p>
<p>Thus, the ranking vector v is an eigenvector of P with eigenvalue 1. Since some of the values in P are 0, however, this eigenvector may not be unique and there also may be many pages tied with a score of 0. To fix this, we introduce an N by N teleportation matrix each of whose entries is 1/N that corresponds to a surfer randomly choosing a URL as discussed above. With some probability r the surfer continues the random walk and with (1 − r) he chooses to teleport. We can thus define a matrix Q,</p>
<p><img src="http://ericwconner.com/wp-content/plugins/easy-latex/cache/tex_0a07369882bdd1dad8664ff8d2feb0fb.png" title="Q = rP + (1-r)T" style="vertical-align:-20%;" class="tex" alt="Q = rP + (1-r)T" /></p>
<p>This new matrix will not have any zeros and will have a unique eigenvector v with eigenvalue 1.</p>
<h2>References</h2>
<p>1] Brian White, Math 51 Lectore Notes: How Google Ranks Web Page. Stanford University, 2006.<br />
[2] Larry Page and Sergey Brin, The PageRank Citation Raking: Bringing Order to the Web. Stanford University, January 29, 1998.<br />
[3] Amy N. Langville and Carl D. Meyer, Deeper Inside PageRank. October 20, 2004.<br />
[4] Nelly Litvak, Markov Chain Analysis of the PageRank Problem. University of Twente.<br />
[5] Jia Li, Markov Chain Interpretation of Google Page Rank. December 1, 2005.<br />
[6] Weijun Xu, Tutorial Notes, Markov Chains. January 30, 2011.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=382</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Implementing rand7() using only rand5()</title>
		<link>http://ericwconner.com/?p=377</link>
		<comments>http://ericwconner.com/?p=377#comments</comments>
		<pubDate>Mon, 25 Apr 2011 21:02:25 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=377</guid>
		<description><![CDATA[Implement rand7(), a method that returns a uniform distribution over the integers 1 to 7, using only rand5(). This question is pretty interesting and not as straightforward as it first appears. For example, a first attempt might be a simple one-liner: int rand7&#40;&#41; &#123; return &#40;rand5&#40;&#41;/5&#41; * 7; &#125; The problem with this approach is [...]]]></description>
			<content:encoded><![CDATA[<blockquote><p>Implement <code>rand7()</code>, a method that returns a uniform distribution over the integers 1 to 7, using only <code>rand5()</code>.</p></blockquote>
<p>This question is pretty interesting and not as straightforward as it first appears.  For example, a first attempt might be a simple one-liner:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> rand7<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span>rand5<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">/</span><span style="color: #0000dd;">5</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">*</span> <span style="color: #0000dd;">7</span><span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>The problem with this approach is that imprecision in integer division will cause us to never get certain values between 1 and 7.  For example, the method above will only return 0 or 7 since anything between 1 and 4 divided by 5 will give an integer result of 0.  To fix this we want to avoid any kind of integer division and instead focus on using multiplication for the transformation.  One approach is to generate <code>rand25()</code> and then repeatedly use it until we get a value between 1 and 7:</p>

<div class="wp_syntax"><div class="code"><pre class="cpp" style="font-family:monospace;"><span style="color: #0000ff;">int</span> rand25<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> <span style="color: #008000;">&#40;</span>rand5<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #000040;">-</span> <span style="color: #0000dd;">1</span><span style="color: #008000;">&#41;</span><span style="color: #000040;">*</span><span style="color: #0000dd;">5</span> <span style="color: #000040;">+</span> rand5<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span>
<span style="color: #008000;">&#125;</span>
<span style="color: #0000ff;">int</span> rand7<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">int</span> n <span style="color: #000080;">=</span> rand25<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">while</span><span style="color: #008000;">&#40;</span>n <span style="color: #000080;">&gt;</span> <span style="color: #0000dd;">7</span><span style="color: #008000;">&#41;</span>
         n <span style="color: #000080;">=</span> rand25<span style="color: #008000;">&#40;</span><span style="color: #008000;">&#41;</span><span style="color: #008080;">;</span>
    <span style="color: #0000ff;">return</span> n<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span></pre></div></div>

<p>In the implementation of <code>rand25()</code> we can&#8217;t simply multiply <code>rand5()</code> by 5 since that would only give us the multiples of 5 between 1 and 25.  Adding a second call to <code>rand5()</code> allows us to map the digits appropriately.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=377</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Amazon EC2, Django, MySQL from the Ground Up</title>
		<link>http://ericwconner.com/?p=347</link>
		<comments>http://ericwconner.com/?p=347#comments</comments>
		<pubDate>Tue, 19 Apr 2011 04:32:59 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=347</guid>
		<description><![CDATA[Introduction Here I am going to show you how to get a server set up on EC2 running mysql and django from the ground up.  I often find these kinds of guides difficult to follow because they tend to focus only on one component of the process and use setups that maybe incompatible with the [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Introduction</strong></p>
<p>Here I am going to show you how to get a server set up on EC2 running mysql and django from the ground up.  I often find these kinds of guides difficult to follow because they tend to focus only on one component of the process and use setups that maybe incompatible with the tools you&#8217;re working with.  To simplify the process I am going to show a complete setup from start to finish.  There are some finer details I won&#8217;t go into like securing the server and setting up iptables, but you can head over to <a href="http://articles.slicehost.com/">Slicehost</a> for some great articles on the subject.  Ok, let&#8217;s do it.</p>
<p><strong>Amazon EC2</strong></p>
<p>The first step you need to take is get an Amazon AWS account.  Once you&#8217;ve done that, sign into the management console and select the EC2 tab.  Along the left you&#8217;ll see four headlines: Instances, Images, Elastic Block Store, and Networking &amp; Security.</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/ec2.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/ec2-1024x466.png" alt="" title="ec2" width="600" height="250" class="alignnone size-large wp-image-370" /></a></p>
<p>For now we&#8217;ll concern ourselves with the first two: instances and images.  The images tab has a sub-option: AMIs.  These Amazon Machine Images are disk images of operating systems with some useful utilities that you can launch as an instance.  An instance is just a machine image running in the elastic cloud.</p>
<p>Go ahead and select AMIs.  On that page from the &#8216;Viewing&#8217; box select &#8216;EBS Images&#8217; and filter to the platform &#8216;Ubuntu&#8217;.  We definitely want to set up an Ubuntu server and we chose EBS (Elastic Block Storage) because Amazon allows you to run really small instances, micro instances, that are virtually free. Let&#8217;s select the latest Ubuntu Hardy image and launch it as instance.</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/amis.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/amis.png" alt="" title="amis" width="600" height="203" class="alignnone size-medium wp-image-369" /></a></p>
<p>Select &#8220;micro&#8221; from the Instance Details modal dialog that pops up and hit Continue.</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/3.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/3.png" alt="" title="3" width="600" height="206" class="alignnone size-medium wp-image-364" /></a></p>
<p>Nice.  You can hit continue on the next couple of dialogs.  These settings can be configured later and aren&#8217;t important for our purposes now.  When you get to the &#8216;Create Key Pair&#8217; dialog go ahead and create and download a new key.  This pair gives you a private key that you can use to authenticate over ssh to your server the first time without a password.  I&#8217;ll call mine eric:</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/5.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/5.png" alt="" title="6" width="600" height="406" class="alignnone size-medium wp-image-367" /></a></p>
<p>We need to add rules to our security group that allow access to SSH and HTTP.  The ones defined in the image below allow ssh and http access from anywhere.</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/6.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/6.png" alt="" title="6" width="600" height="406" class="alignnone size-medium wp-image-367" /></a></p>
<p>On the last tab we can review the changes and then hit Launch.  Wooo.  Now we are getting somewhere.</p>
<p><a href="http://ericwconner.com/wp-content/uploads/2011/04/7.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/7.png" alt="" title="6" width="600" height="406" class="alignnone size-medium wp-image-367" /></a></p>
<p>It will take a minute for the new instance to launch, but once up it will show in your instances pane.  This page shows the details we just configured for the instance as well as a public DNS we can use to access it.  Let&#8217;s go ahead and fire up an ssh session to our server.  Navigate to wherever you downloaded the private key and initialize the session like so:</p>
<pre class="shell">
> ssh -i eric.pem ubuntu@ec2-##-##-##-##.compute-1.amazonaws.com
</pre>
<p>Cool.  Now that we have a session we&#8217;ll want to first make sure aptitude is up to date:</p>
<pre class="shell">
> sudo aptitude update
</pre>
<p>Once we&#8217;ve done that let&#8217;s get cracking and install some utilities:</p>
<pre class="shell">
> sudo aptitude install python-django
> sudo aptitude install mysql-server
> sudo aptitude install python-mysqldb
> sudo aptitude install libapache2-mod-wsgi
</pre>
<p><strong>Create a Django Application</strong><br />
Run django-admin to create a new project in a directory under your home directory:</p>
<pre class="shell">
> mkdir srv
> cd srv
> django-admin startproject mysite
</pre>
<p>You&#8217;ll need to configure your django settings to suit your database and application needs.</p>
<p><strong>Configuring mod_wsgi</strong><br />
Alright now that we have a starter django app going let&#8217;s configure <a href="http://code.google.com/p/modwsgi/">mod_wsgi</a> to serve our application.  We need to enable a site on apache to do this so let&#8217;s create a virtual host.</p>
<pre class="shell">
> sudo nano /etc/apache2/sites-available/mysite.com
</pre>
<p>Copy the following into the new file:</p>
<pre class="shell">
&lt;VirtualHost *:80&gt;
        ServerName mysite.com
        ServerAlias www.mysite.com
        WSGIScriptAlias / /home/demo/public_html/mysite.com/mysite.wsgi
&lt;/VirtualHost&gt;
</pre>
<p>Now that we&#8217;ve defined a wsgi script to serve our app we need to create that script,</p>
<pre class="shell">
> nano /home/demo/public_html/mysite.com/mysite.wsgi
</pre>
<p>Copy the following configuration to that file</p>
<pre class="shell">
import os
import sys

sys.path.append('/home/demo/public_html/mysite.com/')

os.environ['DJANGO_SETTINGS_MODULE'] = 'mysite.settings'

import django.core.handlers.wsgi

application = django.core.handlers.wsgi.WSGIHandler()
</pre>
<p>Finally we need to enable the site and reload the apache configuration</p>
<pre class="shell">
> sudo a2ensite mysite.com
> sudo /etc/init.d/apache2 reload
</pre>
<p>That&#8217;s it!  You should now see the django start page when you navigate to your site.<br />
&nbsp;</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=347</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Paperless</title>
		<link>http://ericwconner.com/?p=342</link>
		<comments>http://ericwconner.com/?p=342#comments</comments>
		<pubDate>Mon, 18 Apr 2011 17:37:58 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=342</guid>
		<description><![CDATA[Paperless is a code submission and review tool for the CS106 program at Stanford that Jeremy Keeshin and I built together. It supports drag and drop file submission by students. Section leaders can then review student submissions and add comments by selecting lines of the code. We even have keyboard shortcuts and markdown!]]></description>
			<content:encoded><![CDATA[<p><a href="http://paperless.stanford.edu/">Paperless</a> is a code submission and review tool for the CS106 program at Stanford that <a href="http://thekeesh.com/">Jeremy Keeshin</a> and I built together.  It supports drag and drop file submission by students.  Section leaders can then review student submissions and add comments by selecting lines of the code.  We even have keyboard shortcuts and markdown! </p>
<p style="text-align: center;"><a href="http://ericwconner.com/wp-content/uploads/2011/04/paperless.png"><img src="http://ericwconner.com/wp-content/uploads/2011/04/paperless.png" alt="" title="paperless" width="400" height="202" class="alignnone size-full wp-image-343" /></p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=342</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C++ String Concatenation</title>
		<link>http://ericwconner.com/?p=337</link>
		<comments>http://ericwconner.com/?p=337#comments</comments>
		<pubDate>Mon, 18 Apr 2011 17:19:18 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[C++]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=337</guid>
		<description><![CDATA[This is an interesting note about how strings are handled in C++. It turns out that if you attempt to concatenate a string literal and a character, you don&#8217;t get the result you expect. string str = &#34;ab&#34; + 'c'; cout &#60;&#60; str &#60;&#60; endl; &#160; char ch = 'c'; string str1 = &#34;ab&#34;; string [...]]]></description>
			<content:encoded><![CDATA[<p>This is an interesting note about how strings are handled in C++.  It turns out that if you attempt to concatenate a string literal and a character, you don&#8217;t get the result you expect.</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"><span style="color: #993333;">string</span> str <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;ab&quot;</span> <span style="color: #339933;">+</span> <span style="color: #ff0000;">'c'</span><span style="color: #339933;">;</span>
<span style="color: #000066;">cout</span> <span style="color: #339933;">&lt;&lt;</span> str <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span>
&nbsp;
<span style="color: #993333;">char</span> ch <span style="color: #339933;">=</span> <span style="color: #ff0000;">'c'</span><span style="color: #339933;">;</span>
<span style="color: #993333;">string</span> str1 <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;ab&quot;</span><span style="color: #339933;">;</span>
<span style="color: #993333;">string</span> str2 <span style="color: #339933;">=</span> str1 <span style="color: #339933;">+</span> ch<span style="color: #339933;">;</span>
<span style="color: #000066;">cout</span> <span style="color: #339933;">&lt;&lt;</span> str2 <span style="color: #339933;">&lt;&lt;</span> endl<span style="color: #339933;">;</span></pre></div></div>

<p>This code produces the following output:</p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;">ed before SaveGraphicsState
abc</pre></div></div>

<p>The first value printed is obviously not the concatenation we expected.  Now, this difference occurs because the C++ <code>string</code> class overloads the <code>+</code> operator.  When we use the string literal <code>"ab"</code> the compiler interprets this value as a <code>const char*</code> (a C-style string).  When we attempt to add <code>'c'</code> to it, the compiler converts the character to its integer equivalent and adds it to the <code>char*</code> pointer.  Our string now points at some different location in memory and when we print it out it simply prints whatever it found there up to a null value.</p>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=337</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Phenomenal Advice from AskHN</title>
		<link>http://ericwconner.com/?p=205</link>
		<comments>http://ericwconner.com/?p=205#comments</comments>
		<pubDate>Wed, 22 Dec 2010 06:26:14 +0000</pubDate>
		<dc:creator>eric</dc:creator>
				<category><![CDATA[Life]]></category>

		<guid isPermaLink="false">http://ericwconner.com/?p=205</guid>
		<description><![CDATA[I&#8217;m reblogging this because I think it is incredible advice: Ask HN: What were your naivetes in your twenties? http://news.ycombinator.com/item?id=1474094 Reply by DanielBMarkham: - Shiny things are nowhere as much fun after you get them as before, even if they have some value. So yes, that Kindle or iPad or whatever will have a real [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m reblogging this because I think it is incredible advice:</p>
<p>Ask HN: What were your naivetes in your twenties?</p>
<p>http://news.ycombinator.com/item?id=1474094</p>
<p>Reply by <a href="http://searchyc.com/user/DanielBMarkham">DanielBMarkham</a>:</p>
<blockquote>
<div class="text">
<p><span style="color: #000000;">- Shiny things are nowhere as much fun after you  get them as before, even if they have some value. So yes, that Kindle  or iPad or whatever will have a real use, and you will be marginally  happier with it than without, but not as much as you think</span></p>
<p><span style="color: #000000;">-  You can talk yourself into (or out of) anything. The only difference  between smart people and other people is that smart people do this with  bigger words and more complex arguments. Be confident, but also assume  that you are broken in ways you can never spot. Find some ways to get a  checksum on life decisions every now and then.</span></p>
<p><span style="color: #000000;">-  You don&#8217;t need very much at all. Maybe a laptop computer and a couple  changes of clothes. Pictures and videos of your life. That&#8217;s about it.</span></p>
<p><span style="color: #000000;">-  Nothing will ever replace experiences. No matter how big the car, nice  the house, or professional-looking the suit, it&#8217;s never going to be as  much fun or mean as much later as the experiences you have in life. And  it&#8217;s not just <em>having</em> the experience, it&#8217;s looking forward to  them, and planning them, and making pictures, movies, and blogs out of  them. The best part, oddly, may be the planning. So planning a  200-dollar trip to the beach in the Fall with people you love may give  you many hours of happiness this summer &#8212; along with the fun of the  trip itself.</span></p>
<p><span style="color: #000000;">- Learn to keep picking  topics and immersing yourself in them. Most everybody will say to drop  out and become part of the system &#8212; 9-5 job and TV/games/internet in  the evening. If you want a life you could sleep through, that&#8217;s fine.  But if you want a life you can tell stories about, keep reinventing  yourself. And that means constantly learning.</span></p>
<p><span style="color: #000000;">-  Lots of shit in life that once looked dumb or stupid opens up into this  huge panorama of beauty once you learn the rules. In so many things you  are like the guy who never saw a baseball game going to the world  series. You kind of get it, but it all seems silly. You don&#8217;t know the  rules. Decide to learn how to appreciate music, for instance. Get a few  college lectures on tape, get some good music to listen to, hang out  with folks who are music connoisseurs. The more you know about various  art forms, the richer your life is.</span></p>
<p><span style="color: #000000;">- Forget philosophy and meaning-of-life shit. You&#8217;re too young. For now, you are what you <em>do</em>. Go do something worthwhile</span></p>
<p><span style="color: #000000;">- Stick to a daily exercise routine at all costs</span></p>
<p><span style="color: #000000;">-  If you are changing and getting better, that means you are changing  friends too. This was very difficult for me, but you can&#8217;t hang out with  the same folks and expect to become a better person. There are  exceptions, of course, but to a large degree your life is controlled by  whom you choose to be friends and hang out with. Be aware that you don&#8217;t  want to be the same person at 30 as you were at 20. I&#8217;m not saying be  an asshole &#8212; keep being friendly by all means &#8212; but be very careful  who you hold yourself up against as &#8220;normal&#8221;</span></p>
<p><span style="color: #000000;">- Dating is a numbers game, like a lot of other things. Learn the skills of dating and don&#8217;t sweat picking up chicks (or guys)</span></p>
<p><span style="color: #000000;">-  Concentrate on your weaknesses. Make them stronger. When you get to  your 30s you can work from your strengths, but there has to be some time  in your life to work on shit you suck at, and for me it was when I had  the most motivation, my 20s.</span></p>
<p><span style="color: #000000;">-  Speaking of which, you have to learn management. No matter what you do,  there will be a manager. Even if you don&#8217;t want to be one, you have to  understand what the job is like to help out your manager. Being a good  leader means being a good servant. This concept sounded easy (or facile)  to me in my 20s, but proved hard to apply in practice.</span></p>
<p><span style="color: #000000;">- You are never ready for kids. Have them early while you have energy. Read all the <strong>books</strong> about kids if you must, but realize that creating a replacement is  about the most biologically easy thing you could do. After all,  evolution has been working on making you a great gene transferral and  primate-raising machine, so don&#8217;t get paranoid and neurotic about all  the latest parenting fashion. Use some sense.</span></p>
<p><span style="color: #000000;">-  Everybody wants to be a rock star and win the lottery. Nobody ever  does, and the ones that do end up destroying their life. Realize slow  success is a million times better than overnight success.</span></p>
<p><span style="color: #000000;">-  Much of the stuff in life that normal people do is geared around  killing time by distracting you with shiny things of no value. You may  never be able to fight this completely, but you should at least deeply  understand it and how it affects your goals</span></p>
<p><span style="color: #000000;">- <em>Create</em>.  With a passion. There are two major kinds of people in this world,  consumers and creators. The herd will push you to consume, life will  push you to consume, consumption is the easy and default path, but true  joy and a full life come from creating. It does not matter one bit how   many people like what you create, just create. Write. Blog. Make videos.  Make a movie. Write a program. The longer the format and the more  creativity involved, the more you are going to turn on and exercise key  parts of your brain. Nobody wants to be 80 and only have stories of  being at the office, but fuck, if you were at the office <em>creating something</em> at least you tried to make a difference. I&#8217;d rather be that guy than  the one who watched Sumo wrestling everyday (or played 20,000 hours of  WoW during his 20s) The only thing you&#8217;re going to have at the end of  your life are the decisions you made, the things you created, and  memories. Learn to maximize these things.</span></div>
</blockquote>
]]></content:encoded>
			<wfw:commentRss>http://ericwconner.com/?feed=rss2&#038;p=205</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
