git commitを楽しくする(その1:hash値ポーカー編)

  • 40
    Like
  • 2
    Comment
More than 1 year has passed since last update.

「作業を楽しくすることは生産性の向上につながる」という信念のもとに、
commitするたびに ポーカーで遊ぶ スクリプトを作りました。
「作業を楽しく」の方向性が完全に斜め上ですが気にしてはいけません。

作るもの

  • commit後に生成される、short hash値7桁の英数文字列を7枚のカードに見立ててポーカーを行う
  • commitのたびに役を自動判定、メッセージを表示する

hash値ポーカー ルール

  • テキサスホールデムに準じ、7枚中任意の5枚で作られる役のうち最強のものを手役とする
  • カードは数字0~9,アルファベット小文字a~fの計16種。強弱もこの順
  • トランプと違ってマークが無いので,フラッシュ系の役は無し
  • ペア形はできやすい反面、16種もあるのでストレートが最難関(なはず。。。ちゃんと検証してないけど)
  • というわけで役の強さは ストレート > ファイブカード(笑) > フォーカード > フルハウス > スリーカード > ツーペア > ワンペア とする

実装

以下のコードを、プロジェクト内の.git/hooks/post-commitに保存。

.git/hooks/post-commit
#!/usr/bin/env ruby

# 手札がストレートかどうか判定する関数
def straight?(cards)
  # ソートした上で、文字列比較を使って判定
  all_cards_sequence = (("0".."9").to_a + ("a".."f").to_a).join
  cards_sequence = cards.split(//).sort.join
  (0..2).each do |i|
    return true if all_cards_sequence.include?(cards_sequence.slice(i,5))
  end
  false
end

# メッセージハッシュ お好みで編集して下さい
messages = {
  straight:        "Congratulations!! Straight!!",
  five_of_a_kind:  "Unbelivable! Five_of_a_kind!",
  four_of_a_kind:  "Bravo! Four_of_a_kind!",
  full_house:      "Excellent! Full_house!",
  three_of_a_kind: "Three_of_a_kind!",
  two_pair:        "Two_pair!",
  one_pair:        "One_pair!"
}

# short hashを取得
cards = `git log -1 --format=format:%h HEAD`.chomp
# cardの枚数の構成を計算
same_card_counts = cards.split(//).group_by{ |r| r }.values.map(&:size).sort.reverse

# 手役の判定
result =
if straight?(cards)
  :straight
elsif same_card_counts.max >= 5
  :five_of_a_kind
elsif same_card_counts.max == 4
  :four_of_a_kind
elsif same_card_counts.max == 3
  if same_card_counts == [3,1,1,1,1]
    :three_of_a_kind
  else
    :full_house
  end
elsif same_card_counts.max == 2
  if same_card_counts == [2,1,1,1,1,1]
    :one_pair
  else
    :two_pair
  end
end

puts "\e[31m"+messages[result]+"\e[0m" if result

実装ポイント

  • post-commit フックを使えばコミットごとに好きなスクリプトを起動できます
  • git logのformatオプションを使うと表示項目をある程度好きに弄れます
  • 最終的な手役の判定ですが、"7枚中任意の5枚を選んだ組合せで作れる手役のうち強さを比較してぐぬぬ"とかやるより、7枚の構成を見て一気に判定した方が楽でした
  • ストレートかどうかの判定は"連続である文字列中に現在の手札が出現するか"という発想でやってみました

所感

  • 方向性はともかく"たくさんcommitしたくなる仕掛け"を施すのは実際にモチベーション上がりますよ(言い訳)
  • 仕掛けた直後にいきなりフォーカード出てバグかと思いました(自虐風自慢)
  • ちょっと重いのでもう少し高速化したいところですね(丸投げ)