るびー めも

Ruby の学習メモを記す

とある Ruby ソースのクラス化について

とあるブログの記事で、以下のようなページを見つけました。

ソーシャルコーディング

プルリクエスト Come on てな具合です。

もともとあったソースコードは、以下のとおりでした。

class Array
  def get_point
    number = 0
    number = rand(10) + 1
  end

  def roulette
    return self if self.size <= 1

    master = Hash.new
    master = self.map do |p|
      {
        :name => p,
        :point => get_point 
      }
    end

    master.each do |p|
      3.times do
        print '.'
        sleep 0.5
      end
      puts kyoko = "#{p[:name].to_s.capitalize},  #{p[:point].to_s} 点。"
      system("say #{kyoko}")
    end
    outman = master.sort{|a,b| a[:point] <=> b[:point]}
    puts kyoko = "#{outman.first[:name].to_s.capitalize}ーーー。アウトーーー。"
    system("afplay gaki.mp3")
    system("say #{kyoko}")
  end 
end

case ARGV[0] 
  when "M2"
    year = %w(おくつ すがわら なかじま ふじい)
  when "M1"
    year = %w(たけみち こまつ ふるだて)
  when "B4"
    year = %w(おくとも かとう いのうえ あべ なかむら ひらが まいた かどわき ほし やぎぬま)
  else
    year = %w()
end

year.roulette if ARGV[0]

とある大学生が、とある研究室のゼミで司会者を決めるためにちゃちゃっと作った
ルーレットプログラム。

git の勉強もかねて、プルリクエストしてみるべというのが事の始まり。

まずは、クラス化に着手するため基本的な動作について検討しました。

ルーレットクラスは、引数にメンバーの配列を貰う。
そのメンバー配列をHash 化して rand() でランダムに選出された点数を挿入し
返すだけで良さそう。その他の機能としては、OSX の say(1)でメンバーの名前と点数を
しゃべらせて、最後にBGM と共に最下位メンバーをアウトにする。という動作

最初に行ったクラス化のソースコードは、以下です。

class Roulette 
  def initialize members
    @result  = Hash.new
    @message = Hash.new
    @members = Array.new(members)
  end
  def start
    @members.each do | member |
      @result[member] = rand(10) + 1
    end
    @result = @result.sort{|a, b| b[1] <=> a[1]}
    self.speak
  end
  protected
  def speak 
    result = @result.dup
    result.each_with_index do | elem, index |
      3.times do 
        print "."
        sleep(0.5)
      end
      if index == result.length - 1
        threads = []
        puts  "#{elem.join(", ")}点。"
        puts message = "#{elem[0]}" + "ーーー。アウトーーー。"
        threads.push(Thread.new{`/usr/bin/afplay ./gaki.mp3`})
        sleep(2)
        threads.push(Thread.new{`/usr/bin/say #{message}`})
        threads.each{|thread| thread.join}
      else
        puts message = "#{elem.join(", ")}点。"
        `/usr/bin/say #{message}`
      end
    end
  end
end

Roulette Class のインスタンスメソッドとして、start と speak を定義しました。
また、当初のソースコードで問題だったのが BGM を再生したあとで say(1)を実行しているところ

YouTube とかで、とある番組を確認してみたんですが BGM と平行して
ナレーションされている感じ。そのため、Thread で並列に処理しました。

上記のコードで、人生初めての github Pull Request を実施。
しかも、採用されマージされてしまいました。

ただ、マージされた後で、リファクタリングした方が良いなと思い立ち
第2段のプルリクエストを実施しました。
#実のところは、speak メソッドを何故か、protected にしてしまっていたので
#修正しないといけないというのが、リファクタリングのきっかけかも

リファクタリングについては、次の記事に続きます、、、