Ruby Poker

 
# Hand is expected to in the format of [ '2C', '3C', '4C', '5C', '6C' ]
 
module Poker
  class Hand
    include Comparable
 
    attr_reader :hand
 
    @@ranks = {
      :royal_flush => 9,
      :straight_flush => 8,
      :four_of_a_kind => 7,
      :full_house => 6,
      :flush => 5,
      :straight => 4,
      :three_of_a_kind => 3,
      :two_pair => 2,
      :pair => 1,
      :high_card => 0
    }
 
    def initialize(hand)
      @hand = hand
    end
 
    def <=>(other)
      self_rank = @@ranks[rank]
      other_rank = @@ranks[other.rank]
 
      if self_rank == @@ranks[:high_card] && other_rank == @@ranks[:high_card]
        card_value(high_card) <=> card_value(other.high_card)
      else
        @@ranks[self.rank] <=> @@ranks[other.rank]
      end
    end
 
    def rank
      return :royal_flush if is_royal? && is_flush?
      return :straight_flush if is_straight? && is_flush?
      return :four_of_a_kind if is_four_of_a_kind?
      return :full_house if is_full_house?
      return :flush if is_flush?
      return :straight if is_straight?
      return :three_of_a_kind if is_three_of_a_kind?
      return :two_pair if is_two_pair?
      return :pair if is_pair?
      return :high_card
    end
 
    def high_card
      @hand.sort { |x,y| card_value(x) <=> card_value(y) }.last
    end
 
    def low_card
      @hand.sort { |x,y| card_value(x) <=> card_value(y) }.first
    end
 
    def is_royal?
      card_value(low_card) == 10 && card_value(high_card) == 14 && is_straight?
    end
 
    def is_four_of_a_kind?
      matches = value_matches(@hand)
      matches.size == 4 && matches.collect { |c| card_value(c) }.uniq!.size == 1
    end
 
    def is_full_house?
      matches = value_matches(hand)
      matches.size == 5 && matches.collect { |c| card_value(c) }.uniq!.size == 2
    end
 
    def is_flush?
      @hand.collect { |c| card_suit(c) }.uniq!.size == 1
    end
 
    def is_straight?
      (card_value(low_card)..card_value(high_card)).to_a.size == 5
    end
 
    def is_three_of_a_kind?
      value_matches(@hand).size == 3
    end
 
    def is_two_pair?
      value_matches(@hand).size == 4
    end
 
    def is_pair?
      value_matches(@hand).size == 2
    end
 
    def jacks_or_better?
      is_pair? && card_value(value_matches(@hand).first) >= 11
    end
 
  private
 
    def value_matches(hand)
      hand.select { |c| matching_value(hand, c) }
    end
 
    def matching_value(hand, card)
      match = false
      hand.each { |c| match = true if card_value(c) == card_value(card) && card != c }
      return match
    end
 
    def card_value(card)
      card.split(/(\d+)([CDHS])/)[1].to_i
    end
 
    def card_suit(card)
      card.split(/(\d+)([CDHS])/)[2]
    end
  end
end
 

How would you do it?

Rails 2.1 Model Caching Issue

There is what I am calling a bug in the new Rails 2.1 caching methods. It will cache models in development mode and spew errors all over when you try to pull them back out. As of now, there are 2 ugly fixes for it. Mine's not much better, but you don't have to modify your existing code to make it work.

 
if RAILS_ENV == 'development'
  module ActiveSupport
    module Cache
      class Store
        def fetch(key, options = {})
          log("write (will save)", key, nil)
          (block_given?) ? yield : nil
        end
      end
    end
  end
end
 

Just get that loaded up and you should be good to go with out any further modification.

July 22

So bored...

July 17th

Been dealing with food poisoning the past couple of days which just sucks. Still trying to find a balance with having a real work schedule.

Working on a method for preemptive caching with Rails. It probably isn't useful for most people but really nice when you can use it.

July 11th

Hung out at a coffee shop in Town Square. Saw Hellboy 2. Not too shabby. Previews were shit.

July 10th

Got a new Macbook Pro laptop for work. Got a new Sony Vaio laptop for me. It was a good day.

I had to use flash to modify a world map for mapping geocoded blog posts and photos. Kind of interesting, not just data in - data out.

Why the hell is "A Evening with Kevin Smith" nearly 4 hours long?

July 9th

Fedex is late delivering my new laptop... bastards.

Heard these guys on KNPR on the way home today. They sound amazing.

I now have 7 plugins in my Rails project at work. How many do people normally use?

Leopard doesn't like blank passwords for users so just don't do it. You shouldn't be doing it anyway. It's a pain in the ass to get a password set once you have a blank one.

July 8th

Got my new project at work up to 100% spec coverage. That is always a good feeling. I am really not liking working on a Mac though. I've just gotten way too comfortable with Linux window managers.

Learned that string interpolation in Ruby is faster than concatenation.

Finished watching the second season of Sleeper Cell. It's a pretty good show. I just hope they don't try to ring out a third season from this story line.

Going to cook dinner. (Greek Pasta with Tomatoes and White Beans)

July 7th

Started my new job at cardplayer.com

Started wok on a new blogging system. Trying to spec out all of the code to show the rest of the developers the best way to do it. Thankfully I'm working with rails 2.1

Also got the "real" go ahead to start a new contract that has been under discussion for a while.

Smoking

So I am now on the umpeenth attempt at trying to quit smoking. The last time I tried using losenges. They taste like crap and they take up way too much of your time. The directions say to not drink anything 15 minutes before or after you take one. That's not so bad but it takes the losenge 30 minutes to dissolve. It also says to take one every hour or two, especially two when you first start out. So if you follow those directions to the 'T' you can't drink anything all day... you'd think by drinking alot of water you would help flush the nicotine out of your body. This probably isn't a problem for most people but I drink alot of liquids during the day, always have.

Now I'm trying the gum. Same directions except now I chew. This whole process just sucks. I really wish I hadn't started but now I have way too many triggers. Mainly when I'm working. If I need to think something over or I finish a milestone, I have to have a cigarette.

Hopefully this time I can stick with it for a while. I know I will have another cigarette before I quit entirely. I just hope this time that I'm further down that road.