プレゼント交換アプリを作っている話

これはフィードフォースエンジニア Advent Calendar 2015の18日目の記事です。
昨日は制作チームのコーダーのa-idecsstyleの話でした。

今回は、私、中野佑(ナカノタスク)がクリスマスでリア充になるためにプレゼント交換するためのWebアプリを作っている話をします!
私のことを知ってる方もはじめましての方もどうぞよろしくお願いします!

あらかじめ言っておくと、今回の記事は完全にプライベートで作っているWebアプリの話なので、会社の話はちょっとだけしか出てこないです!笑
内容としてはこのWebアプリの機能と、実装するにあたってはまったところ、今後の展望についてお話します。
また、これまでのフィードフォースアドベントカレンダーの真面目な感じからちょっと外れて文章を書いてみました!
最後まで楽しんで読んでいただけたら嬉しいです!

さてみなさん、いかがお過ごしでしょうか!来週はもうクリスマスですよ!!
そんな私はどうかって?

「安心してください、彼女はいませんよ」

はい。言ってみたかっただけです…。
ちなみにカノジョできないエンジニア Advent Calendarこんな記事も書いたので是非読んでみてください。

そんな私がリア充になるためにクリスマスでプレゼント交換をしたい!という欲望で作りはじめたWebアプリが今回の話です。
その名も「present-shuffle」です!(そのままです。)

機能

まずはpresent-shuffleの機能の紹介をします。

  • Twitter or Facebookでアカウント作成できる
  • グループを作成できる
  • そのグループ内でプレゼントをあげる人がランダムで決まる

ただこれだけです!
シンプルで素晴らしいWebアプリですね!!

技術構成

私が所属している、フィードフォースでは主にWebアプリケーションフレームワークは最新のRails、データベースはPostgreSQL、サーバサイドは CentOS + nginx + unicorn で動いていることが多いので、
私の環境も勉強がてら合わせました。

また、恥ずかしながらリポジトリは公開しています → https://github.com/TasukuNakano/present-shuffle

present-shuffleでは、Userが主なモデルで、テーブル定義は、

カラム名 役割
uid TwitterやFacebookでログインしたユーザID
name 表示名
present_name プレゼントの名前
target プレゼントを誰に渡すかのユーザID

となっています。

はまったところ

実装をしていて、プレゼントをあげる人を決める際のアルゴリズムに少しはまってしまいました。
最初のアルゴリズムは、

  1. プレゼントを渡してない人リストを作成
    • 自分にプレゼントをあげることがないように、あらかじめ自分自身をそのリストから取り除いておく
  2. そのリストから Array#each で順番に Array#sample で誰にあげるかを決める
  3. プレゼントを渡してない人リストから Array#sample で決まった人を削除する

と考えていて、すぐできるだろうと思っていた時期が私にもありました。

コード的にはこうなります。 da395e9

1
2
3
4
5
6
7
8
target_list_init = User.pluck(:id)
User.all.each do |user|
target_list = target_list_init - [user.id]
user.target = target_list.sample
target_list_init.delete(user.target)
user.save
end

しかし、ここで問題が発生してしまいました。

なんと、プレゼントをもらえない人が現れたのです \(^o^)/
以下の表の様に、最後にプレゼントをあげる人が自分自身で残ってしまった場合、削除してしまってプレゼントを誰にも渡せない!という事態になるのです\(^o^)/

あげる人 プレゼント もらう人
Aさん ネックレス Bさんへ
Bさん イヤリング Cさんへ
Cさん 指輪 Aさんへ
Dさん Amazonギフト券 誰に??

この問題を、会社のもくもく会で悩んでいたところ、見かねた先輩社員方が一緒になって考えていただきました!(*´▽`*)

解決策としては、

といったように

  1. 最初にすべてのUserのオブジェクトを配列として持ちます。
  2. その配列をシャッフル
  3. シャフルし終わった後の配列を Array#each で回して、それぞれユーザのひとつ前のインデックスのユーザをプレゼント対象とします。
    • インデックスはひとつずれていれば良いのですが、次のインデックスにしてしまうと最後のインデックスに達した際に指定できなくなります
    • Rubyでは最初のインデックスから-1をすると、配列の末尾を指し示すのでこちらで対応しました

コード的にはこうなりました。 69fb778

1
2
3
4
5
users = User.all.to_a.shuffle
users.each_with_index do |user, index|
user.target = users[index - 1].id
user.save
end

こうすることで、自分自身を選択することはないですし、プレゼントがもらえない!という事態も防ぐことができました!

ヤッタネ!ヽ(=´▽`=)ノ

今後の展開

クリスマスまで残り1週間ですが、まだまだできてないところはあります。

  • グループ機能
    • WIPをつけてプルリクエストを出している状態
  • サーバ構築
    • nginx と unicorn を連携…
  • デザイン…
    • (´ε`;)ウーン…

果たして残り1週間で公開できるでしょうか!((((;゚Д゚))))ガクガクブルブル

公開しましたら、ぜひ使っていただき、フィードバックをしていただけるととても嬉しいです!

以上になります、こんな大したことない記事を最後まで読んでいただいて、ありがとうございました m(_ _ )m
明日は今年のフィードフォースのバリュー男、 cross_black777 の「フィードフォースで学んだこと」です!