Chatbotを使ってシャッフルランチを続けた話

Yuki IwakamiPosted by

こんにちは!サーバサイドエンジニアの岩上です!
今回は、所属プロジェクトで行っているシャッフルランチを定期的に継続して開催するために行った工夫を紹介したいと思います。
※シャッフルランチとは普段接点のないメンバー同士がグループに分かれて一緒にご飯を食べることでコミュニケーションを活性化させるランチです。グリフォン全体でシャッフルランチを行ったりもしています。

なぜシャッフルランチをプロジェクト内でやったのか? 

チーム開発では異職種間での交流が必須になり、よりコミュニケーションが取れる環境が必要になると思います。
また、今回のプロジェクトでは新規入場者が多く、より異職種間でのコミュニケーションに心配がありました。
そこで、シャッフルランチをやることにより異なる職種の人たちで話す時間を設けて、なんでも言い合えるチームを目指しました!

Problem: シャッフルランチの開催って面倒くさい

ただ、シャッフルランチを開くのって面倒くさいですよね。

  • 定期的に開催するけど業務が忙しかったりしたときにどうしても忘れてしまう
  • 一度忘れるとその先続かなさそうだし、そのうち自然消滅しちゃう
  • 毎回のチーム決めのコストがかかるし、開催する側も嫌になっちゃうし面倒くさい
  • 毎回一緒のメンバーとかチームに偏りがあると不満があがるけど、そこまで考えるのが面倒くさ

Try: なるべく低コストで開催するために

そこで、Botに任せちゃおう!と思い、システムを構築しました!
また、弊社では社内コミュニケーションツールとしてChatWorkを利用しているので、ChatWork APIを利用してChatWorkを利用するBotを作成しました。
システムのゴールは上で挙げた問題の解決です。

Point 1: 偏りのないマッチング

マッチングを評価する評価関数を作成するために必要なパラメータを以下の3つにしました。

  • 職種
  • 性別
  • 今までのマッチングデータ

と言っても、それぞれのパラメータを使って複雑な計算はせず単純なアルゴリズムで計算をしています。
(システムを動かし始めた頃は何も考えずにマッチングさせていたのですが、職種の偏りがあったり毎回同じメンバーだったりでチームメンバーから文句をたくさん言われてしまったのでこんな工夫をしました)
職種」のパラメータを使うことで、そのマッチング結果を見て、ちゃんと様々な職種の方々でチームが構成されているかを評価しています。様々な職種の人が同じチームになれば評価を高くするようにします。

