<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Kickass Labs &#187; Great Minds</title>
	<atom:link href="http://www.kickasslabs.com/category/great-minds/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.kickasslabs.com</link>
	<description>We &#9829; code.</description>
	<lastBuildDate>Wed, 28 Dec 2011 16:57:56 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Quick and Dirty Messaging</title>
		<link>http://www.kickasslabs.com/2008/11/22/93/</link>
		<comments>http://www.kickasslabs.com/2008/11/22/93/#comments</comments>
		<pubDate>Sat, 22 Nov 2008 20:05:55 +0000</pubDate>
		<dc:creator>Brad</dc:creator>
				<category><![CDATA[Great Minds]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[gm]]></category>
		<category><![CDATA[message queue]]></category>
		<category><![CDATA[messaging]]></category>
		<category><![CDATA[rails rumble]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[ruby on rails]]></category>
		<category><![CDATA[rumble]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=93</guid>
		<description><![CDATA[Our Rails Rumble 2008 entry, Great Minds (you can have a look at the latest version or the original Rumble version), required a messaging system. Such systems are easy to do wrong, and we knew we&#8217;d need something that would &#8230; <a href="http://www.kickasslabs.com/2008/11/22/93/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Our <a href="http://railsrumble.com/" title="Rails Rumble 2008" target="rr2008">Rails Rumble 2008</a> entry, <i>Great Minds</i> (you can have a look at the <a href="http://greatminds.kickasslabs.com/" title="Great Minds" target="gmkal">latest version</a> or the <a href="http://greatminds.r08.railsrumble.com/" title="Great Minds - Rumble Version" target="gmrr">original Rumble version</a>), required a messaging system.  Such systems are easy to do wrong, and we knew we&#8217;d need something that would stay solid under unknown load during Rumble judging.</p>
<p>The solution was quick &amp; dirty (as most solutions are during Rails Rumble), but the results worked, and allowed us to qualify for judging and reach a respectable 28th place finish in the &#8220;Completeness&#8221; category.</p>
<p>Check out the details after the fold.</p>
<p><span id="more-93"></span></p>
<h3>Design Constraints</h3>
<p><i>Great Minds</i> is a word game played by 2 or more players.  The game is played in a virtual chat <b>Room</b>, containing one or more <b>Players.</b>  Players can take various actions, such as submitting a word to the game, chatting, or changing their handle/username.  The results of these actions must be transmitted to other players in the room.</p>
<p>Other constraints on the design included:</p>
<ul>
<li><b>No New Technologies:</b>  There are tools like <a href="http://juggernaut.rubyforge.org/" title="Juggernaut" target="juggernaut">Juggernaut</a> that make messaging pretty easy, but we had no hands-on experience with them, and learning a new tool on a 48-hour schedule was deemed a risk to completing the project &#038; qualifying for Rumble judging.</li>
<li><b>Broadcast:</b>  We needed something more than a simple message queue like <a href="http://xph.us/software/beanstalkd/" title="Beanstalk" target="beanstalk">Beanstalk</a>; the consumer of a message couldn&#8217;t remove it from the queue, as there might be other consumers needing the same message.</li>
<li><b>Room State Reconstruction:</b>  Someone coming to the room for the first time (or leaving and returning) should be able to see the current room state, including all participants, recently played words, and recent chat.</li>
<li><b>Replay:</b>  Though we didn&#8217;t get around to implementing it, we wanted to offer the ability to review a particularly funny game.</li>
</ul>
<p>The first two constraints affected our design and technology choices; the second two demanded that the messages be persisted.  (Alternatively, we could have saved the room state in some other way, but as long as we had the messages anyway, it seemed simpler to just keep them and reconstruct the state.)</p>
<h3>Client Implementation</h3>
<p>In the absence of a viable push solution like Juggernaut, we opted for a polling solution:  Clients would periodically send a signal that:</p>
<ul>
<li>let the server know they&#8217;re still alive and connected,</li>
<li>sent any new messages to the server, and</li>
<li>requested any pending messages from the server.</li>
</ul>
<p>On the client side, this meant that every message got packaged as JSON, stuck in a queue, and periodically collected and sent to the server as the optional payload of a keep-alive signal.  With some help from Prototype, this was as simple as:</p>
<pre>
  function SyncMessages() {
          var data = Object.toJSON(MESSAGES_QUEUE);
          var url = '/room/sync_messages';
          var params = {
                  authenticity_token: AUTH_TOKEN,
                  messages: '[]',
                  //messages: Object.toJSON(MESSAGES_QUEUE),
                  last_message_id: LAST_MESSAGE_ID };

          new Ajax.Request(url, {
            method: 'post',
                  parameters: params,
            onSuccess: HandleMessages });
  }

  SyncMessages(); //start first on load
  var message_syncer = new PeriodicalExecuter(SyncMessages, 3);
</pre>
<p><code>HandleMessages()</code> updates the DOM based on messages coming back.</p>
<p>The other feature to note is the <code>LAST_MESSAGE_ID</code> token above.  Each client is responsible for keeping track of the last message ID it got.  On the server side, message IDs are assigned sequentially, so all new messages are guaranteed to have a higher ID.</p>
<p>We could have kept track of each client&#8217;s last message on the server side, but this would have been much more complex &#8211; we would have needed to store data either in the session (which already held a fair amount of stuff) or in another table in order to keep track of who had received what.</p>
<h3>Server Implementation</h3>
<p>On the server side, messages were persisted in a table.  This table would have relatively frequent inserts, somewhat more frequent reads, and no updates or deletions.  For this reason, we went with the default MyISAM table architecture.  (We had considered a design that would have updated the table with delivery status information and would have required InnoDB&#8217;s row-level locking, but in the end we opted for the simpler design.)  The table looks like:</p>
<pre>
  class CreateMessages < ActiveRecord::Migration
    def self.up
      create_table :messages do |t|
        t.integer :message_type_id, :room_id, :game_id, :user_id
        t.string  :data, :user_handle
        t.timestamps
      end
    end

    def self.down
      drop_table :messages
    end
  end
</pre>
<p>It also has an index:</p>
<pre>
  class AddRoomIndexToMessages < ActiveRecord::Migration
    def self.up
      add_index :messages, [:room_id, :id]
    end

    def self.down
      remove_index :messages, [:room_id, :id]
    end
  end
</pre>
<p>Recall that the client keeps track of the last message it got, and periodically requests all messages since.  This index speeds that request - which is just <code>msgs = Message.find :all, :conditions => ['room_id = ? AND id > ?', session['room_id'], last_message_id], <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> rder => 'id'</code>.  (Yes, I know that should be a <a href="http://ryandaigle.com/articles/2008/8/20/named-scope-it-s-not-just-for-conditions-ya-know" title="Named Scopes" title="namedscopes">named scope</a>.  I hadn't gotten around to learning those yet at the time of the Rumble.)</p>
<p>When the a keep-alive signal hits the server:</p>
<ul>
<li>any new messages attached to the signal are added to the <code>messages</code> table,</li>
<li>any game mechanics related to those messages are executed (which may result in more messages being added to the table), and</li>
<li>all messages for the caller's room with an ID greater than the caller's LAST_MESSAGE_ID are packaged as JSON and sent back down in the HTTP response.</li>
</ul>
<p>A note:  If you're in a room and you enter (for example) a chat message, there's actually a server round-trip involved (pushing the message to the server and getting the same message back as a response) before that chat message is shown in your browser.  We worried about this, but not for long - the interactivity delay turned out to be minimal, and it was much simpler to keep it this way (every message is treated the same for all clients) than to create an exception (you update your DOM with your chat messages immediately, but your own chat messages are somehow filtered from your message stream).</p>
<h3>What's Missing?</h3>
<p>Obviously, this was a quick &amp; dirty solution, tailored to the immediate needs of a Rails Rumble project.  Here's what I'd do differently (and indeed, will do differently, as we have plans for the future of Great Minds - stay tuned):</p>
<ul>
<li><b>Security:</b>  We do use the Rails session <code>authenticity_token</code>, but there's still no protection from a server flood from someone who has a token, either by cranking down the polling interval or by fiddling with the LAST_MESSAGE_ID.</li>
<li><b>Server Push:</b>  Polling is wasteful - requests are made whether or not there are any messages to send or receive.  We plan to move to Juggernaut soon.</li>
<li><b>Decoupling from Game Mechanics:</b>  In the first iteration, message receipt and delivery were too intimately tied to game mechanics, with <code>Message</code> objects being explictly constructed and followed by <code>Message.save!</code> calls.  I've already started the process of teasing them apart in preparation for the move to Juggernaut, factoring this into a <code>deliver_message()</code> method.</li>
</ul>
<p>Questions?  Thoughts?  Add a comment!  I promise to get back to you.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.kickasslabs.com%2F2008%2F11%2F22%2F93%2F&amp;title=Quick%20and%20Dirty%20Messaging" id="wpa2a_2"><img src="http://www.kickasslabs.com/wp-content/plugins/add-to-any/share_save_120_16.png" width="120" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2008/11/22/93/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>The fruits of my labor with color and design</title>
		<link>http://www.kickasslabs.com/2008/11/17/the-fruits-of-my-labor-with-color-and-design/</link>
		<comments>http://www.kickasslabs.com/2008/11/17/the-fruits-of-my-labor-with-color-and-design/#comments</comments>
		<pubDate>Mon, 17 Nov 2008 04:23:38 +0000</pubDate>
		<dc:creator>abel</dc:creator>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Great Minds]]></category>

		<guid isPermaLink="false">http://www.kickasslabs.com/?p=52</guid>
		<description><![CDATA[As you know from my previous post, I've been learning a bit about color and design.  I've taken what I've learned to help redesign our game site, Great Minds, from v1.1 to v1.9 and finally v2.0.  Obviously there's a bunch of important stuff going on between v1.1 and v1.9, but there are very subtle, yet important things happening between v1.9 and v2.0. <a href="http://www.kickasslabs.com/2008/11/17/the-fruits-of-my-labor-with-color-and-design/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>Hey again,</p>
<p>As you know from my previous post, I&#8217;ve been learning a bit about color and design.  I&#8217;ve taken what I&#8217;ve learned to help redesign our game site, Great Minds, from this:</p>
<div id="attachment_58" class="wp-caption alignnone" style="width: 160px"><a href="http://www.kickasslabs.com/wp-content/uploads/2008/11/gm-home-010.png" rel="lightbox[52]"><img class="size-thumbnail wp-image-58" title="gm-home-v1.1" src="http://www.kickasslabs.com/wp-content/uploads/2008/11/gm-home-010-150x150.png" alt="Great Minds Homepage, v1.1" width="150" height="150" /></a><p class="wp-caption-text">Great Minds Homepage, v1.1</p></div>
<p>&#8230;to this:</p>
<div id="attachment_60" class="wp-caption alignnone" style="width: 160px"><a href="http://www.kickasslabs.com/wp-content/uploads/2008/11/gm-home-073.png" rel="lightbox[52]"><img class="size-thumbnail wp-image-60" title="gm-home-v1.9" src="http://www.kickasslabs.com/wp-content/uploads/2008/11/gm-home-073-150x150.png" alt="Great Minds Homepage, v1.9" width="150" height="150" /></a><p class="wp-caption-text">Great Minds Homepage, v1.9</p></div>
<p>&#8230;and finally this:</p>
<div id="attachment_90" class="wp-caption alignnone" style="width: 160px"><a href="http://www.kickasslabs.com/wp-content/uploads/2008/11/home-v20.png" rel="lightbox[52]"><img class="size-thumbnail wp-image-90" title="home-v20" src="http://www.kickasslabs.com/wp-content/uploads/2008/11/home-v20-150x150.png" alt="Great Minds Homepage, v2.0" width="150" height="150" /></a><p class="wp-caption-text">Great Minds Homepage, v2.0</p></div>
<p>Obviously there&#8217;s a bunch of important stuff going on between v1.1 and v1.9, but there are very subtle, yet important things happening between v1.9 and v2.0.</p>
<p><span id="more-52"></span></p>
<h2>v1.1 -&gt; v1.9</h2>
<p><strong><span style="text-decoration: underline;">Color</span></strong>: Using what i learned about color theory, i continued using blues.  This time, however, I&#8217;m using my blues for the right reason.  I chose various shades of blue because it&#8217;s a cool, calming color.  Great Minds should be a fun, relaxed experience. If I had used deeper, darker blues, the look would come across as heavy, serious, and gloomy.</p>
<p>I also brought the gradient in from the page background to the inner container background.  This helps generate even more contrast (and therefore dimension), which helps focus the eye.</p>
<p>In addition, I decided to go clean and simple on the style of the game&#8217;s name to make it less distracting.</p>
<p><strong><span style="text-decoration: underline;">Size</span>:</strong> Obviously, the most important thing should be biggest, right?  Well sometimes&#8230;like this time&#8230;and most times.  Here, the largest text is the game title.  However, the largest element is introduction.  Oh yeah, I added an introduction.  The intro helps set the tone of the site along with the newly redesigned game board.</p>
<p>Also, though the &#8216;play&#8217; and &#8216;create&#8217; buttons are very important, they don&#8217;t need to be the largest things on the page.  Therefore, i brought the size down the buttons.</p>
<p><span style="text-decoration: underline;"><strong>Layout</strong></span>: The layout of the instructions and the &#8216;call to action&#8217; are roughly in their original spots.  For those of you that don&#8217;t know what a &#8216;call to action&#8217; is, here&#8217;s a definition:</p>
<p>&#8220;A &#8216;call to action&#8217; in advertising and marketing refers to active copy that compels a user to take action.  Typically the action is to purchase a product or take some step in your sales cycle that will hopefully lead to a sale.&#8221;</p>
<p>In the case of our site, our &#8216;call  to action&#8217; is  getting you to play our game in 1 of 2 ways.  The &#8216;how to play&#8217; element lines up with the &#8216;game modes&#8217; element.  Your eye scans from left to right and you take notice of the buttons, which stand out thanks to their drop shadow.</p>
<p><span style="text-decoration: underline;"><strong>Design</strong></span>: I&#8217;m taking a design idea from the <a href="http://www.aptana.com" target="_blank">Aptana homepage</a> on this one.  Again, since our site isn&#8217;t serious or trying to sell a product, we&#8217;re going with a fun, cool, shades of blue instead of black and slate with small color accents.  In addition, I have to thank <a href="http://www.trazzler.com" target="_blank">Trazzler&#8217;s homepage</a>.  The section titles enclosed in bubbles are an awesome idea that fits in perfectly with the rounded rectangles.</p>
<p><span style="text-decoration: underline;"><strong>Show vs Tell&#8230;Show WINS</strong></span>: There was a ton of text all over the v1.0 site.  Since the game is easy to play, I figured there had to be an easier way to tell visitors how to play.  Enter the emoticons!  These fun little guys helped us to reduce the intimidating text.  This also gave me the opportunity to add some personality to the design.  I like to think of the 3 emoticons as Gabe, Brad, and me.</p>
<h2>v1.9 -&gt; v2.0</h2>
<p><strong><span style="text-decoration: underline;">Color and design tweaks</span></strong>: Gabe pointed out that too many elements have the same glare and jelly treatment.  This prevents our game mode buttons from standing out.  Since those are our real &#8216;call to action&#8217;, the other elements lost their &#8216;jelly-ness&#8217;.  In addition, i used a new radial gradient in the game mode area.  This further differentiates the &#8216;game modes&#8217; since all of the other gradients on the page are linear, helping make it more unique.  I also moved the group of emoticons to the masthead.  They felt like they were floating below the &#8216;game modes&#8217; area, without purpose.  Finally, I added a little drop shadow to the titles.  This is really to help the &#8216;game modes&#8217; area, but to remain consistent i added it to &#8216;how to play&#8217; as well.</p>
<p><span style="text-decoration: underline;"><strong>Fixing the &#8216;Tell&#8217;</strong></span>: I did a good  job reducing the text, but it was still too wordy.  Thanks to Brad, we have more succinct text around our emoticons that better explains each step.</p>
<h2>In conclusion&#8230;</h2>
<p>There were many iterations between v1.1 and v1.9 and I&#8217;d like to report on the them, but this post is long enough as it is.  Brad and Gabe have been crucial in each and every redesign along with a few key people.  Without them helping to keep me on track and pointing out the short comings in each iteration, who knows what madness I might  have tried to implement.  Be on the look out for the realization of this mock-up in the near future.  If you have thoughts, please comment.  I&#8217;d love to hear what implementation ideas you have.</p>
<p>-a</p>
<p>P.S.</p>
<p>There&#8217;s a spelling error in &#8216;how to play&#8217;, step 3.2.  My bad.  Also, the speech bubbles are a little distorted because i had to scale them.  When implement them, they&#8217;ll be nice and clean <img src='http://www.kickasslabs.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>
<p>P.P.S.</p>
<p>I fixed the &#8216;Spinash&#8217; error.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.kickasslabs.com/2008/11/17/the-fruits-of-my-labor-with-color-and-design/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

