# LSRC Name Picker (#129)

**URL:** <https://www.ruby-forum.com/t/lsrc-name-picker-129/108631>\
**Category:** Ruby\
**Created:** [July 5, 2007, 2:53pm UTC](https://www.ruby-forum.com/t/lsrc-name-picker-129/108631 "2007-07-05T14:53:15Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![bbazzarrakk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/47e85d/32.png) [@bbazzarrakk](https://www.ruby-forum.com/u/bbazzarrakk)\
**Post date:** [July 5, 2007, 2:53pm UTC](https://www.ruby-forum.com/t/lsrc-name-picker-129/108631/1 "2007-07-05T14:53:15Z")

</div>

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 M. 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 P.'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 P.: removed_email_address@domain.invalid"
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[i] = ("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…

---

<div class="post-metadata">

**Author:** ![bbazzarrakk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/47e85d/32.png) [@bbazzarrakk](https://www.ruby-forum.com/u/bbazzarrakk)\
**Post date:** [July 5, 2007, 4:05pm UTC](https://www.ruby-forum.com/t/lsrc-name-picker-129/108631/2 "2007-07-05T16:05:26Z")

</div>

Ruby Q. wrote:

> I’m going to look at Carl P.'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.-

---

<div class="post-metadata">

**Author:** ![bbazzarrakk](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/b/47e85d/32.png) [@bbazzarrakk](https://www.ruby-forum.com/u/bbazzarrakk)\
**Post date:** [July 5, 2007, 11:22pm UTC](https://www.ruby-forum.com/t/lsrc-name-picker-129/108631/3 "2007-07-05T23:22:28Z")

</div>

Sorry, I just didn’t have enough time to get this done until now. See  
below  
for an explanation of my solution. Quick summary:

- code at [http://rubyquiz.com/hosted\_solutions/129/gregory/129.zip](http://rubyquiz.com/hosted_solutions/129/gregory/129.zip)  
(thanks,  
James!)
- requires ruby-opengl and RMagick gems
- maintains state in a simple file
- when running, space bar chooses a name or switches back to the idle  
screen and the escape key quits (and saves)

On Thu, Jul 05, 2007 at 09:51:11PM +0900, Ruby Q. wrote:

> 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 M. guy though.  
> Weird.

Heh. I was using both names for my testing as well, and they appear in  
my  
included sample list.txt file.

> 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 went for gratuitous in my solution, largely because I used it as an  
excuse to brush up on my long-languishing OpenGL skills. It depends on  
the  
ruby-opengl gem for 3D rendering and the RMagick gem for dynamically  
generated textures. Anyone planning on working with the ruby-opengl  
library, especially anyone planning on creating or loading textures from  
disk, may find it helpful to look through the framework I set up and the  
texture code.

The actual name picking is dead simple, and all it does to maintain  
state  
is to save the list of names, minus those which were chosen, to the same  
file it got as input when quitting. The main.rb file should be run and  
passed a filename as its only argument. The file should contain the list  
from which names will be chosen, one name per line. Note that the list  
file  
must use UTF8 encoding; RMagick can handle UTF8-encoded non-ASCII  
characters, though you may need to change the font family in  
magick\_texture.rb (see below) to get some of the more interesting  
characters.

The zip file (see above for URL) includes the following source files:

main.rb  
run the program as: ruby main.rb list.txt  
render\_layer.rb  
the base framework for dealing with OpenGL  
name\_file.rb  
the part that actually picks names out of the hat  
interpolate.rb  
handle simple one-shot and repeating animation  
rotate\_anim.rb  
wrap rendering in an animated rotation  
scale\_anim.rb  
wrap rendering in an animated scaling  
magick\_texture.rb  
dynamically generate an OpenGL texture with RMagick  
string\_texture.rb  
use MagicTexture to generate a string as a texture  
letter\_ball.rb  
render a letter (via StringTexture) texture-mapped onto a sphere;  
the code for the sphere and its texture coordinates was modified  
and ported from code found at  
[http://ozviz.wasp.uwa.edu.au/~pbourke/texture\_colour/spheremap/](http://ozviz.wasp.uwa.edu.au/~pbourke/texture_colour/spheremap/)  
reveal\_ball\_string.rb  
uses animations and LetterBall to reveal the chosen name  
render\_text.rb  
render letters with lines (rather than textures or polygons)  
lone\_star.rb  
displays the spinning letters of Lone Star Ruby Conf and uses  
RenderText to do so

Also included is a list.txt file, with one accented character to show  
that  
it works. I’ve only tested this on MacOS X, but I have every reason to  
believe that it will work well anywhere as long as ruby-opengl and  
RMagick  
are properly installed.

–Greg
