<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/clientperf_data_builder.rb</filename>
    </added>
    <added>
      <filename>lib/clientperf_helper.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,3 +1,3 @@
-* Thanks to Howard Rauscher for providing much of the javascript measurement code.
+* Thanks to Howard Rauscher for providing the javascript measurement code.
 
 * Thanks to the FiveRuns team, especially Bruce Williams for helping me to understand how to write rails plugins and hook into ActionController</diff>
      <filename>CONTRIBUTORS</filename>
    </modified>
    <modified>
      <diff>@@ -1,3 +1,4 @@
 = History
+* v0.1.0. This version is decent for consumption. decent graphs, layout, stable installation and compressed javascript.
 * v0.0.2. First time releasing a gem and my manifest was bad. this version fixes that
 * v0.0.1. Just in time for Austin on Rails
\ No newline at end of file</diff>
      <filename>History.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -5,6 +5,8 @@ init.rb
 lib/clientperf.rb
 lib/clientperf_config.rb
 lib/clientperf_controller.rb
+lib/clientperf_data_builder.rb
+lib/clientperf_helper.rb
 lib/clientperf_migrations.rb
 lib/clientperf_result.rb
 lib/clientperf_uri.rb</diff>
      <filename>Manifest</filename>
    </modified>
    <modified>
      <diff>@@ -6,9 +6,17 @@ Measures the time it takes a user's browser to get from the top of a web page to
 
 == Installation
 
+Most cases:
+
 	sudo gem install clientperf
 	clientperf /path/to/rails/app
+	cd /path/to/rails/app
 	rake db:migrate
+	
+For clientperf developers, follow the above steps to generate the clientperf tables for a rails app, then:
+	cd /path/to/rails/app
+	rm -rf vendor/plugins/clientperf
+	git clone git://github.com/efalcao/clientperf.git vendor/plugins/clientperf
 
 == Usage
 </diff>
      <filename>README.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,4 @@
 = TODO
-* charts
-* make it pretty
 * tests (how to test a plugin?)
-* indexes? other small optimizations?
\ No newline at end of file
+* indexes? other small optimizations?
+* rake-based installation rather than a gem binary? how to behave as a rail 2.1 gem when it comes to the migration?
\ No newline at end of file</diff>
      <filename>TODO.rdoc</filename>
    </modified>
    <modified>
      <diff>@@ -27,7 +27,7 @@ module Clientperf
     end
     
     def version
-      &quot;0.0.3&quot;
+      &quot;0.1.0&quot;
     end
     
     private</diff>
      <filename>lib/clientperf.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,6 @@
 class ClientperfController &lt; ActionController::Base
   def index
+    ClientperfUri.destroy_all [&quot;updated_at &lt; ?&quot;, 1.year.ago]
     @uris = ClientperfUri.find(:all, :include =&gt; :clientperf_results)
   end
   
@@ -8,17 +9,6 @@ class ClientperfController &lt; ActionController::Base
     @page_title = @uri.uri
   end
   
-  def reset
-    if request.post?
-      if params[:id]
-        ClientperfUri.destroy(params[:id])
-      else
-        ClientperfUri.destroy_all
-      end
-    end
-    redirect_to :action =&gt; 'index'
-  end
-  
   def measure
     milliseconds = params[:e].to_i - params[:b].to_i rescue nil
     if milliseconds &amp;&amp; params[:u]</diff>
      <filename>lib/clientperf_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,26 @@ class ClientperfResult &lt; ActiveRecord::Base
   belongs_to :clientperf_uri
   after_create :update_uri
   
+  class &lt;&lt; self
+    include ClientperfDataBuilder
+
+    def last_24_hours
+      start_time = (Time.now + 1.hour - 1.day).change(:min =&gt; 0)
+      results = average(:milliseconds, :conditions =&gt; ['created_at &gt; ?', start_time], 
+        :group =&gt; &quot;date_format(created_at,'%Y-%m-%d %H')&quot;)
+
+      build_data_for_chart(results, start_time, 23, :hours) 
+    end
+
+    def last_30_days
+      start_time = (Time.now + 1.day - 30.days).change(:hour =&gt; 0)
+      results = average(:milliseconds, :conditions =&gt; ['created_at &gt; ?', start_time], 
+        :group =&gt; &quot;date_format(created_at,'%Y-%m-%d')&quot;)
+
+      build_data_for_chart(results, start_time, 29, :days)
+    end
+  end
+  
   private
   
   def update_uri</diff>
      <filename>lib/clientperf_result.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,86 +1,20 @@
 class ClientperfUri &lt; ActiveRecord::Base
