kinoppyd.dev

blog

products

accounts & contact

zoomガチャ

posted at 2021-12-01 00:00:21 +0900 by kinoppyd

いえーい、どもども、ハッピー……何だっけ? 12月なんだから何かしらがハッピーな……えーっと、あれよ、その……アレだ、いえーい! ハッピー! やったー!

この記事は SmartHR AdventCalendar の1日目です。

アジャイルチームとガチャ

SmartHRの各チームでは、今年はだいぶアジャイルチーム、とりわけクロスファンクショナルチーム化を目指す流れがありました。多分クロスファンクショナルチームをググると、各分野の専門家たちが1つのチームで問題解決に当たる的な話が出てくると思いますが、SmartHRではその特色をさらに進めて「専門家のもとで誰でもなんでもできるようになる」ような結構スパルタな感じの開発チームを作っています。例えば、チームのQA専門家のもとでプロダクトエンジニアは全員QAの自動テストにコミットできるようになったり、UXWと呼ばれるプロダクトの文言を万人に使いやすくするためのライティングチームのもとプロダクト内で使う文言に全員で注意を払ったり、プロダクトデザインチームの監修のもと開発時にデザインの草案とアクセシビリティを意識したデザインプロトタイプ駆動の開発全員で行ったり、結構いろんなことをプロダクトエンジニアをはじめとするチームの全員がやっているような感じです。

当然、チームのスプリントを計画するスクラムイベントを中心としてスプリントレビューやリファインメント、プランニングや日々のデイリースクラムまで、ありとあらゆるミーティングで属人化の排除が進むようになっています。これは、特定の誰かがチームから離脱したとしても、それによってチーム全体の活動に悪影響を及ぼさないようにという理由からで、特にスクラムイベントのファシリテーションにおいては全員がすべての役割をこなせるように、トークスクリプトを用意した上でランダムに割り当てられたチームメンバーが行います。

さて、ここで問題になるのが誰がファシリテーターをやるかです。先ほどお話した「チームから離脱」というのは、有給なんかも該当します。たとえば、スクラムイベントでいつもファシリテーションをやってくれる人が、その日に体調悪くなって休んだりしたらじゃあ延期だねとはならないですよね? つまり誰でもファシリテーションができなくてはいけないんです。自分がいるチームでは、ファシリテーターのトークスクリプトと、ランダムにファシリテーターを決めるという運用でこの問題に立ち向かっています。でも、どうやってランダムにファシリテーターを決めるんでしょうか?

答えはガチャです。ガチャ。射幸心を煽る悪い文明のアレです。僕も結構嫌いですよ。でもまあ、リスク(例えば課金とか税金とか)さえなければ、わりとガチャは公平で良い文明です。何の理由もなくサイコロ振ってるのとそう大して変わらないですからね。

単に限定的なメンバーの中で回すガチャは、比較的簡単です。なぜなら、その限定的なメンバー全員をSlackのカスタムレスポンスで登録して、特定のキーワードでランダムに選ぶということが可能だからです。しかし、参加者が不特定なケースでのガチャって、どうすれば良いんでしょうか? 例えば、毎週木曜日に開催されるエンジニア定例だけど、参加自由で誰が来るかわからない、参加の候補者は40人を超えるけど実際に来るのは20人みたいなケースです。事前に登録しておきますか? 無理ですよね。なんならハズレのほうが多いですし。じゃあ当日にzoomのミーティングに参加している人の中からダンダムに選びたいってなったら、どうすれば良いんでしょうか?

zoomとガチャ

これに関しても答えは簡単です。zoomのAPIを使って、今現在ミーティングに参加している人の一覧を取得し、その一覧を何かしらの方法でランダムにシャッフルすれば良いのです。簡単。

https://github.com/kinoppyd/zoom-gacha

Rubyのzoom APIクライアントはなんかあんまりいい感じのがないんですが、別にそんなに複雑な動きをするわけでもないのでシンプルなもので十分です。

非常にペラいコードなので特に解説するところもないんですが、zoomのAPIを使って参加者一覧を取得し、その配列をHeadless Gachaに投げています。

zoom = ZoomClient.new
meeting_id = params["meeting_id"].gsub(/ /, "").gsub(/-/, "")
name = zoom.meeting_name(meeting_id)
gacha = HeadlessGachaClient.new.gacha(zoom.users_list(meeting_id)).env.url.to_s

あとはまあ、設置している場所的に社内の人にしか使えないようにGooge OAuth2でメールアドレスを絞っているくらいです。あとは、絵文字とかユーザー名に容赦なく突っ込んでくる人がいるので、アスキー文字以外は消すとか。ほんとそれくらい。

起動時には、環境変数 GOOGLE_CLIENT_ID と GOOGLE_CLIENT_SECRET に Google OAuth のキーとシークレットを、 ZOOM_API_KEY と ZOOM_API_SECRET に Zoom OAuth のキーとシークレットをそれぞれ渡してあげてください。基本的にHerokuにぶん投げれば動くはずです。

zoomガチャのトップページ。不正防止のために全員が回したガチャの結果にアクセスできる。 zoomガチャのトップページ。不正防止のために全員が回したガチャの結果にアクセスできる。

Headless ガチャ????

ヘッドレスなガチャです。流行ってますよね、無頭のたぐい。渡された配列の要素をランダムに並び替えて新しい配列として返すだけのAPIサーバーです。

https://github.com/kinoppyd/headless-gacha

特になにか深いことを考えて作ったわけではなく、酒を飲みながらなんとなくヘッドレスイェーイみたいな感じでついやってしまったんですが、他のAPIをイジるやつと組み合わせてガチャを作るには割と重宝する感じでした。

流れとしては、配列のJSONをパラメータにしてPOSTすると、ガチャった結果をJSONで返すパーマネントリンクにリダイレクトする感じです。パーマリンクを作ることで、不正防止的な感じをまあなんかいい感じにって感じがしています。

こっちもHerokuにぶん投げれば動くはずです。特に認証とか無いので、環境変数無しで動くと思います。

ヘッドレスガチャで返ってきたJSON ヘッドレスガチャで返ってきたJSON

実際に使う場合

実はzoom-gachaのリポジトリの中に、smarthr.co.jpドメインのみを許可するコードと、ヘッドレスガチャのURLがハードコードされている箇所があります。もし自分の環境で利用する場合は、それらを書き換えてください。そのうち環境変数で渡せるようにしておきます。

属人性の排除

わりと大きく話は逸れましたが、zoomに参加している人のなかからランダムにファシリテーターを選べるという行動が、ミーティングやひいてはチームの属人性の排除に役立ちます。今時分が所属しているチームでは、そういう意味で徹底的に属人性の排除を行うために、スクラムイベントのファシリテーター(レトロ、レビュー、リファ、プランニング、デイリーと全部別の人を選ぶ)や、リリースを実行する人、モブプログラミングのドライバーとナビゲーター、プルリクのレビュアなど、何から何までガチャで決めています。

おかげでチームにおいて、誰々がいなかったら困るということはかなりなくなりました。POはいなかったら流石に困りますが、プロダクトエンジニアに関しては誰が同じバスに乗って事故っても問題ない状態です。

レッツガチャ

人生は属人的。だからこそそれ以外は属人性を排除していきましょう。みなさんも12月はレッツガチャ!