<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkUBQnc6eip7ImA9WhRRFE4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299</id><updated>2011-11-27T15:57:33.912-08:00</updated><category term="traffic-violations" /><category term="mobile" /><category term="processing" /><category term="error-codes" /><category term="radio" /><category term="java" /><category term="web" /><category term="proce55ing" /><category term="social-media" /><category term="ebay" /><category term="politics" /><category term="annoyance" /><category term="swype" /><category term="bookmarks" /><category term="analytics" /><category term="home-ownership" /><category term="delicioius" /><category term="life" /><category term="ffi" /><category term="psychology" /><category term="android" /><category term="twitterfeed" /><category term="xm" /><category term="appengine" /><category term="python" /><category term="american dad" /><category term="spam" /><category term="rss" /><category term="twitter" /><category term="python sockets networks algorithms" /><category term="optimization" /><category term="speeding" /><category term="email" /><category term="fun" /><category term="code" /><category term="errno" /><category term="google" /><title>Mens agitat molem</title><subtitle type="html">Technological musings by Jason Mobarak.</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://csjam.blogspot.com/" /><author><name>jam</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>24</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/Csjam" /><feedburner:info uri="csjam" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUcGQH49fSp7ImA9Wx5RF0w.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-880452798603103489</id><published>2010-08-24T22:10:00.000-07:00</published><updated>2010-08-24T22:10:21.065-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-24T22:10:21.065-07:00</app:edited><title>Convert OSStatus to a human readable string</title><content type="html">It's actually fairly easy to get something useful / readable out of an &lt;a href="http://zathras.de/angelweb/blog-carbon-for-the-cocoa-guy-oserror.htm"&gt;OSStatus&lt;/a&gt; code.  This is a simple no-compilation Python script to convert an error code to it's description. &amp;nbsp;It uses&lt;i&gt; "two poorly documented but very usefull functions"&lt;/i&gt; — &lt;a href="http://www.dribin.org/dave/braindump/osx/human_readable_errors"&gt;GetMacOSStatusErrorString and GetMacOSStatusCommentString&lt;/a&gt;&lt;span class="Apple-style-span" style="font-family: monospace; font-size: 12px; white-space: pre;"&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;br /&gt;
Example output:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/547970.js?file=example.txt"&gt;
&lt;/script&gt;&lt;br /&gt;
And the script:&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/547970.js?file=osstatus.py"&gt;
&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-880452798603103489?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Wdm21osxz-nfmkJgIzaeSj4aFFU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Wdm21osxz-nfmkJgIzaeSj4aFFU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Wdm21osxz-nfmkJgIzaeSj4aFFU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Wdm21osxz-nfmkJgIzaeSj4aFFU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/Y0tMnlKUUqc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/880452798603103489/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/08/convert-osstatus-to-human-readable.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/880452798603103489?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/880452798603103489?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/Y0tMnlKUUqc/convert-osstatus-to-human-readable.html" title="Convert OSStatus to a human readable string" /><author><name>jam</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/08/convert-osstatus-to-human-readable.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4NRXozfyp7ImA9Wx5REE8.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-3874266354741959727</id><published>2010-08-16T22:45:00.000-07:00</published><updated>2010-08-16T22:46:34.487-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-16T22:46:34.487-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="java" /><category scheme="http://www.blogger.com/atom/ns#" term="mobile" /><category scheme="http://www.blogger.com/atom/ns#" term="swype" /><category scheme="http://www.blogger.com/atom/ns#" term="processing" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><title>Naïve Swype Implementation (&amp; How It Works)</title><content type="html">How does Swype work?  I don't know for sure, but I came up with a fairly simple approximation of Swype's behavior on Android phones.  Which with a little bit of tweaking (maybe some more math and a better set of dictionaries) it could probably get a lot closer to approximating Swype.&lt;br /&gt;
&lt;br /&gt;
&lt;div id="Swype_container"&gt;&lt;script src="http://www.java.com/js/deployJava.js" type="text/javascript"&gt;
&lt;/script&gt;&lt;script type="text/javascript"&gt;
          /* &lt;![CDATA[ */

          var attributes = { 
            code: 'Swype.class',
            archive: 'http://www.cs.unm.edu/~jmob/blogger/swype_applet/Swype.jar',
            width: 450, 
            height: 400,
            image: 'loading.gif'
          };
          var parameters = { };
          var version = '1.5';
          deployJava.runApplet(attributes, parameters, version);

          /* ]]&gt; */
        
&lt;/script&gt;&lt;/div&gt;&lt;br /&gt;
This is implemented using &lt;a href="http://processing.org/"&gt;Proce55ing&lt;/a&gt; which will export Proce55ing code to a Java applet (&lt;a href="http://gist.github.com/522307#file_swype.pde"&gt;full source&lt;/a&gt;&amp;nbsp;listing).&lt;br /&gt;
&lt;br /&gt;
As for how the implementation works, I started with a &lt;i&gt;word set&lt;/i&gt;&amp;nbsp;which holds a collection of words and word prefixes. &amp;nbsp;The &lt;i&gt;classify&lt;/i&gt;&amp;nbsp;operation serves to tell me if the string I am holding is a &lt;i&gt;complete&lt;/i&gt;&amp;nbsp;word, a &lt;i&gt;partial &lt;/i&gt;word, an &lt;i&gt;incomplete&lt;/i&gt;&amp;nbsp;word, or both.&lt;br /&gt;
&lt;br /&gt;
A returned classification is also able to communicate it's frequency (ranking in &lt;a href="http://en.wiktionary.org/wiki/Wiktionary:Frequency_lists"&gt;frequency&lt;/a&gt; of usage in common english text). &amp;nbsp;These frequencies were acquired from &lt;a href="http://www.gutenberg.org/etext/3201"&gt;Project Gutenburg&lt;/a&gt;. &amp;nbsp;The frequency list is a frequency count from &lt;a href="http://en.wikipedia.org/wiki/Usenet"&gt;Usenet&lt;/a&gt;&amp;nbsp;postings, so it's a bit odd and doesn't include some common words (most notably some connecting words). &amp;nbsp;The other dictionary is a list of the 3000 most common English words.&lt;br /&gt;
&lt;br /&gt;
Keep this in mind when you play with the sample, the dictionaries aren't perfect. &amp;nbsp;The naïve implementation along with the poor dictionaries give the demonstration some&amp;nbsp;peculiarities.&lt;br /&gt;
&lt;br /&gt;
Regargless, the &lt;i&gt;populate&lt;/i&gt;&amp;nbsp;operation of the &lt;i&gt;word set&lt;/i&gt;&amp;nbsp;loads these words, their frequencies, and all &lt;i&gt;prefixes&lt;/i&gt;&amp;nbsp;leading up to the word in a dictionary. &amp;nbsp;For example the word THEY is loaded in as T (stored as incomplete), TH (incomplete), THE (complete &amp;amp; incomplete) and THEY (complete) along with the corresponding word frequencies.&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/522307.js?file=Swype-listing-1.pde"&gt;
&lt;/script&gt;&lt;br /&gt;
Next is all the connecting glue for Proce55ing.  The &lt;i&gt;SwypeState&lt;/i&gt;&amp;nbsp;class maintains the &lt;i&gt;keyboard hit collector,&lt;/i&gt;&amp;nbsp;the&amp;nbsp;&lt;i&gt;word set&lt;/i&gt;&lt;i&gt;,&amp;nbsp;&lt;/i&gt;and the bits that draw the keyboard and the pen. &amp;nbsp;The &lt;i&gt;keyboard&lt;/i&gt;&amp;nbsp;logic and the &lt;i&gt;keyboard&lt;/i&gt;&amp;nbsp;&lt;i&gt;hit collector&lt;/i&gt;&amp;nbsp;are fairly boring, but suffice to say, they draw the keyboard and accurately collect what keys where &lt;i&gt;hit&lt;/i&gt;&amp;nbsp;when drawing over the keyboard.&lt;br /&gt;
&lt;br /&gt;
&lt;script src="http://gist.github.com/522307.js?file=Swype-listing-2.pde"&gt;
&lt;/script&gt;&lt;br /&gt;
Probably the most interesting part of the implementation is figuring out what words where &lt;i&gt;Swyped&lt;/i&gt;. &amp;nbsp;The system&amp;nbsp;passes an event to the &lt;i&gt;key hit collector&lt;/i&gt;&amp;nbsp;when a word is finished, this initiates a seach through the &lt;i&gt;word set&lt;/i&gt;&amp;nbsp;for potential words. &amp;nbsp;For a given word like "THEY" the actual keys swiped can vary widely.&lt;br /&gt;
&lt;br /&gt;
Here are some examples (these all map to "THEY"):&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/_CeryDY5B7Rk/TGoUWLa1_QI/AAAAAAAABpA/XHUt9_fD7Bg/s1600/swype-1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_CeryDY5B7Rk/TGoUWLa1_QI/AAAAAAAABpA/XHUt9_fD7Bg/s320/swype-1.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;T, Y, H, G, F, E, R, T, Y&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGoVVPlTX3I/AAAAAAAABpI/7U98GdLL0fY/s1600/swype-2.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGoVVPlTX3I/AAAAAAAABpI/7U98GdLL0fY/s320/swype-2.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;T, G, H, N, C, D, S, E, R, F, C, X, S, W, T, G, V, C, S, E, Y&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/_CeryDY5B7Rk/TGoV63CHdpI/AAAAAAAABpQ/kiUa9C3gvW0/s1600/swype-3.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/_CeryDY5B7Rk/TGoV63CHdpI/AAAAAAAABpQ/kiUa9C3gvW0/s320/swype-3.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;T, Y, H, J, K, K, J, H, G, F, D, S, A, Q, W, E, R, T, Y&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"&gt;&lt;br /&gt;
&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="font-family: inherit;"&gt;So, you have some things that don't really look like words at all. &amp;nbsp;However, the &lt;i&gt;word set&lt;/i&gt;&amp;nbsp;loaded with all the word prefixes sorts this out. &amp;nbsp;It does this using a simple search that slowly builds up a set of prefixes that map to partial words, or complete words (which get recorded), while throwing away things that map to nothing. &amp;nbsp;As a new letter is examined from the list of hit keys it is added to each of the previously collected prefixes.&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;In this manner words like OR, OUR, OUT that require one vertical swipe can be detected. &amp;nbsp;This word overlap presents another problem though: which word has priority?&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The first&amp;nbsp;strategy&amp;nbsp;used to resolve overlapping words is a sort based on match length. &amp;nbsp;With the idea that the longest match is probably the word the user was trying to spell. &amp;nbsp;For example, a word like THERE will come up with THE as a &lt;i&gt;complete&lt;/i&gt;&amp;nbsp;prefix when THERE was then intended swipe because of the swipe length.&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;The second strategy&amp;nbsp;is where the word frequencies come in to play, they attempt to sort the list of hit words by their frequency. &amp;nbsp;Words with a higher frequency in the English language should bubble to the top.&lt;/div&gt;&lt;br /&gt;
&lt;script src="http://gist.github.com/522307.js?file=Swype-listing-3.pde"&gt;
&lt;/script&gt;&lt;br /&gt;
Improvements:&lt;br /&gt;
&lt;ul&gt;&lt;li&gt;&lt;i&gt;Better dictionaries&lt;/i&gt;:&amp;nbsp;Possibly one that lists all forms of a word with the same frequency (e.g. be, being, been).&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Fat finger search&lt;/i&gt;: extend and trim each swipe path so that less accuracy is needed. &amp;nbsp;That is, a &lt;i&gt;what's around you&lt;/i&gt;&amp;nbsp;operation could be added to each key to get &lt;i&gt;many&lt;/i&gt;&amp;nbsp;more paths to search that could lead to the desired word.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Spell checking&lt;/i&gt;: for people that don't know how to spell, predictive text can be frustrating. &amp;nbsp;A misspelling dictionary could be really using to help with this.&lt;/li&gt;
&lt;li&gt;&lt;i&gt;Markov chain&lt;/i&gt;: I don't know how&amp;nbsp;effective&amp;nbsp;this would be but since &lt;i&gt;Markov Chains&lt;/i&gt;&amp;nbsp;can be used to generate English text it seems like they could be used to select a more likely next word.&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;The full source code is available at &lt;a href="http://gist.github.com/522307#file_swype.pde"&gt;github.com&lt;/a&gt;.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-3874266354741959727?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/487WMWK1EqjPSOIEjuS8n2liiEM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/487WMWK1EqjPSOIEjuS8n2liiEM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/487WMWK1EqjPSOIEjuS8n2liiEM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/487WMWK1EqjPSOIEjuS8n2liiEM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/niogPDYAFeo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/3874266354741959727/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/08/naive-swype-implementation-how-it-works.html#comment-form" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3874266354741959727?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3874266354741959727?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/niogPDYAFeo/naive-swype-implementation-how-it-works.html" title="Naïve Swype Implementation (&amp; How It Works)" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_CeryDY5B7Rk/TGoUWLa1_QI/AAAAAAAABpA/XHUt9_fD7Bg/s72-c/swype-1.png" height="72" width="72" /><thr:total>4</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/08/naive-swype-implementation-how-it-works.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUAASX84fip7ImA9Wx5SFUU.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-2315654369619454067</id><published>2010-08-11T20:43:00.001-07:00</published><updated>2010-08-11T21:35:48.136-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-11T21:35:48.136-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="annoyance" /><category scheme="http://www.blogger.com/atom/ns#" term="email" /><category scheme="http://www.blogger.com/atom/ns#" term="spam" /><title>What happens when your email "unsubscribe" button doesn't work...</title><content type="html">&lt;div style="text-align: left;"&gt;What happens when your email "unsubscribe" button doesn't work?  You get marked as spam.  I'm looking at &lt;b&gt;you &lt;/b&gt;HP.&lt;/div&gt;
&lt;blockquote&gt;"6 months and a million dollars"
&lt;/blockquote&gt;
...a common saying from a fellow co-worker and previous HP employee... well, 6 months and million dollars later HP, your unsubscribe button doesn't work and I'm about to start clicking the &lt;i&gt;mark as spam&lt;/i&gt; button.&lt;div&gt;