+  include ClientperfDataBuilder
+  has_many :clientperf_results, :dependent =&gt; :delete_all
   
-  has_many :clientperf_results, :dependent =&gt; :delete_all do
-    def last_hour
-      end_time = (Time.now + 1.minute).change(:sec =&gt; 0)
-      start_time = end_time - 1.hour
-      results = average(:milliseconds, :conditions =&gt; ['created_at between ? and ?', start_time, end_time] ,
-        :group =&gt; 'minute(created_at)')
+  def last_24_hours
+    start_time = (Time.now + 1.hour - 1.day).change(:min =&gt; 0)
+    results = clientperf_results.average(:milliseconds, :conditions =&gt; ['created_at &gt; ?', start_time], 
+      :group =&gt; &quot;date_format(created_at,'%Y-%m-%d %H')&quot;)
       
-      max = 0  
-      padded_results = (start_time.min..start_time.min + 59).map do |i|
-        minute = i % 60
-        data = data_for(minute, results)
-        max = data if data &amp;&amp; data &gt; max
-        [minute, data]
-      end
-      [padded_results, max]
-    end
-    
-    def last_day
-      end_time = (Time.now + 1.hour).change(:min =&gt; 0)
-      start_time = end_time - 1.day
-      results = average(:milliseconds, :conditions =&gt; ['created_at between ? and ?', start_time, end_time], 
-        :group =&gt; 'hour(created_at)')
-      
-      max = 0  
-      padded_results = (start_time.hour..start_time.hour + 23).map do |i|
-        hour = i % 24
-        data = data_for(hour, results)
-        max = data if data &amp;&amp; data &gt; max
-        [hour, data]
-      end
-      [padded_results, max]  
-    end
-    
-    def last_month
-      end_time = (Time.now + 1.day).change(:hour =&gt; 0)
-      start_time = end_time - 30.days
-      results = average(:milliseconds, :conditions =&gt; ['created_at between ? and ?', start_time, end_time], 
-        :group =&gt; 'day(created_at)')
-        
-      max = 0  
-      padded_results = (start_time.day..start_time.day + 29).map do |i|
-        day = i % Time.days_in_month(start_time.month)
-        data = data_for(day, results)
-        max = data if data &amp;&amp; data &gt; max
-        [day, data]
-      end
-      [padded_results, max]
-    end
-    
-    def data_for(point, results)
-      data = results.detect {|p,d| point == p.to_i}
-      data ? data[1].to_i : 0
-    end
-  end 
-  
-  def chart_url
-    &quot;http://chart.apis.google.com/chart?cht=ls&amp;chs=300x50&amp;chm=B&amp;chd=s:&quot;
-  end
-  
-  def hour_chart
-    &quot;#{chart_url}#{chart_data(clientperf_results.last_hour)}&quot;
-  end
-  
-  def day_chart
-    &quot;#{chart_url}#{chart_data(clientperf_results.last_day)}&quot;
-  end
-  
-  def month_chart
-    &quot;#{chart_url}#{chart_data(clientperf_results.last_month)}&quot;
+    build_data_for_chart(results, start_time, 23, :hours) 
   end
   
-  private
-  
-  def chart_data(args)
-    data, max = args
-    max += 10
-    encode = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
-
-    data.map do |result|
-      char = 62 * result[1] / max.to_f
-      encode[char.round,1]
-    end.join
+  def last_30_days
+    start_time = (Time.now + 1.day - 30.days).change(:hour =&gt; 0)
+    results = clientperf_results.average(:milliseconds, :conditions =&gt; ['created_at &gt; ?', start_time], 
+      :group =&gt; &quot;date_format(created_at,'%Y-%m-%d')&quot;)
+      
+    build_data_for_chart(results, start_time, 29, :days)
   end
 end
\ No newline at end of file</diff>
      <filename>lib/clientperf_uri.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,48 +12,28 @@ module ExtendActionController
   end
   
   def add_clientperf_to(response)