\(
\begin{eqnarray}
is\_same(x,y)=\left\{
\begin{array}{ll}
1&(x=y)\\
0&(x\neq y)
\end{array}
\right.
\end{eqnarray}
\) \(
\begin{eqnarray}
E_c(t)=\sum^{N_t}_{i=1}\sum^{N_t}_{j=i+1}is\_same(c_{t,i},c_{t,j})
\end{eqnarray}
\)

このとき、
\(
\begin{eqnarray}
c_{t,i}:チームtのi番目の人の職種
\end{eqnarray}
\)
\(
\begin{eqnarray}
N_t:チームtの人数
\end{eqnarray}
\)

異なる職種のマッチングであればこの値は低くなります。

性別」のパラメータを使うことで、どのチームも男女比率が近くなるように評価しています。「このチームだけ女性が多い!」「ズルい!」「不正してるだろ!」と言われないようにこの計算をしています。不正はしていません。

\(
\begin{eqnarray}
E_s(t)=\sum^{N_t}_{i=1}\sum^{N_t}_{j=i+1}is\_same(s_{t,i},s_{t,j})
\end{eqnarray}
\)

このとき、
\(
\begin{eqnarray}
s_{t,i}:チームtのi番目の人の性別
\end{eqnarray}
\)

異なる性別のマッチングであればこの値は低くなります。

今までのマッチングデータ」のパラメータを使うことで、以前のマッチングを考慮して毎回異なる人とランチに行けるように評価しています。
なるべく少ない回数のランチでチームの全員と話せるようにこのパラメータを入れています。

\(
\begin{eqnarray}
E_f(t,n)=\sum^{N_t}_{i=1}\sum^{N_t}_{j=i+1}f(p_{t,i},p_{t,j},n)
\end{eqnarray}
\)

また、
\(
\begin{eqnarray}
f(x,y,n)=\left\{
\begin{array}{ll}
f(x,y,n-1)+1&(n回目にxとyが同じチームの場合)\\
f(x,y,n-1)×0.5&(n回目にxとyが異なるチームの場合)\\
0&(n=1)
\end{array}
\right.
\end{eqnarray}
\)

このとき、

\(
n: n回目のシャッフルランチ
\)

なので、これを組み合わせて

\(
\begin{eqnarray}
E(n)=\sum_{t\in T}(E_c(t)+E_s(t)+E_f(t,n))
\end{eqnarray}
\)

この評価値が最小となるようなマッチングを選びます。
単純に1000回のシャッフルとマッチングを行い評価してその中の評価値が最小となるマッチングを選択するようなロジックにしました。

Point 2: 人数は多すぎず少なすぎず

1チームの人数ですが、お店にスムーズに入れる点や喋りやすさの点で考えると4人〜5人くらいになるのがおすすめかなと思います。
チーム数は以下のような式で求めることができます。

var teamCount = Math.floor(member.length / 4);

これで求めたチーム数になるようにメンバーを振り分けていきます。

Point 3: 金額的な運用コストがかからない

このBotを運用していく上でサーバコストがかかってしまってはまた不満の一つになってしまうかと思います。
そこでコストがかからないGoogle Apps Script(以下、GAS)を用いることにしました。
マッチングデータやメンバーの一覧を全てスプレッドシート上で管理して、マッチングデータを更新するときはスプレッドシート上の値を更新するようにしました。
また、GASからChatWorkのAPIを叩くことで全てGAS内で処理することが可能になります。
GASを用いることで運用コストをかけずに行うことができます。

Point 4: 時間的な運用コストがかからない

またプロジェクトというのは人の出入りがあるものだと思います。
そういう手間を省くために、グリフォンではプロジェクトごとにChatWorkの部屋が別れているのですが、そこのメンバーの一覧を取得することで最新のプロジェクトメンバーを取得することができます。
定期的に(1時間毎に設定していた)ChatWork APIを叩いてメンバーを確認して、メンバーに変更があればスプレッドシート上で管理しているメンバーリストを更新します。
おまけですが、メンバーが追加されるような状態のときは「○○さん、プロジェクトにようこそ」のような文言を投稿するようにしてあげると動作の確認をしつつもチームを盛り上げる一つの要因になると思うのでおすすめです!(ジョインしてきたばかりの人でBotなのかどうかもわからない状態なので、ほとんどの人はBotに対して丁寧に返信をしてくれることが多かったです)

Point 5: 責任者を決めておく

チームを決める上で、班長と副班長もランダムで決めていました。
チームの責任者を決めることで、シャッフルランチを責任を持って実行してくれる人ができます。
ただ業務が忙しいとか体調不良とか都合が悪いなどでどうしても班長が参加できなくなってしまう場合もあるので、そのときは副班長に責任を持って開催してもらいます。
(ここの選出ロジックは完全ランダムのため、2回連続で班長になってしまうという方がいたのですが、「これは完全にランダムなので運がいいですね」と伝えてあげるといいと思います)

Point 6: お店の候補をピックアップしてなるべくコストを下げる

手間を省くためにも、Point 4以外にお店のピックアップもしていました。
ぐるなびのAPIを用いて、オフィスから500m(ぐるなびAPIのパラメータではrange=2)のお店を取得して各チーム毎に2つのお店をおすすめするようにしています。
こうすることで「じゃあ紹介されたこの店に行くか」となるチームが多く、お店を選ぶコストを削減することができました。

Point 7: 開催頻度をいい感じにする

あまり頻繁にやるとシャッフルランチに行くことのコストが大きくなってしまうので、隔週でやっていました。
毎週の頻度でもやっていたのですが、1週間に1回みんなの予定をあわせてランチに行くのが大変だったので、余裕を持って2週間に1回の頻度にしました。
なので隔週の月曜日の朝にチームの振り分けを行いBotにチーム発表をChatWork上に投稿してもらうように設定しました。(チーム発表は月曜日の朝の盛り上がりイベントの一つになりました)
チーム内の仲良し度によっては周期を変えてもいいかと思います。

Point 8: リマインドは大事!

チーム分け発表の投稿だけだと、人間なのでどうしても忘れてしまいます。
そこで、忘れた頃に思い出すように、チーム発表の投稿へのリンクを載せてリマインドしてあげます。
頻度としては、毎週月曜日と水曜日に設定していました。
「あ!忘れてた!」と言っていた人もたまにいたので、リマインドを投稿する効果はあったはずです。

Point 9: Botはキャラクタが投稿するように

Botがロボットっぽく投稿しても聞いてもらえないので、Botが可愛がってもらえるように、ちゃんと言う事を聞いてもらえるようにキャラクタ設定をしてあげます。
プロジェクトのキャラクタがいればそれを設定するのがいいと思います。
と言っても、アイコンと名前を設定するだけですが。
あまり関係なく感じるかと思いますが、こういう小さなところからこだわることでシャッフルランチをより気にしてもらえるようになりました。

実際の投稿例

こちらが投稿した内容です。

(キャラクタ名、名前、アイコンはモザイクをかけています)
これに対してこのようにランダムに選出される班長の方が皆さんの予定を聞きつつお店まで決めたりします。


面倒くさいお店選びも楽ちんです!

シャッフルランチを続けることができました!

このChatbotのお陰でチーム分けのコストも全くかからず、いい感じのマッチングでマッチすることでチーム全員と話す機会を作り続けることができました。
また、上の実際の例の画像のように、お店選びのコストも削減することで、運用コストもほとんどかからず続けられます!

ほとんど毎回全てのチームがランチを開催し続けることができ、チームの雰囲気も良い状態で開発を進めることができるようになりました!

Botって、いいですね!