&lt;a href="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGNvW2rvlcI/AAAAAAAABo4/0AOmLuFvGQ0/s1600/hpspam.PNG"&gt;&lt;img src="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGNvW2rvlcI/AAAAAAAABo4/0AOmLuFvGQ0/s400/hpspam.PNG" border="0" alt="" id="BLOGGER_PHOTO_ID_5504365608003671490" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 400px; height: 223px; " /&gt;&lt;/a&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span"&gt;&lt;u&gt;
&lt;/u&gt;&lt;/span&gt;&lt;/div&gt;&lt;a href="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGNvW2rvlcI/AAAAAAAABo4/0AOmLuFvGQ0/s1600/hpspam.PNG"&gt;&lt;/a&gt;I have reservations about clicking this button since it's not technically &lt;i&gt;spam&lt;/i&gt;-- and I don't want to pollute Google's cache of data of what's considered spam.  Really, I need a &lt;i&gt;"I don't want these emails sent to me anymore, figure out how to get rid of them"&lt;/i&gt; button.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;Alas, that doesn't exist.  Instead I have to resort to click on a damn "unsubscribe" button that's squirreled away at the bottom of the email.  Then, two weeks later, I get to figure out that HP &lt;b&gt;really&lt;/b&gt; doesn't want to forget about me.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;I'm like that one girlfriend you wish you'd never dumped, except, for HP, it's really best if we don't see each other again.&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-size: x-small;"&gt;(Maybe I'll go in to my filters and &lt;a href="http://en.wikipedia.org/wiki/Kill_file"&gt;kill file&lt;/a&gt; them, but that'll result in even more annoyance.)&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-2315654369619454067?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/x4ARL7GR5XDZOt8JaKAdiZizAgk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x4ARL7GR5XDZOt8JaKAdiZizAgk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/x4ARL7GR5XDZOt8JaKAdiZizAgk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/x4ARL7GR5XDZOt8JaKAdiZizAgk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/bmNdnPbNE2I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/2315654369619454067/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/08/what-happens-when-your-email.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2315654369619454067?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2315654369619454067?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/bmNdnPbNE2I/what-happens-when-your-email.html" title="What happens when your email &quot;unsubscribe&quot; button doesn't work..." /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_CeryDY5B7Rk/TGNvW2rvlcI/AAAAAAAABo4/0AOmLuFvGQ0/s72-c/hpspam.PNG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/08/what-happens-when-your-email.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEUEQ38-eSp7ImA9WxFbEko.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-5227968261120976677</id><published>2010-07-01T07:32:00.000-07:00</published><updated>2010-07-04T13:43:22.151-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-04T13:43:22.151-07:00</app:edited><title>Buzz Bookmarklet</title><content type="html">&lt;p&gt;I found it odd that I couldn't easily find a "bookmarlet" for Buzz that I could easily drag into my bookmarks bar.&lt;/p&gt;&lt;p&gt;Maybe I'm blind, or wasn't looking in the right places... so I wrote one.  It's probably broken in some cases, and is fairly rudimentary, but here it is:&lt;/p&gt;&lt;p&gt;&lt;a href="javascript:e=encodeURIComponent;b='http://www.google.com/buzz/post';u=e(document.location.href);els=document.getElementsByTagName('meta');o=null;for(i=0;i&amp;lt;els.length;i++){if(els[i].name=='description'){o=els[i];break;}}m='';if(o!=null)m=e(o.content);a='resizable=0,scrollbars=0,width=690,height=415';window.open(b+'?url='+u+'&amp;message='+m,'_blank',a);void(0)"&gt;&lt;img src="http://www.gstatic.com/buzz/api/images/buzz-link.png" height="16" width="15"/&gt;Post to Buzz&lt;/a&gt; (drag to bookmarks bar)&lt;/p&gt;
&lt;p&gt;If interested, here's the code:&lt;/p&gt;
&lt;script src="http://gist.github.com/460026.js?file=buzz_bookmarklet.js"&gt;&lt;/script&gt;
&lt;p&gt;This is a more fancy (shorter) version that uses querySelector:&lt;/p&gt;
&lt;script src="http://gist.github.com/460026.js?file=buzz_bookmarklet_qs.js"&gt;&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-5227968261120976677?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/UDXJuGQ1_ZGdfFCMahpQ2BLkT14/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UDXJuGQ1_ZGdfFCMahpQ2BLkT14/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/UDXJuGQ1_ZGdfFCMahpQ2BLkT14/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/UDXJuGQ1_ZGdfFCMahpQ2BLkT14/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/BFpeJe3X4PQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/5227968261120976677/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/07/buzz-bookmarklet.html#comment-form" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5227968261120976677?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5227968261120976677?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/BFpeJe3X4PQ/buzz-bookmarklet.html" title="Buzz Bookmarklet" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>2</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/07/buzz-bookmarklet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0IDSXw9eCp7ImA9WxFUGU0.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-3570744862816725983</id><published>2010-02-09T22:12:00.000-08:00</published><updated>2010-06-30T07:52:58.260-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-30T07:52:58.260-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="optimization" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="web" /><title>Silly Space Optimization on Google's Home Page?</title><content type="html">&lt;p&gt;According to &lt;a href="http://twitter.com/chrisskelton"&gt;@chrisskelton&lt;/a&gt; and &lt;a href="http://twitter.com/wkvong"&gt;@wkvong&lt;/a&gt;, Google leaves off the ending &lt;code&gt;&amp;lt;/html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;/body&amp;gt;&lt;/code&gt; tags from their home page to optimize for space:&lt;/p&gt;&lt;!-- QuoteURL styled embed start --&gt; &lt;blockquote class="quoteurl-block" style="margin:0;padding:0;"&gt; &lt;ol class="quoteurl-quote" style="background-color:#fff;color:#000;padding:.4em;border:1px solid #888;-moz-border-radius: .5em;border-radius: .5em;width:90%;max-width:700px;margin:auto;"&gt; &lt;li class="hentry status u-chrisskelton" style="clear:both;list-style:none;padding-top:.7em;padding-bottom:.7em;border-top:1px dashed #ccc;position:relative;background-color:#fff;"&gt; &lt;div class="thumb vcard author" style="float:left;margin-right:1em;margin-left:.5em;"&gt; &lt;a class="url" href="http://twitter.com/chrisskelton"&gt;&lt;!--&lt;img width="48" height="48" style="border:none;" src="http://a3.twimg.com/profile_images/678917431/me_normal.png" class="photo fn" alt="Christopher Skelton"/&gt;--&gt;&lt;/a&gt; &lt;/div&gt; &lt;div class="status-body" style="margin-right:30px;padding-right:1em;"&gt; &lt;a class="author" style="font-weight:bold;" title="Christopher Skelton" href="http://twitter.com/chrisskelton"&gt;chrisskelton&lt;/a&gt; &lt;span class="entry-content" style="font-style:normal"&gt;Today I learned that Google excludes the &amp;lt;/body&amp;gt; and &amp;lt;/html&amp;gt; tags from their main page to save 18 bytes.&lt;/span&gt; &lt;span class="meta entry-meta" style="color:#888;font-family:georgia;font-size:0.8em;font-style:italic;"&gt; &lt;a rel="bookmark" class="entry-date" style="color:#888;text-decoration:none;" href="http://twitter.com/chrisskelton/status/8840923332" onmouseover="this.style.textDecoration='underline';" onmouseout="this.style.textDecoration='none';"&gt; &lt;span title="2010-02-09 04:30:02" class="published"&gt;09 Feb 2010&lt;/span&gt; &lt;/a&gt; &lt;span&gt;from web&lt;/span&gt; &lt;/span&gt; &lt;/div&gt; &lt;div class="actions" style="position:relative;clear:both;"&gt;&lt;/div&gt; &lt;/li&gt; &lt;li class="hentry status u-wkvong" style="clear:both;list-style:none;padding-top:.7em;padding-bottom:.7em;border-top:1px dashed #ccc;position:relative;background-color:#fff;"&gt; &lt;div class="thumb vcard author" style="float:left;margin-right:1em;margin-left:.5em;"&gt; &lt;a class="url" href="http://twitter.com/wkvong"&gt;&lt;!--&lt;img width="48" height="48" style="border:none;" src="http://a3.twimg.com/profile_images/597087929/glider_normal.png" class="photo fn" alt="Wai Keen Vong"/&gt;--&gt;&lt;/a&gt; &lt;/div&gt; &lt;div class="status-body" style="margin-right:30px;padding-right:1em;"&gt; &lt;a class="author" style="font-weight:bold;" title="Wai Keen Vong" href="http://twitter.com/wkvong"&gt;wkvong&lt;/a&gt; &lt;span class="entry-content" style="font-style:normal"&gt;You know Google is crazy because Google's home page doesn't close its &amp;lt;body&amp;gt; or &amp;lt;html&amp;gt; tags for performance&lt;/span&gt; &lt;span class="meta entry-meta" style="color:#888;font-family:georgia;font-size:0.8em;font-style:italic;"&gt; &lt;a rel="bookmark" class="entry-date" style="color:#888;text-decoration:none;" href="http://twitter.com/wkvong/status/8880782944" onmouseover="this.style.textDecoration='underline';" onmouseout="this.style.textDecoration='none';"&gt; &lt;span title="2010-02-10 01:29:53" class="published"&gt;10 Feb 2010&lt;/span&gt; &lt;/a&gt; &lt;span&gt;from web&lt;/span&gt; &lt;/span&gt; &lt;/div&gt; &lt;div class="actions" style="position:relative;clear:both;"&gt;&lt;/div&gt; &lt;/li&gt; &lt;/ol&gt; &lt;/blockquote&gt;&lt;small class="quoteurl-cite" style="float:right;"&gt; -- &lt;a href="http://www.quoteurl.com/tsgrk"&gt;this quote&lt;/a&gt; was brought to you by &lt;a href="http://www.quoteurl.com"&gt;quoteurl&lt;/a&gt;&lt;/small&gt; &lt;br class="quoteurl-end" style="clear:both;" /&gt; &lt;!-- QuoteURL embed end --&gt;&lt;p&gt;Indeed, if you check out the source code for the Google home page it's not there:&lt;/p&gt;&lt;p&gt;&lt;img src="http://www.cs.unm.edu/~jmob/img/goog-no-htm-body.png"&gt;&lt;/p&gt;&lt;p&gt;To put this in perspective: according to &lt;a href="http://searchenginewatch.com/2156461"&gt;SearchEngineWatch.com&lt;/a&gt; Google gets about &lt;code&gt;91 million&lt;/code&gt; hits per day (in 2006).  Assuming all those searches start on the home page (and there's no caching involved), that's:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;18 bytes * 91,000,000 hits = 1638000000 bytes
                             1599609.38 kilobytes
                             1562.12    megabytes
                             1.53       gigabytes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;If we go by monthly hits:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;18 bytes * 2,733,000,000 hits = 49194000000 bytes
                                48041015.63 kilobytes
                                46915.05    megabytes
                                45.82       gigabytes
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;That's 1.5 gigabytes per-day (or 45.82 gigabytes per-month) that Google doesn't have to send, it doesn't pay for, and consumers don't pay for&amp;mdash; all by leaving off a few useless tags.  Not really that crazy.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-3570744862816725983?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/yz9S5j27Ma-wCijlVXhCZpNR2Tg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yz9S5j27Ma-wCijlVXhCZpNR2Tg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/yz9S5j27Ma-wCijlVXhCZpNR2Tg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/yz9S5j27Ma-wCijlVXhCZpNR2Tg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/evRyTkYI0cI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/3570744862816725983/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/02/silly-space-optimization-on-googles.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3570744862816725983?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3570744862816725983?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/evRyTkYI0cI/silly-space-optimization-on-googles.html" title="Silly Space Optimization on Google's Home Page?" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/02/silly-space-optimization-on-googles.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0QFQXY_fCp7ImA9WxBXFEU.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-168604865855568682</id><published>2010-01-25T20:36:00.000-08:00</published><updated>2010-01-25T21:55:10.844-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-25T21:55:10.844-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ffi" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="error-codes" /><category scheme="http://www.blogger.com/atom/ns#" term="errno" /><title>Simple Errno Lookup with Python</title><content type="html">&lt;p&gt;Visual Studio has a tool [&lt;a href="http://msdn.microsoft.com/en-us/library/akay62ya.aspx" title="Visual Studio ERRLOOK Utility"&gt;ERRLOOK&lt;/a&gt;] which looks up explanations of error codes.  When you don't have the convenience of application code that automatically converts and reports this back to you it's nice to have.&lt;/p&gt;&lt;p&gt;I don't know of a similiar utility on Linux (or other Unix variants), but I know the library calls exist to write it (at least for well known system error codes).&lt;/p&gt;&lt;p&gt;Below is my first pass at writing this utility for Linux / Mac OS X using &lt;a href="http://python.org"&gt;Python&lt;/a&gt;'s &lt;a href="http://docs.python.org/library/ctypes.html" title="CTypes Module"&gt;CTypes&lt;/a&gt;.&lt;/p&gt;&lt;script src="http://gist.github.com/286405.js?file=errnolookup.py"&gt;&lt;/script&gt;&lt;p&gt;The benifit of using python is that it doesn't need to be compiled (though this is a small benefit)&amp;mdash; it's also an example of using CTypes to do &lt;a href="http://en.wikipedia.org/wiki/Foreign_function_interface" title="Wikipedia Entry for Foreign function interface"&gt;FFI&lt;/a&gt;.  Python also has the &lt;a href="http://docs.python.org/library/errno.html" title="Python errno module"&gt;errno&lt;/a&gt; module which provides a mapping between a numeric error code and a symbolic name.&lt;/p&gt;&lt;p&gt;The calls to load &lt;code&gt;libc.dylib&lt;/code&gt; or &lt;code&gt;libc.so.1&lt;/code&gt; might need to be tweaked depending on the system it's running on.&lt;/p&gt;&lt;p&gt;Example output:&lt;/p&gt;&lt;script src="http://gist.github.com/286405.js?file=example.txt"&gt;&lt;/script&gt;&lt;div class="source"&gt;[&lt;a href="http://github.com/silverjam/play/raw/master/CsJam/simple-errno-lookup.mkd"&gt;Source&lt;/a&gt; for this post in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; mark-up]&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-168604865855568682?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/e3fHPxYVkMQTMxCP7TpD9w8ntMk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e3fHPxYVkMQTMxCP7TpD9w8ntMk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/e3fHPxYVkMQTMxCP7TpD9w8ntMk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/e3fHPxYVkMQTMxCP7TpD9w8ntMk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/pw7qUzoNf_U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/168604865855568682/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/01/simple-errno-lookup-with-python.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/168604865855568682?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/168604865855568682?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/pw7qUzoNf_U/simple-errno-lookup-with-python.html" title="Simple Errno Lookup with Python" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/01/simple-errno-lookup-with-python.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0UMRHY_cSp7ImA9WxBXFEU.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-1822248909142302962</id><published>2010-01-22T21:32:00.000-08:00</published><updated>2010-01-25T21:54:45.849-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-25T21:54:45.849-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="twitterfeed" /><category scheme="http://www.blogger.com/atom/ns#" term="social-media" /><category scheme="http://www.blogger.com/atom/ns#" term="delicioius" /><category scheme="http://www.blogger.com/atom/ns#" term="twitter" /><category scheme="http://www.blogger.com/atom/ns#" term="bookmarks" /><category scheme="http://www.blogger.com/atom/ns#" term="rss" /><title>Using TwitterFeed to send certain del.icio.us bookmarks to Twitter</title><content type="html">&lt;p&gt;&lt;a href="http://twitterfeed.com" title="Twitter Feed, RSS to Social Network Publishing Service"&gt;TwitterFeed&lt;/a&gt; is a really cool service.  Using Twitter feed you can push any &lt;a href="http://en.wikipedia.org/wiki/RSS" title="RSS on Wikipedia"&gt;RSS&lt;/a&gt; feed to Twitter, which enables a super simple way to push pretty much any kind of syndicated data to Twitter (and now &lt;a href="http://facebook.com"&gt;Facebook&lt;/a&gt;, &lt;a href="http://laconi.ca"&gt;Laconica&lt;/a&gt;, and &lt;a href="http://hellotxt.com/"&gt;HelloTxt&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;&lt;a href="http://del.icio.us/jmob" title="My del.icio.us account"&gt;I&lt;/a&gt; also use &lt;a href="http://del.icio.us" title="Delicous Social Bookmarking"&gt;del.icio.us&lt;/a&gt; to save interesting bookmarks in a easily accessable persistent location.&lt;/p&gt;&lt;p&gt;The problem was several fold:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Twitter is a great way to talk about things (including links)&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Twitter isn't so great at categorizing links and making them easy to find later&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;I wanted to save links on del.icio.us but share them on Twitter&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Not everything I shared on del.icio.us was something I wanted to spam &lt;a href="http://twitter.com/silverjam" title="My Twitter Account"&gt;my&lt;/a&gt; Twitter &lt;a href="http://en.wikipedia.org/wiki/Twitter" title="Twitter Wikipedia Entry"&gt;followers&lt;/a&gt; with.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Turns out the solution is pretty simple.  On del.icio.us you can create &lt;a href="http://delicious.com/tag/" title="Delicious tags"&gt;tags&lt;/a&gt;.  These tags help oranize bookmarks.&lt;/p&gt;&lt;p&gt;For each tag you can get an RSS feed (see where this is going?).  RSS feeds for tags look like this:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;http://feeds.delicious.com/v2/rss/&amp;lt;username&amp;gt;/&amp;lt;tag-name&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;You can also visit the tag's webpage and select the &lt;em&gt;RSS feed&lt;/em&gt; button next to the &lt;a href="http://en.wikipedia.org/wiki/Uniform_Resource_Locator" title="URL on Wikipedia"&gt;URL&lt;/a&gt; bar (then record new link in the URL bar):&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pah06X9BI/AAAAAAAABmM/5_YTmOQpkKA/s1600-h/screen-capture-1-1.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 355px; height: 29px;" src="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pah06X9BI/AAAAAAAABmM/5_YTmOQpkKA/s400/screen-capture-1-1.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5429751837934220306" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;I selected the tag name &lt;em&gt;tweet-this&lt;/em&gt; for this set-up.&lt;/p&gt;&lt;p&gt;The next step is to visit &lt;a href="http://twitterfeed.com"&gt;TwitterFeed&lt;/a&gt; and get set-up with an account.  Once you've got your account you'll be at a &lt;em&gt;Feed Dashboard&lt;/em&gt;, select &lt;em&gt;Create a New Feed&lt;/em&gt; and enter the previously recorded URL:&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pc5dmFPkI/AAAAAAAABms/Fd8bGw5y_nU/s1600-h/screen-capture-2.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 176px; height: 47px;" src="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pc5dmFPkI/AAAAAAAABms/Fd8bGw5y_nU/s400/screen-capture-2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5429754443015208514" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Select &lt;em&gt;test rss feed&lt;/em&gt; to make sure everything is working.  &lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pc50z32YI/AAAAAAAABm0/8frz_NCEcC8/s1600-h/screen-capture-3.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 105px;" src="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pc50z32YI/AAAAAAAABm0/8frz_NCEcC8/s400/screen-capture-3.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5429754449247066498" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;p&gt;The rest is point and shoot with the TwitterFeed set-up process.  Now, only bookmarks recorded on del.icio.us with the &lt;em&gt;tweet-this&lt;/em&gt; tag will show up on Twitter.&lt;/p&gt;&lt;div class="source"&gt;[&lt;a href="http://github.com/silverjam/play/raw/master/CsJam/delicioius-twitterfeed.mkd"&gt;Source&lt;/a&gt; for this post in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; mark-up]&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-1822248909142302962?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/4gPfwComl8-tEmXvY2e0KypKiKU/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4gPfwComl8-tEmXvY2e0KypKiKU/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/4gPfwComl8-tEmXvY2e0KypKiKU/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/4gPfwComl8-tEmXvY2e0KypKiKU/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/TStlHzffE4Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/1822248909142302962/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/01/using-twitterfeed-to-send-certain.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/1822248909142302962?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/1822248909142302962?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/TStlHzffE4Y/using-twitterfeed-to-send-certain.html" title="Using TwitterFeed to send certain del.icio.us bookmarks to Twitter" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/_CeryDY5B7Rk/S1pah06X9BI/AAAAAAAABmM/5_YTmOQpkKA/s72-c/screen-capture-1-1.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/01/using-twitterfeed-to-send-certain.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkADRH05eSp7ImA9WxBXFEU.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-2056845813561581776</id><published>2010-01-21T20:56:00.000-08:00</published><updated>2010-01-25T21:46:15.321-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-25T21:46:15.321-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="ebay" /><category scheme="http://www.blogger.com/atom/ns#" term="python" /><category scheme="http://www.blogger.com/atom/ns#" term="analytics" /><category scheme="http://www.blogger.com/atom/ns#" term="appengine" /><title>Exponential Visitor Graph (Ebay)</title><content type="html">&lt;p&gt;I thought this was fairly entertaining...&lt;/p&gt;&lt;p&gt;I wrote a simple &lt;a href="http://bag-o-code.appspot.com/counter/start" title="Page Hit Counter"&gt;page hit counter&lt;/a&gt; for a couple Ebay / Craigslist listing we were doing (using Google's &lt;a href="http://appspot.com" title="AppEngine"&gt;AppEngine&lt;/a&gt;, and Yahoo's &lt;a href="http://developer.yahoo.com/yui/" title="Yahoo YUI"&gt;YUI&lt;/a&gt;).&lt;/p&gt;&lt;p&gt;Recently I added a feature to allow it to graph visitor counts over time (basically a cheesy analytics engine).&lt;/p&gt;&lt;p&gt;I guess one of the items was particularly desirable (a very complete, good codition SNES system with a lot of games) because it had what I image is probably a pretty typical graph of visits to an Ebay auction:&lt;/p&gt;&lt;p&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_CeryDY5B7Rk/S1k3Gz-C2yI/AAAAAAAABmE/jiDFgKJJjFo/s1600-h/screen-capture.png"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 400px; height: 339px;" src="http://1.bp.blogspot.com/_CeryDY5B7Rk/S1k3Gz-C2yI/AAAAAAAABmE/jiDFgKJJjFo/s400/screen-capture.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5429431415941028642" /&gt;&lt;/a&gt; &lt;/p&gt;&lt;p&gt;It's pretty obvious that the spike (a huge spike) in visitors is when the auction was about to close when everyone was manically hitting reload.  Just eyeballing the graph, it looks like an exponential increase.&lt;/p&gt;&lt;div class="source"&gt;[&lt;a href="http://github.com/silverjam/play/raw/master/CsJam/ebay-visitor-graph.mkd"&gt;Source&lt;/a&gt; for this post in &lt;a href="http://daringfireball.net/projects/markdown/"&gt;Markdown&lt;/a&gt; mark-up]&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-2056845813561581776?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/I2NLWre0SpE28HXOHogA-WwTH8U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I2NLWre0SpE28HXOHogA-WwTH8U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/I2NLWre0SpE28HXOHogA-WwTH8U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/I2NLWre0SpE28HXOHogA-WwTH8U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/_k75EfGR_-s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/2056845813561581776/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/01/exponential-visitor-graph-ebay.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2056845813561581776?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2056845813561581776?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/_k75EfGR_-s/exponential-visitor-graph-ebay.html" title="Exponential Visitor Graph (Ebay)" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/_CeryDY5B7Rk/S1k3Gz-C2yI/AAAAAAAABmE/jiDFgKJJjFo/s72-c/screen-capture.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/01/exponential-visitor-graph-ebay.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08HQXY7cCp7ImA9WxBQFk8.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-7691959473583009607</id><published>2010-01-15T23:57:00.001-08:00</published><updated>2010-01-16T00:17:10.808-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T00:17:10.808-08:00</app:edited><title>Updated: Token Bucket Downloader</title><content type="html">&lt;p&gt;I've updated the rate limiting downloader (that uses token bucket algorithm) to be more user friendly out of the box.  It attempts to use urllib2 by default so it can rate limit pretty much any url. &lt;/p&gt;

