<?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:blogger="http://schemas.google.com/blogger/2008" 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:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;AkIHR3Y8fSp7ImA9WhBRFkw.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854</id><updated>2013-03-06T17:08:56.875-08:00</updated><title>Step Three: Profit!</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://www.stepthreeprofit.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>42</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/StepThreeProfit" /><feedburner:info uri="stepthreeprofit" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><geo:lat>30.292424</geo:lat><geo:long>-97.73856</geo:long><link rel="license" type="text/html" href="http://creativecommons.org/licenses/by-nc-sa/3.0/" /><feedburner:emailServiceId>StepThreeProfit</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;DkcNQn48eSp7ImA9WhBTFEs.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-7357857972053518516</id><published>2013-02-09T18:41:00.001-08:00</published><updated>2013-02-09T18:41:33.071-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-02-09T18:41:33.071-08:00</app:edited><title>Space Party: Space Captain</title><content type="html">My game studio, Hot Trouble, is working on a local co-op video game called Space Party. It's inspired by Artemis, Space Team, FTL, and Puzzle Pirates. In this game you and your friends all take on different roles crewing a spaceship. Each role has its own minigame that you have to play to do your job and keep the spaceship running.&lt;br /&gt;
&lt;br /&gt;
We're releasing each of the minigames as a standalone game as part of the OneGameAMonth.com initiative. The first one is out now and it's called &lt;a href="http://goo.gl/mkDTa"&gt;Space Captain&lt;/a&gt;. You pilot a ship around different sectors of the galaxy looking for an Earth-like planet to colonize. Watch out for the other planets though, as they're inhabited by hostile aliens that will chase you down and destroy your ship. You don't have any weapons, so your only option is to run.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=baBQbiQoXsc:bkWs7mHGZnM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=baBQbiQoXsc:bkWs7mHGZnM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=baBQbiQoXsc:bkWs7mHGZnM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/baBQbiQoXsc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/7357857972053518516/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=7357857972053518516" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7357857972053518516?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7357857972053518516?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/baBQbiQoXsc/space-party-space-captain.html" title="Space Party: Space Captain" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2013/02/space-party-space-captain.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQEQHc4eip7ImA9WhNaEUg.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-49023007138330219</id><published>2013-01-25T13:45:00.000-08:00</published><updated>2013-01-25T13:45:01.932-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2013-01-25T13:45:01.932-08:00</app:edited><title>JSON: It's Time to Move On</title><content type="html">I love JSON. I love it because it's not XML. I used to think XML was a pretty good idea compared to unpacking structs, but the more it was used for generic tasks like RPC and config file formats, the more it became clear that it was really only suitable for documents. This makes sense, as that's what it was designed to do. XML was being used to represent data structures, and the problem with that is that there is a mismatch between what XML is good at expressing and the sort of data structures you generally want to encode for computational tasks.&lt;br /&gt;
&lt;br /&gt;
JSON is obviously a better choice for a number of common data types and structures such as floats, strings, maps, and lists. The syntax is easier to read and more concise for encoding these types. More importantly, however, is that there is a clear mapping between the data structures and their encoding. This was something you had to invent in XML or use one of a number of incompatible standards, such that XML became a proliferation of different languages speaking about the same things.&lt;br /&gt;
&lt;br /&gt;
JSON has served us well, but much like XML, as it's been used for more and more things, it's shortcomings are becoming apparent. JSON suffers from essentially the same problem as XML, a like of universal mappings for common items that need to be encoded and decoded consistently.&lt;br /&gt;
&lt;br /&gt;
The missing type which most commonly causes me trouble with JSON is byte strings. Javascript only has one string type, while other languages often have two: one for byte strings and one for unicode strings. To be honest, I'm not totally sure if Javascript strings are supposed to be unicode strings. String literals can include unicode escape sequences. However, I'm not clear on if you can have pure byte strings (i.e. with invalid unicode sequences) and I don't know, for instance, if String.charAt(x) counts bytes or unicode characters. However, most JSON encoders assume all strings to be unicode. Therefore, JSON in practice has only a unicode string type and does not support byte strings.&lt;br /&gt;
&lt;br /&gt;
Many applications, however, have byte strings. The most common solution is to base64 encode your byte strings into ASCII characters and encode them into JSON as unicode strings. In addition to being slower, it requires increased semantic complexity. Both the sender and receiver of the JSON now need to know where the base64 encoded strings are in the nested JSON data structure so that they can be encoded and decoded between byte strings and base64.&lt;br /&gt;
&lt;br /&gt;
This has caused people to invent their own protocols on top of or around JSON. For instance, you can tag every string as to whether it needs to be base64 decoded or not. Another solution is to remove all byte strings from the JSON and instead include tagged offsets. The binary data can then be appended to the end of the JSON data as a packed binary blob and the offsets used to extract individual byte strings. A very simple solution I've seen is to encode the whole data structure using a binary-friendly format such as BSON or MessagePack, base64 encode the entire result, and send it as a single JSON string.&lt;br /&gt;
&lt;br /&gt;
The advantage to building something on top of or around JSON is that the encoder and decoder do all of the work of analyzing the data structure and patching incompatibilities with standard JSON. The disadvantage is that now you're using a nonstandard protocol which is going to need to be implemented for both the sender and receiver, for every language you want to use.&lt;br /&gt;
&lt;br /&gt;
The best solution overall is to realize the limitations of JSON and decide on a new protocol which fixes these limitations. There are several alternatives to JSON already, but they focus more on efficiency on encoding and decoding rather than on the more fundamental semantic mismatch issues. Of the binary formats I've looked at (BSON, BJSON, MessagePack), only BSON has separate data types for unicode strings and byte strings. I'm not specifically advocating BSON, but at least they have the right idea on that front.&lt;br /&gt;
&lt;br /&gt;
This new protocol doesn't even necessarily need to be a binary protocol. It just needs to support byte strings as a semantic type. In the end, everything needs to be JSON-compatible in order to be browser-compatible, so building something on top of JSON would probably be a fine solution. People are already doing this, as I mentioned above. The next step is to give it a name and release it on github so that everyone can use it and start adding support for more languages.&lt;br /&gt;
&lt;br /&gt;
Here is my minimum feature least for a new encoding:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;It should be JSON-style where you just give it a data structure and it serializes it, and you give it a string and it deserializes it into a data structure. (As opposed to Protobuf/Thrift style with schemas)&lt;/li&gt;
&lt;li&gt;Support for all the JSON datatypes - string, float, map, list, boolean, null&lt;/li&gt;
&lt;li&gt;Add support for byte strings in addition to unicode strings&lt;/li&gt;
&lt;li&gt;Add support for integers in addition to floats&lt;/li&gt;
&lt;li&gt;Add support for dates&lt;/li&gt;
&lt;li&gt;Browser-compatible, which probably means encoded as JSON between the client and server&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
Nice-to-have optional features:&lt;/div&gt;
&lt;div&gt;
&lt;ul&gt;
&lt;li&gt;Sets as well as lists&lt;/li&gt;
&lt;li&gt;Ordered maps as well as unordered maps&lt;/li&gt;
&lt;/ul&gt;
&lt;div&gt;
In the meantime, I've switched to using BSON when not in browsers and I'm still using JSON in the browser. This is not a good solution, but it's the best available at the moment that doesn't require inventing a custom protocol.&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=cCKbs-bLAxw:1-r1QXqCWqo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=cCKbs-bLAxw:1-r1QXqCWqo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cCKbs-bLAxw:1-r1QXqCWqo:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/cCKbs-bLAxw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/49023007138330219/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=49023007138330219" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/49023007138330219?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/49023007138330219?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/cCKbs-bLAxw/json-its-time-to-move-on.html" title="JSON: It's Time to Move On" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2013/01/json-its-time-to-move-on.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUNR304cSp7ImA9WhJaEUw.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-614334761701037343</id><published>2012-10-01T10:24:00.002-07:00</published><updated>2012-10-01T10:24:56.339-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-10-01T10:24:56.339-07:00</app:edited><title>Adventure Time Game Jam</title><content type="html">I was recently fortunate enough to participate in the &lt;a href="http://www.adventuretimegamejam.com/"&gt;Adventure Time Game Jam&lt;/a&gt;, sponsored by Fantastic Arcade. They managed to get licensing rights from Pendleton Ward and Cartoon Network to use Adventure Time characters in games, under the condition that we could only distribute our games through the game jam site, and that Cartoon Network could post the ones they like on their own site.&lt;br /&gt;
&lt;br /&gt;
The were about 700 participants, and approximately 100 games were produced. The winning game was by indie studio Vlambeer. It was such a great game too!&lt;br /&gt;
&lt;br /&gt;
My own team consisted of myself as programmer, &lt;a href="http://coriejohnson.com/"&gt;Corie Johnson&lt;/a&gt; as UI/UX/graphic designer, and &lt;a href="http://celinethefeline.com/"&gt;Celine Suarez&lt;/a&gt; as voice actress and graphic artist. Corie also recorded the opening theme song and composed an original rap which she performed for the ending screen.&lt;br /&gt;
&lt;br /&gt;
It was a unique experience. The game jam took place in&amp;nbsp;an abandoned yoga studio next to the Alamo Drafthouse South Lamar.&amp;nbsp;When we first arrived, there were no chairs.&amp;nbsp;&amp;nbsp;Our Internet was stolen from the Drafthouse. There was a main in the corner with an Einstein's Arcade t-shirt making ethernet cables and each time he finished one, one more person got to get online. In another corner, Vlambeer were sitting on the ground playing Infinite Swat with xbox controllers on a laptop.&lt;br /&gt;
&lt;br /&gt;
For some reason pizza and beer kept arriving from unknown origins for 48 hours.&amp;nbsp;All of the audio was recorded on iPhones in the shower at the space where we were doing the game jam. The ending rap was composed and the main theme recorded in the car driving to and from the space. There was no time to waste on second guessing decisions as the clock was constantly ticking. In the end I think we had one of the most finished games. You can &lt;a href="http://www.adventuretimegamejam.com/submissions/20-lumpy-space-chess"&gt;download it from the site&lt;/a&gt;. Also check out how it was mentioned in the &lt;a href="http://www.wired.com/gamelife/2012/09/adventure-time-game-jam/?pid=3102"&gt;top 8 coolest games from the jam on Wired&lt;/a&gt;!&lt;br /&gt;
&lt;br /&gt;
For me it was great working with such a talented team. I basically just hacked code nonstop. I did the whole game in &lt;a href="http://kineticjs.com/"&gt;KineticJS&lt;/a&gt;, which is a great HTML5 graphics framework, and I used &lt;a href="http://buzz.jaysalvat.com/"&gt;Buzz&lt;/a&gt; for the sound. These libraries saved me a lot of time and I learned a lot about the affordances and limitations of HTML5 games.&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=VEFnjkgFmk8:UNEHP4hKSBM:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=VEFnjkgFmk8:UNEHP4hKSBM:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=VEFnjkgFmk8:UNEHP4hKSBM:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/VEFnjkgFmk8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/614334761701037343/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=614334761701037343" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/614334761701037343?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/614334761701037343?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/VEFnjkgFmk8/adventure-time-game-jam.html" title="Adventure Time Game Jam" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/10/adventure-time-game-jam.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YMQXcyfip7ImA9WhJRF0Q.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-6414853887465941846</id><published>2012-07-20T08:44:00.001-07:00</published><updated>2012-07-20T08:46:20.996-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-20T08:46:20.996-07:00</app:edited><title>Freefall Tutorial Screencast</title><content type="html">I made a &lt;a href="http://youtu.be/gqLQM7YJx4s"&gt;screencast&lt;/a&gt; walking through the tutorial for building a Freefall example app. In this particular example, I built a simple leaderboard services where you can post scores and then get a sorted list of all the scores. Make sure to watch it in HD so that the text is legible.&lt;br /&gt;
&lt;br /&gt;
&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;br /&gt;&lt;object width="320" height="266" class="BLOGGER-youtube-video" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0" data-thumbnail-src="http://i.ytimg.com/vi/gqLQM7YJx4s/0.jpg"&gt;&lt;param name="movie" value="http://www.youtube.com/v/gqLQM7YJx4s?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" /&gt;&lt;param name="bgcolor" value="#FFFFFF" /&gt;&lt;param name="allowFullScreen" value="true" /&gt;&lt;embed width="320" height="266"  src="http://www.youtube.com/v/gqLQM7YJx4s?version=3&amp;f=user_uploads&amp;c=google-webdrive-0&amp;app=youtube_gdata" type="application/x-shockwave-flash" allowfullscreen="true"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=qBGH4v01EKA:G5bMj7iKpMY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=qBGH4v01EKA:G5bMj7iKpMY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=qBGH4v01EKA:G5bMj7iKpMY:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/qBGH4v01EKA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/6414853887465941846/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=6414853887465941846" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6414853887465941846?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6414853887465941846?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/qBGH4v01EKA/freefall-tutorial-screencast.html" title="Freefall Tutorial Screencast" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/freefall-tutorial-screencast.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkcDRnk7cSp7ImA9WhJRFUs.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-8201323300177639862</id><published>2012-07-17T15:27:00.005-07:00</published><updated>2012-07-17T15:27:57.709-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-17T15:27:57.709-07:00</app:edited><title>Freefall Tutorial Docs</title><content type="html">I've been working on some &lt;a href="https://github.com/blanu/freefalldb/tree/master/doc"&gt;tutorial docs&lt;/a&gt; for using Freefall. There is a usage tutorial that describes all of the different commands you can use with the command line tool. There is also an app development tutorial which walks you through developing a simple leaderboard service. By the end of the tutorial you should have a leaderboard up and running on Google App Engine!&lt;br /&gt;
&lt;br /&gt;
If you go through the tutorial, please let me know how it goes. Any feedback on the documentation would be helpful as I want this to be a tool which people can actually use.&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Xtn3Y8CKpR4:ypPrshbxXeA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Xtn3Y8CKpR4:ypPrshbxXeA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Xtn3Y8CKpR4:ypPrshbxXeA:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/Xtn3Y8CKpR4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/8201323300177639862/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=8201323300177639862" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8201323300177639862?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8201323300177639862?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/Xtn3Y8CKpR4/freefall-tutorial-docs.html" title="Freefall Tutorial Docs" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/freefall-tutorial-docs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEYCQnY8cCp7ImA9WhJRFEQ.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-8445241012878558924</id><published>2012-07-16T20:32:00.000-07:00</published><updated>2012-07-16T20:36:03.878-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-16T20:36:03.878-07:00</app:edited><title>Austin on Kickstarter</title><content type="html">I was recently asked if I knew anyone that had done a Kickstarter campaign and might want to be on a crowdfunding panel here in Austin. I started thinking about all of the local folks I knew that had done Kickstarters. There were quite a few! I wanted to share them with you. These are just people I know personally (and friends of friends), so there must be a lot more projects going on in Austin that I don't know about. This is exciting to think about.&lt;br /&gt;
&lt;br /&gt;
Here is the list:&lt;br /&gt;
&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/872179144/tammany-hall?ref=live"&gt;Tammany Hall&lt;/a&gt;, &lt;a href="http://www.kickstarter.com/projects/872179144/the-great-fire-of-london?ref=users"&gt;The Great Fire of London&lt;/a&gt;&amp;nbsp;- Pandasaurus Games / Nathan McNair&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/dystopianholdings/inevitable-dystopian-tabletop-gaming?ref=live"&gt;Inevitable&lt;/a&gt; - Dystopian Holdings / Jonathan Leistiko&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/wileywiggins/thunderbeam-for-the-ipad?ref=live"&gt;Thunderbeam&lt;/a&gt; - Karakasa Games / Wiley Wiggins&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/liseman/growerbot-your-social-gardening-assistant?ref=history"&gt;growerbot&lt;/a&gt; - Luke Iseman&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/bigpoppae/big-poppa-es-poetry-project?ref=search"&gt;Big Poppa E's Poetry Project&lt;/a&gt; - Big Poppa E&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/1830488365/the-blue-hit-recordings-project?ref=users"&gt;The Blue Hit Recordings Project&lt;/a&gt; - The Blue Hit&lt;br /&gt;
&lt;a href="http://www.beatboxbeverages.com/"&gt;Beatbox Beverages&lt;/a&gt;&amp;nbsp;(not launched yet) - Beatbox Beverages / Aimy Steadman&lt;br /&gt;
&lt;a href="http://www.kickstarter.com/projects/brandonwiley/cat22-culture-art-and-technology-in-the-22nd-centu?ref=live"&gt;CAT22&lt;/a&gt; - me!&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=xxcWNzXC78s:zTkfIQRrAFY:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=xxcWNzXC78s:zTkfIQRrAFY:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xxcWNzXC78s:zTkfIQRrAFY:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/xxcWNzXC78s" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/8445241012878558924/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=8445241012878558924" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8445241012878558924?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8445241012878558924?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/xxcWNzXC78s/austin-on-kickstarter.html" title="Austin on Kickstarter" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/austin-on-kickstarter.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DEIBRHY4eyp7ImA9WhJREEk.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-6902539537356512059</id><published>2012-07-11T15:42:00.000-07:00</published><updated>2012-07-11T15:42:35.833-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-11T15:42:35.833-07:00</app:edited><title>Freefall Scaling</title><content type="html">Freefall is a cloud-based NoSQL database which is designed from the ground up to be ultra-scalable. For the most part, users of Freefall don't need to know anything about the details. It just works. However, scalability enthusiasts might be interested in knowing what's going on under the hood.&lt;br /&gt;
&lt;br /&gt;
The first step in designing Freefall to scale is that it runs on top of Google App Engine. This means that, for the most part, Google will autoscale the number of servers in order to handle the rate of incoming requests. There are plenty of parameters you can tweak on the App Engine web dashboard in order to optimize performance, but for basic functionality you don't need to change a thing.&lt;br /&gt;
&lt;br /&gt;
The next step is the separation of frontend and backend services. The public API of your services, the actions and the views, are handled by the frontend servers. The transforms, the internal logic of your application and the bulk of the computation, are handled by the backend servers. This means that a client will never block while waiting for a time-consuming computation to complete. Actions and views are designed to return very quickly, freeing up the frontend servers to handle more requests, while the backend servers compute asynchronously. Therefore, when the service is overloaded with too many writes to process, the failure mode is stale data, not catastrophic collapse.&lt;br /&gt;
&lt;br /&gt;
The next step is to separate reads and writes. Views are read-only. In fact, views are pre-computed and pre-serialized and cached in memory. So when you load a view all the frontend server has to do is read the pre-serialized bytes out of memory and write them to the HTTP socket. Views are therefore extremely fast. Actions are write-only. The purpose of an action is to change the application's state. All the frontend servers do for an action is to deserialize the incoming data and add the request to a queue. The actual processing of the action is done asynchronously on the backend. Actions are therefore extremely fast.&lt;br /&gt;
&lt;br /&gt;
On the backend, an action and a transform are essentially the same, the only differences between them being whether it is part of the public API or internal logic and whether the input is supplied by the client or from internally stored data. From a processing perspective, they operate in the same way. The input data is loaded and the transform function is run. It makes changes to the output based on the input and the results of computation. After the output has been changed, two things happen: views are calculated, and transforms are triggered. If the particular model which is the output of the transform is marked as a view, then the state of that model is serialized and cached in memory so that it can be retrieved by the client. If any transforms are configured to be triggered by the output model then they are called and the process repeats again. Eventually all of the transforms have been processed and all of the views have been calculated and the system returns to a state of rest until the next action is performed.&lt;br /&gt;
&lt;br /&gt;
That's the system in a nutshell, but I glossed over some details which are important to the technical aspects of how Freefall scales so well. If we were to process one transform at a time then that could make things very slow. So instead, App Engine can process multiple transforms at once by launching simultaneous backend servers which pull tasks from the queue. This allows for highly parallelized computation, similar to MapReduce. There are a number of ways that parallel computation can go awry, but everything works out in Freefall because of some clever design elements. First of all, the structure of transforms creates a data flow graph. Transforms can have multiple inputs, but only one output, and cycles are not allowed. The structure of the graph therefore partially serializes computation because a transform isn't executed until its inputs have changed.&lt;br /&gt;
&lt;br /&gt;
Additionally, transforms are pure, side-effect free functions. So the value of the output is entirely determined by the value of the inputs (and the computation). It therefore doesn't matter what order we run the computations in as long as they have the correct inputs. This may seem confusing because the transform functions modify the output state. However, this is all a ruse to make it easier to write transforms in a more familiar syntax. Transforms do not actually modify the output model, but rather they are monadic functions, which is to say that they produce monads. A monad in this case is a list of requested changes to make to the model. The model is not actually modified, the modifications that are requested are just collected and returned at the end of the function. This is important because it means we can run the function as many times as we like without fear of it actually modifying the database. In fact, we do sometimes run the function multiple times. Freefall is a Software Transactional Memory (STM) database. We run the set of requested changes in a transaction, possibly simultaneously with a lot of other transactions. If any two transactions modify the same model then we abort and retry. The function which was aborted is rerun using the new values for the model. This is the one case in which it does matter in which order we run the functions as the rerun function might return a different output given its new input. However, this is essentially a case of two things happening simultaneously and so in the interest of moving forward one of the two simultaneous events is chosen to happen first and the other second. Deadlock is therefore avoided and consistency is maintained (because everything happens in transactions).&lt;br /&gt;
&lt;br /&gt;
So that's basically all of the magic: queues, caching, asynchronous monadic functions, and software transactional memory. The result is a database that won't fall over under read load and can be scaled up to handle arbitrarily high write load by launching more backend processing servers.&lt;br /&gt;
&lt;br /&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=6mqu-iw6ygI:ugfZ-kKa2R0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=6mqu-iw6ygI:ugfZ-kKa2R0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=6mqu-iw6ygI:ugfZ-kKa2R0:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/6mqu-iw6ygI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/6902539537356512059/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=6902539537356512059" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6902539537356512059?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6902539537356512059?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/6mqu-iw6ygI/freefall-scaling.html" title="Freefall Scaling" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/freefall-scaling.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUMNQX84cSp7ImA9WhJREEk.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-6892117336999389777</id><published>2012-07-11T14:51:00.000-07:00</published><updated>2012-07-11T14:51:30.139-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-11T14:51:30.139-07:00</app:edited><title>Freefall: What Is It And Why Is It Awesome?</title><content type="html">To describe it simply, Freefall is a NoSQL database. It is similar to other NoSQL databases such as CouchDB, SimpleDB, or MongoDB. However, there are some key differences in Freefall, particularly in how you use it.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Unlike most databases, you do not run Freefall on your own servers. It runs as a Google App Engine app. You run your own instance and you pay Google for the bandwidth and computation time. The reason that you need to run your own instance is because Freefall isn't just a generic database. You specify the services provided by your application and then Freefall generates a custom App Engine app to provide those services. It also generates custom client libraries to call the services. So your experience as a developer is of a high-level API provided as a library for the language of your choice to access your specific services. In this way Freefall is similar to Rails because it provides most of the infrastructure and you just provide your application-specific code. Most importantly, you don't need to know anything at all about Google App Engine! It's all taken care of by Freefall. You just need to define your specific services and then you're ready to go.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
For example, let's say you wanted a simple high score tracking service. You could define a "reportScores" action which reports a new score for a given playerid. You could then define a "highest" transform which discards all scores for a given player which aren't the highest seen. You could then define a "highScores" view which returns a list of the high scores. Freefall would then generate all of the code to make a server which supports these functions and client libraries with high-level methods such as "void reportScores(String playerid, float score)". You can then deploy your server-side code to App Engine and call the client library to access your high score service.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
As you can see from the above example, Freefall is an MVC framework. You define actions which are the public API for changing the state of your application. You can also define internal transforms which derive new state from the state changed by actions, or from other transforms. Eventually, the state changes reach one of the defined views, in which case the changes become publicly accessible. Actions and views together form the public API of your service, while transforms represent the internal logic on your service. Together they form a data flow graph in which actions flow into transforms and then into views. Actions are the input and views are the output.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
Transforms are a powerful feature of Freefall as they allow for arbitrary computations to take place to process your data. You can do validation, authorization, sorting, joins, and filtering. Transforms are similar to CouchDB views, except that they can take multiple inputs and they can be chained by using the output of one transform as the input for another. This makes them much more flexible than CouchDB views. Additionally, transforms (and actions) are full python functions. They can even import modules! They are stored in .py files, not in the database, so you can use version control to keep track of your code.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
So when you really get down to it, Freefall is much more than a NoSQL database. It's a framework for doing data-driven server-side computations in a convenient and scalable way. Other databases just store the data and require you to do computation client-side, or they provide limited or awkward server-side computation. Freefall provides all of the power of python on the server, without all of the hassle and with much better scalability than setting up a python-based web server.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=IYgMWBrERqI:fK3Teud_vGU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=IYgMWBrERqI:fK3Teud_vGU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=IYgMWBrERqI:fK3Teud_vGU:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/IYgMWBrERqI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/6892117336999389777/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=6892117336999389777" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6892117336999389777?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6892117336999389777?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/IYgMWBrERqI/freefall-what-is-it-and-why-is-it.html" title="Freefall: What Is It And Why Is It Awesome?" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/freefall-what-is-it-and-why-is-it.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEFQX8yfSp7ImA9WhJREEk.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-3327953909802012662</id><published>2012-07-11T14:03:00.000-07:00</published><updated>2012-07-11T14:03:30.195-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-07-11T14:03:30.195-07:00</app:edited><title>Announcing Freefall: Cloud Services for Mobile Apps</title><content type="html">For the past few years I've been working as a scalability consultant for Internet startups, mostly on scaling websites. People call me when their Rails servers are crushed by the popularity of their product, and I fix them. There's no magic bullet to scaling. There are a few principles of good design and they are largely not followed, so my job is to bring things back in line with best practices for optimum scaling. For a while I've been thinking about taking these best practices and packaging them up into something people could use directly, rather than implementing the same set of optimizations for each client. However, I found that web companies tend to already be committed to a particular stack. As I've also been doing Android and iOS development lately, I thought mobile developers might be the ideal market for a new, super-scalable backend system. I've noticed that mobile developers aren't that interested in hacking backend code. They'd rather just get on with their mobile apps and leave the backend to someone else. There are a lot of cloud backend services already available, but my idea was different, it was a universal backend for anything from leaderboards to MMOs.&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I was pitching this idea to any mobile developer that would listen at SXSW Interactive this year and I was lucky enough to pitch it to John Warren at &lt;a href="http://minicorestudios.com/"&gt;Minicore Studios&lt;/a&gt;. I've known John for a while as I am a friend of the St. Edward's Digital MBA program from which he graduated. He'd been talking about starting a game development studio, and sure enough he had done so and they had a booth at SXSW Screenburn. My pitch to John was that he would not need to hire server-side developers or sysadmins to run the servers for the online components of his games. His mobile front-end developers could just continue writing their games on Android, iOS, PC, and Xbox. There would be client libraries available in all of the necessary languages and the developers could use them like any other library, not ever thinking about the server side of things. The system would be flexible to whatever he needed to do with online services, not limited to a static set of services such as leaderboards and achievements like most cloud services. Best of all, there would be no monthly fees, it would be open source and built on top of &lt;a href="https://developers.google.com/appengine/"&gt;Google App Engine&lt;/a&gt;, so you just pay Google for your bandwidth and computation, and you only pay for what you use.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I guess John thought it was a good idea, because he hired me on the spot to build this service. I've been working all summer at Minicore building an open source persistant world server for the indie game development community to use free of charge. What can I say? This has been a dream opportunity for me. After spending so much time fixing broken design I was able to build something which follow best practices from the ground up. It's flexible, it's fast, and most of all it scales like crazy.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;
&lt;div&gt;
I'm going to post more technical details soon, as well as documentation and guides. Right now I just wanted to let the world know that this is happening. I just got the first service working, leaderboards for Minicore's &lt;a href="https://play.google.com/store/apps/details?id=minicore.MemTanks.GamePro&amp;amp;feature=search_result#?t=W251bGwsMSwxLDEsIm1pbmljb3JlLk1lbVRhbmtzLkdhbWVQcm8iXQ.."&gt;Tanks for the Memories for Android&lt;/a&gt;, and I decided it was time to make a post. In the meantime, check out the &lt;a href="https://github.com/blanu/freefalldb"&gt;project source&lt;/a&gt; (without documentation as of yet) and give a &lt;a href="https://twitter.com/johnewarren"&gt;shout out to John&lt;/a&gt; to thank him for making this possible for the indie game community.&lt;/div&gt;
&lt;div&gt;
&lt;br /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=0MkHpaIUl7A:x4mjhlWGmq0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=0MkHpaIUl7A:x4mjhlWGmq0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=0MkHpaIUl7A:x4mjhlWGmq0:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/0MkHpaIUl7A" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/3327953909802012662/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=3327953909802012662" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3327953909802012662?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3327953909802012662?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/0MkHpaIUl7A/announcing-freefall-cloud-services-for.html" title="Announcing Freefall: Cloud Services for Mobile Apps" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/07/announcing-freefall-cloud-services-for.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0UDSH4-cSp7ImA9WhVXFE4.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-8626713910491776378</id><published>2012-04-14T14:31:00.003-07:00</published><updated>2012-04-14T14:34:39.059-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-04-14T14:34:39.059-07:00</app:edited><title>High-level Languages for the 6502</title><content type="html">&lt;span style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;What's up, hackers? I know you guys don't particularly care about this subject, but I am have become temporarily obsessed with it, so here for your perusal, my research on high-level languages for the 6502!&lt;/span&gt;&lt;div style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;&lt;a href="http://ahefner.livejournal.com/20528.html"&gt;Common-Lisp assembler&lt;/a&gt; - This is lisp-syntax assembler. Except you can also use lisp structures such as conditionals and loops. You can also define new lisp functions. It compiles to normal assembly. So I think it's more like macros than an actual lisp runtime. (See also &lt;a href="http://josephoswald.nfshost.com/comfy/summary.html"&gt;COMFY&lt;/a&gt;)&lt;/div&gt;&lt;div style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;&lt;a href="http://code.google.com/p/python-on-a-chip/"&gt;Python on a chip&lt;/a&gt; - A subset of python syntax and VM!&lt;/div&gt;&lt;div style="font-family: arial; text-align: -webkit-auto; font-size: small; "&gt;&lt;ul&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Requires roughly 55 KB program memory&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Initializes in 4KB RAM; print "hello world" needs 5KB; 8KB is the minimum recommended RAM.&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Supports integers, floats, tuples, lists, dicts, functions, modules, classes, generators, decorators and closures&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Supports 25 of 29 keywords and 89 of 112 bytecodes from Python 2.6&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Can run multiple stackless green threads (round-robin)&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Has a mark-sweep garbage collector&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Has a hosted interactive prompt for live coding&lt;/li&gt;&lt;li style="margin-bottom: 0.3em; "&gt;Licensed under the GNU GPL ver. 2&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span&gt;&lt;a href="http://www.dwheeler.com/6502/"&gt;Lots of great stuff&lt;/a&gt; about 6502 languages, particularly Forth. - Great info on how to implement your own languages on the 6502. Forth is an obvious choice, but I haven't found any good Forth implementations as of yet. There seem to be a lot of Forth projects that may or may not be related which I need to evaluate.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=WsolhBE1HTM:nUS7_rnt-I8:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=WsolhBE1HTM:nUS7_rnt-I8:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=WsolhBE1HTM:nUS7_rnt-I8:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/WsolhBE1HTM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/8626713910491776378/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=8626713910491776378" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8626713910491776378?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/8626713910491776378?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/WsolhBE1HTM/high-level-languages-for-6502.html" title="High-level Languages for the 6502" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2012/04/high-level-languages-for-6502.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4ASHc8eSp7ImA9WhZbEE8.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-3402117673948657359</id><published>2011-06-13T20:53:00.000-07:00</published><updated>2011-06-13T20:59:09.971-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-06-13T20:59:09.971-07:00</app:edited><title>New Blog, Step Three: Privacy!</title><content type="html">This summer I have an internship with the Tor Project through Google Summer of Code. I started a blog for that and to generally talk about privacy stuff which will never be a profitable endeavor. Ironically, I'm getting paid by Google to work on it, but for Google this is an entirely non-profit endeavor in the name of charity and the general betterment of the world.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Privacy and profit have something in common in that each is an elusive goal. Thanks to my friend &lt;a href="http://dasyatidae.net/~drake/"&gt;Drake Wilson&lt;/a&gt; for suggesting the related name for the new site, &lt;a href="http://stepthreeprivacy.org/"&gt;Step Three: Privacy!&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll still be posting on here when I have startup and coding related matters to discuss, although I would recommend coders check out the other blog as well as there's some neat stuff on there if you do networking stuff in python.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=J2XbO4TFtl0:b53DJgoFmck:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=J2XbO4TFtl0:b53DJgoFmck:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=J2XbO4TFtl0:b53DJgoFmck:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/J2XbO4TFtl0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/3402117673948657359/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=3402117673948657359" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3402117673948657359?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3402117673948657359?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/J2XbO4TFtl0/new-blog-step-three-privacy.html" title="New Blog, Step Three: Privacy!" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2011/06/new-blog-step-three-privacy.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0UHSXs4fip7ImA9Wx9VE08.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-4081512317394127491</id><published>2011-01-29T07:51:00.000-08:00</published><updated>2011-01-29T09:13:58.536-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-29T09:13:58.536-08:00</app:edited><title>How to Help in Eqypt: A Historical Perspective and a Call to Action</title><content type="html">It's really amazing how the censorship bar keeps getting raised. When I co-founded &lt;a href="http://freenetproject.org/"&gt;Freenet&lt;/a&gt; over ten years ago, there were lots of assumptions shared about what online censorship was and how far people would be willing to go and also about what free speech was and what people wanted to communicate online. These assumptions have carried through to the design of today's censorship resistant systems. For instance, &lt;a href="http://torproject.org/"&gt;Tor&lt;/a&gt; still uses SSL we used to think that no one in their right mind would block SSL because then they'd be blocking HTTPS and critical systems such as any online commerce. The essential assumption was that there was a certain level to which censors would not go and we just needed to hide our traffic below that level. This was a good assumption for a long time, but now the game has changed.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Iran was the first wake-up call. They went farther than China was every willing to go by severely throttling SSL specifically. This was really a smart move because it didn't slow down the ability to read pages on the Internet, as most are unencrypted. It did slow down Tor and the ability to log in to any sites that use SSL for logins (hopefully all of them at this point). Since logins are required for most publishing services such as email, Twitter, Facebook, etc., this throttled both the ability to send information out. Of course online commerce was affected, but they were willing to accept that. The Iran attack became the new gold standard in online censorship. All systems need to adapt to this new reality. Since SSL is now a target, SSL is no longer a good wrapper for traffic. This is why I started &lt;a href="https://github.com/blanu/Dust"&gt;Dust&lt;/a&gt;, to provide &lt;a href="http://blanu.net/Dust.pdf"&gt;a more modern transport layer&lt;/a&gt; for bypassing current censorship methods. I really believe we can make something which is undetectable and thus cannot be throttled or blocked. I think information theory is on our side here and that this is a war we can win.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;However, Egypt raised the bar yet again by simply unplugging the Internet. This is remarkable as it not only shows how much farther censors are willing to go now, but also how the nature of online freedom of speech has changed. One of the classic examples we used to use to discuss the purpose of Freeenet was that China blocked access to &lt;a href="http://cnn.com/"&gt;CNN&lt;/a&gt;. This seems like a comically naive goal now. People aren't trying to access news from major publishers. They're organizing protests via Twitter. This is totally decentralized content, it's peer-to-peer communication.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Unfortunately, this isn't a software fix. If the cables aren't plugged in, there's no clever ways we can encode the data to get it past the censors. This particular situation is a hardware problem. The infrastructure is centralized in such a way that it's easy for the government of a country to just switch it off and so this is what happened. Some respected individuals have called for the &lt;a href="https://twitter.com/#!/shervin/status/30764964721463296"&gt;building&lt;/a&gt; of a &lt;a href="http://www.shareable.net/blog/the-next-net"&gt;new Internet&lt;/a&gt; without these problems.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think this is a very noble endeavor, but I want to be straight with you about the problems with this idea. Essentially, we've tried this and it doesn't work. We've been trying this for ten years. Building an Internet out of Wifi mesh points is like wiring a city for electricity using USB cables. The 3G and 4G wireless Internet that we have now is connected by a high speed wired backbone and this is what makes it work well. There are many problems with a entirely mesh network, but the primary one is range. Once you start looking at coverage areas and doing the math you quickly discover that the number of mesh nodes required to cover any decent areas is astronomical, particularly because you need to connect out to the larger Internet either by crossing the border to a friendly nation or connecting to a satellite link.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There is something we can do, though. We can design a custom network for these situations which, while it doesn't connect to the general Internet, provides network connectivity to people on the ground with each other. Here's a brief overview of my design:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://en.wikipedia.org/wiki/Femtocell"&gt;Femtocells&lt;/a&gt; are superior to Wifi access points here. The computing device of choice is going to be the camera and GPS-equipped phone, not the laptop. Phones are used to drifting from tower to tower. They have hand-off protocols for switching towers seamlessly. That's why you can talk on the phone while driving down the highway. A femtocell is essentially a "fake" cellular phone tower that intercepts your phone signals and routes them over your own network connection instead of the phone company backbone. You normally get these to improve reception in areas with poor or non-existent tower coverage. Places like, for instance, Egypt right now.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My proposal is to combine portable, battery-powered femtocells with a custom backend that, instead of routing your data packets over an ethernet connection, stores the data for exchange on a store-and-forward mesh network, much as in the FidoNet network referred to in the Rushkoff article. Then, instead of having fixed towers and moving phones we have moving towers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is all kind of technical, I suppose, so let me break it down for you in terms of a use case. You're in Egypt and you want to get news about what's going on, send out videos of important happenings to the world, and organize with your fellow citizens to take political action. You have a phone with a camera and text and MMS messaging. There are mobile cell phone towers roaming around the city. (This is something you'd need to organize and is a whole issue in itself, but some people specialize in this kind of theory. It's solvable.) When you come in range of an access point, you can send text and MMS messages. You also receive any that have been sent to you. The access point is actually another citizen with a backpack femtocell and battery. They could be walking, although I've also seen a similar plan executed using motorcycles. The tower stores your sent messages. The towers move in such a pattern that they come into range of each other. At this point they exchange stored messages. When a tower comes in range of a phone for which it has stored messages, it sends them to the phone and then deletes them. Sending messages to people in your phone contact list works the same as always. Getting information out of the country just requires sending a text or MMS message to someone that is known to have a satellite, dial-up, or other link outside. Once the information moves through the mesh to them, they can send it on.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think this is the right way to do decentralized mesh networking in situations like what is happening now in Egypt. This is something we can build right now. I'm ready to start on this whenever you are. The first step is that we're going to need some femtocells. After that, it becomes a software problem again, like hacking a Wifi router to run OpenWRT.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If this is a topic you're interested in, I will be giving a talk about this on March 11 at the Dorkbot SXSW event: &lt;a href="http://dorkbot.org/dorkbotaustin/2011/01/dorkbot-teaming-up-with-ignite-austin-for-sxsw-awesomeness/"&gt;The Vision of the Future: 2021&lt;/a&gt;. Come by and say hi and we can figure out how to make this happen.&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=xSt3Ez-ar4U:Xc2YlW7ud54:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=xSt3Ez-ar4U:Xc2YlW7ud54:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=xSt3Ez-ar4U:Xc2YlW7ud54:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/xSt3Ez-ar4U" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/4081512317394127491/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=4081512317394127491" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/4081512317394127491?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/4081512317394127491?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/xSt3Ez-ar4U/how-to-help-in-eqypt-historical.html" title="How to Help in Eqypt: A Historical Perspective and a Call to Action" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>2</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2011/01/how-to-help-in-eqypt-historical.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0YERHg8eSp7ImA9Wx9XEkU.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-120853737443938910</id><published>2011-01-05T18:57:00.000-08:00</published><updated>2011-01-05T20:45:05.671-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-01-05T20:45:05.671-08:00</app:edited><title>Retro Indie Game Development with HTML5 - The Series</title><content type="html">Like many web developers I've become interesting in the recent developments in &lt;a href="http://diveintohtml5.org/"&gt;HTML5&lt;/a&gt;. Web browsers can now do things they've never been able to do and it's an exciting time. It's also an exciting time for games right now. Two phenomena in game development have arisen which make game development fun again: retro games and indie games, although they are often found in conjunction. Retro games use the old school 8-bit graphics and sound we loved when we were kids. Some of these retro titles are from studios such as the new &lt;a href="http://en.wikipedia.org/wiki/Mega_Man_9"&gt;Megaman&lt;/a&gt; games or &lt;a href="http://en.wikipedia.org/wiki/Cave_Story"&gt;Cave Story&lt;/a&gt; for the Wii. There has also been a rising tide of indie games such as &lt;a href="http://minecraft.net/"&gt;Minecraft&lt;/a&gt; and the games of the &lt;a href="http://www.humblebundle.com/"&gt;Humble Indie Bundle&lt;/a&gt; such as &lt;a href="http://braid-game.com/"&gt;Braid&lt;/a&gt;. Some of these have retro graphics and some like &lt;a href="http://machinarium.net/demo/"&gt;Machinarium&lt;/a&gt; have pretty nice art. Not to save that low resolution art isn't nice, "pixel art" has become its own genre with its own talented artists. Some of these indie games have actually been quite successful with both Minecraft and the Humble Indie Bundle raising millions of dollars in sales.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I think the simultaneous rise of HTML5, the retro style, and the commercial success of the indie development methodology have created a great opportunity for the hacker turned entrepreneur. Additionally, all of the open source code, DIY tools, and &lt;a href="http://creativecommons.org/choose/"&gt;Creative Commons&lt;/a&gt; licensed artwork provide a relatively low barrier to entry. Take, for instance, &lt;a href="http://realmofthemadgod.com/"&gt;Realm of the Mad God&lt;/a&gt;. This is a really fun retro indie MMO. It was actually developed as part of a &lt;a href="http://www.tigsource.com/2009/10/24/tigsource-presents-assemblee-competition/"&gt;contest&lt;/a&gt; where artists first made Creative Commons licensed art assets and programmers then used these to make a game. The &lt;a href="http://github.com/amitp/mapgen2"&gt;map generation code&lt;/a&gt; is also open source. You could go out and write a game like this today and, even better, you don't have to do it in Flash like they did. A game like this could be written in pure HTML/CSS/Javascript, which is good news for web developers that have already been working in this medium for a while.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My plan is to write a series of posts about all of the great things I've discovered about developing retro indie HTML5 games as I've been working on my own game. While this may seem like a very specific topic, it opens up the doors to a variety of topics with nice concrete examples. For instance, I've often wondered, HTML5 sounds cool I guess but what is it good for, actually? In developing my game, it became quite apparent that it would be pretty much impossible without some very specific HTML5 features, not the obvious things like the &lt;a href="http://diveintohtml5.org/canvas.html#divingin"&gt;Canvas&lt;/a&gt; and &lt;a href="http://www.w3schools.com/html5/tag_audio.asp"&gt;Audio&lt;/a&gt; APIs, but specifically &lt;a href="http://www.whatwg.org/specs/web-workers/current-work/"&gt;Web Workers&lt;/a&gt; have been indispensable.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So watch the blog for future posts in this series. I'm going to start with &lt;a href="http://www.kesiev.com/akihabara/"&gt;Akihabara&lt;/a&gt;, the HTML5 game library specifically designed for retro games. Also let me know if there's anything specific you're interested in it and if I something to share on the subject then I'll try to make a post about it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=sI1abIVzYDc:YILKLzFKx3w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=sI1abIVzYDc:YILKLzFKx3w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=sI1abIVzYDc:YILKLzFKx3w:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/sI1abIVzYDc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/120853737443938910/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=120853737443938910" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/120853737443938910?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/120853737443938910?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/sI1abIVzYDc/retro-indie-game-development-with-html5.html" title="Retro Indie Game Development with HTML5 - The Series" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2011/01/retro-indie-game-development-with-html5.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkUNRX08fSp7ImA9WxFVGE4.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-2656942190433978527</id><published>2010-06-17T22:13:00.001-07:00</published><updated>2010-06-17T22:18:14.375-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-17T22:18:14.375-07:00</app:edited><title>The Original Introduction Problem in P2P Networks</title><content type="html">&lt;div&gt;&lt;a href="http://bitcoin.org/"&gt;BitCoin&lt;/a&gt; was released this week, a very interesting P2P currency based on proof-of-work with a novel method to deal with double-spending via a P2P timestamp server. Cool stuff.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the BitCoin forums, a &lt;a href="http://www.bitcoin.org/smf/index.php?topic=84.0"&gt;discussion&lt;/a&gt; was going on regarding how new BitCoin nodes connect to IRC in order to find other BitCoin nodes. This method was somewhat controversial because it was drawing the ire of the IRC network admins because it looked like they were running a botnet. Additionally, if the IRC server goes down then new users can't join the BitCoin network. However, what are you going to do? When you first run a node, it doesn't know about any other nodes. It's a tough situation.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is a common problem in P2P, known as Original Introduction, although bootstrapping is also a good word for it. The problem with bootstrapping is that you can't decentralize it. Whether it's IRC or HTTP or DNS, the client needs to be hardcoded with an address or list of addresses which is sufficiently fresh that at least one of the listed addresses is still active. After the first node is reached, you are no longer in Original Introduction mode and can use the full range of techniques for decentralization, such as gossip. Unless, of course, you get disconnected from the network and all of your known peers go away, in which case you're back to bootstrapping.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;There are two properties that are at odds when you chose a bootstrapping method: robustness (scalability/reliability) and freshness. Robustness is increased at the expense of freshness by caching on multiple servers, as is usually done with HTTP peer lists. Freshness is maximized (at least up to the TCP timeout) at the expense of robustness by having everyone connected, as with IRC. Of course, the key is finding the right mix of robustness and freshness because you need both for the bootstrap to be successful.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here are some of my current favorite methods for bootstrapping:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Append list of fresh peers to executable or installer dynamically on download. People usually get the application from its official website, so the website is already a point of failure for new users. You're already hardcoding an address in the application, the address that the application will use to bootstrap. So instead just add fresh peers at the moment of download. You need some fancy code in the executable to read the list off the end, but I've implemented this in an NSIS installer and it's not that hard. Most software developers are upset by the idea of this method.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Connect via XMPP to Google App Engine application. This gives the freshness of IRC, but with more robust scaling. App Engine is mostly for writing web apps, but it provides email and XMPP handling as well. It would be simple to write one application that could handle peer lists via either XMPP or HTTP with the same handler code. I'm currently using this in an application and it works well and is very reliable. I only wish there was a second App Engine to use as a fallback because it does have occasional downtime.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;An alternative to requiring all nodes to include the complexity of a protocol like IRC or XMPP is to have a few special sentinel nodes which sit on the network and collect addresses of connected nodes via the usual decentralized methods available to an active node. These sentinel nodes periodically upload fresh addresses, say via HTTP POST to a number of websites. A new node can then download a fresh address list from any of the websites which is currently functioning and reachable. If you have 5 sentinels each uploading every 5 minutes (staggered), then you'll have updates roughly once a minute. This is on par with IRC in terms of freshness and is robust as you care to make it by varying the number of HTTP mirrors and the number of sentinels.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=hOKGnfos5gk:CJHS5yl6PjA:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=hOKGnfos5gk:CJHS5yl6PjA:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=hOKGnfos5gk:CJHS5yl6PjA:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/hOKGnfos5gk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/2656942190433978527/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=2656942190433978527" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/2656942190433978527?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/2656942190433978527?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/hOKGnfos5gk/original-introduction-problem-in-p2p.html" title="The Original Introduction Problem in P2P Networks" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>4</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2010/06/original-introduction-problem-in-p2p.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ICQnk_fSp7ImA9WxFWGUU.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-7692553570962234888</id><published>2010-06-07T21:52:00.000-07:00</published><updated>2010-06-08T00:19:23.745-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-08T00:19:23.745-07:00</app:edited><title>The Truth About Mobile Bandwidth Pricing</title><content type="html">AT&amp;amp;T just ended unlimited bandwidth for the iPhone and people seem to be confused about what this means. As a follow-up to my post on &lt;a href="http://www.stepthreeprofit.com/2009/04/truth-about-consume-bandwidth-pricing.html"&gt;consumer bandwidth pricing&lt;/a&gt;, let me break down the mobile bandwidth pricing strategies for you.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It's not really a cap, it's a pricing strategy. Also, it's not about keeping a few extreme users from ruining the network for everyone. For congestion management you'd need peak usage pricing like electricity companies use, only for geographical areas instead of (or in addition to) time-based pricing. For instance, raise the price of bandwidth in Manhattan during daytime and at the Austin Convention Center's cell tower during SXSW. Cumulative usage-based pricing doesn't solve congestion. It's just a strategy to raise prices.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Here's the breakdown of how much you'll pay per month depending on your data usage on the various networks that support smartphones.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://spreadsheets.google.com/oimg?key=0Avlr_GhOXqwfdHhBd2dORmJ4UzdaaG14T2FCZG52UkE&amp;amp;oid=1&amp;amp;zx=dkrofy6ouyng"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 450px; height: 320px;" src="http://spreadsheets.google.com/oimg?key=0Avlr_GhOXqwfdHhBd2dORmJ4UzdaaG14T2FCZG52UkE&amp;amp;oid=1&amp;amp;zx=dkrofy6ouyng" border="0" alt="" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;As you can see, AT&amp;amp;T starts low and then after the 2GB "cap" quickly cuts across all the prices of the carriers that offer unlimited bandwidth. If you actually use less than 2GB/month, it's still a pretty good deal, second only to Sprint. At 4GB/month, it's the most expensive.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Also notice that Tmobile is more expensive if you get a 2-year contract that if you have no contract. This is their terrible new pricing plan in which they no longer subsidize phones in order to lock you into a contract. Instead, they essentially finance your phone by having you pay less up front but then more per month. When your 2-year contract is up, you will have paid more than you saved on the initial phone purchase. So if you get a Tmobile phone, don't get a contract. Just buy the phone outright.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=cgLRDIYUUXo:5Pqkkb5oWYk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=cgLRDIYUUXo:5Pqkkb5oWYk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=cgLRDIYUUXo:5Pqkkb5oWYk:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/cgLRDIYUUXo" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/7692553570962234888/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=7692553570962234888" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7692553570962234888?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7692553570962234888?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/cgLRDIYUUXo/truth-about-mobile-bandwidth-pricing.html" title="The Truth About Mobile Bandwidth Pricing" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2010/06/truth-about-mobile-bandwidth-pricing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEQBRXg5eyp7ImA9WxJTE0g.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-1737593846208182623</id><published>2009-04-21T13:49:00.000-07:00</published><updated>2009-04-21T15:19:14.623-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-04-21T15:19:14.623-07:00</app:edited><title>The Truth About Consumer Bandwidth Pricing</title><content type="html">There's been a lot of noise made recently about Time Warner instituting bandwidth caps. Everyone was angry at Time Warner, whereas Time Warner claims it's losing money because of a few people hogging all the bandwidth, that usage based pricing is more fair and also necessary to pay for building up their networks, and that all of this BitTorrent traffic and streaming video is killing their networks and needs to be capped.&lt;br /&gt;&lt;br /&gt;I have an inside perspective on this matter because when I was the Director of Product Management at BitTorrent, we often spoke with ISPs. We knew that Comcast was throttling BitTorrent traffic far before it made it into the news and I flew down to Comcast headquarters in Philadelphia to discuss the situation. I was suprised when the told me that they had plenty of bandwidth and that BitTorrent wasn't anywhere close to crushing their network. Their problem was that they don't want to sell bandwidth, a comodity with a price racing to zero. They want to sell entertainment services, which have a higher profit margin. They are therefore threatened by online video as it competes with cable TV.&lt;br /&gt;&lt;br /&gt;The consumer ISP strategy thus has a twofold purpose: raise the price of bandwidth, and at the same time make the Internet a less appealing way to watch video. Both of these purposes are accomplished by bandwidth caps. Additionally, the new pricing models make it complicated to determined how much you're going to be paying exactly for bandwidth, allowing the ISPs to increase prices covertly. If they were to just declare that prices were going up because they felt like it, people would be very angry indeed, and it might lead to government regulation of pricing.&lt;br /&gt;&lt;br /&gt;In order to unravel the mystery of the new pricing models, I've made some graphs that show how much you will pay in dollars for a number of total gigabytes transferred in a month. I was very suprised by the results.&lt;br /&gt;&lt;br /&gt;To start, here is a graph of a lot of different plans, such as various Time Warner plans, AT&amp;amp;T DSL, and the main 3G mobile carriers.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=400x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,300%7C1,0,141660&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088,ffff00,00ffff,ff00ff&amp;amp;chdl=ATTEVDO%7CSprintEVDO%7CTWCBC%7CTWCLite%7CATT%7CComcast%7CAmazonS3%7CVerizonEVDO%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C60,60,60,60,60,540,1020,1500,1980,2460,7260,12060,16860,21660,33660,45660,69660,93660,117660,141660%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C60,60,60,60,60,110,160,210,260,310,810,1310,1810,2310,3560,4810,7310,9810,12310,14810%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C15,17,19,21,23,25,27,29,31,33,53,73,90,90,90,90,90,90,90,90%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250%7C43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C0.085,0.255,0.425,0.595,0.765,0.935,1.105,1.275,1.445,1.615,3.315,5.015,6.715,8.415,12.665,16.915,25.415,33.915,42.415,50.915%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C60,60,60,60,60,340,620,900,1180,1460,4260,7060,9860,12660,19660,26660,40660,54660,68660,82660%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,125,150,150,150&amp;amp;chds=1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660,1,300,0.085,141660" /&gt;&lt;br /&gt;&lt;br /&gt;On the bottom is gigabytes and on the left is dollars. Yes, dollars. 300 GB would costs you $140,000 on AT&amp;amp;T 3G. You'll notice that only the 3G providers show up at all, everything else being squished into a single line on the bottom. This is because while Time Warner is charges overages of $1/GB, Sprint is charging $50/GB, Verison $280/GB, and AT&amp;amp;T a ridiculous $480/GB after you exceed the 5GB cap. Everyone is mad about the Time Warner caps, but it's really the 3G caps that are totally insane. Every iPhone user is on AT&amp;amp;T, so when Hulu for iPhone comes out it's going to be crazy.&lt;br /&gt;&lt;br /&gt;So don't use more than 5G of 3G per month or else you're getting ripped off. Let's compare some ISPs just in the 1-5G range to see how they stack up.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,5%7C1,0,150&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088,ffff00&amp;amp;chdl=TWCLite%7CATT%7CComcast%7CAmazonS3%7CAnyEVDO%7CTWCBC%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5%7C15,17,19,21,23%7C1,2,3,4,5%7C80,80,80,80,80%7C1,2,3,4,5%7C43,43,43,43,43%7C1,2,3,4,5%7C0.085,0.255,0.425,0.595,0.765%7C1,2,3,4,5%7C60,60,60,60,60%7C1,2,3,4,5%7C150,150,150,150,150%7C1,2,3,4,5%7C75,75,75,75,75&amp;amp;chds=1,5,0.085,150,1,5,0.085,150,1,5,0.085,150,1,5,0.085,150,1,5,0.085,150,1,5,0.085,150,1,5,0.085,150" /&gt;&lt;br /&gt;&lt;br /&gt;Amazon S3 is included here at the bottom just to show how much more expensive consumer bandwidth is than hosting bandwidth. The bottom tier of Time Warner service is a clear winner here, following by the original capper Comcast. 3G services are in the middle, with premium tier cable and DSL services losing. In this bandwidth bracket, you don't really get much benefit from upgrading your service.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now let's look at ISP choices excluding 3G.&lt;br /&gt;&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,300%7C1,0,150&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088&amp;amp;chdl=TWCLite%7CATT%7CComcast%7CAmazonS3%7CTWCBC%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C15,17,19,21,23,25,27,29,31,33,53,73,90,90,90,90,90,90,90,90%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80,80%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250%7C43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43,43%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C0.085,0.255,0.425,0.595,0.765,0.935,1.105,1.275,1.445,1.615,3.315,5.015,6.715,8.415,12.665,16.915,25.415,33.915,42.415,50.915%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,125,150,150,150&amp;amp;chds=1,300,0.085,150,1,300,0.085,150,1,300,0.085,150,1,300,0.085,150,1,300,0.085,150,1,300,0.085,150" /&gt;&lt;br /&gt;&lt;br /&gt;The lowest Time Warner tier wins again if you lose little bandwidth, and then Comcast wins everything else up to 250G where they have put a hard cap.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Now let's look in depth at just the Time Warner tiers.&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,300%7C1,0,150&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088&amp;amp;chdl=TWCLite%7CTWCStandard%7CTWCSuperLite%7CTWCBC%7CTWCSuperTurbo%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C30,30,30,30,30,30,30,30,30,30,40,50,60,70,95,105,105,105,105,105%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C43,43,43,43,43,43,43,43,43,43,43,43,43,53,78,103,118,118,118,118%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C15,17,19,21,23,25,27,29,31,33,53,73,90,90,90,90,90,90,90,90%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,125,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100,150,200,250,300%7C55,55,55,55,55,55,55,55,55,55,55,55,55,55,70,95,130,130,130,130&amp;amp;chds=1,300,0,150,1,300,0,150,1,300,0,150,1,300,0,150,1,300,0,150,1,300,0,150" /&gt;&lt;br /&gt;&lt;br /&gt;The graph is interesting because Time Warner imposes an overage fee cap of $75. This causes the lowest tier to come out best for both low and high numbers of gigabytes. The lowest tier charges $15/month for 1GB and $2/GB for each additional GB, up to $75 in overages, meaning that your total bill is capped at $90. You therefore get unlimited bandwidth for $90 with that plan. Whereas their highest tier plan is $75 for 100 GB and then $1/GB after that up to $75 in overage charges. You get unlimited bandwidth for $150 with this plan. So the lowest tier wins and the highest tier loses. The middle tiers only come into play for medium amounts of bandwidth.&lt;br /&gt;&lt;br /&gt;So, let's look at medium amounts of bandwidth where the multiple tiers come into play.&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,100%7C1,0,150&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088&amp;amp;chdl=TWCLite%7CTWCStandard%7CTWCSuperLite%7CTWCBC%7CTWCSuperTurbo%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C30,30,30,30,30,30,30,30,30,30,40,50,60,70,95,105%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C43,43,43,43,43,43,43,43,43,43,43,43,43,53,78,103%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C15,17,19,21,23,25,27,29,31,33,53,73,90,90,90,90%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,100%7C55,55,55,55,55,55,55,55,55,55,55,55,55,55,70,95&amp;amp;chds=1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150" /&gt;&lt;br /&gt;&lt;br /&gt;This graphs shows a situation similar to the one pitched by Time Warner. There are multiple tiers and you get the best deal by choosing the right tier for the amount of bandwidth you use. However, note that the goal is not to avoid overages. The goal is to avoid having your overage charges cost more than the monthly charge of the next plan up. So while the lowest tier only includes 1GB/month, it's the best plan up to around 10GB/month. Similarly, the standard plan will be better than an upgrade up to 50GB/month. The highest tier is only good for people that use &gt;80 GB/month. And Time Warner Business Class is, as shown on all of the graphs, always just a terrible deal.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;It was just discovered that AT&amp;amp;T DSL is implementing bandwidth caps. They have a different model because they don't have a cap on overage fees. That sounds like it would probably be a worse deal than Time Warner. Let's take a look, first at just the different AT&amp;amp;T DSL tiers.&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,100%7C1,0,100&amp;amp;chco=ff0000,00ff00,0000ff,888800&amp;amp;chdl=ATTPro%7CATTBasic%7CATTElite%7CATTExpress&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C30,30,30,30,30,30,30,30,30,30,30,30,30,30,45,50,60,70%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C20,20,20,20,20,20,20,20,20,20,20,30,40,50,75,80,90,100%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,45,55%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C25,25,25,25,25,25,25,25,25,25,25,25,25,35,60,65,75,85&amp;amp;chds=1,100,0,100,1,100,0,100,1,100,0,100,1,100,0,100" /&gt;&lt;br /&gt;&lt;br /&gt;This is the more classical model that you'd expect with overages. Since there are no caps on overage fees, you get the best deal by choosing a plan matched to your usage. If you guess incorrectly, you overpay. The ordering of plans from cheapest to most expensive becomes inverted from low usage to high usage.&lt;br /&gt;&lt;br /&gt;Now let's compare the various AT&amp;amp;T DSL plans to the various Time Warner cable plans.&lt;br /&gt;&lt;img src="http://chart.apis.google.com/chart?chs=300x300&amp;amp;cht=lxy&amp;amp;chxt=x,y&amp;amp;chxr=0,1,100%7C1,0,150&amp;amp;chco=ff0000,00ff00,0000ff,888800,008888,880088,ffff00,00ffff,ff00ff&amp;amp;chdl=TWCSuperLite%7CTWCBC%7CTWCLite%7CATTExpress%7CTWCStandard%7CATTPro%7CATTBasic%7CATTElite%7CTWCSuperTurbo%7CTWCTurbo&amp;amp;chd=t:1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C15,17,19,21,23,25,27,29,31,33,53,73,90,90,90,90,90,90%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150,150%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C30,30,30,30,30,30,30,30,30,30,40,50,60,70,95,100,105,105%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C25,25,25,25,25,25,25,25,25,25,25,25,25,35,60,65,75,85%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C43,43,43,43,43,43,43,43,43,43,43,43,43,53,78,83,93,103%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C30,30,30,30,30,30,30,30,30,30,30,30,30,30,45,50,60,70%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C20,20,20,20,20,20,20,20,20,20,20,30,40,50,75,80,90,100%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,35,45,55%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75,75%7C1,2,3,4,5,6,7,8,9,10,20,30,40,50,75,80,90,100%7C55,55,55,55,55,55,55,55,55,55,55,55,55,55,70,75,85,95&amp;amp;chds=1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150,1,100,0,150" /&gt;&lt;br /&gt;&lt;br /&gt;There are a lot of lines on this graph, but you only need to look at the bottom. The lowest tier of Time Warner again wins for low bandwidth. After than, successive AT&amp;amp;T DSL plans win. Despite the fact that their pricing structure is worse, their actual prices are better than Time Warner as long as you're good at guessing how much bandwidth you're going to use. If you're bad at guessing, only the lowest two tiers of Time Warner could ever possibly be better than AT&amp;amp;T DSL and only for a small range of usage. So if you're bad at guessing your usage, your best bet is to get the highest tier of AT&amp;amp;T DSL.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusions&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I was suprised by the outcome of these charts. The Time Warner caps are not that big of a deal and the AT&amp;amp;T caps are even less of a big deal. What you really need to watch out for is the 3G caps. Those are just totally off the rails.&lt;br /&gt;&lt;br /&gt;The best deal for consumer Internet is AT&amp;amp;T DSL, even with the caps and overage fees. If you know how much bandwidth you're going to use, buy the appropriate tier. If you don't know how much bandwidth you're going to use, you're safest buying the highest tier.&lt;br /&gt;&lt;br /&gt;If you're going to go with Time Warner, the lower tiers are a better deal. Go with the lowest tier you can and only upgrade if your overage fees are costing you more than the next tier. Never buy the highest tier or business class, they are ripoffs.&lt;br /&gt;&lt;br /&gt;3G is a terrible deal. If you use less than 5G a month, all the 3G providers are priced the same and are not a very good deal for Internet. Use the lowest tier of Time Warner instead. Under no circumstances use more than 5G of 3G in a month, you will get ripped off big time.&lt;br /&gt;&lt;br /&gt;Also, Hulu for iPhone is going to be a train wreck.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=POp6456dnhQ:024nXNbY3fo:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=POp6456dnhQ:024nXNbY3fo:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=POp6456dnhQ:024nXNbY3fo:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/POp6456dnhQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/1737593846208182623/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=1737593846208182623" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/1737593846208182623?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/1737593846208182623?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/POp6456dnhQ/truth-about-consume-bandwidth-pricing.html" title="The Truth About Consumer Bandwidth Pricing" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>5</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2009/04/truth-about-consume-bandwidth-pricing.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEARX0-fip7ImA9WxVWF0s.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-3138449478825990202</id><published>2009-02-27T12:06:00.000-08:00</published><updated>2009-02-27T12:47:24.356-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-27T12:47:24.356-08:00</app:edited><title>Diakonos: A Programmer's Text Editor in Ruby</title><content type="html">A text editor (or for some an IDE) is the most important tool a programmer has, other than the programming language itself. Religious wars over editors are inevitable because people spend so much time with their editor. Some people flip-flop, but many people become both functionally and emotionally attached. No one wants to spend time learning new keybindings when they could be programming instead.&lt;br /&gt;&lt;br /&gt;Personally, I use nano. This is not out of ignorance, mental damage, or a deep moral perversion as my friends that use emacs and vi insist. I want an editor which is small and quick to install. It must be available on all platforms and easy to install (if there's no Debian/Ubuntu package in the main repositories, forget it). I'm not going to mess around with configuring it. And I basically just don't like vi. So nano has been winning the war for my soul for many years. However, like all programmers, I dream of a better world. I wouldn't mind a slightly (or even somewhat) better editor, but I everything I've ever tried lacked the beautiful simplicity of nano. With more features comes more hassle.&lt;br /&gt;&lt;br /&gt;Then I found &lt;a href="http://purepistos.net/diakonos/"&gt;Diakonos&lt;/a&gt;. It's a console-based text editor (which I like because I ssh into my server and edit things as much as I edit them locally), and it's written in Ruby. It has the modern features, such as multiple buffers, syntax highlighting, and syntax-aware indentation. It's scriptable, either through the Ruby interface or through external programs (in any language) which are fed the old buffer on stdin and output new buffer contents on stdout.&lt;br /&gt;&lt;br /&gt;Like all editors under my consideration, it has &lt;a href="http://purepistos.net/diakonos/"&gt;packages&lt;/a&gt; in the main repositories of both Debian and Ubuntu. It also has Windows and OS X binaries (also a Ruby gem for you Ruby guys). It's as quick and easy to install as nano, and through it has lots more features, they are not obtrusive. The &lt;a href="http://wiki.purepistos.net/doku.php?id=Diakonos:Getting-Started"&gt;keybindings&lt;/a&gt; are the "standard" Windows-style ones (ctrl-x cut, ctrl-c copy, ctrl-v paste). You can of course configure it to emacs or whatever style you want, but I am personally happy to use a similar set of keys across my editor and web browser.&lt;br /&gt;&lt;br /&gt;I am particularly excited about finally having an editor that's not written in C. This is a personal issue. Many people like C, but I just think it's time for us to move on as a society. I have a T-shirt that says "I would code in C for love, but not for money." While you may love C, autoconf, and make, I am personally very excited about an editor both written in and scriptable in Ruby. It seems like a step towards the future. It's also nice to have a fresh codebase which doesn't inherit several decades of design decisions.&lt;br /&gt;&lt;br /&gt;My apologies for insulting your favorite text editors and programming languages, my Internet friends. I meant no harm. Just check out &lt;a href="http://purepistos.net/diakonos/"&gt;Diakonos&lt;/a&gt; for a bit and see what you think. It has a feel which is both fresh and yet somehow also classic. A "modern classic" if you will. And it's fun. In a way I can't really articulate, it's just enjoyable to use. Also, the author is a really nice guy and the IRC channel isn't full of obnoxious jerks (#mathetes on freenode), just good folks like you and me, hacking on code. I'll see you there!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=5J901cSkhvA:fPuOd286hhc:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=5J901cSkhvA:fPuOd286hhc:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=5J901cSkhvA:fPuOd286hhc:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/5J901cSkhvA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/3138449478825990202/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=3138449478825990202" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3138449478825990202?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3138449478825990202?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/5J901cSkhvA/diakonos-programmers-text-editor-in.html" title="Diakonos: A Programmer's Text Editor in Ruby" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>3</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2009/02/diakonos-programmers-text-editor-in.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MCR305fip7ImA9WxVWEUs.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-761418093048309331</id><published>2009-02-20T10:55:00.000-08:00</published><updated>2009-02-20T14:37:46.326-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-20T14:37:46.326-08:00</app:edited><title>Startup Camp Austin, Feb 28th</title><content type="html">Next Saturday, Feb 28th, from 1pm-6pm, is the second annual Startup Camp Austin!&lt;br /&gt;&lt;br /&gt;Last year's Startup Camp Austin was pretty great. A lot has changed since then in the Austin Startup Scene. It's really quite booming. With events like SXSW Accelerator and the CapitalFactory application deadline coming up at the beginning of March, we decided that now was a good time to get together again and talk about the ongoing developments of interest to Austin startups.&lt;br /&gt;&lt;br /&gt;There are still a few slots left, so if you'd like to do a presentation, pitch, or demo, or lead a roundtable discussion, &lt;a href="http://barcamp.org/StartupCampAustin"&gt;sign up on the wiki&lt;/a&gt; and I'll save you a slot in the program. Also feel free to just add discussion topics and we can discuss whatever anyone feels like discussing.&lt;br /&gt;&lt;br /&gt;Also, please RVSP on the &lt;a href="http://www.facebook.com/home.php#/event.php?eid=51278069210"&gt;Facebook event&lt;/a&gt; so that we know how much food to provide.&lt;br /&gt;&lt;br /&gt;I have to say, I'm pretty excited about this camp. The first Startup Camp was kind of scary because we'd never put on an Unconference before and I had just moved back to Austin and started my own startup. I really wanted to help make Austin a great place for startups, but it was just one person's dream. Since then, things have become so exciting! There are lots of events for startups now, from SD2020 to SXSW Accelerator. There are several new experiments in funding going on, including a startup incubator and a startup organized as a coop. Coworking spaces and BarCamps have become hot items, sprouting up in Dallas, Houston, and San Antonio as well. So many of my friends have lost or quit their jobs due to the economic turmoil and instead of feeling down about it have decided that now is a great time to start a startup. It's really a very optimistic time for startup entrepreneurs as we see opportunities in every problem.&lt;br /&gt;&lt;br /&gt;So if you're currently at a startup, are interested in starting one, or just curious about how things are going in the Austin startup community, come to the ACTLab next Saturday. It's located on the UT Campus in the Communications Building (CMB) on the 4th floor, in Studio 4B. The Communications Building is on the southeast corner of Dean Keaton and Guadalupe, across from Madam Mam's. There's a parking lot right across the street (south of Madam Mam's) which is usually $6 to park all day.&lt;br /&gt;&lt;br /&gt;I hope to see you there!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=gc4aXxSZP0Y:Ms9PX5O7eyk:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=gc4aXxSZP0Y:Ms9PX5O7eyk:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=gc4aXxSZP0Y:Ms9PX5O7eyk:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/gc4aXxSZP0Y" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/761418093048309331/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=761418093048309331" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/761418093048309331?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/761418093048309331?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/gc4aXxSZP0Y/startup-camp-austin-feb-28th.html" title="Startup Camp Austin, Feb 28th" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2009/02/startup-camp-austin-feb-28th.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkQCQns7fip7ImA9WxVQE0k.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-6593952008544207259</id><published>2009-01-30T09:34:00.000-08:00</published><updated>2009-01-30T10:32:43.506-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-30T10:32:43.506-08:00</app:edited><title>Austin Gets Its Own Startup Incubator</title><content type="html">I love having a startup in Austin. I think it's a great place to do a startup right now. At the Tech Happy Hour last night, one early stage investor likened Austin to a gasoline soaked pile of rags just waiting for a spark. Indeed!&lt;br /&gt;&lt;br /&gt;For a while I've felt that the missing element in the Austin startup scene is an early stage, small investment startup incubator in the spirit of &lt;a href="http://ycombinator.com/"&gt;Y Combinator&lt;/a&gt; and &lt;a href="http://www.techstars.org/"&gt;TechStars&lt;/a&gt;. Austin is a great place to bootstrap, and angel and VC funding are available, but for many young entrepreneurs the best way to get started is with a startup incubator. You get to meet people with startup experience, you get to pitch, and you get some press. It's one of the best ways to get started, especially if you're on the engineering side and you need to meet people with business experience.&lt;br /&gt;&lt;br /&gt;Austin finally has such a venture, and it's called &lt;a href="http://capitalfactory.com/"&gt;Capital Factory&lt;/a&gt;. You can read their &lt;a href="http://www.prweb.com/releases/2009/01/prweb1935684.htm"&gt;press release&lt;/a&gt; to get the sales pitch, but let me just break down the numbers for you. If you're one of the three companies picked, you get $20,000 for 5%, giving you a $380,000 valuation, which is comparable or slightly better than YC and TechStars in terms of valuation. There are of course many intangibles to compare between the various incubators, but it basically comes down to where you want to start your company: the Bay Area, Boulder, or Austin. For myself, I choose Austin!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;They're also still looking for a few good investor-mentors, so if you want to help the Austin startup scene and you've got some time and money to invest, check them out. I can't wait until pitch day to see what new startups are started!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=vHObxueYq1I:0Emk0i72wZU:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=vHObxueYq1I:0Emk0i72wZU:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=vHObxueYq1I:0Emk0i72wZU:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/vHObxueYq1I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/6593952008544207259/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=6593952008544207259" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6593952008544207259?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/6593952008544207259?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/vHObxueYq1I/austin-gets-its-own-startup-incubator.html" title="Austin Gets Its Own Startup Incubator" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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://www.stepthreeprofit.com/2009/01/austin-gets-its-own-startup-incubator.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0ANQXw_fCp7ImA9WxVRGUQ.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-2462772863469387049</id><published>2009-01-23T10:48:00.000-08:00</published><updated>2009-01-26T11:56:30.244-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-26T11:56:30.244-08:00</app:edited><title>P2P Money with App Engine, OAuth, and QR Codes</title><content type="html">In honor of National Service Day, I decided to take a day off from my regularly scheduled &lt;a href="http://ringlight.us/"&gt;Ringligh&lt;/a&gt;t hacking and work on some community service hacking. In Austin we have a complimentary currency called the &lt;a href="http://www.austintimeexchange.org/"&gt;Austin Time Exchange Network&lt;/a&gt; (ATEN). There's a lot to say about &lt;a href="http://en.wikipedia.org/wiki/Complementary_currency"&gt;complimentary currency&lt;/a&gt; and its role in helping economies during a downturn. However, I want to delve mainly into the technical details of my hack, so if you're interested I recommend &lt;a href="http://www.amazon.com/Future-Money-Creating-Wealth-Wiser/dp/0712699910/ref=sr_1_5?ie=UTF8&amp;amp;s=books&amp;amp;qid=1232738278&amp;amp;sr=8-5"&gt;Bernard Lietaer&lt;/a&gt;. The basic idea is that you can pay people for their time in ATEN currency, denominated in hours, rather than dollars. This is quite good for situations where no one has dollars they want to spend, but they do have work they want to do and get done, such as the current economy. There's no shortage of needs or workers, only a shortage of money. So let's make our own money! Problem solved! You'll still use dollars to pay taxes, your mortgage, and Wal-Mart, but you can use ATEN hours to buy local goods and services from people in Austin that accept this currency.&lt;br /&gt;&lt;br /&gt;The goal of this project, named &lt;a href="http://www.austintimemachine.org/"&gt;Austin Time Machine&lt;/a&gt; (ATM) is to provide a means to withdraw electronic currency into a physical paper form (cash) and later deposit paper to an electronic account. This is particularly useful for the sorts of situations which are normally "cash only", for instance festivals where it's unreasonable to expect all of the booths to have computers and Internet. Since the paper currency is backed by a separate online currency (in this case &lt;a href="http://www.opensourcecurrency.org/"&gt;OpenSourceCurrency.org&lt;/a&gt;), the ATM service doesn't need to manage things like account balance. It only needs to keep track of bill serial numbers and manage authentication to the "bank" so that it can transfer credits to and from user accounts.&lt;br /&gt;&lt;br /&gt;So on to the technical details. The first interesting bit is that &lt;a href="http://www.opensourcecurrency.org/"&gt;OpenSourceCurrency.org&lt;/a&gt; supports &lt;a href="http://oauth.net/"&gt;OAuth&lt;/a&gt; for authenticating users. Additionally, I implemented the whole service on &lt;a href="http://code.google.com/appengine/"&gt;App Engine&lt;/a&gt;, which is wonderful because I don't have to run it on my server or manage uptime. However, this meant that I had to port the &lt;a href="http://oauth.googlecode.com/svn/code/python/oauth/"&gt;python OAuth library&lt;/a&gt; to use the App Engine API. In particular, I had to replace all of the use of httplib with &lt;a href="http://code.google.com/appengine/docs/python/urlfetch/"&gt;App Engine's urlfetch service&lt;/a&gt;. This code will be useful to anyone attempting to authenticate to external services from inside an App Engine application. This app also provides a handy example of how to write an OAuth client. It's a little bit more complicated than it needs to be, but it's not that bad if you use an OAuth library to generate the signatures and such. It's basically involves just POSTing some fields to a few URLs and providing callback URLs that the website will POST back to. You pass some tokens around this way and end up with a token which, when included in a call to whatever web service you're trying to access, will serve to authenticate you as acting on the behalf of the user.&lt;br /&gt;&lt;br /&gt;The next component of the app is the storage of serial numbers when you withdraw bills and verification of serial numbers when you deposit. Nothing particularly exciting here. I created an &lt;a href="http://code.google.com/appengine/docs/python/datastore/"&gt;App Engine Model&lt;/a&gt; for each bill and save and access them using the standard App Engine ORM API. This is worth checking out if you haven't used App Engine before though because it's a simple example of how it works, and it's very different than SQL. Basically you need to assign a unique (string) key to each object and this is how you access them. The mechanisms you might except from SQL such as the UNIQUE keyword are absent.&lt;br /&gt;&lt;br /&gt;With all of the nitty gritty storage and OAuth stuff taken care of, the bulk of the application is very simple. OpenSourceCurrency.org is a Rails app and so exposes a simple REST and JSON (or XML) API to do transactions. There are a couple of gaps in the API (from the perspective of this particular app) which I work around in this code. The API only lets you transfer money &lt;span style="font-weight: bold;"&gt;from&lt;/span&gt; the current user to a specified destination user, and you need the userid of the destination user. For withdrawl it's easy, I transfer money from the authenticated user to my own account, since I happen to know my userid. For deposit, I perform a tricky manuever. I charge the user a 0.1 hour fee, transferring it from their account to mine just like in a withdrawl. The result of that call includes their userid in the JSON output. I then take that userid and have the ATM service log into my own account (specifying credential via HTTP Auth, not OAuth) and transfer from my account to the account of the user, specified by their userid. A bit complicated! However, I'm working with &lt;a href="http://herestomwiththeweather.blogspot.com/"&gt;Tom Brown&lt;/a&gt;, creator of the OpenSourceCurrency.org API, to create a simpler API.&lt;br /&gt;&lt;br /&gt;Finally, once you've made a withdrawl, the bill needs to be generated so you can print it. This is currently done with just a little bit of HTML. A PDF export would be nice for printing multiple bills on one page, but for the prototype HTML was of course the fastest. The QR code generation turned out to be extremely simple because the &lt;a href="http://code.google.com/apis/chart/"&gt;Google Chart API&lt;/a&gt; recently added QR code support. So the QR code is just a single HTML img tag with a URL which will automatically generate a QR code. Nice!&lt;br /&gt;&lt;br /&gt;Feel free to play this all this stuff. Check out &lt;a href="http://blip.tv/file/get/Herestomwiththeweather-StupidCurrencyTricksOAuthAndQRCode777.flv"&gt;Tom's screencast on using the ATM&lt;/a&gt;, &lt;a href="http://www.austintimemachine.org/"&gt;the live ATM site&lt;/a&gt;, and of course the &lt;a href="http://blanu.net/atm/"&gt;source code&lt;/a&gt; (also available as a &lt;a href="http://blanu.net/atm.zip"&gt;zip&lt;/a&gt;).&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Sm1sgyax2R0:v2xkSCGVe0w:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Sm1sgyax2R0:v2xkSCGVe0w:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Sm1sgyax2R0:v2xkSCGVe0w:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/Sm1sgyax2R0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/2462772863469387049/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=2462772863469387049" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/2462772863469387049?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/2462772863469387049?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/Sm1sgyax2R0/p2p-money-with-app-engine-oauth-and-qr.html" title="P2P Money with App Engine, OAuth, and QR Codes" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2009/01/p2p-money-with-app-engine-oauth-and-qr.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QNRXw-eSp7ImA9WxRbGEo.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-843400921806035496</id><published>2008-12-09T14:39:00.000-08:00</published><updated>2008-12-09T17:09:54.251-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-09T17:09:54.251-08:00</app:edited><title>Scalable Clustering with Thrift and SQS</title><content type="html">Since the &lt;a href="http://ringlight.us/"&gt;Ringlight beta&lt;/a&gt; launch, we're edging up towards 100 users. It's certainly not the load that the engineers at Twitter have to deal with, but I would like to impress upon you my &lt;span style="font-weight: bold;"&gt;Law of Scaling&lt;/span&gt;:&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 153); font-weight: bold;"&gt;Every power of ten, something different breaks (or becomes unusably slow).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;So even with modest growth from 10 to 100 users, it's probably time to fix something.&lt;br /&gt;&lt;br /&gt;Once principle of scalable design is to &lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;decouple slow operations from the user interface&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;For instance, subscribers of &lt;a href="http://ringlight.us/present/Plans"&gt;Ringlight Personal Edition&lt;/a&gt; have the added feature of one-click backup of all of their files. However, this operation can take a long time to complete. Even just generating the list of files to back up can be time consuming if you have a really large number of files. Therefore, it is advantageous to move all of this out of the website and into a background process. The web application just records that you have clicked the one-click backup option and then alerts the background process that it's time to figure out exactly what needs to be done about this. This sort of architecture will keep your web page loading snappy and your users happy even on a heavily overloaded website, as you're not wasting their time making them wait for the page to load.&lt;br /&gt;&lt;br /&gt;There are a number of ways to communicate between your web application and the background process. Of particular interest from a scalability standpoint are message queueing services such as &lt;a href="http://rubyforge.org/projects/starling/"&gt;Starling&lt;/a&gt; and &lt;a href="http://aws.amazon.com/sqs/"&gt;SQS&lt;/a&gt;. These allow for high scalability by allowing many producers (your web server instances) talk to many consumers (your background processes).&lt;br /&gt;&lt;br /&gt;Starling is a server written in Ruby (for Python, see &lt;a href="http://code.google.com/p/peafowl/"&gt;Peafowl&lt;/a&gt;) that you run yourself. SQS is a hosted service that you pay for based on usage (number of messages sent and bandwidth used). Both are reasonable choices and have pretty similar APIs. You connect to the service, and then push strings onto a particular queue (identified by a queue name, which is also a string). Other processes can fetch strings from the queue given its name. Pretty easy! They also both have client libraries in most major languages, so integration into your app shouldn't be very difficult.&lt;br /&gt;&lt;br /&gt;Of course, they only support strings, so if you have fancy objects that you want to send then you'll need to serialize and deserialize them to and from strings. There are of course language-specific ways to do this (Java Object Serialization, Python Pickles, etc.), but I prefer &lt;a href="http://incubator.apache.org/thrift/"&gt;Thrift&lt;/a&gt; because it's fast, efficient, and is the same in multiple languages. This is handy because you can implement different components in different languages, which is sometimes useful. For instance, my web server is in Java and my background process is in Python.&lt;br /&gt;&lt;br /&gt;Thrift also provides some additional handy components besides serialization, in particular a transport layer that provides RPC semantics over arbitrary transport mechanisms. It comes by default with socket and HTTP transports.&lt;br /&gt;&lt;br /&gt;What I have implemented and made available for you in case you might find it useful is an &lt;a href="http://blanu.net/thrift-sqs/"&gt;SQS transport for Thrift&lt;/a&gt;. It effectively provides cross-language multicast RPC in a few lines of code. The key piece of code is &lt;a href="http://blanu.net/thrift-sqs/py/TSqsClient.py"&gt;TSqsClient&lt;/a&gt;, which provides the SQS transport using the &lt;a href="http://code.google.com/p/boto/"&gt;&lt;span style="text-decoration: underline;"&gt;boto&lt;/span&gt;&lt;/a&gt; library for Python. This is the piece that you'll need to port if you want to support other languages. The rest of the code is just for example purposes and is derived from simple-thrift-queue, which is a nice example of how to build an application using Thrift. The available methods are defined in the &lt;a href="http://blanu.net/thrift-sqs/squeue.thrift"&gt;thrift file&lt;/a&gt;. It's important that they are defined as async and void, as this is a one-way transport. The &lt;a href="http://blanu.net/thrift-sqs/py/qproducer.py"&gt;producer&lt;/a&gt; calls methods on the stub classes generated by the Thrift compiler. These method calls are queued up SQS. The &lt;a href="http://blanu.net/thrift-sqs/py/qconsumer.py"&gt;consumer&lt;/a&gt; gets the method calls from SQS and calls the methods on the &lt;a href="http://blanu.net/thrift-sqs/py/qhandler.py"&gt;handler&lt;/a&gt; class. Additionally, there are a couple of utilities. One to &lt;a href="http://blanu.net/thrift-sqs/py/qget.py"&gt;fetch a single message&lt;/a&gt; from SQS, so you can test the producer, and one&lt;a href="http://blanu.net/thrift-sqs/py/qclear.py"&gt; clear the queue&lt;/a&gt; if you send too many messages.&lt;br /&gt;&lt;br /&gt;Once nice thing about using Thrift is that you can swap out the transport easily. You can replace my SQS transport with a Starling one, or ditch queues altogether and use sockets or HTTP. The advantage of using SQS is that the producers and consumers can all be on different machines or the same machine, it makes no difference. Used together, you have a very flexible and very scalable system with very few lines of code. &lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;Just update your thrift file and handler class to use your API and everything else is handled for you!&lt;/span&gt;&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=3bU8m8VWEDM:IQ0m4p_ur7o:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=3bU8m8VWEDM:IQ0m4p_ur7o:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=3bU8m8VWEDM:IQ0m4p_ur7o:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/3bU8m8VWEDM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/843400921806035496/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=843400921806035496" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/843400921806035496?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/843400921806035496?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/3bU8m8VWEDM/scalable-clustering-with-thrift-and-sqs.html" title="Scalable Clustering with Thrift and SQS" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2008/12/scalable-clustering-with-thrift-and-sqs.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4DSX04eSp7ImA9WxRWF0k.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-5797991065895662602</id><published>2008-11-03T12:20:00.000-08:00</published><updated>2008-11-03T12:26:18.331-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-03T12:26:18.331-08:00</app:edited><title>Ringlight Beta Launch Party</title><content type="html">After almost a year of hacking, testing, and web design, I'm ready to release a &lt;a href="http://ringlight.us/"&gt;Ringlight&lt;/a&gt; beta to the public.&lt;br /&gt;&lt;br /&gt;I'd like all of my friends and coworkers to join me at &lt;a href="http://conjunctured.com/"&gt;Conjunctured&lt;/a&gt; to celebrate this momentous occasion.   The party is this Wednesday, November 5th, from 6-9pm.&lt;br /&gt;&lt;br /&gt;Austin is a great place to do a startup and I couldn't have made it this far without the community. Let's work together to make things awesome!&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=L8kJW4UKeJY:WrLkigPRJV0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=L8kJW4UKeJY:WrLkigPRJV0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=L8kJW4UKeJY:WrLkigPRJV0:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/L8kJW4UKeJY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/5797991065895662602/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=5797991065895662602" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/5797991065895662602?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/5797991065895662602?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/L8kJW4UKeJY/ringlight-beta-launch-party.html" title="Ringlight Beta Launch Party" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2008/11/ringlight-beta-launch-party.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0QERXw_cSp7ImA9WxRXF00.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-3935330371215173132</id><published>2008-10-22T11:29:00.000-07:00</published><updated>2008-10-22T11:48:24.249-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-22T11:48:24.249-07:00</app:edited><title>The Rackspace Cloud Event</title><content type="html">Today I attended the &lt;a href="http://cloud.rackspace.com/"&gt;Rackspace Cloud Event&lt;/a&gt; at the ACLU stage, just a couple floors above the &lt;a href="http://www.actlab.utexas.edu/"&gt;ACTLab&lt;/a&gt;. I'll skip the marketing and get right to what startups and developers might care about.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Rackspace bought Slicehost&lt;/li&gt;&lt;li&gt;Rackspace bought Jungle Disk&lt;/li&gt;&lt;li&gt;Their version of Google App Engine, previously Mosso, is now called "Cloud Sites"&lt;/li&gt;&lt;li&gt;Their S3 is called "Cloud Files" and is $0.15/GB per month&lt;/li&gt;&lt;li&gt;They will be offerering pay-as-you-go CDN for Cloud Files through Limelight for $0.22/GB&lt;/li&gt;&lt;/ul&gt;I've always had a problem with Mosso ("Cloud Sites") in that it promises to scale your app for you, but it never says what type of scaling it actually does. Luckily, one of the engineers talked to me afterwards and answered all of my questions. Here's how it scales:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A master load balancer which will be hot swapped in case of failure&lt;br /&gt;&lt;/li&gt;&lt;li&gt;A cluster of web server load balancers&lt;/li&gt;&lt;li&gt;A cluster of app servers&lt;/li&gt;&lt;li&gt;Master-slave replicated databases&lt;/li&gt;&lt;/ul&gt;So they're basically doing all the things that are good and reasonable. I didn't have a chance to ask about caching issues such as whether a memcached cluster or any other caching solution was available. Also, while they don't do automatic sharding of your database (which would be cool, but kind of insane), they do support apps with multiple master databases and will support separate replication for each master. It really beats services which just provide a cluster of app servers in terms of ultimate scalability.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=lDdUra21aO8:ril-4a-MuP0:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=lDdUra21aO8:ril-4a-MuP0:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=lDdUra21aO8:ril-4a-MuP0:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/lDdUra21aO8" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/3935330371215173132/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=3935330371215173132" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3935330371215173132?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/3935330371215173132?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/lDdUra21aO8/rackspace-cloud-event.html" title="The Rackspace Cloud Event" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2008/10/rackspace-cloud-event.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4NSH4zfip7ImA9WxdbGE4.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-7151509806613632148</id><published>2008-08-15T12:55:00.000-07:00</published><updated>2008-08-15T13:09:59.086-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-15T13:09:59.086-07:00</app:edited><title>Autocomplete Form Fields (with jQuery)</title><content type="html">I recently added a feature to &lt;a href="http://ringlight.us/"&gt;Ringlight&lt;/a&gt; which lets you share a private file with a particular user. There is a field to enter the username that you want to share with and obviously this field needs to autocomplete as you type. This is a feature that users expect now and so it's not really optional.&lt;br /&gt;&lt;br /&gt;jQuery makes it very easy to add this feature:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Download the &lt;a href="http://www.pengoworks.com/workshop/jquery/autocomplete.htm"&gt;autocomplete&lt;/a&gt; extension for jQuery. You'll need both the &lt;a href="http://www.pengoworks.com/workshop/jquery/lib/jquery.autocomplete.js"&gt;javascript&lt;/a&gt; and &lt;a href="http://www.pengoworks.com/workshop/jquery/lib/jquery.autocomplete.css"&gt;CSS&lt;/a&gt; files.&lt;/li&gt;&lt;li&gt;Add an input field to your form: &lt;input id="youAutocompleteMe" type="text"&gt;&lt;/li&gt;&lt;li&gt;Set the cacheLength option to speed up responsiveness: options={cacheLength: "20"};&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Call the autocomplete extension: $("#youAutocompleteMe").autocomplete(url, options);&lt;/li&gt;&lt;li&gt;You'll need a server-side script installed at the url you pass to autocomplete to return matches.&lt;/li&gt;&lt;/ol&gt;The autocomplete function will call the given url, passing the text currently in the input box in the q parameter.  Your server-side code should return a newline-delimited list of matches.&lt;br /&gt;&lt;br /&gt;That's it! It's pretty easy. The key to performance is setting that cacheLength parameter as it default to 1, which doesn't provide much caching at all.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=_cbh269XYjA:7J6mBO9kINs:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=_cbh269XYjA:7J6mBO9kINs:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=_cbh269XYjA:7J6mBO9kINs:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/_cbh269XYjA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/7151509806613632148/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=7151509806613632148" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7151509806613632148?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/7151509806613632148?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/_cbh269XYjA/autocomplete-form-fields-with-jquery.html" title="Autocomplete Form Fields (with jQuery)" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>1</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2008/08/autocomplete-form-fields-with-jquery.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkQHQHc9cSp7ImA9WxdbEkw.&quot;"><id>tag:blogger.com,1999:blog-7182371568763719854.post-514491371269184690</id><published>2008-08-08T08:39:00.000-07:00</published><updated>2008-08-08T09:52:11.969-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-08-08T09:52:11.969-07:00</app:edited><title>AJAX File Upload Progress Bars (with jQuery)</title><content type="html">I recently added progress bars (actually, a percentage instead of a bar, but it was the same to implement) to &lt;a href="http://ringlight.us/"&gt;Ringlight&lt;/a&gt; uploads and downloads. I was suprised to find that the available server-side libraries for dealing with file uploads seemed to be inadequate for adding this functionality to my website.&lt;br /&gt;&lt;br /&gt;The basic technique for adding progress bars is relatively simple. With jQuery:&lt;br /&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Install the &lt;a href="http://www.phpletter.com/Demo/AjaxFileUpload-Demo/"&gt;Ajax File Upload extension&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;Install the &lt;a href="http://groups.google.com/group/jquery-en/browse_thread/thread/e99f3bc0cfa12696"&gt;periodic execution extension&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Register some &lt;a href="http://docs.jquery.com/Ajax"&gt;Ajax event callbacks&lt;/a&gt; to reveal the progress bar on the page when the upload starts and also to catch errors.&lt;/li&gt;&lt;li&gt;Call the $.ajaxFileUpload function with the URL of the upload handler script, the id of the file input element, and the callback function to handle output from the upload handler.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Have the upload handler return a Json object with an id for the upload.&lt;/li&gt;&lt;li&gt;Call your progress bar update function with the periodic execution model: $.periodic(updateProgressBar);&lt;/li&gt;&lt;li&gt;The updateProgressBar function should fetch the download status from a server-side script, supplying the upload id and a callback function: $.getJSON("fetchProgress", {id: id}, function(data) {/* update progress bar with data.percentDownloaded*/});&lt;/li&gt;&lt;li&gt;The fetchProgress script should return upload progress information in a Json object. I return percentDownloaded, but you can include anything you'd like, such as upload rate. You should also provide error information here, such as if the upload failed.&lt;/li&gt;&lt;li&gt;The callback function for fetchProgress should update the page to reflect updated progress. For instance, updating a percentage to completion could be as simple as $("#percent").empty().append(data.percentDownloaded);&lt;/li&gt;&lt;/ol&gt;This was all very simple to implement and jQuery made it possible in very few lines of code. The difficulty was in providing a percentDownloaded value. The difficulty comes from the fact that it is common for browsers to not include the Content-Length field for uploaded files. The file upload handling libraries generally solve this problem by either 1) not providing a content length or 2) loading the whole file into memory (or disk, in some cases) and then finding the length of it. Either way, not very useful for a progress bar! This total failure to handle streaming files is a &lt;a href="http://www.hackerdashery.com/2008/05/how-not-to-handle-streams.html"&gt;common problem in libraries&lt;/a&gt; and if you could avoid it in the libraries you implement then the world would be most appreciative.&lt;br /&gt;&lt;br /&gt;In the meantime, there are a number of action items that require your attention. First, calculate the file length by taking the HTTP request Content-Length field and subtracting the size of everything which is not the file in order to yield the file length. I did this with the following shoddy algorithm:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Extract the MIME boundary from the Content-Disposition field.&lt;/li&gt;&lt;li&gt;Subtract the size of the MIME boundary twice (there is a boundary on both sides of the file).&lt;/li&gt;&lt;li&gt;Subtract 2 because the second boundary has a trailing "--".&lt;/li&gt;&lt;li&gt;Subtract 4 because each boundary has a trailing two-character newline (\r\n).&lt;/li&gt;&lt;li&gt;Subtract 8 because my numbers were always off by exactly 8. I'm not sure where this additional 8 is coming from.&lt;/li&gt;&lt;/ol&gt;As I said, this algorithm is shoddy, a kludge not fit for use in production. However, it works for now! It needs extensive testing and tweaking on a variety of browsers. The next steps:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Improve algorithm so that it's robust enough to work with most browsers&lt;/li&gt;&lt;li&gt;Submit a patch to python's FieldStorage class to support this algorithm&lt;/li&gt;&lt;li&gt;Submit a bug report to Mozilla requesting that they supply content length in file uploads&lt;/li&gt;&lt;/ol&gt;For now, my upload progress bars are working, so I'm happy.&lt;div class="feedflare"&gt;
&lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:yIl2AUoC8zA"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=yIl2AUoC8zA" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:63t7Ie-LG7Y"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=63t7Ie-LG7Y" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:qj6IDK7rITs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=qj6IDK7rITs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:V_sGLiPBpWU"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Unx77EOzq3E:6rlo2rN1Ds4:V_sGLiPBpWU" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:F7zBnMyn0Lo"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?i=Unx77EOzq3E:6rlo2rN1Ds4:F7zBnMyn0Lo" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:YwkR-u9nhCs"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=YwkR-u9nhCs" border="0"&gt;&lt;/img&gt;&lt;/a&gt; &lt;a href="http://feeds.feedburner.com/~ff/StepThreeProfit?a=Unx77EOzq3E:6rlo2rN1Ds4:cGdyc7Q-1BI"&gt;&lt;img src="http://feeds.feedburner.com/~ff/StepThreeProfit?d=cGdyc7Q-1BI" border="0"&gt;&lt;/img&gt;&lt;/a&gt;
&lt;/div&gt;&lt;img src="http://feeds.feedburner.com/~r/StepThreeProfit/~4/Unx77EOzq3E" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://www.stepthreeprofit.com/feeds/514491371269184690/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=7182371568763719854&amp;postID=514491371269184690" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/514491371269184690?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/7182371568763719854/posts/default/514491371269184690?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/StepThreeProfit/~3/Unx77EOzq3E/ajax-file-upload-progress-bars-with.html" title="AJAX File Upload Progress Bars (with jQuery)" /><author><name>blanu</name><uri>http://www.blogger.com/profile/10742095104796078540</uri><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>2</thr:total><feedburner:origLink>http://www.stepthreeprofit.com/2008/08/ajax-file-upload-progress-bars-with.html</feedburner:origLink></entry></feed>
