[SUMMARY] LSRC Name Picker (#129)

Discussion in 'Ruby' started by Ruby Quiz, Jul 5, 2007.

  1. Ruby Quiz

    Ruby Quiz Guest

    Everyone who had my name in their example prize list deserves extra credit. I
    won millions in cash and prizes as I examined the solutions this week. I can't
    wait until the checks start coming in the mail.

    I was occasionally beat out by some Yukihiro Matsumoto guy though. Weird.

    As usual, there were a lot of great solutions. We had everything from clever
    ASCII art to full GUI applications. There were also a lot of clever ways to
    taunt the attendees before a name is picked.

    I'm going to look at Carl Porth's solution because the code is compact and
    pretty approachable. I also laughed out-loud when I ran his code. Do play
    around with the other solutions though or you will be missing a lot of fun
    applications and code.

    Carl's solution is a Camping application. If you aren't too familiar with
    Camping, as I wasn't, Carl's solution makes a nice gentle introduction. Here's
    how it begins:

    #!/usr/bin/env ruby -wKU

    require "rubygems"
    require "camping"
    require "RMagick"

    module Enumerable
    def rand
    entries[Kernel.rand(entries.size)]
    end
    end

    Camping.goes :NamePicker

    # ...

    First we see that Carl loads Camping and RMagick as his weapons of choice. Then
    we have a simple helper method for choosing a random member of some Enumerable
    object.

    The final line is how you always begin a Camping application. It tells the
    framework to create a namespace for your application in a module called
    NamePicker. The code then goes on to fill in that namespace:

    # ...

    module NamePicker::Controllers
    class Index < R '/'
    def get
    render :index
    end
    end

    class Stylesheet < R '/style.css'
    def get
    @headers['Content-Type'] = 'text/css'
    File.read(__FILE__).gsub(/.*__END__/m, '')
    end
    end

    class StaticImage < R '/images/(.*)'
    def get(static_name)
    @headers['Content-Type'] = "image/jpg"
    @headers['X-Sendfile'] = "#{current_dir}/images/#{static_name}"
    end
    end

    class PickedNameImage < R '/picked_names/(.*?)\.gif'
    def get(name)
    make_image(name)
    @headers['Content-Type'] = "image/gif"
    @headers['X-Sendfile'] = "#{current_dir}/picked_names/#{name}.gif"
    end
    end

    class Page < R '/(\w+)'
    def get(page_name)
    render page_name
    end
    end
    end

    # ...

    These are the controllers for this application. They manage all of the traffic
    through the pages.

    The main point of interest in these is Camping's R() routing method. As you can
    see, it builds classes these controllers can inherit from. The regular
    expression you pass to it are the URLs that controller will service.

    The first controller covers index requests. The next two serve up static file
    and image content. PickedNameImage also serves images, but these are
    dynamically generated from a selected name using the make_image() helper method.
    Both types of images are handled by Camping just by the code setting some
    headers about the file to send. The final controller handles all other page
    requests.

    You can see that the Stylesheet controller makes use of some content embedded
    later in the file. It looks like this:

    # ...

    __END__

    body {
    background-color:black;
    text-align:center;
    font-size:30px;
    font-family:impact;
    color:red;
    letter-spacing:3px;
    }
    a { color:red }
    p { margin:80px }

    Now, unlike Rails, Camping views are just simple Ruby methods. Here's a look at
    those:

    # ...

    module NamePicker::Views
    def layout
    html do
    head do
    title "LOLPIXNAMES"
    link :href=> R(Stylesheet), :rel=>'stylesheet', :type=>'text/css'
    end
    body { self << yield }
    end
    end

    def index
    p { img :src => R(StaticImage, "icanpixname.jpg") }
    p { a "PIX A NAME", :href => '/pick_name' }
    end

    def pick_name
    all_names = open('names').readlines.map do |e|
    e.gsub(/[^a-zA-Z 0-9]/,'')
    end.reject { |e| e.empty? }

    picked_names = Dir["picked_names/*.gif"].map do |e|
    e.sub(/picked_names\/(.*?)\.gif$/,'\\1')
    end

    unpicked_names = all_names - picked_names
    name = unpicked_names.rand

    p do
    img :src => R(StaticImage, "ipixedname.jpg")
    br
    img :src => "picked_names/#{name}.gif"
    end
    p { a "I CAN PIX YR NAME AGAIN", :href => '/pick_name' }
    p { a "KTHXBYE", :href => '/credits' }
    end

    def credits
    h1 "CREDITZ"
    ul do
    li "http://flickr.com/photos/mag3737/296800129/"
    li "http://flickr.com/photos/brian-fitzgerald/608882248/"
    li "http://www.ocf.berkeley.edu/~gordeon/fonts.html"
    end
    p "Carl Porth: "
    end
    end

    # ...

    The point of interest in these methods is the appearance of Markaby, which is
    used to build HTML pages. Markaby is very similar to Builder, if you are
    familiar with that library, save that it doesn't need the explicit receiver.

    The only action that does some work here is pick_name(). It pulls in names from
    a name file, cross-checks those against what it has previously generated, and
    selects an unpicked name. Then it renders some HTML to show the selection.

    All we have left at this point are the helper methods:

    # ...

    module NamePicker::Helpers
    def make_image(text)
    gif = Magick::ImageList.new

    decode_name(text.upcase).each do |frame_text|
    frame = Magick::Image.new(30*frame_text.size, 52) do
    self.background_color = 'black'
    end

    Magick::Draw.new.annotate(frame, 0,0,0,0, frame_text) do
    self.font = 'Impact.ttf'
    self.pointsize = 50
    self.fill = 'white'
    self.stroke = 'black'
    self.stroke_width = 2
    self.gravity = Magick::CenterGravity
    end

    gif << frame
    end

    gif.delay = 15
    gif.iterations = 1

    gif.write("picked_names/#{text}.gif")
    end

    def encode_name(name, indexes=[])
    return [] if name.size == indexes.size + 1

    new_index = ((0...name.size).to_a - indexes).rand
    random_words(name, indexes) + encode_name(name, indexes << new_index)
    end

    def random_words(word, indexes_to_replace,
    number_of_words=indexes_to_replace.size)
    (0..number_of_words).to_a.map do
    new_word = word.dup
    indexes_to_replace.each { |i| new_word = ("A".."Z").rand }
    new_word
    end
    end

    def decode_name(name)
    encode_name(name).reverse
    end

    def current_dir
    File.expand_path(File.dirname(__FILE__))
    end
    end

    All of these methods work together to generate the selected name image shown
    when the application runs. The process builds an animated Gif image where the
    frames show the name in various degrees of being scrambled. As the animation
    plays out, the name unscrambles to reveal a winner.

    The make_image() method does the heavy lifting by iterating over variations of
    the name and using RMagick to build frames for them. The other methods scramble
    the name by replacing certain indices with random letters.

    That's about all there is to Carl's code, save some humor. Fire it up in your
    browser to make sure you get a taste of that. "KTHXBYE!"

    My thanks to all who solved the quiz, made me laugh, and, most importantly, to
    those who awarded me prizes.

    Tomorrow we have a problem using a c__ss_c g_me...
     
    Ruby Quiz, Jul 5, 2007
    #1
    1. Advertising

  2. Ruby Quiz wrote:
    > I'm going to look at Carl Porth's solution because the code is compact and
    > pretty approachable. I also laughed out-loud when I ran his code. Do play
    > around with the other solutions though or you will be missing a lot of fun
    > applications and code.
    >
    > Carl's solution is a Camping application. If you aren't too familiar with
    > Camping, as I wasn't, Carl's solution makes a nice gentle introduction. Here's
    > how it begins:
    >

    Apart from being such a fun solution and being picked by you James I
    would give Carl extra credit because this is one of the best
    intros/examples to Camping you can find on the Net.
    _why you should pick and edit this summary and post it as an example in
    the Camping wiki.
    Cheers,
    V.-

    --
    http://www.braveworld.net/riva
     
    Vassilis Rizopoulos, Jul 5, 2007
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Charles A. Lackman

    Date Time Picker

    Charles A. Lackman, Nov 24, 2004, in forum: ASP .Net
    Replies:
    4
    Views:
    1,068
  2. Robert

    JScript time picker

    Robert, Jul 7, 2003, in forum: ASP .Net
    Replies:
    1
    Views:
    950
    Eliyahu Goldin
    Jul 7, 2003
  3. leov
    Replies:
    18
    Views:
    1,210
    Stefan Ram
    Feb 28, 2006
  4. Ruby Quiz

    [QUIZ] LSRC Name Picker (#129)

    Ruby Quiz, Jun 24, 2007, in forum: Ruby
    Replies:
    42
    Views:
    446
    Gregory Brown
    Jul 4, 2007
  5. Ari Brown

    LSRC Name Picker

    Ari Brown, Jul 3, 2007, in forum: Ruby
    Replies:
    4
    Views:
    130
    James Edward Gray II
    Jul 3, 2007
Loading...

Share This Page