&lt;p&gt;Previously the script required an http proxy and the only means of adjusting operating parameters was global variables in the script.  A proxy server is no longer required and all operating parameters can be adjusted via script options.&lt;/p&gt;

&lt;p&gt;If an http proxy is selected the python http library (httplib) is used, this is a more rudimentary library so not as many situations are handled.  It's possible to install a proxy handler in urllib2 but I didn't do this.&lt;/p&gt;

&lt;p&gt;This is more-or-less a "complete" rate limiting download manager.  Option output:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;   Usage: rlfetch.py [options] url

   Options:
     -h, --help            show this help message and exit
     -f FILE, --file=FILE  output filename
     -d DIR, --dest=DIR    destination directory
     -p SERVER:PORT, --proxy=SERVER:PORT
                           http proxy server
     -z BYTES, --buffer=BYTES
                           buffer size
     -l KBS, --limit=KBS   kbs limit
     -b KBS, --burst=KBS   burst limit
     -t SECONDS, --tick=SECONDS
                           tick interval&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Current &lt;a href="http://github.com/silverjam/play/blob/master/TokenBucket/rlfetch.py" title="View Code at GitHub"&gt;state of the code&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-7691959473583009607?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/suUNOAf4PpdZEqTlPrIDke53g6U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/suUNOAf4PpdZEqTlPrIDke53g6U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/suUNOAf4PpdZEqTlPrIDke53g6U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/suUNOAf4PpdZEqTlPrIDke53g6U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/lhWFcvXu4AQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/7691959473583009607/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/01/updated-token-bucket-downloader.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/7691959473583009607?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/7691959473583009607?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/lhWFcvXu4AQ/updated-token-bucket-downloader.html" title="Updated: Token Bucket Downloader" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/01/updated-token-bucket-downloader.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMCRHY6fSp7ImA9WxBQEk8.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-3752055922414371474</id><published>2010-01-11T07:00:00.000-08:00</published><updated>2010-01-11T07:24:25.815-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-11T07:24:25.815-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="python sockets networks algorithms" /><title>Basic Token Bucket Rate Limiter</title><content type="html">&lt;p&gt;In locations were you have limited internet resources it's sometimes necessary to implement &lt;i&gt;rate limiting&lt;/i&gt;.  I was curious exactly how this worked so I worked out a simple &lt;a href="http://en.wikipedia.org/wiki/Token_bucket"&gt;Token Bucket&lt;/a&gt; based rate limiting HTTP downloader.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;This Python script does a couple things:
