Whyday 2011
Happy Whyday! We’re doing a last minute contest that will end next Monday. This weekend, put your best practices away and celebrate Why’s contributions to our unique culture. Create something wonderful. If you’re still looking for something to build, check out some of the example ideas on the Whyday website.
Go wild! Put your work in a Gist and include a README explaining what it does and how it works. Again, you only have until Monday, so get started as soon as you can!
Happy hacking!
Prize
This week’s winner will receive a code for $25 worth of credit for the 6sync hosting platform!
-
Finished in 1st place with a final score of 4.0/5. (View the Gist)foxes
#!/usr/bin/env ruby require File.join(File.dirname(__FILE__), 'foxes.rb') unless ARGV.length == 1 $stderr.puts "Usage: #{$0} input.png" exit 1 end begin input = File.open(ARGV[0], 'r') foxes = Foxes.new input rescue $stderr.puts "Argh! #{$!}" exit 1 end begin foxes.execute rescue Foxes::NotFoxified $stderr.puts "#{ARGV[0]} is not yet foxified!" exit 1 endfoxify#!/usr/bin/env ruby require File.join(File.dirname(__FILE__), 'foxes.rb') unless ARGV.length == 3 $stderr.puts "Usage: #{$0} input.png code.rb output.png" exit 1 end begin modes = %w{r r w+} input, code, output = *ARGV.map { |a| File.open(a, modes.shift) } foxes = Foxes.new input foxes.foxify code foxes.png output rescue $stderr.puts "Argh! #{$!}" exit 1 endREADME.mdFoxes
Adds Ruby code to a PNG file. This allows foxes to run a PNG file as Ruby code, while keeping the PNG file intact and viewable. It basically just adds the "ruby" ancillary FourCC to the PNG spec and throws the code in.
If you read the PNG spec, you'll notice PNG is just like bacon.
The foxes are licensed by why the lucky stiff under the CC BY-SA 2.0 license, and are part of why's (poignant) guide to Ruby.
Usage
$ ./foxify foxes.png bacon.rb output.png $ ./foxes output.png Chunky bacon!! Chunky bacon!!foxes.png
bacon.rb2.times do puts "Chunky bacon!!" end
foxes.rbView full entryrequire 'zlib' class Foxes PNG_HEADER = "\x89PNG\r\n\x1A\n" class NotFoxified < RuntimeError; end # Foxes accepts a File pointing to a PNG image. def initialize(file) @file = file @file.seek 0 if @file.read(8) != PNG_HEADER raise ArgumentError, 'Not a PNG file!' end # Simple way to read the PNG file. @chunks = {} while !@file.eof? length, type = *@file.read(8).unpack('NA*') data = @file.read length crc = @file.read(4).unpack('N').first if Zlib::crc32(type + data) != crc raise RuntimeError, "CRC checksum error on #{type}" end @chunks[type] ||= [] @chunks[type] << data end end # Adds to code in the file to the PNG file. def foxify(file) @chunks['ruby'] = [Zlib::Deflate.deflate(file.read)] end # Executes the Ruby code in the PNG file. def execute raise NotFoxified unless @chunks['ruby'] Object.class_eval(Zlib::Inflate.inflate(@chunks['ruby'].join), @file.path) end # Writes the PNG data to file. def png(file) file.write PNG_HEADER # Make sure IEND is actually at the end (Ruby 1.9). iend = @chunks.delete 'IEND' @chunks['IEND'] = iend @chunks.each do |type, data| data.each do |data_part| file.write [data_part.length, type].pack('NA*') file.write data_part file.write [Zlib::crc32(type + data_part)].pack('N') end end end end
-
Finished in 2nd place with a final score of 3.4/5. (View the Gist)README.md
Binary Clock
A simple and concise (474 bytes minified, 1KB normal) binary clock in Shoes.
Compatible with Shoes 2 (Raisins) and 3 (Policeman).
Design inspired by The Game of Life on the ShoeBox.
capture.png
binary_clock.rbmargin, space, width = 30, 20, 24 with_help = true Shoes.app :title => "Binary Clock", :width => 6*width+5*space+2*margin, :height => 3*width+2*space+2*margin, :resizable => false do on, off = rgb(0, 0, 255, 0.45), gray(0,0) if Shoes::VERSION == 'Policeman' background rgb(6, 6, 89) else background gradient(rgb(0, 0, 128), rgb(12, 12, 50)) end stroke gray(1.0, 0.5) strokewidth 2.5 fill off lights = Array.new(3) { |i| Array.new(6) { |j| next if i == 0 and j == 5 # The first light is not needed for hours x, y = margin + (5-j)*(space+width), margin + i*(space+width) para 2**j, :size => 'xx-small', :left => x+20, :top => y+20, :stroke => gray if with_help oval x, y, width } } and lights.first.compact! every 1 do now = Time.now [now.hour, now.min, now.sec].zip(lights) { |v, row| row.each_with_index { |light, i| light.style :fill => (v[i] == 1 ? on : off) } } end end
binary_clock.minified.rbView full entryShoes.app(:title=>"Binary Clock",:width=>304,:height=>172,:resizable=>false){ on,off=rgb(0,0,255,0.45),gray(0,0);background rgb(6,6,89) stroke gray(1.0,0.5);strokewidth 2.5;fill off lights=Array.new(3){|i|Array.new(6){|j|next if j-i==5;x,y=250-j*44,30+i*44 para 2**j,:size=>'xx-small',:left=>x+20,:top=>y+20,:stroke=>gray;oval x,y,24}} lights[0].pop;every(1){now=Time.now;[now.hour,now.min,now.sec].zip(lights){|v,r| r.each_with_index{|l,j|l.style:fill=>(v[j]==1?on:off)}}}}
-
Finished in 3rd place with a final score of 2.8/5. (View the Gist)README.md
IRB implemented in single line of ruby code:
$ ruby i.rb
> a = "Simple"
=> Simple
> b = "IRB"
=> IRB
> a + ' ' + b
=> Simple IRB
> IO.read($0)
=> until(puts(%Q[=> #{eval("#{print('> ')}#{gets.chomp}")}])) do end
> exit
$
No exception handling, no line navigation, no history, no multi-line support :-(
i.rbView full entryuntil(puts(%Q[=> #{eval("#{print('> ')}#{gets.chomp}")}])) do end