<?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"
	>

<channel>
	<title>Moose56 Blog</title>
	<atom:link href="http://moose56.com/blog/feed/" rel="self" type="application/rss+xml" />
	<link>http://moose56.com/blog</link>
	<description>Pictures/code/words of David Madden</description>
	<pubDate>Tue, 26 Aug 2008 17:13:00 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.6.1</generator>
	<language>en</language>
			<item>
		<title>TitleCase</title>
		<link>http://moose56.com/blog/2008/05/22/titlecase/</link>
		<comments>http://moose56.com/blog/2008/05/22/titlecase/#comments</comments>
		<pubDate>Thu, 22 May 2008 03:40:36 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/?p=53</guid>
		<description><![CDATA[John Gruber posted his title case script the other day which prompted a request from Dan Benjamin to convert it into Ruby. This is my quick and dirty attempt. 
If only I was such a highly skilled regexp ninja as Gruber is!.



#!/usr/bin/env ruby -wKU

class TitleCase

  @small_words    = %w(a an and as [...]]]></description>
			<content:encoded><![CDATA[<p>John Gruber posted his <a href="http://daringfireball.net/2008/05/title_case">title case</a> script the other day which prompted a request from <a href="http://hivelogic.com">Dan Benjamin</a> to convert it into Ruby. This is my quick and dirty attempt. </p>
<p>If only I was such a highly skilled regexp ninja as Gruber is!.</p>
<p><span id="more-41"></span></p>
<p>
<pre class="viewsource"><code class="ruby">
#!/usr/bin/env ruby -wKU

class TitleCase

  @small_words    = %w(a an and as at but by en for if in of on or the to v[.]? via vs[.]?);
  @small_words_r  = /(#{@small_words.join("|")})\b/
  @inline_period  = /[[:alpha:]|[:digit:]][.][[:alpha:]|[:digit:]]/
  @special_case   = /AT&#038;T|Q&#038;A/i
  @uppercase_word = /[[:upper:]]{2,}/

  # Static/Class method to do the work
  def TitleCase.parse(str)

    result = []

    # split on white space
    str.each("\s") do |word|

      word.strip!

      # do not downcase SEC etc.
      if @uppercase_word.match(word) then result << word; next end

      word.downcase!
      # capitalise all but small_words_r and inline_period
      word.capitalize! unless @small_words_r.match(word) || @inline_period.match(word)
      # deal with special cases
      word.upcase! if @special_case.match(word)

      result << word
    end

    # capitalize first and last word
    result[0].capitalize! unless @inline_period.match(result[0])
    result[result.size-1].capitalize! unless @inline_period.match(result[result.size-1])

    result.join(" ")
  end

end

# Test line
#puts TitleCase.parse("Does this work? a an this is daringfireball.net vs. hivelogic.com")

text = STDIN.gets
puts TitleCase.parse(text)
</code></pre></p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/05/22/titlecase/feed/</wfw:commentRss>
		</item>
		<item>
		<title>CSSpress</title>
		<link>http://moose56.com/blog/2008/05/16/csspress/</link>
		<comments>http://moose56.com/blog/2008/05/16/csspress/#comments</comments>
		<pubDate>Fri, 16 May 2008 20:51:35 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[CSS]]></category>

		<category><![CDATA[Ruby]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/?p=52</guid>
		<description><![CDATA[So today I launched a little command line application for compressing CSS files.

My main motivations for this were that I wanted a little tool to strip out comments and whitespace as well as crunch down some of the style values into more optimized versions. As well as this I wanted to write a program in [...]]]></description>
			<content:encoded><![CDATA[<p>So today I launched a little command line application for compressing CSS files.</p>
<p><span id="more-40"></span></p>
<p>My main motivations for this were that I wanted a little tool to strip out comments and whitespace as well as crunch down some of the style values into more optimized versions. As well as this I wanted to write a program in Ruby that someone else might actually find usefull as well as help me learn a little more about the language.</p>
<p>Currently it can do a pretty good job of removing the comments and the white space and I am working on the rest. You can find out more about it at <a href="http://www.csspress.net">csspress.net</a>.</p>
<h3>A long road</h3>
<p>What follows is a little account of how I got this far with it. If you don&#8217;t care about implementation stuff you probably don&#8217;t want to read on.</p>
<p>In order to distribute the tool I found that by packaging my application as a <a href="http://www.rubygems.org/">RubyGem</a> and hosting it on <a href="http://rubyforge.org/">RubyForge</a> anyone can download it simply by typing sudo gem install csspress (anyone on a mac that is) and they can use it right away. No difficult messing with source code.</p>
<p>In terms of writing it in Ruby, that was not crucial to the programs operation. From the users point of view they don&#8217;t care what its implemented in, only that it works. The advantage of using Ruby from my point of view is that I like programming with it and with the gem system it makes it child&#8217;s play to deploy it.</p>
<h3>Gems</h3>
<p>In order to package your code as a gem you have to use a specific directory structure. I already had a rudimentary working version of my application so I had to fit it in around this structure. It was a little trial and error at first and then I found <a href="http://newgem.rubyforge.org/">New Gem Generator</a>, this provides a command that generates the directory structure and as well as a load of useful files and rake tasks. You might find it a bit over the top (is so try <a href="http://seattlerb.rubyforge.org/hoe/">Hoe</a>), but after spending a bit of time and a little more trial and error I have come to really like it.</p>
<h3>Tips</h3>
<p>If you use a version control system like Subversion or Git you should ignore the doc/ and pkg/ directories as well as the index.html file, as these contain files that will change a lot and cause you a lot of problems.</p>
<p>I also found it useful to have a dig about in some of the gems I already had installed on my system. Its really good to see how other people have done it before you.<br />
<h3>What&#8217;s coming</h3>
<p>If I am honest it took me longer to set up the gem, SVN repository and rubyforge account than it did to write the program. Now its all in place though I can now get cracking on improving the tool and adding functionality.</p>
<p>Download it and give it a go; you might find it useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/05/16/csspress/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Binary Tree in Ruby</title>
		<link>http://moose56.com/blog/2008/05/09/binary-tree-in-ruby/</link>
		<comments>http://moose56.com/blog/2008/05/09/binary-tree-in-ruby/#comments</comments>
		<pubDate>Fri, 09 May 2008 15:55:25 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/05/09/binary-tree-in-ruby/</guid>
		<description><![CDATA[Today I thought I would have a play at implementing a binary tree in ruby and see if I could dig up any things I had not used before.


I first came up with a RSpec for it and set about building it and reading about the different methods you can use.
Here is the spec I [...]]]></description>
			<content:encoded><![CDATA[<p>Today I thought I would have a play at implementing a binary tree in ruby and see if I could dig up any things I had not used before.
<p>
<span id="more-39"></span></p>
<p>I first came up with a <a href="http://rspec.info/">RSpec</a> for it and set about building it and reading about the different methods you can use.</p>
<p>Here is the spec I came up with (This is the complete one, at the beginning they were all pending):</p>
<p>
<pre class="viewsource"><code class="ruby">
require "binary_tree"

describe BinaryTree do

  before(:each) do
    @tree = BinaryTree.new
    @keys = %w{F B G A D I C E H}
    @keys.each {|key| @tree.insert(key)}
  end

  it "should have a node for each key inserted" do
    @keys.each do |key|
     @tree.has?(key).should == true
    end
  end

  it "should have the same number of keys as there are nodes" do
    num = 0
    @tree.traverse_inorder do |node|
      num += 1
    end
    num.should eql(@keys.size)
  end

  it "should be tarversable in-order" do
    expected = %w{A B C D E F G H I}
    actual = []
    @tree.traverse_inorder do |node|
      actual << node.key
    end
    expected.should == actual
  end

  it "should be tarversable pre-order" do
    expected = %w{F B A D C E G I H}
    actual = []
    @tree.traverse_preorder do |node|
      actual << node.key
    end
    expected.should == actual
  end

  it "should be tarversable post-order" do
    expected = %w{A C E D B H I G F}
    actual = []
    @tree.traverse_postorder do |node|
      actual << node.key
    end
    expected.should == actual
  end

  it "should be able to return a node when given a key which it contains" do
    @tree.insert("Z")
    "Z".should == @tree.search("Z").key
  end

  it "should return nil if no matching key is found" do
    nil.should == @tree.search("Z")
  end

  it "should be able to delete nodes"

  it "should remain balanced following insertion and deletion of nodes"

end
</code></pre>
</p>
<p>As you can see there are still two to implement. The code that meets this specification is below.</p>
<p>
<pre class="viewsource"><code class="ruby">
# This class stores the tree and handles the insertion
# of new keys. Once the initial key has been inserted
# the insertion is handled by the node objects in the tree.
#
# Traversal of the tree is also controled by this class and
# can be pre-order, post-order or in-order by calling the
# relavant method.
#
# The BinaryTree should be able to store any object that includes
# the Comparable module.
#
# ====TODO
# - Impliment tree balancing
# - Impliment node deletion
#
class BinaryTree

  # This class represents a single node in the tree.
  # It holds a key and references to both its left
  # and right sub trees.
  #
  # It is also able to determin if it is a leaf node
  # using the .leaf? method.
  #
  class Node
    attr_reader :key, :left, :right

    # Create a Node and store the key as well
    # as its left and right sub trees.
    #
    def initialize( key, left=nil, right=nil )
      @key = key
      @left, @right = left, right
    end

    # Insert a new key into the correct subtree based on the
    # value of &lt;i&gt;self&lt;/i&gt;.
    #
    # Duplicate keys are ignored.
    #
    def insert( key )
      if key &lt; @key
        # insert left
        @left.nil?  ? @left  = Node.new( key ) : @left.insert( key )
      elsif key &gt; @key
        # insert right
        @right.nil? ? @right = Node.new( key ) : @right.insert( key )
      end # duplicate key, do nothing
    end

    # Test if &lt;i&gt;self&lt;/i&gt; is a leaf node.
    #
    def leaf?
      @left.nil? &#038;&#038; @right.nil?
    end

    # Return the Key of &lt;i&gt;self&lt;/i&gt; as a String
    #
    def to_s
      @key.to_s
    end
  end

  attr_reader :root

  # Create a new BinaryTree
  #
  def initialize
    @root = nil
  end

  # call-seq:
  #   insert(key) -> self
  #
  # Add a new key to &lt;i&gt;self&lt;/i&gt;
  #
  # Eamples:
  #   tree = BinaryTree.new
  #   tree.insert(5).insert(2).insert(8).insert(1)
  #
  def insert( key )
    if @root.nil?
      @root = Node.new( key )
    else
      @root.insert( key )
    end
    self
  end

  # call-seq:
  #   traverse_inorder {|node| block } -> self
  #
  # Traverses &lt;i&gt;self&lt;/i&gt; in-order.
  #
  # Calls &lt;i&gt;block&lt;/i&gt; once for each node in &lt;i&gt;self&lt;/i&gt;, passing that
  # Node as a parameter.
  #
  # Eamples:
  #   tree = BinaryTree.new
  #   tree.insert(5).insert(2).insert(8).insert(1)
  #
  #   tree.traverse_inorder { |node| print "#{node} " } # -> 1 2 5 8
  #
  def traverse_inorder( node=@root, &#038;block )
    return if node.nil?
    traverse_inorder( node.left,  &#038;block )
    yield node
    traverse_inorder( node.right, &#038;block )
  end

  # call-seq:
  #   traverse_preorder {|node| block } -> self
  #
  # Traverses &lt;i&gt;self&lt;/i&gt; pre-order.
  #
  # Calls &lt;i&gt;block&lt;/i&gt; once for each node in &lt;i&gt;self&lt;/i&gt;, passing that
  # Node as a parameter.
  #
  # Eamples:
  #   tree = BinaryTree.new
  #   tree.insert(5).insert(2).insert(8).insert(1)
  #
  #   tree.traverse_preorder { |node| print "#{node} " } # -> 5 2 1 8
  #
  def traverse_preorder( node=@root, &#038;block )
    return if node.nil?
    yield node
    traverse_preorder( node.left,  &#038;block )
    traverse_preorder( node.right, &#038;block )
  end

  # call-seq:
  #   traverse_postorder {|node| block } -> self
  #
  # Traverses &lt;i&gt;self&lt;/i&gt; post-order.
  #
  # Calls &lt;i&gt;block&lt;/i&gt; once for each node in &lt;i&gt;self&lt;/i&gt;, passing that
  # Node as a parameter.
  #
  # Eamples:
  #   tree = BinaryTree.new
  #   tree.insert(5).insert(2).insert(8).insert(1)
  #
  #   tree.traverse_postorder { |node| print "#{node} " } # -> 1 2 8 5
  #
  def traverse_postorder( node=@root, &#038;block )
    return if node.nil?
    traverse_postorder( node.left,  &#038;block )
    traverse_postorder( node.right, &#038;block )
    yield node
  end

  # call-seq:
  #   search(key) -> aNode
  #
  # Search &lt;i&gt;self&lt;/i&gt; for &lt;i&gt;key&lt;/i&gt; returning the Node if found
  # or nil if not.
  #
  def search( key, node=@root )
    return nil if node.nil?
    if key &lt; node.key
      search(key, node.left)
    elsif key &gt; node.key:
      search(key, node.right)
    else
      return node
    end
  end

  # Test &lt;i&gt;self&lt;/i&gt; for &lt;i&gt;key&lt;/i&gt;.
  #
  def has?( key )
    not self.search(key).nil?
  end
end
</code></pre>
</p>
<p>Download all the code from here: <a href='http://moose56.com/blog/wp-content/uploads/2008/05/binary_tree.tgz' title='binary_tree.tgz'>binary_tree.tgz</a> and have a play. All the comments have been written with RDoc in mind so the documentation that is generated is quite nice. This example may give someone a helpful working example of RSpec and RDoc.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/05/09/binary-tree-in-ruby/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Needleman-Wunsch algorithm in Ruby</title>
		<link>http://moose56.com/blog/2008/04/17/needleman-wunsch-algorithm-in-ruby/</link>
		<comments>http://moose56.com/blog/2008/04/17/needleman-wunsch-algorithm-in-ruby/#comments</comments>
		<pubDate>Thu, 17 Apr 2008 11:58:41 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/04/17/needleman-wunsch-algorithm-in-ruby/</guid>
		<description><![CDATA[While at university I had the pleasure of studying bioinformatics. Bioinformatics is all about using the processing power of computers to lean about and infer data from DNA and protein sequences.
For example if you want to find the common parts of a DNA sequence from 500 different sequences and each sequence is 50000 bases long [...]]]></description>
			<content:encoded><![CDATA[<p>While at university I had the pleasure of studying bioinformatics. Bioinformatics is all about using the processing power of computers to lean about and infer data from DNA and protein sequences.</p>
<p>For example if you want to find the common parts of a DNA sequence from 500 different sequences and each sequence is 50000 bases long it will take some time to compare them all and you are bound to make some mistakes.</p>
<p>This is where bioinformatics comes in and uses tried and tested computer science principles to make these large tasks easier, more accurate and faster. One example is the Needleman-Wunsch algorithm which is used to score a string of bases against another.</p>
<p><span id="more-38"></span></p>
<p>The course I was on covered this and it also came up in the exam. Although no code implementation of the algorithm was provided I found making a working copy very helpful in understanding it as well as getting some coding practice.</p>
<p>My inital version was in Java but I re-wrote it in Ruby as some of the abilities of the language regarding overriding of array methods made it slightly more terse.
<p>I list my code below to help people in the future as well as a number of resources that helped me</p>
<h3>Resources</h3>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Needleman-Wunsch_algorithm">The Wikipedia description of the algorithm</a></li>
<li><a href="http://snippets.dzone.com/posts/show/2199">A Ruby implementation of the Wikipedia sudo code</a></li>
<li><a href="http://ruby.brian-schroeder.de/editierdistanz/">Ruby and Python version of the Edit distance algorithm by Brian Schroeder</a> (the algorithm is similar to N-W)</li>
</ul>
<h3>Code</h3>
<p>
<pre class="viewsource"><code class="ruby">
# The cell object holds the value of an allignment
# and the location of the previous cell
class Cell
  @@valid_paths = [:ABOVE, :LEFT, :DIAG, nil]
  attr_reader :value, :path_from

  def initialize(value, path_from=nil)
    raise "Invalid path: '#{path_from}'"
      unless @@valid_paths.include?(path_from)
    @value = value
    @path_from = path_from
  end

  # This enables comparison between one cell to another.
  def <=>(other)
    self.value <=> other.value
  end
end</code></pre>
</p>
<p>
<pre class="viewsource"><code class="ruby">
# The grid object is a generic 2D array which can store any object.
# In this case it stores Cell objects and provides a numbers of
# functions to make traversing and accessing the grid cleaner
class Grid
  # 2D array initalised to nil
  def initialize(number_of_rows, number_of_cols)
    @grid = Array.new(number_of_rows){Array.new(number_of_cols){nil}}
  end

  # Allows use of [x,y] over [x][y]
  def [](row, column)
    @grid[row][column]
  end

  # Allows use of [x,y]=z over [x][y]=z
  def []=(row, column, value)
    @grid[row][column] = value
  end

  # Loops through each index to negate the need for
  # nested loops or blocks in other parts of the code
  def each_index
    @grid.each_with_index do |row, row_index|
      row.each_with_index do |col, column_index|
        yield row_index, column_index
      end
    end
  end

  # Returns each row array from the grid.
  # Not convinced how usefull this is
  def each
    @grid.each do |row|
      yield row
    end
  end

  # Very basic output of the grid
  def to_s
    @grid.map{ |row| row.join("\t") }.join("\n")
  end
end</code></pre>
</p>
<p>
<pre class="viewsource"><code class="ruby">
class NeedlemanMunch

  attr_reader :score, :allignment

  def initialize(reference_seq, comparison_seq, similarity_matrix, gap_penalty=-1)

    @ref_sq, @comp_sq = reference_seq , comparison_seq

    # Size of f_matrix
    @cols = @ref_sq.size+1
    @rows = @comp_sq.size+1

    # Allignment score params
    @gap_pen = gap_penalty
    @sim_matrix = similarity_matrix

    # Matrix creation
    @f_matrix = Grid.new(@rows, @cols)

    # Results
    @score = nil
    @allignment = nil

    # Calcultate the allignment and score
    # then trace the path
    calculate_f_matrix
    trace_path
  end

  def print_f_matrix
    output = ""
    @f_matrix.each do |row|
      line = ""
      row.each do |col|
        line << "#{col.value}:#{col.path_from}\t"
      end
      output << line << "\n"
    end
    output
  end

  def to_s
    puts @allignment
  end

private

  def calculate_f_matrix
    @f_matrix.each_index do |r, c|
      @f_matrix[r,c] =
        if    first_cel?(r,c) then Cell.new(0)
        elsif first_col?(r,c) then Cell.new(@f_matrix[r-1,c].value + @gap_pen)
        elsif first_row?(r,c) then Cell.new(@f_matrix[r,c-1].value + @gap_pen)
        else  calc_cell(r,c)
      end
    end
    @score = @f_matrix[@rows-1,@cols-1].value
  end

  # Three functions that determin the location
  # of a cell in the grid based on the coords
  def first_cel?(row, col) row==0 &#038;&#038; col==0 end
  def first_row?(row, col) row==0 &#038;&#038; col!=0 end
  def first_col?(row, col) row!=0 &#038;&#038; col==0 end

  # Calculate the value of the cell based on the 3 surrounding
  # cells, the dynamic programming bit.
  def calc_cell(row, col)
    [Cell.new(@f_matrix[row-1, col  ].value + @gap_pen, :ABOVE),
     Cell.new(@f_matrix[row,   col-1].value + @gap_pen, :LEFT),
     Cell.new(@f_matrix[row-1, col-1].value + match_score(row,col), :DIAG)].max
  end

  # Get the score for 2 bases from the similarity matrix
  def match_score(row, col)
    @sim_matrix[(@ref_sq[col-1].chr + @comp_sq[row-1].chr).upcase]
  end

  # Function: trace_path
  #
  # When the f_matrix for both sequences has been
  # calculated the allignment must be worked out.
  #
  def trace_path
    ref = ''
    seq = ''
    i = @comp_sq.length
    j = @ref_sq.length

    # This is currently a horrid case statement
    # that crawls back through the f_matrix looking
    # at each cells path_from attribute to determin
    # the allignment of the two sequences.
    #
    # This will determin one allignment, there may be
    # others!
    while (i>0 and j>0)
      current = @f_matrix[i,j]

      case current.path_from
      when :DIAG
        ref = @comp_sq[i-1].chr << ref
        seq = @ref_sq[j-1].chr << seq
        i -= 1
        j -= 1
      when :ABOVE
        ref = @comp_sq[i-1].chr + ref
        seq = '-' << seq
        i -= 1
      when :LEFT
        ref = '-' << ref
        seq = @ref_sq[j-1].chr + seq
        j-= 1
      else
        # Something has gone wrong
        raise UnknownPathError
      end
    end

    while (i>0)
      ref = @comp_sq[i-1].chr + ref
      seq = '-' << seq
      i-=1
    end

    while (j > 0)
      ref = '-' + ref
      seq = @ref_sq[j-1].chr << seq
      j -= 1
    end
    @allignment = [seq , ref]
  end
end</code></pre>
</p>
<p>
<pre class="viewsource"><code class="ruby">
class UnknownPathError &lt; StandardError; end</code></pre>
</p>
<p>
<pre class="viewsource"><code class="ruby">
if __FILE__ == $0

  example = 2

  # a few similarity matrix options for you to try
  if example == 1

    similarity_matrix = {
      'AA' => 10, 'AG' => -1, 'AC' => -3, 'AT' => -4,
      'GA' => -1, 'GG' =>  7, 'GC' => -5, 'GT' => -3,
      'CA' => -3, 'CG' => -5, 'CC' =>  9, 'CT' =>  0,
      'TA' => -4, 'TG' => -3, 'TC' =>  0, 'TT' =>  8
    }
    gap_penalty = -5
    a = 'GAATTCAGTTA'
    b = 'GGATCGA'

  elsif example == 2

    similarity_matrix = {
      'AA' =>  2, 'AG' => -1, 'AC' => -1, 'AT' => -1,
      'GA' => -1, 'GG' =>  2, 'GC' => -1, 'GT' => -1,
      'CA' => -1, 'CG' => -1, 'CC' =>  2, 'CT' => -1,
      'TA' => -1, 'TG' => -1, 'TC' => -1, 'TT' =>  2
    }
    gap_penalty = -1
    a = 'ACCGGTAT'
    b = 'ACCTATC'

  elsif example == 3

    similarity_matrix = {
      'AA' => 1, 'AG' => 0, 'AC' => 0, 'AT' => 0,
      'GA' => 0, 'GG' => 1, 'GC' => 0, 'GT' => 0,
      'CA' => 0, 'CG' => 0, 'CC' => 1, 'CT' => 0,
      'TA' => 0, 'TG' => 0, 'TC' => 0, 'TT' => 1
    }
    gap_penalty = 0
    a = 'AGACTAGTTAC'
    b = 'CGAGACGT'

  end

  nm = NeedlemanMunch.new(a, b, similarity_matrix, gap_penalty)
  puts nm.allignment
  puts nm.score
  puts nm.print_f_matrix
end</code></pre>
</p>
<p>Hope this helps someone even if it is just with some Ruby stuff.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/04/17/needleman-wunsch-algorithm-in-ruby/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Java Paint: Part 1</title>
		<link>http://moose56.com/blog/2008/04/15/java-paint-part-1/</link>
		<comments>http://moose56.com/blog/2008/04/15/java-paint-part-1/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 16:47:59 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Java]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/04/15/java-paint-part-1/</guid>
		<description><![CDATA[Java includes a load of libraries for creating applications with graphical user interfaces (GUI). One of the first things that a programming student is introduced to when learning about Java GUI development is drawing shapes onto a &#8220;canvas&#8221;. In this post I am going to talk about Java Swing objects that can help achieve this [...]]]></description>
			<content:encoded><![CDATA[<p>Java includes a load of libraries for creating applications with graphical user interfaces (GUI). One of the first things that a programming student is introduced to when learning about Java GUI development is drawing shapes onto a &#8220;canvas&#8221;. In this post I am going to talk about Java Swing objects that can help achieve this and begin to flesh out a little program that demonstrates some of the ideas that are covered.</p>
<p><span id="more-36"></span></p>
<p>This is a really good place to start for some intermediate Java topics and we will cover:</p>
<ul>
<li>Inheritance</li>
<li>Collections</li>
<li>Double buffering</li>
<li>Polymorphism</li>
</ul>
<p>So before we get going here is a little disclaimer; the following code is an example of how to go about implementing the requirements. It is not the only way or the right way. Second, I am not a Java guru, expert, oracle etc. I just like to tinker with stuff and thought I would share my findings to help others.</p>
<p>So lets begin, first up we need some form of specification. What do we actually want the program to do? I want the user to be able to select a type of shape (Circle or Square) and be able to click on the window of the application and draw the specified shape. I also want everything that the user draws to remain on the window when the window is moved or minimized. The window should be of a specific size and the user should not be able to maximize the window.</p>
<p>Did you get all that? so the fist task might be to dig all of the program features out of this brief paragraph. One thing that quickly becomes apparent however is the large amount of stuff that is not specified. This is a real pain when trying to design a program as the person that list the requirements will usually have a good idea of what they want it to do and will focus on that. This leaves a load of small decisions that still need to be made. In this example there are a few, take the shapes for example. The different types have been specified (square and circle), but the size, color and border are anyones guess. Also the method that the user has to select a specific shape is not specified.</p>
<p>As you can see even with a relatively small program the requirements can be large. For the sake of this little tutorial though I will finish with the specification as I want to focus on the way Java works and how to go about implementing this in Java. You will see how the specification is fulfilled and any other requirements decided further into the post.</p>
<p>As this is part 1 I am only going to implement a limited set of features. I have decided to split it as there are a number of things to take in and it would turn into the longest post in the world and become very boring and hard to follow if I crammed everything into one post. So in this post I will cover setting up a frame and a canvas, mouse interaction with the canvas, and drawing onto the canvas. I will then put this all together and produce a program that can draw a square.</p>
<h2>The Frame</h2>
<p>The following code is taken from <a href="http://java.sun.com/docs/books/tutorial/uiswing/components/toplevel.html">here</a> and is adapted for this example. The class MainFrame creates a window on the screen. This is the window that everything else will happen within. This is an important part of the application because it interacts with the underlying operating system and handles all the displaying stuff so we don&#8217;t have to worry about it.</p>
<p>The main method is used to get everything up and running by calling the createAndShowGUI() method which contains all the code to specify how we want our frame to look and behave.</p>
<p>
<pre class="viewsource"><code class="java">
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class MainFrame {

    private static void createAndShowGUI() {

        // Create and set up the window.
        JFrame frame = new JFrame("A Frame");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        // Set frame size
        frame.setSize ( 300, 350 );
        // prevent frame from maximising
        frame.setResizable (false);
        // center the frame on the screen
        frame.setLocationRelativeTo (null);
        // display it
        frame.setVisible(true);
    }

    public static void main(String[] args) {

        // Schedule a job for the event-dispatching thread:
        // creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}</code></pre>
</p>
<p>Compiling and running this code should give you an empty window in the center of your screen like the one pictured below.</p>
<p><img src="http://65.38.103.130/~moose56/blog/wp-content/uploads/2008/03/mainframe.jpg" alt="mainFrame.jpg" width="344" height="394" border="0"/></p>
<p>For a bit more info on what is going on in the main method check out this <a href="http://www.velocityreviews.com/forums/t133638-swing-and-threads.html">forum post</a>.</p>
<h2>The Canvas</h2>
<p>As well as the JFrame class Java Swing also provides a JPanel class. The JPanel is described as a lightweight container panel. Basically this means you can use it to contain other controls or other objects. What we are going to use it for in this example is the canvas which the user paints on. This will be where the majority of our applications logic will be held as the canvas will be responsible for listening for user input and the dealing with it should the users perform an action.</p>
<p>In order the get a picture of what this is imagine that the JFrame created in the previous example is a blank table and the JPanel is a clean piece of paper we are going to lay on top of it to draw on. The image below shows are frame with a JPanel covering the JFrames content pane. The content pane is the part of the JFrame that we are going to put are JPanel in. In the picture the JPanel has been colored white as by default its transparent.</p>
<p><img src="http://65.38.103.130/~moose56/blog/wp-content/uploads/2008/03/mainframe-with-panel.jpg" alt="mainFrame_with_panel.jpg" border="0" width="346" height="386" /></p>
<p>Because we need the JPanel to react to user input and we will also want to override a few of its method (you will just have to trust me on this for now). I am going to create a sub class of JPanel called CanvasPanel. This is were all are code will go.</p>
<p>In order to detect the user clicking onto the CanvasPanel we need to add a MouseAdapter and a MouseMotionAdapter to the CanvasPanel. This can be done in the constructor. A small demo version of the CanvasPanel class is shown below.</p>
<p>
<pre class="viewsource"><code class="java">
import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import javax.swing.JPanel;

class CanvasPanel extends JPanel {

    public CanvasPanel () {

        this.setBackground ( Color.WHITE );

        // add the input listners
        addMouseListener ( new MouseAdapter () {
            public void mousePressed ( MouseEvent e ) {
                System.out.println ("Mouse Pressed: X = " +
                    e.getX () + ", Y = " + e.getY () );
            }
        });

        addMouseMotionListener ( new MouseMotionAdapter () {
            public void mouseDragged ( MouseEvent e ) {
                System.out.println ("Mouse Dragged: X = " +
                    e.getX () + ", Y = " + e.getY () );
            }
        });
    }
}</code></pre>
</p>
<p>As you can see its pretty simple at the moment. All we have is a constructor that sets the background color to white and then adds are mouse input listners. Within these two listners I have stuck a couple of rudimenty console output lines to test that its all working. In order to get our MainFrame object using this fancy new CanvasPanel we need to update the createAndShowGUI method to this:</p>
<p>
<pre class="viewsource"><code class="java">
private static void createAndShowGUI () {
    // Create and set up the window.
    JFrame frame = new JFrame ( "A Frame" );
    frame.setDefaultCloseOperation ( JFrame.EXIT_ON_CLOSE );

    /*
     here is the new line
    */
    frame.getContentPane().add(new CanvasPanel());

    // Display the window.
    frame.setSize ( 300, 350 );
    // prevent frame from maximising
    frame.setResizable ( false );
    // center the frame on the screen
    frame.setLocationRelativeTo ( null );
    frame.setVisible ( true );
}</code></pre>
</p>
<p>So as discussed previously we a telling our MainFrame object to use our CanvasPanel by adding a new CanvasPanel object to the MainFrame&#8217;s ContentPane. Running this should display a frame that looks the same as before but when you click on it the X and Y coordinates are printed to the console.</p>
<h2>The Shapes</h2>
<p>So you want to add a shape? Well yes of course you do or you would not have bothered to read this far. A shape is an interesting thing in Java and I advise you to have dig around in the libraries to see what is already available. To cut a long story short Java already has a pretty good shape class hierarchy in the standard library. I know is a favorite topic for lecturers to use when talking about inheritance and its all in the Java library. The majority of objects that Java specifies for representing shapes impliment the Shape interface. In this iteration of the example we want to focus on the <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/awt/Rectangle.html">Rectangle</a> class.</p>
<p>Before we can start painting however we need to understand a few other things about the CanvasPanel object we created earler. What we need is to override the paintComponent within CanvasPanel. This method is called every time something is updated or changed like the location of the frame on the screen or another application&#8217;s window passes in front of our window. The paintComponent method is passed a <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/awt/Graphics.html">Graphics</a> object. A quick look at the documentation for this and we find a number of very usefull sounding methods like drawRect() and drawOval(). The Graphics object is the thing we need. Everything we want to display we draw on this object.</p>
<p>Now before we get going with our rectangle I need to talk about a few things. What I want to happen is that when a user clicks on the CanvasPanel a new square is drawn. If the user drags the mouse over the panel then a line of squares should be drawn. This raises a few questions. How do I remeber where all the squares are meant to be and how do I triger the paintComponent method myself?</p>
<p>First up I think we need a Square object to see what we are talking about:</p>
<p>
<pre class="viewsource"><code class="java">
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

public class Square extends Rectangle {
    int SIZE = 20;
    Color squareColor = Color.RED;

    public Square ( int x, int y ) {
        super();
        this.x = x;
        this.y = y;
        this.height = SIZE;
        this.width = SIZE;
    }

    public void paintMe ( Graphics g ) {
        g.setColor ( squareColor );
        g.fillRect ( x, y, width, height );
    }
}</code></pre>
</p>
<p>I have extended the Java Rectangle class and have added a special method called paintMe to my Square which takes a Graphics objects and draws a square onto it. We now have to add a little bit to the CanvasPanel in order for it to be able to store the Square objects and pass a Graphics object to them. First off I need an array to hold all of the Square objects that are created by the user. Initially you may be thinking easy, declare an Array, no problem. Thinking about it though this is not a good idea mainly because we do not know how big the array needs to be. The user may draw 1 Square or 1000 so we need a container object that can handle this. Introducing the <a href="http://java.sun.com/j2se/1.5.0/docs/api/java/util/ArrayList.html">ArrayList</a>. With an array list we don&#8217;t need do declare a size as it has the ability to shrink and grow depending on what is added or removed from it.</p>
<p>So every time we detect mouse activity on the CanvasPanel we create a new shape and add it to the ArrayList. Then we call the repaint() method which trigers the repainting of the Canvas and draws the new shape. This is done by overriding the paintComponent() method and looping through the ArrayList and calling the paintMe() method of each shape. All of these modifications are shown in the updated version of the CanvasPanel class below:</p>
<p>
<pre class="viewsource"><code class="java">
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;
import java.util.ArrayList;
import javax.swing.JPanel;

class CanvasPanel extends JPanel {

    // declare arraylist to store shapes
    ArrayList&lt;Square&gt; s = new ArrayList&lt;Square&gt;();

    public CanvasPanel () {

        this.setBackground ( Color.WHITE );

        // add the input listners
        addMouseListener ( new MouseAdapter () {
            public void mousePressed ( MouseEvent e ) {
                newSquare ( e.getX (), e.getY () );
            }
        } );

        addMouseMotionListener ( new MouseMotionAdapter () {
            public void mouseDragged ( MouseEvent e ) {
                newSquare ( e.getX (), e.getY () );
            }
        } );
    }

    private void newSquare ( int x, int y ) {

        // add new square to list
        s.add(new Square( x, y ));

        // repaint screen
        repaint ();
    }

    public void paintComponent ( Graphics g ) {
        super.paintComponent ( g );

        // loop through each square
        for(Square tmp:s)
            // paint it
            tmp.paintMe(g);
    }
}</code></pre>
</p>
<p>As you can see every time input is detected a call to newSquare() is made with the X and Y of the input. A new Square is created and added to the ArrayList and then a call to repaint() is made. This invokes the paintComponent() method which loops through all the shapes and passes them the Graphics object for each Square to paint its self onto.</p>
<h3>Tidy up</h3>
<p>If you run the program now you should be able to draw squares onto the canvas, but there is one small issue in that the square is drawn from top left corner. I want the mouse pointer to be in the middle of the square when it is drawn. To do this we simple change the way the Square object interprets the X and Y values that it&#8217;s given by offsetting them by half of the squares length so that the constructer now looks like this:</p>
<p>
<pre class="viewsource"><code class="java">
public Square ( int x, int y ) {
    super();
    this.x = x - (SIZE/2);
    this.y = y - (SIZE/2);
    this.height = SIZE;
    this.width = SIZE;
}</code></pre>
</p>
<p>Now run the program and the squares are nicely centered on the pointer.
<p><img src="http://65.38.103.130/~moose56/blog/wp-content/uploads/2008/04/squares.jpg" alt="squares.jpg" border="0" width="352" height="392" /></p>
<h2>Thats a wrap</h2>
<p>That&#8217;s it for part 1. In the next part I will cover double buffering.</p>
<h2>Resources</h2>
<p>You can download the source files for part 1 <a href="http://65.38.103.130/~moose56/blog/wp-content/uploads/2008/04/part1.zip" title="part1.zip">here</a>.</p>
<p>Here are some of the books and web pages that I found really useful in trying to understand this topic:</p>
<h3>Books</h3>
<ul>
<li><a href="http://www.amazon.co.uk/Core-Java-Fundamentals-v/dp/0131482025/">Core Java</a> (newer version available)</li>
<li><a href="http://www.amazon.co.uk/Head-First-Java/dp/0596009208/">Head First Java</a></li>
<li><a href="http://www.amazon.co.uk/Killer-Game-Programming-Java-Book/dp/0596007302">Killer Game Programming in Java</a></li>
</ul>
<h3>Web Pages</h3>
<ul>
<li><a href="http://java.sun.com/products/jfc/tsc/articles/painting/">Painting in AWT and Swing</a></li>
<li><a href="http://java.sun.com/docs/books/tutorial/uiswing/painting/index.html">Performing Custom Painting</a></li>
<li><a href="http://java.sun.com/docs/books/tutorial/uiswing/components/index.html">Using Swing Components</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/04/15/java-paint-part-1/feed/</wfw:commentRss>
		</item>
		<item>
		<title>This is very depressing!</title>
		<link>http://moose56.com/blog/2008/04/15/who-will-rid-me-of-this-turbulent-browser/</link>
		<comments>http://moose56.com/blog/2008/04/15/who-will-rid-me-of-this-turbulent-browser/#comments</comments>
		<pubDate>Tue, 15 Apr 2008 15:19:59 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[IE]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/04/15/who-will-rid-me-of-this-turbulent-browser/</guid>
		<description><![CDATA[Who will rid me of this turbulent browser?


When will IE6 die a death? I know there are a few people out there who say quit complaining and live with it, but I really am fed up with having to accommodate it.
End of rant.
]]></description>
			<content:encoded><![CDATA[<p>Who will rid me of this turbulent browser?</p>
<p><span id="more-33"></span></p>
<p><img src="http://65.38.103.130/~moose56/blog/wp-content/uploads/2008/04/browsersie.jpg" alt="ie.jpg" border="0" width="199" height="150" /></p>
<p>When will IE6 die a death? I know there are a few people out there who say quit complaining and live with it, but I really am fed up with having to accommodate it.</p>
<p>End of rant.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/04/15/who-will-rid-me-of-this-turbulent-browser/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Have you been fireballed?</title>
		<link>http://moose56.com/blog/2008/03/14/have-you-been-fireballed/</link>
		<comments>http://moose56.com/blog/2008/03/14/have-you-been-fireballed/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 00:17:16 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/03/14/have-you-been-fireballed/</guid>
		<description><![CDATA[Daring Fireball the excellent blog by John Gruber occasionally brings sites to their knees in a digg-esk manner if he deems them worthy of a link.
From this day on, the effect will be known as being FIREBALLED. (If this has already been done or has an even more witty name its my bad!)
Update: John already [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://daringfireball.net">Daring Fireball</a> the excellent blog by John Gruber occasionally brings sites to their knees in a digg-esk manner if he deems them worthy of a link.</p>
<p>From this day on, the effect will be known as being <strong>FIREBALLED</strong>. <small>(If this has already been done or has an even more witty name its my bad!)</small></p>
<p>Update: John already uses it, Doh! Oh well back to the drawing board.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/03/14/have-you-been-fireballed/feed/</wfw:commentRss>
		</item>
		<item>
		<title>BBC iPlayer on the Mac</title>
		<link>http://moose56.com/blog/2008/02/19/bbc-iplayer-on-the-mac/</link>
		<comments>http://moose56.com/blog/2008/02/19/bbc-iplayer-on-the-mac/#comments</comments>
		<pubDate>Tue, 19 Feb 2008 11:06:33 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/02/19/bbc-iplayer-on-the-mac/</guid>
		<description><![CDATA[Recently the BBC have launched the iPlayer. This is a service which allows people to watch TV programs or listen to radio shows from that last 7 days again on their computer as many times as they like. That is unless they have a Mac.

This is because the DRM they use is a Microsoft thing [...]]]></description>
			<content:encoded><![CDATA[<p>Recently the BBC have launched the iPlayer. This is a service which allows people to watch TV programs or listen to radio shows from that last 7 days again on their computer as many times as they like. That is unless they have a Mac.</p>
<p><span id="more-28"></span></p>
<p>This is because the DRM they use is a Microsoft thing and so will not work on the OS X platform. I suppose this is not such a big deal because if you are running a modern Mac you may have a copy of windows installed and you can use that to run the iPlayer. The BBC have also made the programs available to stream online so that any flash enabled browser can show them.</p>
<p>So what&#8217;s the big issue, am I just a mac fanboy crying because they have ignored my beloved computer. No! I do however find it amusing that the BBC decided to rip of the &#8216;i&#8217; naming convention for their player and then not fully support the mac platform.</p>
<h3>A Solution?</h3>
<p>In setting up this system the BBC required some way of delivering content to computer users and limiting the length of time that the file was available or usable. They chose the Microsoft DRM method like Channel 4 and its 4 on demand service (another non mac service). What I think might have been a better option was to use iTunes. This is an application that I would guess is on the majority of macs even if the owners don&#8217;t use it. It also has a built in content delivery system and pretty good DRM. Content can also be viewed on iPods, iPhones and Apple TV with no extra work. It also plays nicely with Windows.</p>
<p>Now this nearly came to fruition yesterday when BBC World programs became available for purchase on the iTunes music store. I say nearly because only a handful of shows are available and you have to pay for them.</p>
<p>Now I guess that it is not as strait forward as it sounds to get Apple to put a load of video content on iTunes and then give it away for free (even for a limited period of 7 days a program). Their will be costs and by implementing their own system the BBC can keep a tighter grip on things. I just feel that they missed a great opportunity.</p>
<p>Mac users are not alone in this either because the iPlayer does not work on Linux and surprisingly Vista (yes the Microsoft Windows one!). It is not all bad news however because the BBC has been ordered to make the iPlayer multi platform and that the flash streaming alternative that they currently offer is not good enough.</p>
<p>Should be interesting to see how they finally sort this out.</p>
<h3>Update</h3>
<p>An article on the Register <a href="http://www.theregister.co.uk/2008/02/20/iplayer_flash_iphone/">here</a> indicates that the BBC will soon make the iPlayer available on the iPhone and the iPod Touch. This means they will have to provide another method of serving the programs rather that streaming flash video because neither of these devices support flash.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/02/19/bbc-iplayer-on-the-mac/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Mootools and its documentation</title>
		<link>http://moose56.com/blog/2008/02/14/a-very-unproductive-day-with-mootools-and-its-documentation/</link>
		<comments>http://moose56.com/blog/2008/02/14/a-very-unproductive-day-with-mootools-and-its-documentation/#comments</comments>
		<pubDate>Thu, 14 Feb 2008 19:23:39 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Javascript]]></category>

		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/02/14/a-very-unproductive-day-with-mootools-and-its-documentation/</guid>
		<description><![CDATA[So today I was trying to update my moose56.com homepage and thought I would add some javascript effects using the Mootools library.

I have used the Script.aculo.us library before, but I thought I would try out Mootools as it has a really nice object orientated design.
Now I don&#8217;t know if its just me, but I can&#8217;t [...]]]></description>
			<content:encoded><![CDATA[<p>So today I was trying to update my moose56.com homepage and thought I would add some javascript effects using the Mootools library.</p>
<p><span id="more-19"></span></p>
<p>I have used the <a href="http://script.aculo.us/">Script.aculo.us</a> library before, but I thought I would try out <a href="http://mootools.net/">Mootools</a> as it has a really nice object orientated design.</p>
<p>Now I don&#8217;t know if its just me, but I can&#8217;t make any sense of the documentation to the extent that I can only get things to work by following the examples which is fine until I can&#8217;t fine an example for what I need.</p>
<p>Where the documentations messes me up is that when I create an object I want to know its parameters and its methods. Now it does tell you all of this, but I really can&#8217;t see it clearly. If you are used to the Java or Ruby or any other programming documentation you will be very confused.</p>
<p>Anyway, hopefully I will figure it out eventually, maybe I am just a douche.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/02/14/a-very-unproductive-day-with-mootools-and-its-documentation/feed/</wfw:commentRss>
		</item>
		<item>
		<title>Leopard 10.5.2 update pain</title>
		<link>http://moose56.com/blog/2008/02/13/leopard-1052-update-pain/</link>
		<comments>http://moose56.com/blog/2008/02/13/leopard-1052-update-pain/#comments</comments>
		<pubDate>Wed, 13 Feb 2008 11:53:33 +0000</pubDate>
		<dc:creator>moose56</dc:creator>
		
		<category><![CDATA[Apple]]></category>

		<guid isPermaLink="false">http://moose56.com/blog/2008/02/13/leopard-1052-update-pain/</guid>
		<description><![CDATA[Well it did arrive after all. My update was not totally strait forward however so just incase it happens to anyone else here is how I dealt with it.

The problem started because it was a huge update, my PowerBook G4 needed 346MBs! I am currently using a BTOpenzone connection which cuts out after a period [...]]]></description>
			<content:encoded><![CDATA[<p>Well it did arrive after all. My update was not totally strait forward however so just incase it happens to anyone else here is how I dealt with it.</p>
<p><span id="more-18"></span></p>
<p>The problem started because it was a huge update, my PowerBook G4 needed 346MBs! I am currently using a BTOpenzone connection which cuts out after a period of inactivity and is really slow. So the download cut out a number of times before it managed to get all of the update.</p>
<p>Eventually however the software update tool told me that it was finished downloading and did I want to instal it? I clicked yes and off it went.</p>
<p>Thats as far as it got. According to the update progress bar it was configuring the update for about 2.5 hours. I assume that the update package must have been corrupted from the download problems I had.</p>
<p>I went back into the Software update tool to repeat the download. The problem is though that there seems to de no way of telling the program to get rid of the old update file and download a new copy. I tried a number of things and a few googles for any tips, but no luck.</p.>
<p>In the end I downloaded the package manually from the Apple <a href="http://www.apple.com/support/downloads/">updates</a> page on their website and instal it that way. It worked fine that time.</p>
]]></content:encoded>
			<wfw:commentRss>http://moose56.com/blog/2008/02/13/leopard-1052-update-pain/feed/</wfw:commentRss>
		</item>
	</channel>
</rss>