&lt;ul&gt;&lt;li&gt;Limits rate of data consumption in kilobytes per second&lt;/li&gt;
&lt;li&gt;Prints out the instantaneous KB/s and the overal/actual KB/s [this is done by monitoring the file size on disk]&lt;/li&gt;
&lt;/ul&gt;&lt;/p&gt;&lt;!-- -
--&gt;&lt;p&gt;Token bucket is a pretty simple algorithm.  The basic algorithm is to create an artificial stream of tokens, which are generated as fast you want to allow the real stream to go.  If tokens are not removed from the "bucket" then tokens are only generated up to a "burst limit", which is the maximum amount over the average limit that's desirable (this could change to help trend a stream toward the average limit).&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;In the Python implementation, 3 threads are used.  Thread one monitors the rate of download.  Thread two consumes tokens and downloads real data from an HTTP source.  Thread three generates tokens and places them in a bucket, stopping when the burst limit has been reached.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;The code is available below or at &lt;a href="http://codepad.org/FEjmgqZk"&gt;codepad.org&lt;/a&gt;.&lt;/p&gt;
&lt;button id="show-source-button"&gt;Show highlighted source&lt;/button&gt;
&lt;script type="text/javascript"&gt;$("#show-source-button").click(function(){$("#the-source").slideToggle("slow");})&lt;/script&gt;
&lt;pre id="the-source"&gt;&lt;span style='color:#696969; '&gt;# -*- python -*-&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; os
&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; random
&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; time
&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; httplib
&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; urlparse
&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; sys

&lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; threading

&lt;span style='color:#800000; font-weight:bold; '&gt;from&lt;/span&gt; pprint &lt;span style='color:#800000; font-weight:bold; '&gt;import&lt;/span&gt; pprint

&lt;span style='color:#696969; '&gt;###########################&lt;/span&gt;
&lt;span style='color:#696969; '&gt;# Tuning knobs&lt;/span&gt;
BUFSIZE &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;8192&lt;/span&gt;
BPS_LIMIT &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;50&lt;/span&gt; &lt;span style='color:#808030; '&gt;*&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1024&lt;/span&gt;
BURST_BPS_LIMIT &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;70&lt;/span&gt; &lt;span style='color:#808030; '&gt;*&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1024&lt;/span&gt;
TICK &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008000; '&gt;0.01&lt;/span&gt;
&lt;span style='color:#696969; '&gt;###########################&lt;/span&gt;

g_usage &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"%s &amp;lt;download directory&gt; &amp;lt;target url&gt;"&lt;/span&gt;

