コルネの進捗や備忘録が記されたなにか

進捗や成果物や備忘録てきななにかを雑に更新していきます。

【Power Automate × Microsoft Teams】ワードウルフを作成してみる ~その1~


スポンサードリンク

はじめに

今回はPower Automate と Microsoft Teams を利用して「ワードウルフ」を作成してみようと思います。
ワードウルフってなに?という方も大勢いらっしゃると思うので簡単に説明しますと、

ワードウルフとは、みんなで“あるお題”について話し合う中、「みんなとは異なるお題」を与えられた少数派の人(ワードウルフ)を探し出すゲームです。村人に紛れた人狼を見つけ出す「人狼ゲーム」に似ているので、ワード人狼と呼ばれることもあります。
例えば、下のイラストでは、「えび」というお題を与えられた多数派が市民で、「かに」というお題を与えられた少数派がワードウルフ、ということになります。 f:id:koruneko:20200725180215p:plain
少数派のお題を与えられた人がワードウルフ ただし、ゲーム開始時は、自分がどちらの陣営なのか分かりません。
周囲の会話をヒントに、自分が「市民」なのか「ワードウルフ」なのかを探っていきます。もし「自分のお題が周囲と違うな」と思ったら、あなたがワードウルフかもしれません。その時は周りの会話から「市民のお題」を推理して話を合わせたり嘘をついたりしながら、自分がワードウルフであることがバレないように振る舞いましょう。
お題について話し合った後、多数決で処刑する人を決めます。『ワードウルフを処刑できれば市民チームの勝ち』で、『市民が処刑されればワードウルフの勝ち』となります。

ワード人狼こと『ワードウルフ』のルール・コツ・アプリ3選を徹底紹介!より引用

というゲームです。

処理の流れ

今回作成するフローは以下のようになっています。

f:id:koruneko:20200726172721p:plain

処理の流れは以下のようになっています。

  1. Excel より、参加者の一覧とお題の一覧を取得
  2. 参加者情報の作成
  3. 各参加者の個人チャットにお題を送信
  4. チャネルに開始確認メッセージを送信
  5. 残り時間の通知を行う
  6. 終了のお知らせとともに各参加者のチャットに投票メッセージを送信する
  7. 結果の送信
  8. ゲームの続行を確認

Excel テーブルの作成

今回データはExcel のテーブルに保持しています。
テーブルは2つあり、

  1. 参加者の情報が記載されたテーブル
  2. お題が記載されたテーブル

を用意しています。

まずは「参加者の情報が記載されたテーブル」です。
こちらには、参加者の名前と参加者のメールアドレスを設定します。

f:id:koruneko:20200725184009p:plain

続いて、「お題が記載されたテーブル」です。
こちらには、「市民」用のお題と、「ウルフ」用のお題、そしてそのお題の種類とIndex を割り振っています。

f:id:koruneko:20200725184142p:plain

これらのテーブルはゲームを開始する前に予め作成しておいてください。

Power Automate の作成

変数の宣言

まず初めに今回利用する変数の宣言を行います。

「変数を初期化する」アクションを利用して変数の初期化を行います。

f:id:koruneko:20200726032117p:plain

今回利用する変数はこちらになります。

f:id:koruneko:20200726030110p:plain

変数名 種類 初期値
mention 文字列 -
userArray アレイ -
wolf 整数 0
choise 文字列 -
result アレイ -
voltMessage 文字列 -
resultMessage 文字列 -
isContinue ブール true

変数名は任意に変更してもよいですが、その場合以降の操作でもその都度名前を置き換えてください。

これらの変数の初期化はスコープなどで纏められるとフローの見た目がすっきりするのですが、なにかいい方法ないですかね...

Excel テーブルをPower Automate で読み取り

先ほど作成したExcel テーブルをPower Automate で読み取ります。

「テーブルの取得」アクションを利用してExcel テーブルの読み取りを行います。

f:id:koruneko:20200726032300p:plain

アクションにはそれぞれ作成したExcel が存在する場所を選択し、それぞれにあったテーブルを選択します。

f:id:koruneko:20200726031909p:plain

参加者情報の作成

最初に宣言した変数に参加者情報を作成します。

f:id:koruneko:20200726033009p:plain

変数への設定には、「配列変数に追加」、「文字列変数に追加」、「変数の設定」を利用します。

f:id:koruneko:20200726033525p:plain


「参加者へのメンションの作成」には「文字列変数に追加」アクションを利用します。
値には以下を設定します。

名前

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 の解析

を行っていきたいと思います。

f:id:koruneko:20200726172640p:plain

まずは、index の付与方法について説明します。

「データ操作」より「選択」を選択します。

f:id:koruneko:20200726173151p:plain

作成したら以下のように設定してください。

開始

@{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 の解析」を選択してください。

f:id:koruneko:20200726174125p:plain

設定値は以下のように入力します。

コンテンツ

@{body('選択')}

スキーマ

{
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "Index": {
                "type": "integer"
            },
            "dispName": {
                "type": "string"
            },
            "mention": {
                "type": "string"
            }
        }
    }
}

これまでの説明と同様の設定を行っている場合はこちらのスキーマで大丈夫かと思いますが、設定を変えている。もしくはエラーとなる。などの場合は、実行結果より「選択」の「出力」をコピーし、「サンプルから生成」よりスキーマの作成を行ってください。

参加者確認メッセージをチームに送信する