-    if response.body =~ /&lt;html[^&gt;]*?&gt;/im
-      replacement = %q(\1
+    if response.body =~ /(&lt;html[^&gt;]*?&gt;).*(&lt;\/html&gt;)/im
+      top = %q(\1
         &lt;script type='text/javascript'&gt;
-          var clientPerfStart = (new Date()).getTime();
-          var clientPerf = function() {
-            var attach = function(instance, eventName, listener) {
-            	var listenerFn = listener;
-            	if (instance.addEventListener) {
-            		instance.addEventListener(eventName, listenerFn, false);
-            	}
-            	else if (instance.attachEvent) { // Internet explorer
-            		listenerFn = function() {
-            	    	listener(window.event);
-            		};
-            		instance.attachEvent(&quot;on&quot; + eventName, listenerFn);
-            	}
-            	else {
-            	    // I could do some further attachment here, if I wanted too. for older browsers
-            	    // ex: instance['on' + eventName] = listener;
-            		throw new Error(&quot;Event registration not supported&quot;);
-            	}
-            };
-            
-            var endRun = function() {
-              var clientPerfEnd = (new Date()).getTime();
-              var img = document.createElement('img');
-              img.src = '/clientperf/measure.gif?b=' + clientPerfStart + '&amp;e=' + clientPerfEnd + '&amp;u=' + location.href;
-              document.body.appendChild(img);
-            };
-            
-            try {
-                attach(window, 'load', endRun);
-            }
-            catch(e) {
-                window.onload = endRun;
-            }
-          }
-          clientPerf();
+          var _clientPerfStart = (new Date()).getTime();
         &lt;/script&gt;
       )
       
-      response.body.sub!(/(&lt;html[^&gt;]*?&gt;)/im, replacement)
+      bottom = %q(
+        &lt;script type='text/javascript'&gt;
+        (function() {
+        	function fn() { var end = (new Date()).getTime(), img = document.createElement('img'); img.src = '/clientperf/measure.gif?b='+_clientPerfStart+'&amp;e='+end+'&amp;u='+encodeURIComponent(location.href); document.body.appendChild(img); };
+        	if (window.addEventListener) { window.addEventListener('load', fn, false); }
+        	else if (window.attachEvent) { window.attachEvent('onload', fn); }
+        	else { var chain = window.onload; window.onload = function(e) { if(chain !== undefined) { chain(e); } fn(); } }
+        })();
+        &lt;/script&gt;
+        &lt;/html&gt;
+      )
+      
+      response.body.sub!(/(&lt;html[^&gt;]*?&gt;)/im, top)
+      response.body.sub!(/&lt;\/html&gt;/im, bottom)
+      
       response.headers[&quot;Content-Length&quot;] = response.body.size
     end
   end</diff>
      <filename>lib/extend_action_controller.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,20 +1,26 @@
-&lt;h2&gt;all urls&lt;/h2&gt;
-&lt;table&gt;
-	&lt;tr&gt;
-		&lt;td&gt;URL&lt;/td&gt;
-		&lt;td&gt;# of times measured&lt;/td&gt;
-		&lt;td&gt;avg. client time (ms)&lt;/td&gt;
-		&lt;td&gt;first measured&lt;/td&gt;
-		&lt;td&gt;last measured&lt;/td&gt;
-	&lt;/tr&gt;
-	&lt;% @uris.each do |uri| %&gt;
-	&lt;tr&gt;
-		&lt;td&gt;&lt;%= link_to uri.uri, &quot;/clientperf/#{uri.id}&quot; %&gt;&lt;/td&gt;
-		&lt;td&gt;&lt;%= uri.clientperf_results.count %&gt;&lt;/td&gt;
-		&lt;td&gt;&lt;%= uri.clientperf_results.average(:milliseconds).to_i %&gt;&lt;/td&gt;
-		&lt;td&gt;&lt;%= uri.created_at.strftime(&quot;%M/%d/%y&quot;) %&gt;&lt;/td&gt;
-		&lt;td&gt;&lt;%= uri.updated_at.strftime(&quot;%M/%d/%y&quot;) %&gt;&lt;/td&gt;
-	&lt;/tr&gt;
-	&lt;% end %&gt;
-&lt;/table&gt;
-&lt;p&gt;&lt;%= button_to &quot;Reset all data&quot;, {:action =&gt; 'reset'},  :confirm =&gt; &quot;are you sure?&quot; %&gt;&lt;/p&gt;
\ No newline at end of file
+&lt;div id=&quot;urls&quot;&gt;
+	&lt;div class=&quot;block&quot;&gt;
+		&lt;h2&gt;all urls&lt;span id=&quot;explanation&quot;&gt;[ avg. seconds | # of times seen ]&lt;/span&gt;&lt;/h2&gt;
+		&lt;table&gt;
+			&lt;% @uris.each do |uri| %&gt;
+			&lt;tr&gt;
+				&lt;td class=&quot;vital-stats&quot;&gt;[ &lt;%= number_with_precision(uri.clientperf_results.average(:milliseconds) / 1000.to_f, 2) %&gt;s | &lt;%= uri.clientperf_results.count %&gt; ]&lt;/td&gt;
+				&lt;td&gt;&lt;%= link_to uri.uri, &quot;/clientperf/#{uri.id}&quot; %&gt;&lt;/td&gt;
+			&lt;/tr&gt;
+			&lt;% end %&gt;
+		&lt;/table&gt;
+	&lt;/div&gt;
+&lt;/div&gt;
+&lt;div id=&quot;overall&quot;&gt;
+	&lt;div class=&quot;block&quot;&gt;
+		&lt;h2&gt;overall graphs&lt;/h2&gt;
+		&lt;div class=&quot;chart&quot;&gt;
+			&lt;h4&gt;24 hour&lt;/h4&gt;
+			&lt;img src=&quot;&lt;%= chart(ClientperfResult.last_24_hours) %&gt;&quot; /&gt;
+		&lt;/div&gt;
+		&lt;div class=&quot;chart&quot;&gt;
+			&lt;h4&gt;30 day&lt;/h4&gt;
+			&lt;img src=&quot;&lt;%= chart(ClientperfResult.last_30_days)%&gt;&quot; /&gt;
+		&lt;/div&gt;
+	&lt;/div&gt;
+&lt;/div&gt;
\ No newline at end of file</diff>
      <filename>views/clientperf/index.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -1,18 +1,24 @@
-&lt;h2&gt;summary&lt;/h2&gt;
-&lt;p&gt;recorded &lt;%= @uri.clientperf_results.count %&gt; times with average time of &lt;%= @uri.clientperf_results.average(:milliseconds).to_i %&gt;ms. last recorded &lt;%= @uri.updated_at.strftime(&quot;%Y-%m-%d&quot;) %&gt;.&lt;/p&gt;
-
-&lt;h2&gt;trends&lt;/h2&gt;
-&lt;div class=&quot;chart&quot;&gt;
-	&lt;h4&gt;last hour&lt;/h4&gt;
-	&lt;img src=&quot;&lt;%= @uri.hour_chart %&gt;&quot; /&gt;
+&lt;div id=&quot;trends&quot;&gt;
+	&lt;div class=&quot;block&quot;&gt;
+		&lt;h2&gt;trends&lt;/h2&gt;
+		&lt;div class=&quot;chart&quot;&gt;
+			&lt;h4&gt;24 hour&lt;/h4&gt;
+			&lt;img src=&quot;&lt;%= chart(@uri.last_24_hours) %&gt;&quot; /&gt;
+		&lt;/div&gt;
+		&lt;div class=&quot;chart&quot;&gt;
+			&lt;h4&gt;30 day&lt;/h4&gt;
+			&lt;img src=&quot;&lt;%= chart(@uri.last_30_days)%&gt;&quot; /&gt;
+		&lt;/div&gt;	
+	&lt;/div&gt;
 &lt;/div&gt;
-&lt;div class=&quot;chart&quot;&gt;
-	&lt;h4&gt;last day&lt;/h4&gt;
-	&lt;img src=&quot;&lt;%= @uri.day_chart %&gt;&quot; /&gt;
-&lt;/div&gt;
-&lt;div class=&quot;chart&quot;&gt;
-	&lt;h4&gt;last month&lt;/h4&gt;
-	&lt;img src=&quot;&lt;%= @uri.month_chart %&gt;&quot; /&gt;
-&lt;/div&gt;
-
-&lt;p&gt;&lt;%= button_to &quot;Reset this URI&quot;, {:action =&gt; 'reset', :id =&gt; @uri.id},  :confirm =&gt; &quot;are you sure?&quot; %&gt;&lt;/p&gt;
\ No newline at end of file
+&lt;div id=&quot;summary&quot;&gt;
+	&lt;div class=&quot;block&quot;&gt;
+		&lt;h2&gt;summary&lt;/h2&gt;
+		&lt;ul&gt;
+			&lt;li&gt;&lt;span&gt;measured:&lt;/span&gt;&lt;b&gt;&lt;%= @uri.clientperf_results.count %&gt;&lt;/b&gt; times&lt;/li&gt;
+			&lt;li&gt;&lt;span&gt;average time:&lt;/span&gt;&lt;b&gt;&lt;%= number_with_precision(@uri.clientperf_results.average(:milliseconds) / 1000.to_f, 2) %&gt;&lt;/b&gt; seconds&lt;/li&gt;
+			&lt;li&gt;&lt;span&gt;first seen:&lt;/span&gt;&lt;b&gt;&lt;%= @uri.created_at.strftime(&quot;%m/%d/%Y&quot;) %&gt;&lt;/b&gt;&lt;/li&gt;
+			&lt;li&gt;&lt;span&gt;last seen:&lt;/span&gt;&lt;b&gt;&lt;%= distance_of_time_in_words(@uri.updated_at, Time.now) %&gt;&lt;/b&gt; ago&lt;/li&gt;
+		&lt;/ul&gt;		
+	&lt;/div&gt;
+&lt;/div&gt;
\ No newline at end of file</diff>
      <filename>views/clientperf/show.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -2,7 +2,21 @@
 	&lt;head&gt;
 		&lt;title&gt;clientperf &lt;%= &quot;: #{@page_title}&quot; if @page_title %&gt;&lt;/title&gt;
 		&lt;style type=&quot;text/css&quot;&gt;
-			body {margin:0; font-family: helvetica, arial, sans-serif; font-size: 14px;}
+			body {
+				margin:0; 
+				font-family: helvetica, arial, sans-serif; 
+				font-size: 14px;
+				min-width: 990px;
+			}
+			
+			ul {
+				margin: 0;
+				padding: 0;
+			}
+			
+			li {
+				list-style-type: none;
+			}
 			
 			#header {
 				background-color: #dedede;
@@ -29,14 +43,53 @@
 			#header h3 span {
 			}
 			
-			#content {
-				padding: 0 20px;
-			}
-			
 			#content h2 {