g_bucketTokens &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;
g_exit &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;False&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; parseArgv&lt;span style='color:#808030; '&gt;(&lt;/span&gt;argv&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;len&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;argv&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#808030; '&gt;&amp;lt;&lt;/span&gt; &lt;span style='color:#008c00; '&gt;3&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;
    directory &lt;span style='color:#808030; '&gt;=&lt;/span&gt; argv&lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;not&lt;/span&gt; os&lt;span style='color:#808030; '&gt;.&lt;/span&gt;path&lt;span style='color:#808030; '&gt;.&lt;/span&gt;isdir&lt;span style='color:#808030; '&gt;(&lt;/span&gt;directory&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;
    url &lt;span style='color:#808030; '&gt;=&lt;/span&gt; argv&lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#008c00; '&gt;2&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt;
    s &lt;span style='color:#808030; '&gt;=&lt;/span&gt; urlparse&lt;span style='color:#808030; '&gt;.&lt;/span&gt;urlsplit&lt;span style='color:#808030; '&gt;(&lt;/span&gt;url&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    _&lt;span style='color:#808030; '&gt;,&lt;/span&gt; filename &lt;span style='color:#808030; '&gt;=&lt;/span&gt; os&lt;span style='color:#808030; '&gt;.&lt;/span&gt;path&lt;span style='color:#808030; '&gt;.&lt;/span&gt;split&lt;span style='color:#808030; '&gt;(&lt;/span&gt;s&lt;span style='color:#808030; '&gt;.&lt;/span&gt;path&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; url&lt;span style='color:#808030; '&gt;,&lt;/span&gt; os&lt;span style='color:#808030; '&gt;.&lt;/span&gt;path&lt;span style='color:#808030; '&gt;.&lt;/span&gt;join&lt;span style='color:#808030; '&gt;(&lt;/span&gt;directory&lt;span style='color:#808030; '&gt;,&lt;/span&gt; filename&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
     
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; takeTokens&lt;span style='color:#808030; '&gt;(&lt;/span&gt;tokencount&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;global&lt;/span&gt; g_bucketTokens
    &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; g_bucketTokens &lt;span style='color:#808030; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; tokencount&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        g_bucketTokens &lt;span style='color:#808030; '&gt;-&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; tokencount
        &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;False&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; printKbs&lt;span style='color:#808030; '&gt;(&lt;/span&gt;filename&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; _&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        start&lt;span style='color:#808030; '&gt;,&lt;/span&gt; end &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;
        tot&lt;span style='color:#808030; '&gt;,&lt;/span&gt; num &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;while&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; g_exit&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"KB/s monitor exiting..."&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;break&lt;/span&gt;
            end &lt;span style='color:#808030; '&gt;=&lt;/span&gt; time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;time&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            size &lt;span style='color:#808030; '&gt;=&lt;/span&gt; g_byteCount
            &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; start &lt;span style='color:#800000; font-weight:bold; '&gt;is&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;not&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
                inst &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;size &lt;span style='color:#808030; '&gt;-&lt;/span&gt; old&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#808030; '&gt;/&lt;/span&gt; &lt;span style='color:#008000; '&gt;1024.0&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#808030; '&gt;/&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;end &lt;span style='color:#808030; '&gt;-&lt;/span&gt; start&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
                tot &lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; inst
                num &lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;1&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"I: %.02f kb/s, A: %.02f kb/s"&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;inst&lt;span style='color:#808030; '&gt;,&lt;/span&gt; tot &lt;span style='color:#808030; '&gt;/&lt;/span&gt; num&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            start &lt;span style='color:#808030; '&gt;=&lt;/span&gt; time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;time&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            old &lt;span style='color:#808030; '&gt;=&lt;/span&gt; size
            &lt;span style='color:#800000; font-weight:bold; '&gt;for&lt;/span&gt; x &lt;span style='color:#800000; font-weight:bold; '&gt;in&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;xrange&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#e34adc; '&gt;int&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;2&lt;/span&gt; &lt;span style='color:#808030; '&gt;/&lt;/span&gt; TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; g_exit&lt;span style='color:#808030; '&gt;:&lt;/span&gt; &lt;span style='color:#800000; font-weight:bold; '&gt;break&lt;/span&gt; 
                time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;sleep&lt;span style='color:#808030; '&gt;(&lt;/span&gt;TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; _

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; feedBucketTokens&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;global&lt;/span&gt; g_bucketTokens
    tokens_per &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;int&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;BPS_LIMIT &lt;span style='color:#808030; '&gt;*&lt;/span&gt; TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Tokens per tick: %d"&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;tokens_per&lt;span style='color:#808030; '&gt;,&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;while&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; g_exit&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Token feeder exiting..."&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;break&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; g_bucketTokens &lt;span style='color:#808030; '&gt;&gt;&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; BURST_BPS_LIMIT&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;sleep&lt;span style='color:#808030; '&gt;(&lt;/span&gt;TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;continue&lt;/span&gt;
        g_bucketTokens &lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; tokens_per
        time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;sleep&lt;span style='color:#808030; '&gt;(&lt;/span&gt;TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;class&lt;/span&gt; BucketReader &lt;span style='color:#808030; '&gt;(&lt;/span&gt;object&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;__init__&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;self&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fp&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        self&lt;span style='color:#808030; '&gt;.&lt;/span&gt;fp &lt;span style='color:#808030; '&gt;=&lt;/span&gt; fp
    &lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; read&lt;span style='color:#808030; '&gt;(&lt;/span&gt;self&lt;span style='color:#808030; '&gt;,&lt;/span&gt; bufsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;while&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; takeTokens&lt;span style='color:#808030; '&gt;(&lt;/span&gt;bufsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
                &lt;span style='color:#800000; font-weight:bold; '&gt;break&lt;/span&gt;
            time&lt;span style='color:#808030; '&gt;.&lt;/span&gt;sleep&lt;span style='color:#808030; '&gt;(&lt;/span&gt;TICK&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; self&lt;span style='color:#808030; '&gt;.&lt;/span&gt;fp&lt;span style='color:#808030; '&gt;.&lt;/span&gt;read&lt;span style='color:#808030; '&gt;(&lt;/span&gt;bufsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        
&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; prepareFile&lt;span style='color:#808030; '&gt;(&lt;/span&gt;filename&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    fp &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;open&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;filename&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'ab+'&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    fp&lt;span style='color:#808030; '&gt;.&lt;/span&gt;seek&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;2&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    fsize &lt;span style='color:#808030; '&gt;=&lt;/span&gt; fp&lt;span style='color:#808030; '&gt;.&lt;/span&gt;tell&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; fp&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fsize

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; startHttpReq&lt;span style='color:#808030; '&gt;(&lt;/span&gt;url&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    headers &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#800080; '&gt;{&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;"Range"&lt;/span&gt; &lt;span style='color:#808030; '&gt;:&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"bytes=%d-"&lt;/span&gt; &lt;span style='color:#808030; '&gt;%&lt;/span&gt; fsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#800080; '&gt;}&lt;/span&gt;
    pprint&lt;span style='color:#808030; '&gt;(&lt;/span&gt;headers&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    h &lt;span style='color:#808030; '&gt;=&lt;/span&gt; httplib&lt;span style='color:#808030; '&gt;.&lt;/span&gt;HTTPConnection&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"aproxyserver"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; &lt;span style='color:#008c00; '&gt;8080&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    h&lt;span style='color:#808030; '&gt;.&lt;/span&gt;request&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#0000e6; '&gt;"GET"&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; url&lt;span style='color:#808030; '&gt;,&lt;/span&gt; headers&lt;span style='color:#808030; '&gt;=&lt;/span&gt;headers&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    r &lt;span style='color:#808030; '&gt;=&lt;/span&gt; h&lt;span style='color:#808030; '&gt;.&lt;/span&gt;getresponse&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    pprint&lt;span style='color:#808030; '&gt;(&lt;/span&gt;r&lt;span style='color:#808030; '&gt;.&lt;/span&gt;getheaders&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;return&lt;/span&gt; r

g_byteCount &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#008c00; '&gt;0&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; readLoop&lt;span style='color:#808030; '&gt;(&lt;/span&gt;fpIn&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fpOut&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;global&lt;/span&gt; g_byteCount
    &lt;span style='color:#800000; font-weight:bold; '&gt;while&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        d &lt;span style='color:#808030; '&gt;=&lt;/span&gt; fpIn&lt;span style='color:#808030; '&gt;.&lt;/span&gt;read&lt;span style='color:#808030; '&gt;(&lt;/span&gt;BUFSIZE&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        fpOut&lt;span style='color:#808030; '&gt;.&lt;/span&gt;write&lt;span style='color:#808030; '&gt;(&lt;/span&gt;d&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        fpOut&lt;span style='color:#808030; '&gt;.&lt;/span&gt;flush&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        g_byteCount &lt;span style='color:#808030; '&gt;+&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;len&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;d&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;len&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;d&lt;span style='color:#808030; '&gt;)&lt;/span&gt; &lt;span style='color:#808030; '&gt;&amp;lt;&lt;/span&gt; BUFSIZE&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;break&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;def&lt;/span&gt; main&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;global&lt;/span&gt; g_exit
    &lt;span style='color:#800000; font-weight:bold; '&gt;try&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        params &lt;span style='color:#808030; '&gt;=&lt;/span&gt; parseArgv&lt;span style='color:#808030; '&gt;(&lt;/span&gt;sys&lt;span style='color:#808030; '&gt;.&lt;/span&gt;argv&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; params &lt;span style='color:#800000; font-weight:bold; '&gt;is&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;None&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;print&lt;/span&gt; g_usage &lt;span style='color:#808030; '&gt;%&lt;/span&gt; &lt;span style='color:#808030; '&gt;(&lt;/span&gt;sys&lt;span style='color:#808030; '&gt;.&lt;/span&gt;argv&lt;span style='color:#808030; '&gt;[&lt;/span&gt;&lt;span style='color:#008c00; '&gt;0&lt;/span&gt;&lt;span style='color:#808030; '&gt;]&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
            &lt;span style='color:#800000; font-weight:bold; '&gt;raise&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;SystemExit&lt;/span&gt;&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#008c00; '&gt;1&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        url&lt;span style='color:#808030; '&gt;,&lt;/span&gt; filename &lt;span style='color:#808030; '&gt;=&lt;/span&gt; params
        threading&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Thread&lt;span style='color:#808030; '&gt;(&lt;/span&gt;target&lt;span style='color:#808030; '&gt;=&lt;/span&gt;feedBucketTokens&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;start&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        threading&lt;span style='color:#808030; '&gt;.&lt;/span&gt;Thread&lt;span style='color:#808030; '&gt;(&lt;/span&gt;target&lt;span style='color:#808030; '&gt;=&lt;/span&gt;printKbs&lt;span style='color:#808030; '&gt;(&lt;/span&gt;filename&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;.&lt;/span&gt;start&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        fpOut&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fsize &lt;span style='color:#808030; '&gt;=&lt;/span&gt; prepareFile&lt;span style='color:#808030; '&gt;(&lt;/span&gt;filename&lt;span style='color:#808030; '&gt;)&lt;/span&gt; 
        fpInput &lt;span style='color:#808030; '&gt;=&lt;/span&gt; startHttpReq&lt;span style='color:#808030; '&gt;(&lt;/span&gt;url&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fsize&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
        readLoop&lt;span style='color:#808030; '&gt;(&lt;/span&gt;BucketReader&lt;span style='color:#808030; '&gt;(&lt;/span&gt;fpInput&lt;span style='color:#808030; '&gt;)&lt;/span&gt;&lt;span style='color:#808030; '&gt;,&lt;/span&gt; fpOut&lt;span style='color:#808030; '&gt;)&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;except&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;KeyboardInterrupt&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        &lt;span style='color:#800000; font-weight:bold; '&gt;pass&lt;/span&gt;
    &lt;span style='color:#800000; font-weight:bold; '&gt;finally&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
        g_exit &lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;True&lt;/span&gt;

&lt;span style='color:#800000; font-weight:bold; '&gt;if&lt;/span&gt; &lt;span style='color:#e34adc; '&gt;__name__&lt;/span&gt; &lt;span style='color:#808030; '&gt;=&lt;/span&gt;&lt;span style='color:#808030; '&gt;=&lt;/span&gt; &lt;span style='color:#0000e6; '&gt;'__main__'&lt;/span&gt;&lt;span style='color:#808030; '&gt;:&lt;/span&gt;
    main&lt;span style='color:#808030; '&gt;(&lt;/span&gt;&lt;span style='color:#808030; '&gt;)&lt;/span&gt;

&lt;span style='color:#696969; '&gt;# vim: et:sts=4:ts=4:sw=4:&lt;/span&gt;
&lt;/pre&gt;
&lt;script type="text/javascript"&gt;$("#the-source").hide();&lt;/script&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-3752055922414371474?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rQb7tb15wtps_uKeO_eAc5giWkM/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rQb7tb15wtps_uKeO_eAc5giWkM/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rQb7tb15wtps_uKeO_eAc5giWkM/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rQb7tb15wtps_uKeO_eAc5giWkM/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/1VsFVzYzDmI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/3752055922414371474/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2010/01/basic-token-bucket-rate-limiter.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3752055922414371474?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3752055922414371474?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/1VsFVzYzDmI/basic-token-bucket-rate-limiter.html" title="Basic Token Bucket Rate Limiter" /><author><name>jam</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2010/01/basic-token-bucket-rate-limiter.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UHQHczeSp7ImA9WxVVGU4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-548388748179914312</id><published>2009-03-13T00:40:00.001-07:00</published><updated>2009-03-13T01:00:31.981-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-13T01:00:31.981-07:00</app:edited><title>IPython on Wx \ Windows</title><content type="html">&lt;p&gt;This is almost strictly for Google to index in hopes that it helps someone else trying to do what I was doing.  Also, this was probably in the documentation somewhere, but I hate reading documentation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;IPython&lt;/em&gt; is an enhanced interactive shell for Python.  Out of the box if you run the &lt;em&gt;WxIPython&lt;/em&gt; program you may get the following error when attempting to do tab completion:
&lt;pre&gt;'InteractiveShell' object has no attribute 'Completer'&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;This just means that you didn't install &lt;a href="http://ipython.scipy.org/moin/PyReadline/Intro"&gt;PyReadline&lt;/a&gt;.  &lt;em&gt;IPython&lt;/em&gt; should really be smart enough to figure this out on its own &amp;mdash; &lt;a href="http://en.wikipedia.org/wiki/Command_line_completion"&gt;tab completion&lt;/a&gt; is part of the core functionality of &lt;em&gt;IPython&lt;/em&gt;.  Therefore, they could also bundle &lt;em&gt;PyReadline&lt;/em&gt; with the default Windows installation package.  Especially since it looks like &lt;em&gt;PyReadline&lt;/em&gt; was developed by the same group.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-548388748179914312?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/1NRNHlSvl3uQCm-3hgDMFgP5FFA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1NRNHlSvl3uQCm-3hgDMFgP5FFA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/1NRNHlSvl3uQCm-3hgDMFgP5FFA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/1NRNHlSvl3uQCm-3hgDMFgP5FFA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/gXgJoBbYynY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/548388748179914312/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/03/ipython-on-wx-windows.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/548388748179914312?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/548388748179914312?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/gXgJoBbYynY/ipython-on-wx-windows.html" title="IPython on Wx \ Windows" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/03/ipython-on-wx-windows.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUMQ3c_eyp7ImA9WxVXEkg.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-5035237184189014061</id><published>2009-02-10T01:21:00.000-08:00</published><updated>2009-02-10T01:31:22.943-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-10T01:31:22.943-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="american dad" /><category scheme="http://www.blogger.com/atom/ns#" term="politics" /><title>Can you spot the social commentary?</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_CeryDY5B7Rk/SZFHhk9kcBI/AAAAAAAAAiI/zO6CigxclHE/s1600-h/americandad.PNG"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 320px; height: 239px;" src="http://2.bp.blogspot.com/_CeryDY5B7Rk/SZFHhk9kcBI/AAAAAAAAAiI/zO6CigxclHE/s320/americandad.PNG" alt="" id="BLOGGER_PHOTO_ID_5301096878574956562" border="0" /&gt;&lt;/a&gt;
&lt;p&gt;I guess freeze framed like this it's pretty easy to spot.  This is from &lt;a href="http://www.imdb.com/title/tt0397306/"&gt;American Dad&lt;/a&gt; &lt;a href="http://www.imdb.com/title/tt0397306/episodes#season-4"&gt;season 4&lt;/a&gt;, &lt;a href="http://www.imdb.com/title/tt1329562/"&gt;episode 9&lt;/a&gt;, time index around 6 minutes (as the picture shows) -- captured from &lt;a href="http://www.hulu.com/watch/56671/american-dad-stan-time"&gt;Hulu&lt;/a&gt;.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-5035237184189014061?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/VQxnfevzeahXHNBy0PPziFyGaug/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VQxnfevzeahXHNBy0PPziFyGaug/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/VQxnfevzeahXHNBy0PPziFyGaug/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/VQxnfevzeahXHNBy0PPziFyGaug/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/2jjvHjmaVPc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/5035237184189014061/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/02/can-you-spot-social-commentary.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5035237184189014061?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5035237184189014061?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/2jjvHjmaVPc/can-you-spot-social-commentary.html" title="Can you spot the social commentary?" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/_CeryDY5B7Rk/SZFHhk9kcBI/AAAAAAAAAiI/zO6CigxclHE/s72-c/americandad.PNG" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/02/can-you-spot-social-commentary.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUEGQns6fSp7ImA9WxFbEEw.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-4717728500887495927</id><published>2009-02-08T20:10:00.000-08:00</published><updated>2010-07-01T12:47:03.515-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-07-01T12:47:03.515-07:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="code" /><category scheme="http://www.blogger.com/atom/ns#" term="google" /><category scheme="http://www.blogger.com/atom/ns#" term="processing" /><category scheme="http://www.blogger.com/atom/ns#" term="android" /><category scheme="http://www.blogger.com/atom/ns#" term="proce55ing" /><title>Parallax Scrolling in Android</title><content type="html">&lt;p&gt;
 A while ago I heard about something called &lt;a style="font-style: italic;" href="http://en.wikipedia.org/wiki/Parallax_scrolling"&gt;parallax scrolling&lt;/a&gt; [&lt;a href="#csjam-footnote-1"&gt;1&lt;/a&gt;] being used on Google's &lt;a href="http://en.wikipedia.org/wiki/Google_Android"&gt;Android&lt;/a&gt; platform (specifically on the &lt;a href="http://en.wikipedia.org/wiki/HTC_Dream"&gt;G1&lt;/a&gt;). I had just gotten the G1 at that point and hadn't noticed that it was doing something special when scrolling between the three screens in the "home" application.
&lt;/p&gt;
&lt;p&gt;
 The idea is pretty simple, you have two surfaces that scroll at two different speeds, one is bigger or father away, depending on how you look at it.
&lt;/p&gt;
&lt;p&gt;
 On the G1 it allows the background of the home screen to be smaller than the total "viewable area" that the three home screens cover. This is useful since the size of the home screen areas can change drastically when the phone is flipped open.  It also creates the illusion of depth.
&lt;/p&gt;
&lt;p&gt;
 Below is my implementation using &lt;a href="http://www.processing.org/"&gt;Proce55ing&lt;/a&gt;&lt;span id="parallax-instructions"&gt; (click and drag the light purple square).&lt;/span&gt;
&lt;/p&gt;
&lt;div id="content"&gt;
 &lt;div id="parallax_container"&gt;
  &lt;!--[if !IE]&gt; --&gt;
  &lt;object classid="java:parallax.class" type="application/x-java-applet" archive="http://www.cs.unm.edu/~jmob/blogger/parallax_applet/parallax.jar" standby="Loading Processing software..." width="400" height="400"&gt;
  &lt;param name="archive" value="http://www.cs.unm.edu/~jmob/blogger/parallax_applet/parallax.jar"&gt;
  &lt;param name="mayscript" value="true"&gt;
  &lt;param name="scriptable" value="true"&gt;
  &lt;param name="image" value="http://www.cs.unm.edu/~jmob/blogger/parallax_applet/loading.gif"&gt;
  &lt;param name="boxmessage" value="Loading Processing software..."&gt;
  &lt;param name="boxbgcolor" value="#FFFFFF"&gt;
  &lt;param name="test_string" value="outer"&gt;
  &lt;!--&lt;![endif]--&gt;
  &lt;object classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93" codebase="http://java.sun.com/update/1.5.0/jinstall-1_5_0_15-windows-i586.cab" standby="Loading Processing software..." width="400" height="400"&gt;
  &lt;param name="code" value="parallax"&gt;
  &lt;param name="archive" value="http://www.cs.unm.edu/~jmob/blogger/parallax_applet/parallax.jar"&gt;
  &lt;param name="mayscript" value="true"&gt;
  &lt;param name="scriptable" value="true"&gt;
  &lt;param name="image" value="http://www.cs.unm.edu/~jmob/blogger/parallax_applet/loading.gif"&gt;
  &lt;param name="boxmessage" value="Loading Processing software..."&gt;
  &lt;param name="boxbgcolor" value="#FFFFFF"&gt;&lt;param name="test_string" value="inner"&gt;
  &lt;!--[if !IE]&gt; --&gt;
   &lt;object&gt;
  &lt;!--&lt;![endif]--&gt;
    &lt;embed src="http://blip.tv/play/AevhKZPlCw" 
           type="application/x-shockwave-flash" 
           width="400" height="430" 
           allowscriptaccess="always" 
           allowfullscreen="true"
           id="parallax-blip"&gt;
        &lt;!--script type="text/javascript"&gt;$("#parallax-instructions").hide();&lt;/script--&gt;
    &lt;/embed&gt;
  &lt;p&gt;
   &lt;strong&gt;
   This browser does not have a Java Plug-in. &lt;a href="http://java.sun.com/products/plugin/downloads/index.html" title="Download Java Plug-in"&gt;Get the latest Java Plug-in here.&lt;/a&gt;&lt;/strong&gt;
  &lt;/p&gt;
  &lt;!--[if !IE]&gt; --&gt;
    &lt;/object&gt;
  &lt;!--&lt;![endif]--&gt;
  &lt;/object&gt;
  &lt;!--[if !IE]&gt; --&gt;
  &lt;/object&gt;
  &lt;!--&lt;![endif]--&gt;
 &lt;/div&gt;
 &lt;script type="text/javascript"&gt;
/*   alert("hi");
   if ( $("#parallax-blip").is(":visible") ) {
     $("#parallax-instructions").hide();
     alert("yo");
   }*/
 &lt;/script&gt;
 &lt;p&gt;
  Source code: &lt;a href="http://www.cs.unm.edu/%7Ejmob/blogger/parallax_applet/parallax.pde"&gt;parallax&lt;/a&gt; (plain text)
 &lt;/p&gt;
&lt;/div&gt;
&lt;script src="http://gist.github.com/460454.js?file=parallax.pde"&gt;&lt;/script&gt;
&lt;p style="font-style: italic; color: rgb(102, 102, 102);" id="csjam-footnote-1"&gt;
 1 - Turns out I was probably reading a Qt developer blog. &lt;a href="http://ariya.blogspot.com/2008/11/android-like-parallax-sliding.html"&gt;These&lt;/a&gt; &lt;a href="http://labs.trolltech.com/blogs/2008/11/03/parallax-sliding/"&gt;posts&lt;/a&gt; support that conclusion.
&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-4717728500887495927?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/miUdf_MzeFugJB6r9-d3u8YcW64/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/miUdf_MzeFugJB6r9-d3u8YcW64/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/miUdf_MzeFugJB6r9-d3u8YcW64/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/miUdf_MzeFugJB6r9-d3u8YcW64/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/KHUfePrc99s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/4717728500887495927/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/02/parallax-scrolling-in-android.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4717728500887495927?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4717728500887495927?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/KHUfePrc99s/parallax-scrolling-in-android.html" title="Parallax Scrolling in Android" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/02/parallax-scrolling-in-android.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIARHk5eyp7ImA9WxVRGUw.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-7546836390021540338</id><published>2009-01-25T11:51:00.000-08:00</published><updated>2009-01-25T12:49:05.723-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-25T12:49:05.723-08:00</app:edited><title>Don't Irritate Small Company Hiring Managers</title><content type="html">&lt;p&gt;&lt;!--
--&gt;Where I work is a relatively small company.  We don't have much the way of an Human Resource (HR) department.  We've got one person that's in charge of general personnel related issues but the manager of the development group is the one that initially contacts prospective employees (candidates).&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;&lt;!--
--&gt;The manager of the development group is really just a glorified developer.  Our development group is small enough that there's not enough management tasks to occupy all of his time.  His time distribution is about 75% development and 25% management.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;&lt;!--
--&gt;This time distribution is important because it means he's got disparate responsibilities, and in regards to contacting employment candidates that's not all he's doing &amp;mdash; he's not sitting around all day talking to candidates.  So if a candidates isn't courteous in his communication it leaves an impression &amp;mdash;  because he's dealing with a &lt;em&gt;small number of candidates&lt;/em&gt;, and because he actually &lt;em&gt;does other things&lt;/em&gt;.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;&lt;!--
--&gt;This is why it surprises me when every once in a while I get a colleague that asks for a recommendation to start our (remember &lt;em&gt;small company&lt;/em&gt;) hiring process, but they don't make every effort to remain in good standing!&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;&lt;!--
--&gt;One scenario went like this:&lt;!--
--&gt;&lt;ul&gt;&lt;!--
--&gt;&lt;li&gt;A past schoolmate contacted me, said he might be unemployed soon&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;I got him in contact with our company and recommended him&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;He started talking with our development manager&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;Promised to send us a resume, but never sent it&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;Development manager and I talked about him, and his &lt;em&gt;unresponsiveness&lt;/em&gt; a few times&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;The &lt;em&gt;development manager&lt;/em&gt; contacted him again (it should be the other way around)&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;He got back to us and said he'd decided on a another position&lt;!--
--&gt;&lt;/ul&gt;&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;The failure was that he didn't tell us that he'd found another position even when he'd previously agreed to send us a resume.  This wasted my time and more importantly the development managers time, annoyed both of us, and thusly made us both think he's an idiot.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;Our opinion of him was underscored by the fact that he got a mere &lt;em&gt;consulting / contracting&lt;/em&gt; position.  So it was a stupid decision on his part given the stability of our company and the fact that we're a development &amp;ldquo;oasis&amp;rdquo; in Albuquerque were there are few software companies that offer such a low stress environment.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;So, I think there are a few guidelines when talking with small companies:&lt;ul&gt;&lt;!--
--&gt;&lt;li&gt;Keep in mind that whoever you're talking to about getting hired probably has other responsibilities&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;Don't assume that they are dealing with so many candidates that they don't care if you don't follow up with them&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;Let them know when things change&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;Try not to irritate them because they'll remember you&lt;/li&gt;&lt;/ul&gt;&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;If you follow the above guidelines it's more likely that even if you find another position you'll remain in good standing with the small company.  Small companies can be great but they have different dynamics than bigger companies.  Throwing away opportunities is bad in general, so it's important to keep the above in mind when dealing with a small company.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-7546836390021540338?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SCrNkq4m3moNcRm5QrlVVtitNBo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SCrNkq4m3moNcRm5QrlVVtitNBo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SCrNkq4m3moNcRm5QrlVVtitNBo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SCrNkq4m3moNcRm5QrlVVtitNBo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/CBs_wOicVpA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/7546836390021540338/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/01/dont-irritate-small-company-hiring.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/7546836390021540338?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/7546836390021540338?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/CBs_wOicVpA/dont-irritate-small-company-hiring.html" title="Don't Irritate Small Company Hiring Managers" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/01/dont-irritate-small-company-hiring.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk4NSHsyfip7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-6972866114334752770</id><published>2009-01-16T16:36:00.001-08:00</published><updated>2010-01-16T01:43:19.596-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:43:19.596-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="xm" /><category scheme="http://www.blogger.com/atom/ns#" term="radio" /><category scheme="http://www.blogger.com/atom/ns#" term="psychology" /><category scheme="http://www.blogger.com/atom/ns#" term="fun" /><title>The Annoying XM Dj and "That Song You Love"</title><content type="html">I have a theory about those annoying XM Djs and XM devices that allow you to record that favorite song you like.&lt;br /&gt;
Those really popular, good songs, always seems to have a voice over in front of them, so if you record it you've got the annoying voiceover in the front (or the end) of the song... I think this is done on purpose, but that's a different theory.&lt;br /&gt;
The theory is that the voice over distracts you long enough for you to recognize the song and initiate a recording. Otherwise, without the voice over, you just go in to enjoying the song, enjoying the escapism, relishing in the feeling it evokes — totally not thinking about mudane trivialities like pressing the record button on the XM device.&lt;br /&gt;
At that point, why do I even care that it's coming from an &lt;em&gt;XM device&lt;/em&gt; — I'm just listening to good music.&lt;br /&gt;
Consider the following scenario:&lt;br /&gt;
&lt;blockquote&gt;Hey, it's that song I really like &lt;em&gt;(singing)&lt;/em&gt;&lt;br /&gt;
♪ ... Oh if I were a boy ... ♪ &lt;em&gt;(song ends)&lt;/em&gt;&lt;br /&gt;
♪ ... Womanizer, womanizer ... ♪ &lt;br /&gt;
Damn you Britney you don't deservce to follow Beyoncé!&lt;br /&gt;
Crap! Why didn't I record that!?&lt;br /&gt;
&lt;/blockquote&gt;Remember, that's just a dramatization, and the scenario is necessarily reality... but it happens all too often.&lt;br /&gt;
If you manage to record the song with the Dj in the front you have to suffer through the Dj's blather everytime you want to enjoy the recorded song.  The annoyance is particularly bad on songs with a long non-vocal intro.  Dj's &lt;em&gt;classically&lt;/em&gt; use this as a license to talk over the song.&lt;br /&gt;
&lt;br /&gt;
&lt;em&gt;&lt;a href="http://www.amazon.com/Pioneer-GEX-XMP3-Portable-Satellite-Receiver/dp/B001I70YRI?ie=UTF8&amp;amp;tag=csjam-20&amp;amp;link_code=btl&amp;amp;camp=213689&amp;amp;creative=392969" target="_blank"&gt;Pioneer GEX-XMP3 Portable XM Satellite Radio Receiver w/ Home Kit&lt;/a&gt;&lt;img alt="" border="0" height="1" src="http://www.assoc-amazon.com/e/ir?t=csjam-20&amp;amp;l=btl&amp;amp;camp=213689&amp;amp;creative=392969&amp;amp;o=1&amp;amp;a=B001I70YRI" style="border-bottom-style: none !important; border-color: initial !important; border-left-style: none !important; border-right-style: none !important; border-top-style: none !important; border-width: initial !important; margin-bottom: 0px !important; margin-left: 0px !important; margin-right: 0px !important; margin-top: 0px !important; padding-bottom: 0px !important; padding-left: 0px !important; padding-right: 0px !important; padding-top: 0px !important;" width="1" /&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-6972866114334752770?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/D7w83omJjTl3U8IPXnl4EyuiTVw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D7w83omJjTl3U8IPXnl4EyuiTVw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/D7w83omJjTl3U8IPXnl4EyuiTVw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/D7w83omJjTl3U8IPXnl4EyuiTVw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/Ke1I5FCkUMY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/6972866114334752770/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/01/annoying-xm-dj-and-that-song-you-love.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/6972866114334752770?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/6972866114334752770?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/Ke1I5FCkUMY/annoying-xm-dj-and-that-song-you-love.html" title="The Annoying XM Dj and &quot;That Song You Love&quot;" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/01/annoying-xm-dj-and-that-song-you-love.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU8CR384eip7ImA9WxVRFUw.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-5027977150797629230</id><published>2009-01-16T16:14:00.000-08:00</published><updated>2009-01-20T20:57:46.132-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-20T20:57:46.132-08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="home-ownership" /><category scheme="http://www.blogger.com/atom/ns#" term="traffic-violations" /><category scheme="http://www.blogger.com/atom/ns#" term="life" /><category scheme="http://www.blogger.com/atom/ns#" term="speeding" /><title>Speed Bumps / Humps</title><content type="html">&lt;p&gt;Interesting argument on speed bumps:&lt;/p&gt;&lt;!--
--&gt;&lt;blockquote&gt;&lt;!--
--&gt;They don't really work and they're annoying, I just speed to the next one and slow down&lt;/blockquote&gt;&lt;!--
--&gt;&lt;p&gt;In this case I was arguing for the addition of more speed bumps.  We just bought a house not to long ago and didn't properly evaluate the irritation factor of our proximity to a main entrance of a large housing division.&lt;/p&gt;&lt;p&gt;I figure there's several points related to speeding in our neighborhood:&lt;/p&gt;&lt;!--
--&gt;&lt;ul&gt;&lt;!--
--&gt;&lt;li&gt;&lt;!--
--&gt;&lt;p&gt;The neighborhood was designed before they started designing housing divisions like mazes to add a kind of  &amp;quot;natural traffic calming&amp;quot; &amp;mdash; without the funky hardware like traffic circles and speed humps.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;From what I've seen these kind of divisions have no houses facing arterial streets (arterial on the scale of a housing development).  All houses are facing a &amp;quot;capillary&amp;quot; street, the undesirable locations are the ones whose backyards face the arterial streets or whose backyards face the large city streets that bound the division.&lt;/p&gt;&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;&lt;p&gt;Because there are relatively few places to get out of the division people are frustrated and impatient when they are on the verge of exiting &amp;mdash; thus the speeding to get out&lt;/p&gt;&lt;/li&gt;&lt;!--
--&gt;&lt;li&gt;&lt;p&gt;People are just jerks and don't care that it's a residential street!&lt;/p&gt;&lt;/li&gt;&lt;!--
--&gt;&lt;/ul&gt;&lt;!--
--&gt;&lt;p&gt;There are other factors like the fact that there's a several speed bumps on the road in question, just none between my house (and about 14 other house) and the exit of the division -- which doesn't quite make sense.  People seem to see the exit, notice that there's no speed bumps, and haul tail to the exit.&lt;/p&gt;&lt;!--
--&gt;&lt;p&gt;Regarding the above argument... if speed bumps don't work, I guess I don't really care, at least they're being annoyed by the speed bumps while they're speeding between them.  This way there's mutual irritation between me the driver.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-5027977150797629230?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/HE3Nvvh5O1yKS2KlnM3bfvikdsg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HE3Nvvh5O1yKS2KlnM3bfvikdsg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/HE3Nvvh5O1yKS2KlnM3bfvikdsg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/HE3Nvvh5O1yKS2KlnM3bfvikdsg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/uLMj5zUomEA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/5027977150797629230/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2009/01/speed-bumps-humps.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5027977150797629230?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5027977150797629230?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/uLMj5zUomEA/speed-bumps-humps.html" title="Speed Bumps / Humps" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2009/01/speed-bumps-humps.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0MMRH45eCp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-4241960419871303964</id><published>2008-03-26T21:50:00.000-07:00</published><updated>2010-01-16T01:51:25.020-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:51:25.020-08:00</app:edited><title>Testing</title><content type="html">(post dated to reflect when material was discussed in class)  Testing is hard...  Reading the description of testing the space shuttle engines in Chapter 11 reminded me a great deal of how large software projects are debugged when one doesn't have much of and understanding of the system.  You attach a debugger to the running program, try to reproduce the bug, maybe you have a break point set on an entry point that's likely a source of the bug and you follow potentially suspect data down to the point where it gets mangled incorrectly.&lt;br /&gt;
&lt;br /&gt;
If you're lucky you have enough of an understanding of why the program decided to mangle the data that way and you can fix the bug.  Otherwise you're left inserting probes and breakpoints in other suspect locations to give you a quick view of data as it moves around the system.&lt;br /&gt;
&lt;br /&gt;
From my own experience top down debugging is tedious and time consuming.  Once I've fixed a bug via a top down approach it's &lt;span style="font-weight: bold;"&gt;really&lt;/span&gt; nice if I can pinpoint the source of the problem well enough to test the fix "bottom up".  If I can, putting a unit test in place to ensure the bug stays fix solidifies a bottom up test that identifies a failure point and ensures that future changes don't reintroduce the defect -- or, at the least, it identifies a place in the code that my need to be revisited if future changes make a bug fix obsolete.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-4241960419871303964?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5SgCZxNzZoVnK-jAiGhUIh6wzPY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5SgCZxNzZoVnK-jAiGhUIh6wzPY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5SgCZxNzZoVnK-jAiGhUIh6wzPY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5SgCZxNzZoVnK-jAiGhUIh6wzPY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/sjLMt01Di4o" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/4241960419871303964/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/03/testing.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4241960419871303964?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4241960419871303964?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/sjLMt01Di4o/testing.html" title="Testing" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/03/testing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0EHQ3s6eyp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-3098061777187082307</id><published>2008-03-24T07:19:00.000-07:00</published><updated>2010-01-16T01:53:52.513-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:53:52.513-08:00</app:edited><title>Re: No Silver Bullet</title><content type="html">When I initially started reading &lt;span style="font-style: italic;"&gt;No Silver Bullet&lt;/span&gt;, by &lt;span style="font-style: italic;"&gt;Frederick P Brooks, Jr&lt;/span&gt; I was unaware of its first publish date, and first few pages have little temporal evidence.  But the farther I got in to the article a couple things show up ... such as referencing time-sharing systems, "high level" languages and unix.  All of which have been around for the outset of my programming life and had already reached a more "mature" state long before I came in to the software world.&lt;br /&gt;
&lt;br /&gt;
I suppose the relative agelessness of the first few pages wouldn't have been apparent if I had read the bits of text that dated the article beforehand.  I think the agelessness of the text is important.  Because it speaks to the fact that the problems Brooks initially defined haven't really changed all the that much in software engineering.  I work in a totally different computing world than what was around when the article was written yet the problems he describes don't sound foreign at all to me.&lt;br /&gt;
&lt;br /&gt;
Brooks introduces several things that promised to "solve" the software problem.  Yet 20 years later, none of these solutions have broken through to the main stream.  People are still getting things done with imperfect software and still making money.  Granted, certain methodologies that may've fallen out of the utopia of "perfect software" are very applicable to certain domains.&lt;br /&gt;
&lt;br /&gt;
For most people, software that's "good enough" is all that's needed.  For me the most important point Brooks makes is that software is hard, and nothing is going to make software easy, hence the title &lt;span style="font-style: italic;"&gt;No Silver Bullet&lt;/span&gt; ... pursuing infallible software is fine for academia but it is probably an expensive loosing battle for 80% of software projects.  Anecdotally, I've experienced this in my own professional experience through writing my own fair share bugs.  The anecdote follows the following premise: write a bug, ship it to customers for period of time, record the period of time that the bug was in wild until it was fixed and released again.  If you look at that time period and you look at how much revenue the software generated in that time period you can come up with a rough estimate of the "cost index" of that bug.  If you make 150k over a 2 month period selling the software with the imperfection it seems to show that the software was still delivering value, even though it may have an (innumerable) amount of imperfections.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-3098061777187082307?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/5S9uZqd1_XHWMe7Ea62nQhrYtwA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5S9uZqd1_XHWMe7Ea62nQhrYtwA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/5S9uZqd1_XHWMe7Ea62nQhrYtwA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/5S9uZqd1_XHWMe7Ea62nQhrYtwA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/cF6sMeke7qg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/3098061777187082307/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/04/re-no-silver-bullet.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3098061777187082307?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/3098061777187082307?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/cF6sMeke7qg/re-no-silver-bullet.html" title="Re: No Silver Bullet" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/04/re-no-silver-bullet.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0AEQ3k9fyp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-8195079062396763158</id><published>2008-03-14T16:54:00.001-07:00</published><updated>2010-01-16T01:55:02.767-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:55:02.767-08:00</app:edited><title>Project Infrastructure Usage Requirements</title><content type="html">I kind of see this class as "playing house" for doing more serious project management on bigger projects in a professional setting. One difference is that most of us won't have to set up all the project management goo, we'll just have to use it.  Using the term "playing house" is a little demeaning but it communicates some of the &lt;i&gt;vibes &lt;/i&gt;I'm sensing from my group members (which might not actually be there, my group members have lots of other classwork to worry about, and this is the only class I'm taking).&lt;br /&gt;
&lt;br /&gt;
One of these "vibes" is that it seems a little artificial to build up all this project management stuff and then actually use it, because we haven't had use for this stuff previously are we aren't forced to use it in this class.   We'd probably be better initiated in to using this stuff if we had a standard set of tools that the whole class could play with, along with assignments like &lt;i&gt;Using a Ticket System&lt;/i&gt;, or &lt;i&gt;Using a Revision Control System&lt;/i&gt;.  In the meantime, I don't know how usage the project infrastructure will see since their don't seem to be many hard requirements in the class to do so.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-8195079062396763158?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/TRyRf8DnbbEWp3BxjGuGepbuBG0/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TRyRf8DnbbEWp3BxjGuGepbuBG0/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/TRyRf8DnbbEWp3BxjGuGepbuBG0/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/TRyRf8DnbbEWp3BxjGuGepbuBG0/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/JaWm-ArFy34" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/8195079062396763158/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/03/project-infrastructure-usage_14.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/8195079062396763158?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/8195079062396763158?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/JaWm-ArFy34/project-infrastructure-usage_14.html" title="Project Infrastructure Usage Requirements" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/03/project-infrastructure-usage_14.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkAHQn08eSp7ImA9WxZWFk0.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-4314646749050311467</id><published>2008-03-14T16:50:00.001-07:00</published><updated>2008-03-15T11:12:13.371-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-03-15T11:12:13.371-07:00</app:edited><title>Mailing Lists and Project Management Documentation</title><content type="html">Our new mailing list has been working swimmingly.  At least until the whole engineering wing of UNM apparently lost power.  Hopefully we'll be able to use our list again soon.&lt;br/&gt;&lt;br/&gt;I didn't manage to make it to any classes this week, but I should have plenty of time to catch up on what I missed over spring break.  Hopefully we'll also be able to hammer out more of the design stuff for our project so we can get started writing code.&lt;br/&gt;&lt;br/&gt;While I wasn't going to class I contributed to the &lt;i&gt;Project Managment&lt;/i&gt; document that we needed to write (which was due today at 5p), which outlined the basic project tasks, as well as (the part that I wrote) an outline of all the machinery we've set up the manage the project and how we intend to use it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-4314646749050311467?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/POBLZ5-M6zmB3aqEWQI3LCKeKak/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POBLZ5-M6zmB3aqEWQI3LCKeKak/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/POBLZ5-M6zmB3aqEWQI3LCKeKak/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/POBLZ5-M6zmB3aqEWQI3LCKeKak/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/SUcsWg3BDXo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/4314646749050311467/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/03/mailing-lists-and-project-management.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4314646749050311467?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/4314646749050311467?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/SUcsWg3BDXo/mailing-lists-and-project-management.html" title="Mailing Lists and Project Management Documentation" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/03/mailing-lists-and-project-management.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D0ACRXw5fSp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-886394819335051043</id><published>2008-03-08T23:52:00.000-08:00</published><updated>2010-01-16T01:56:04.225-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:56:04.225-08:00</app:edited><title>Google Groups, Loosing E-Mail, GMail Marking Google Groups (DomainKey signed) Email as Spam</title><content type="html">We decided today to 86 my choice of Google Groups as our group communication mechanism.  Our group lead (Ben) posted several emails to the list about meeting times for this Saturday, none of which went through.  So the meeting ended up being rather last minute (since no one knew where it was).  I had problems with my GMail account thinking that the Google Groups email was spam.&lt;br /&gt;
&lt;br /&gt;
Whenever I would send email from the wrong account (since the default email gmail sends mail from is not the one that's subscribed to our list) I wouldn't get any feedback from the list that said I couldn't post to list (since that email address is not a member).  I happened to peruse my spam folder and found all the "you can't post to this list" emails laying there.  GMail's spam classifier apparently didn't think the chain of valid domain keys (from one of Google's own domains even) was enough to prevent the mail from being spam.  Needless to say Google Groups is out, hopefully a mailman list provided by the CS department's System Support Group is in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-886394819335051043?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/BTTUPOEmkl-XvdO0ayJEfj0lzKQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BTTUPOEmkl-XvdO0ayJEfj0lzKQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/BTTUPOEmkl-XvdO0ayJEfj0lzKQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/BTTUPOEmkl-XvdO0ayJEfj0lzKQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/emYi5Vb6HYE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/886394819335051043/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/03/google-groups-loosing-e-mail-gmail.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/886394819335051043?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/886394819335051043?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/emYi5Vb6HYE/google-groups-loosing-e-mail-gmail.html" title="Google Groups, Loosing E-Mail, GMail Marking Google Groups (DomainKey signed) Email as Spam" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/03/google-groups-loosing-e-mail-gmail.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D08CRH8zfCp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-8166194658093991570</id><published>2008-03-05T08:22:00.000-08:00</published><updated>2010-01-16T01:57:45.184-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:57:45.184-08:00</app:edited><title>Xen and the Art of Not Functioning</title><content type="html">For the most part I enjoy doing system administrator work ... like setting up the software for our group to use.  However, the real meat of sysadmin's job is not dealing with software that works well, it's dealing with, and working around software that's broken (most of the time with out the ability to change code).&amp;nbsp; &lt;br /&gt;
&lt;br /&gt;
Such was the case with an Ubuntu bug I ran in to that caused Apache and other processes to hang (sometimes) when calling readdir_r or readdir64_r (which is a thread safe version of the readdir call).  The bug initially manifested when I first installed the Ubuntu O/S image for my new Virtual Private Server (VPS) -- I've had had a VPS with another provider, but this was the first time using Ubuntu Gusty (version 7.10).  My VPS is provided by &lt;a href="http://vpslink.com/"&gt;VPSLink &lt;/a&gt;(subsidiary of &lt;a href="http://www.spry.com/"&gt;Spry&lt;/a&gt;), I found the &lt;a href="http://forums.vpslink.com/showthread.php?t=2606"&gt;following report&lt;/a&gt; on the VPSLink forums of problems with the particular O/S image I had installed.  I followed the advice there and installed a different (still Ubuntu) O/S image and set up all the software packages I needed by hand (mainly just Apache).&lt;br /&gt;
&lt;br /&gt;
Everything was good for a while until I ran in to a problem with attempting to do an SVN move (which is implemented as a delete and a copy from the previous revision).  The WebDAV "COPY" command was failing because the Apache server was misconfigured (&lt;a href="http://www.science.uva.nl/research/air/wiki/Subversion502BadGateway"&gt;this document&lt;/a&gt; describes several misconfiguration scenarios including mine).  I fixed the configuration problem and attempted to restart Apache ... low and behold Apache went in to what appeared to be a busy wait loop just pegging the CPU.  What's better is that the process didn't appear to be any code that I could see with user land tools.  The system call tracer &lt;a href="http://linux.die.net/man/1/strace"&gt;strace&lt;/a&gt; would sit silent when attaching to the process.  When I started Apache under strace I could see that the process was stopping after calling getdents.  The library call tracer &lt;a href="http://linux.die.net/man/1/ltrace"&gt;ltrace&lt;/a&gt; showed that execution stopped inside of apr_read_dir which coincides with what strace said (since it's likely that apr_read_dir would call getdents).&lt;br /&gt;
&lt;br /&gt;
APR is the &lt;a href="http://apr.apache.org/"&gt;Apache portable runtime&lt;/a&gt; which is supposed to provide a cross platform shim for C applications.  Out of desparation (since I'd killed Apache in the middle of trying to get my group members set-up to use SVN) I tried installing an Apache build with a different concurrency model (the non-threaded model) even though this didn't really seem like a likely cause of the problem, since it was clear from the strace output that Apache wasn't even getting past reading it's configuration file.  To my chagrine this did not help ... but discovering that readdir64_r was the last thing on the stack (by attaching gdb to the running process, which I had never done &lt;a href="http://apr.apache.org/"&gt;with gdb&lt;/a&gt; before), led me to ask the Oracle (aka Google) about bugs involving readdir64_r, Ubuntu, and Xen and I found &lt;a href="https://bugs.launchpad.net/ubuntu/+source/sysvinit/+bug/152664"&gt;this bug report&lt;/a&gt; which describes an almost identical problem.&lt;br /&gt;
&lt;br /&gt;
The only exception is that they were seeing a segfault instead of the process grinding the CPU.  At the bottom of the above bug report they suggest installing the Xen variant of the C library.  This solution fixed everything.  Clearly my VPS provider does not do adequate testing of their O/S images.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-8166194658093991570?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/Ej4f8deyA3SiNfC3OFFN_UBv8j4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ej4f8deyA3SiNfC3OFFN_UBv8j4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/Ej4f8deyA3SiNfC3OFFN_UBv8j4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/Ej4f8deyA3SiNfC3OFFN_UBv8j4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/nJoQV2V6QAE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/8166194658093991570/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/03/xen-and-art-of-not-functioning.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/8166194658093991570?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/8166194658093991570?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/nJoQV2V6QAE/xen-and-art-of-not-functioning.html" title="Xen and the Art of Not Functioning" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/03/xen-and-art-of-not-functioning.html</feedburner:origLink></entry><entry gd:etag="W/&quot;D04CRn4zeSp7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-5628139250704767917</id><published>2008-02-28T21:19:00.000-08:00</published><updated>2010-01-16T01:59:27.081-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T01:59:27.081-08:00</app:edited><title>Subversion, Trac, Mailing Lists</title><content type="html">I've been working on getting the management infrastructure going for our project.  So fact I've successfully set-up Trac for our project management along with Subversion.  I've also imported Ben's prior work on Hex Chess.  I plan on writing up at least some brief documentation describing how we're going to use these tools.  Hopefully this information can become part of our project management document.  The biggest problems I had with setting up Subversion and Trac was figuring how to navigate Apache configuration files.  Apache documentation is great and examples are plentiful but I had trouble getting useful feed back from apache when it didn't like something (the log messages emitted weren't very helpful).  Perhaps I just need to enable more verbose logging.&lt;br /&gt;
&lt;br /&gt;
Our Trac and Subversion URLs are as follows:&lt;br /&gt;
&lt;br /&gt;
https://trac.bgn.deadbeefbabe.org&lt;br /&gt;
https://svn.bgn.deadbeefbabe.org&lt;br /&gt;
&lt;br /&gt;
The SSL certificates served are self-signed so you'll have to navigate past your browser's warnings that the site might be lying about who it is (even though communication will still be encrypted).  Trac should be set-up so that only authenticated users can modify it (that is, members of our group).  Obvious Subversion can only be modified by members of our group (hopefully, if I set everything up correctly).  I plan on only using https for communicating with Subversion so hopefully the Eclipse Subversion plug-in fully supports https access to Subversion.&lt;br /&gt;
&lt;br /&gt;
As for a mailing list, the easiest solution was to use Google Groups (http://googlegroups.com). As long as we don't mind Google reading about our CS 460 project it provides a really plainless way to get a mailing list set-up (and we can set the group so that only we can communicate on it / read archives).  Google groups provides a cohesive conjoining of the "newsgroup" and the "mailing list" since they are both pretty much the same product with a different implementation this works really well.  Obviously we'll be using the Google Group as a mailing list.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-5628139250704767917?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/t9caBznhmjHIFpHDN6cu2QSn7hQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t9caBznhmjHIFpHDN6cu2QSn7hQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/t9caBznhmjHIFpHDN6cu2QSn7hQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/t9caBznhmjHIFpHDN6cu2QSn7hQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/uqoeb4-uwqI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/5628139250704767917/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2008/02/subversion-trac-mailing-lists.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5628139250704767917?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/5628139250704767917?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/uqoeb4-uwqI/subversion-trac-mailing-lists.html" title="Subversion, Trac, Mailing Lists" /><author><name>jam</name><uri>http://www.blogger.com/profile/01376788615602689607</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="32" height="32" src="http://4.bp.blogspot.com/_CeryDY5B7Rk/SYdG6FKq9eI/AAAAAAAAAg8/NY_l9R5v09g/S220/avatar.jpg" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2008/02/subversion-trac-mailing-lists.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEcAQnYyfip7ImA9WxBQFk4.&quot;"><id>tag:blogger.com,1999:blog-6096825618667407299.post-2582191833641112753</id><published>2008-02-10T20:23:00.000-08:00</published><updated>2010-01-16T02:00:43.896-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-01-16T02:00:43.896-08:00</app:edited><title>More Interfaces...</title><content type="html">Recently on projects were I really wanted to test everything I've been creating interfaces more frequently.  With object oriented languages interfaces are usually described pretty easily in some fashion, despite the fact that some languages may not directly support them.&lt;br /&gt;
&lt;br /&gt;
This practice of "creating interfaces for everything" means that if I'm interacting with a class that runs processes the only way to test code that depends on this class is to either actually run test processes on the system or create something that pretends to run processes.  There are many situations in which running processes is bad, in my case it was the fact the processes in question could take a long time to complete, in other cases you may not want unit tests to depend on the state of the system.  So that leaves creating something that pretends to run processes.&lt;br /&gt;
&lt;br /&gt;
Inheritance in languages like Java and C# can be a messy business, in many cases I don't need the complexity imposed on me by API level classes, there's usually only a few methods of an API class that I need and the usage is fairly simple.  Because of this implementing a subclass of an API level classes can leave wholes open to the underlying code that I don't necessarily want to expose.  In some cases API level classes &lt;span style="font-style: italic;"&gt;can't&lt;/span&gt; be subclasses (in the case of sealed/final classes in C#/Java).  Therefore, we add more indirection, and create an interface.&lt;br /&gt;
&lt;br /&gt;
What good is creating an interface?  It can describe &lt;span style="font-style: italic;"&gt;exactly&lt;/span&gt; how I'm using the API level class and it only exposes the bits of functionality that I need to test.  With an interface I can implement a real class that actually runs processes and a fake class that lies about running process and pretends to fail in certain cases in order to test how the code reacts to failure cases.  The downside is that creating interfaces everywhere can increase the complexity of the code, more types just means more names and ideas that can contribute to confusion about the overall design of the code.&lt;br /&gt;
&lt;br /&gt;
In the alternate case of subclassing the process class for testing, the code remains simple and the need to create 3 new types is avoided (1 for the interface, 1 for the  real implementer, and 1 for the test implementer).  However, I think masses of types can still be managed and using interfaces frequently when using hard to test API classes can make code more reliable and easily tested.  Interfaces around complex API classes can also improve the &lt;span style="font-style: italic;"&gt;descriptiveness&lt;/span&gt; of the code, in that the interface can be used to describe how API classes are being used.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6096825618667407299-2582191833641112753?l=csjam.blogspot.com' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/u2I59p-CKYKnfawykQx6_f5Hrlo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2I59p-CKYKnfawykQx6_f5Hrlo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/u2I59p-CKYKnfawykQx6_f5Hrlo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/u2I59p-CKYKnfawykQx6_f5Hrlo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/Csjam/~4/Td6I2o2R2Tk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://csjam.blogspot.com/feeds/2582191833641112753/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://csjam.blogspot.com/2007/02/more-interfaces-please.html#comment-form" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2582191833641112753?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/6096825618667407299/posts/default/2582191833641112753?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/Csjam/~3/Td6I2o2R2Tk/more-interfaces-please.html" title="More Interfaces..." /><author><name>jam</name><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://csjam.blogspot.com/2007/02/more-interfaces-please.html</feedburner:origLink></entry></feed>