参加者の確認メッセージをチームに参加者をメンションして送信します。
「メッセージをフローボットとしてチャネルに投稿する」アクションを利用します。

f:id:koruneko:20200726043658p:plain

任意のチーム、チャネルを選択して、送信するメッセージを作成します。

f:id:koruneko:20200726043904p:plain

メッセージは下記のように設定します。

メッセージ

@{variables('mention')}
以上、@{length(variables('userArray'))}人のメンバーでゲームを開始します。

「@{length(variables('userArray'))}」では、userArray に設定してある配列の数を返します。
これにより参加人数をつたえることができますね。

処理をループさせる

これから作成するフローはゲームを続けるが選択されている場合、処理を繰り返すようにしたいです。
具体的にフローの処理風にいいますと、「isContinue」が「true」の場合処理を繰り返し実行させたいと思います。

そこで用いるのが、「Do Until」です。

f:id:koruneko:20200726170312p:plain

ループの実行条件には以下のように記載します。

@equals(variables('isContinue'), false)

これにより、「isContinue」が「false」となったときに「Do Until」処理を抜けるといった風に記載できました。

以降の処理は「Do Until」内に記載していきます。

今回のお題を取得する

お題の取得には「行の取得」を利用します。

f:id:koruneko:20200726170843p:plain

お題は上で取得したお題のテーブルと同様のものを利用します。
違うのは、全て取得するのではなく1行だけ取得するという点です。

f:id:koruneko:20200726170745p:plain

テーブルを選択したら、「キー列」、「キー値」を設定します。
今回「キー列」にはindex が記載されている「index」を設定します。

「キー値」には、以下を設定します。

キー値

@{Rand(1, length(body('お題を一覧表示')?['value']))}

これにより、お題のテーブルに存在する行からランダムに1行取得することができます。

「ワードウルフ」となる参加者を設定

「ワードウルフ」となる参加者を「wolf」という変数に設定します。

「変数の設定」アクションを追加して、以下のように設定します。

名前

wolf

@{rand(1, length(variables('userArray')))}

f:id:koruneko:20200726171953p:plain

これにより、1~参加人数の間の数字がランダムに設定されます。
上で設定したような、参加者情報に記載されているindex とwo;f に設定されている数字が一致したユーザーを「ワードウルフ」として扱えばいいですね!

参加者にお題の送信

続いて参加者に向けてお題を個別に送信する処理を作成します。

f:id:koruneko:20200726205427p:plain

送信するお題は先ほど作成した「wolf」と参加者情報の「Index」を比較して、市民用のお題か、ワードウルフ用のお題を送信します。

「コントロール」より「Apply to each」を選択して、以下のように設定します。

以前の手順から出力を選択

@{body('JSON_の解析')}

送るお題の判定処理です。
「コントロール」より「条件」を選択します。

f:id:koruneko:20200726205744p:plain

条件は「次の値に等しい」を選択します。

左辺

@items('参加者にお題の送信')?['Index']

右辺

@variables('wolf')

参加者へのお題の送信には「メッセージをフローボットとしてユーザーに投稿する」を選択します。

f:id:koruneko:20200726210748p:plain

以下のように入力してください。

ヘッドライン

ワードウルフ

受信者

@{items('参加者にお題の送信')?['mention']}

メッセージ

@{items('参加者にお題の送信')?['dispName']}さん@{uriComponentToString('%0A')}
あなたのワードは「@{body('お題の取得')?['WordsA']}」です。

f:id:koruneko:20200726210845p:plain

「uriComponentToString('%0A')」は改行を表しています。

続いて、誰にどのメッセージを送ったか記録するために変数に文字列を追加します。
「文字列変数に追加」を選択します。

名前

resultMessage

メッセージ

@{items('参加者にお題の送信')?['dispName']}:「@{body('お題の取得')?['WordsA']}」<br>

f:id:koruneko:20200726211310p:plain

作成が完了したら、「いいえ」の処理にも同じような処理を作成してください。
「WordsA」を「WordsB」に変更するだけです。

ゲーム開始の確認

ゲーム開始の確認を行うメッセージをチャネルに投稿します。
送るメッセージはアダプティブカードとし、ユーザーがアクションを起こすまで待機するようにしたいと思います。

Teams のアクションから、「アダプティブ カードを Teams チャネルに投稿して応答を待機」を選択します。

f:id:koruneko:20200727013203p:plain

任意のチャネルを選択したら、「アダプティブカードの編集」を選択してください。

f:id:koruneko:20200727013052p:plain

すると、アダプティブカードの編集エディタが表示されたかと思います。

f:id:koruneko:20200727013536p:plain

こちらのアダプティブカードは、左の「Card Element」と記載のパレットより、デザインエリアにドラッグ & ドロップを行い、「Element Properties」よりプロパティを編集することでアダプティブカードを構築することが可能です。
他にも下の「Card Payload Editor」よりJSON を直接編集して作成することも可能です。

JSON はこちらで作成し、出力することも可能です。Adaptive Cards Designer

また、Hiroさんが、Adaptive Cards 入門用ドキュメントを作成・公開しましたにてAdaptive Cards の解説を行っていますので、是非ご覧になってください!

アダプティブカードの編集を行い以下のようなアダプティブカードを作成してください。
下記JSON を貼り付けることでも作成可能です。

f:id:koruneko:20200727013504p:plain

{
    "$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までよろしくお願いしますー!


スポンサードリンク