-				margin-top: 20px;
+				margin: 0 0 20px 0;
 				border-bottom: 1px solid #d3d3d3;
 			}
+			
+			#urls, #overall, #trends, #summary {
+				float: left;
+			}
+			
+			#urls, #trends {
+				width: 60%;
+			}
+			
+			#urls li {
+				margin-bottom: 3px	;
+			}
+			
+			.vital-stats, #explanation {
+				color: #666;
+				padding-right: 5px;
+				font-weight: normal;
+			}
+			
+			#explanation {
+				margin-left: 10px;
+				font-style: italic;
+				font-size: 12px;
+				position: relative;
+				bottom: 2px;
+			}
+			
+			table {
+				font-size: 14px;
+			}
+			
+			td { padding-bottom: 3px;}
+			
+			#overall, #summary{
+				width: 40%;
+			}
+			
+			.block {
+				padding: 20px;
+			}
+			
+			#summary li {margin-bottom: 6px;}
+			#summary li span { float:left; width: 100px; }
 		&lt;/style&gt;
 	&lt;/head&gt;
 	&lt;body&gt;</diff>
      <filename>views/layouts/clientperf.html.erb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>7b4dc84ea9d9ac3202ece74b883acff54d3fd87a</id>
    </parent>
  </parents>
  <author>
    <name>Eric Falcao</name>
    <email>efalcao@gmail.com</email>
  </author>
  <url>http://github.com/efalcao/clientperf/commit/9a6dd311d28024fd978663ffda9902957b1ae1da</url>
  <id>9a6dd311d28024fd978663ffda9902957b1ae1da</id>
  <committed-date>2008-06-21T00:52:17-07:00</committed-date>
  <authored-date>2008-06-21T00:52:17-07:00</authored-date>
  <message>decent graphs, compressed js, js top and bottom, half-decent layout, worthy of a blog post at this point...</message>
  <tree>58263d1fece2336d96d57bd28400a2aaea8a32f6</tree>
  <committer>
    <name>Eric Falcao</name>
    <email>efalcao@gmail.com</email>
  </committer>
</commit>
