はじめに
今回はPower Automate と Microsoft Teams を利用して「ワードウルフ」を作成してみようと思います。
ワードウルフってなに?という方も大勢いらっしゃると思うので簡単に説明しますと、
ワードウルフとは、みんなで“あるお題”について話し合う中、「みんなとは異なるお題」を与えられた少数派の人(ワードウルフ)を探し出すゲームです。村人に紛れた人狼を見つけ出す「人狼ゲーム」に似ているので、ワード人狼と呼ばれることもあります。
例えば、下のイラストでは、「えび」というお題を与えられた多数派が市民で、「かに」というお題を与えられた少数派がワードウルフ、ということになります。
少数派のお題を与えられた人がワードウルフ ただし、ゲーム開始時は、自分がどちらの陣営なのか分かりません。
周囲の会話をヒントに、自分が「市民」なのか「ワードウルフ」なのかを探っていきます。もし「自分のお題が周囲と違うな」と思ったら、あなたがワードウルフかもしれません。その時は周りの会話から「市民のお題」を推理して話を合わせたり嘘をついたりしながら、自分がワードウルフであることがバレないように振る舞いましょう。
お題について話し合った後、多数決で処刑する人を決めます。『ワードウルフを処刑できれば市民チームの勝ち』で、『市民が処刑されればワードウルフの勝ち』となります。
ワード人狼こと『ワードウルフ』のルール・コツ・アプリ3選を徹底紹介!より引用
というゲームです。
処理の流れ
今回作成するフローは以下のようになっています。
処理の流れは以下のようになっています。
- Excel より、参加者の一覧とお題の一覧を取得
- 参加者情報の作成
- 各参加者の個人チャットにお題を送信
- チャネルに開始確認メッセージを送信
- 残り時間の通知を行う
- 終了のお知らせとともに各参加者のチャットに投票メッセージを送信する
- 結果の送信
- ゲームの続行を確認
Excel テーブルの作成
今回データはExcel のテーブルに保持しています。
テーブルは2つあり、
- 参加者の情報が記載されたテーブル
- お題が記載されたテーブル
を用意しています。
まずは「参加者の情報が記載されたテーブル」です。
こちらには、参加者の名前と参加者のメールアドレスを設定します。
続いて、「お題が記載されたテーブル」です。
こちらには、「市民」用のお題と、「ウルフ」用のお題、そしてそのお題の種類とIndex を割り振っています。
これらのテーブルはゲームを開始する前に予め作成しておいてください。
Power Automate の作成
変数の宣言
まず初めに今回利用する変数の宣言を行います。
「変数を初期化する」アクションを利用して変数の初期化を行います。
今回利用する変数はこちらになります。
変数名 | 種類 | 初期値 |
---|---|---|
mention | 文字列 | - |
userArray | アレイ | - |
wolf | 整数 | 0 |
choise | 文字列 | - |
result | アレイ | - |
voltMessage | 文字列 | - |
resultMessage | 文字列 | - |
isContinue | ブール | true |
変数名は任意に変更してもよいですが、その場合以降の操作でもその都度名前を置き換えてください。
これらの変数の初期化はスコープなどで纏められるとフローの見た目がすっきりするのですが、なにかいい方法ないですかね...
Excel テーブルをPower Automate で読み取り
先ほど作成したExcel テーブルをPower Automate で読み取ります。
「テーブルの取得」アクションを利用してExcel テーブルの読み取りを行います。
アクションにはそれぞれ作成したExcel が存在する場所を選択し、それぞれにあったテーブルを選択します。
参加者情報の作成
最初に宣言した変数に参加者情報を作成します。
変数への設定には、「配列変数に追加」、「文字列変数に追加」、「変数の設定」を利用します。
「参加者へのメンションの作成」には「文字列変数に追加」アクションを利用します。
値には以下を設定します。
名前
mention
値
<at>@{items('参加者情報の作成')?['E-Mail']}</at><br>
「< at>< /at>」でメンションの作成を行っています。
「< br>」ではメンションメッセージごとに改行を行いたかったので改行コードを設定しています。
「@{items('参加者情報の作成')?['E-Mail']}」では、先ほど取得したExcel テーブルの参加者情報から「E-Mail」を選択しています。
こちらを選択すると、選択中のアクションが「Apply to each」で囲われ、「以前の手順から出力を選択*」には「@{body('参加者を一覧表示')?['value']}」が設定されたかと思います。
これは、「参加者を一覧表示」で取得した結果数分だけApply to each 内の処理を実行します。
* こちらの「Apply to each」を画像のように「参加者情報の作成」にリネームした場合、「@{items('参加者情報の作成')?['E-Mail']}」が「@{items('Apply_to_each')?['E-Mail']}」となったままになっている可能性があります。(マウスカーソルをあわせたり、値をコピーしてテキストエディタなどに貼り付けてみると確認できます。)
もしそのような場合は、再度選択し直してみてください。
「参加者情報を配列変数に格納」と「choicesの作成(アダプティブカード)」には「配列変数に追加」アクションを利用します。
今回は2通りの方法で配列変数に追加を行っています。
「参加者情報を配列変数に格納」では直前のアクションで「作成」を行っています。
こちらの「作成」では、下記のように設定しています。
入力
{ "dispName": @{items('参加者情報の作成')?['dispName']}, "mention": @{items('参加者情報の作成')?['E-Mail']} }
「参加者情報を配列変数に格納」には「作成」アクションの出力結果を設定します。
名前
userArray
値
@{outputs('作成')}
「choicesの作成(アダプティブカード)」では「作成」アクションを利用せずに「値」に直接「入力」に設定した値を設定しています。
名前
choise
値
{ "title":"@{items('参加者情報の作成')?['dispName']}" , "value":"@{items('参加者情報の作成')?['dispName']}" },
参加者情報にindex を付与する
上で作成した参加者情報をもとに、
- index の付与
- JSON の解析
を行っていきたいと思います。
まずは、index の付与方法について説明します。
「データ操作」より「選択」を選択します。
作成したら以下のように設定してください。
開始
@{range(0, length(variables('userArray')))}
マップ
{ "Index": @{add(item(), 1)}, "dispName": @{variables('userArray')?[item()]?['dispName']}, "mention": @{variables('userArray')?[item()]?['mention']} }
「開始」の設定値の解説です。
こちらは、0~「userArray」の長さ、つまり参加者の数までの整数の配列を返します。
「マップ」の設定値の解説です。
まず「Index」です。これがindex を設定している箇所ですね。
こちらでは、「開始」で設定した配列の要素を順に設定しています。
今回index は1から順に設定したかったので「add」関数を用いています。
残りの項目については、上で取得した参加者情報をそのまま割り当てているだけですね。
続いて「JSON の解析」です。 先ほど同様「データ操作」より、「JSON の解析」を選択してください。
設定値は以下のように入力します。
コンテンツ
@{body('選択')}
{ "type": "array", "items": { "type": "object", "properties": { "Index": { "type": "integer" }, "dispName": { "type": "string" }, "mention": { "type": "string" } } } }
これまでの説明と同様の設定を行っている場合はこちらのスキーマで大丈夫かと思いますが、設定を変えている。もしくはエラーとなる。などの場合は、実行結果より「選択」の「出力」をコピーし、「サンプルから生成」よりスキーマの作成を行ってください。
参加者確認メッセージをチームに送信する
参加者の確認メッセージをチームに参加者をメンションして送信します。
「メッセージをフローボットとしてチャネルに投稿する」アクションを利用します。
任意のチーム、チャネルを選択して、送信するメッセージを作成します。
メッセージは下記のように設定します。
メッセージ
@{variables('mention')} 以上、@{length(variables('userArray'))}人のメンバーでゲームを開始します。
「@{length(variables('userArray'))}」では、userArray に設定してある配列の数を返します。
これにより参加人数をつたえることができますね。
処理をループさせる
これから作成するフローはゲームを続けるが選択されている場合、処理を繰り返すようにしたいです。
具体的にフローの処理風にいいますと、「isContinue」が「true」の場合処理を繰り返し実行させたいと思います。
そこで用いるのが、「Do Until」です。
ループの実行条件には以下のように記載します。
@equals(variables('isContinue'), false)
これにより、「isContinue」が「false」となったときに「Do Until」処理を抜けるといった風に記載できました。
以降の処理は「Do Until」内に記載していきます。
今回のお題を取得する
お題の取得には「行の取得」を利用します。
お題は上で取得したお題のテーブルと同様のものを利用します。
違うのは、全て取得するのではなく1行だけ取得するという点です。
テーブルを選択したら、「キー列」、「キー値」を設定します。
今回「キー列」にはindex が記載されている「index」を設定します。
「キー値」には、以下を設定します。
キー値
@{Rand(1, length(body('お題を一覧表示')?['value']))}
これにより、お題のテーブルに存在する行からランダムに1行取得することができます。
「ワードウルフ」となる参加者を設定
「ワードウルフ」となる参加者を「wolf」という変数に設定します。
「変数の設定」アクションを追加して、以下のように設定します。
名前
wolf
値
@{rand(1, length(variables('userArray')))}
これにより、1~参加人数の間の数字がランダムに設定されます。
上で設定したような、参加者情報に記載されているindex とwo;f に設定されている数字が一致したユーザーを「ワードウルフ」として扱えばいいですね!
参加者にお題の送信
続いて参加者に向けてお題を個別に送信する処理を作成します。
送信するお題は先ほど作成した「wolf」と参加者情報の「Index」を比較して、市民用のお題か、ワードウルフ用のお題を送信します。
「コントロール」より「Apply to each」を選択して、以下のように設定します。
以前の手順から出力を選択
@{body('JSON_の解析')}
送るお題の判定処理です。
「コントロール」より「条件」を選択します。
条件は「次の値に等しい」を選択します。
左辺
@items('参加者にお題の送信')?['Index']
右辺
@variables('wolf')
参加者へのお題の送信には「メッセージをフローボットとしてユーザーに投稿する」を選択します。
以下のように入力してください。
ヘッドライン
ワードウルフ
受信者
@{items('参加者にお題の送信')?['mention']}
メッセージ
@{items('参加者にお題の送信')?['dispName']}さん@{uriComponentToString('%0A')} あなたのワードは「@{body('お題の取得')?['WordsA']}」です。
「uriComponentToString('%0A')」は改行を表しています。
続いて、誰にどのメッセージを送ったか記録するために変数に文字列を追加します。
「文字列変数に追加」を選択します。
名前
resultMessage
メッセージ
@{items('参加者にお題の送信')?['dispName']}:「@{body('お題の取得')?['WordsA']}」<br>
作成が完了したら、「いいえ」の処理にも同じような処理を作成してください。
「WordsA」を「WordsB」に変更するだけです。
ゲーム開始の確認
ゲーム開始の確認を行うメッセージをチャネルに投稿します。
送るメッセージはアダプティブカードとし、ユーザーがアクションを起こすまで待機するようにしたいと思います。
Teams のアクションから、「アダプティブ カードを Teams チャネルに投稿して応答を待機」を選択します。
任意のチャネルを選択したら、「アダプティブカードの編集」を選択してください。
すると、アダプティブカードの編集エディタが表示されたかと思います。
こちらのアダプティブカードは、左の「Card Element」と記載のパレットより、デザインエリアにドラッグ & ドロップを行い、「Element Properties」よりプロパティを編集することでアダプティブカードを構築することが可能です。
他にも下の「Card Payload Editor」よりJSON を直接編集して作成することも可能です。
JSON はこちらで作成し、出力することも可能です。Adaptive Cards Designer
また、Hiroさんが、Adaptive Cards 入門用ドキュメントを作成・公開しましたにてAdaptive Cards の解説を行っていますので、是非ご覧になってください!
アダプティブカードの編集を行い以下のようなアダプティブカードを作成してください。
下記JSON を貼り付けることでも作成可能です。
{ "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", "type": "AdaptiveCard", "version": "1.2", "body": [ { "type": "TextBlock", "text": "ゲームを開始します", "weight": "Bolder", "size": "Medium" }, { "type": "TextBlock", "isSubtle": true, "wrap": true, "text": "参加者全員にワードを送信しました。 \n今回のお題は「@{body('お題の取得')?['Type']}」です。 \n「開始」ボタンを押すとゲームが開始します。" } ], "actions": [ { "type": "Action.Submit", "title": "開始" } ] }
「@{body('お題の取得')?['Type']}」となっている箇所はPower Automate 上でも利用されている値が代入されてチャネルに投稿されます。
入力が完了したら更新メッセージ(Action.Submit ボタンが押された後に表示されるメッセージ)を編集し、「カードの更新が必要」に「はい」を選択します。
ここまで作成できたら一度、動作確認を行っておくとよいかもですね。
* Do until ループを抜けるような処理、もしくは記載にしておくこと!無限ループしちゃいますよ!!
もし、無限ループを起こしてしまった場合は、対象フローの「実行履歴」より、実行中のフローを選択し、右上にある「キャンセル」を押してフローの実行をキャンセルしてください。
なお、この方法でキャンセルした場合、Do until 内の処理の履歴を確認できないため注意してください。
確認できるようにならないかな...
長くなってきたので、今回はここまでで区切ります。
次回はこの続き、「カウントダウンメッセージ」を送信するから始めたいと思います。
もし不明点や質問、アドバイスなどありましたらコメントや私のTwitter、@koruneko32767までよろしくお願いしますー!