こんにちは、PowerAppsにステ全振りのあんこ先生です。
いつもはアプリの作り方やコントロールの使い方を紹介しているブログやってます。
思いのほか3日目の記事が好評だったため、おかわり記事を書くことにしました。
その際紹介したデイリーミッションの作り方について紹介しようと思います。
デイリーミッションの目的は、ユーザーにワクワクを与えて毎日アプリを起動してもらうことです。
せっかくチームアプリを作ったけど、だれもアクセスしてくれない…
そんな問題を解決する一助になりますよ。
こんなアプリ作って運用してる人です。
アプリでデイリーミッションを作ろう!
デイリーミッションとは
毎日与えられたタスクを達成すると、ポイントが付与される機能のことです。
ソシャゲでよくみかけるアレですね。
期間限定なのでやらないと損した気分になるのか、みなさん夢中になってます。
そんな機能をPowerAppsとPlannerで再現します。
なお、ポイントの使い道はアイデア次第です。
弊社では、アバターの見た目を変えたり、ご褒美スイーツがあったりと色々試してみました。
どうしたらメンバーが喜ぶか考えるのも楽しいですよね。
デイリーミッションのリスト作成
SharePointリスト、コレクションなどご自由に作成してください。
内容を頻繁に変えるならリストがオススメです。
アプリ起動時の1回しか使わないので、直接記述してもいいですね。
レコードの構成と内容は図の通りですが、最悪タイトルさえあれば機能します。
今回はひとまずコレクションcolDMに落としますね。
アプリ起動時に1レコード抽出する
OnStartを使ってアプリ起動時に1レコードを抽出します。
やり方は何通りかあります。
確率が一定でよいならShuffle関数が適任です。
テーブル内のレコードを無作為にかき回します。
あとはFirst関数で最初の1レコードを抜いて変数に格納すれば完了です。
Set(glbDM,First(Shuffle(colDM)))
確率を偏らせたい場合
手っ取り早いのは、確率を高めたい案件の数を増やすことです。
1つ増やせば単純に2倍当たりやすくなりますね。
いやいや、もっと細かく割り当てたい!という場合はひと手間必要です。
まずデイリーミッションのレコードの構成にLow列とHigh列を追加します。
値は重複や漏れがない埋めてください。
そしてRandBetween関数を使ってその範囲内の値をランダムで生成します。
あとは Low<=その値<=High の条件で抜いて変数に格納すれば完了です。
set(glbDM,
With({hit:RandBetween(1,100)},
LookUp(colDM2,Low<=hit && High>=hit)
)
)
デイリーミッションの管理
せっかく抜き取ったデイリーミッションですが、保存しないと消えてしまいます。
そのため、Plannerのタスクとして保存します。
理由は後述しますが、ポイント計算させるなら個人ごとにプランを作成することをオススメします。
また、デイリーミッションと他のタスクを区別できるよう、頭に識別子をつけるか、専用バケットを用意しておきましょう。
今回は専用バケットデイリーミッションを用意しておきました。
ただ、起動するたびにデイリーミッションが作成されては困りますよね。
そのためかんたんな制御を行います。
処理の流れは次の通りです。
昨日以前で完了していないタスクを確認する
はじめに昨日以前の完了していないタスク有無を探します。
デイリーミッションなのでいつまでも残ってたらいけませんからね。
タスクを取得するには2通りあります。
今回はバケットも絞りたいので指定したプランのタスクを返すPlanner.ListTasksV3を使います。
もうひとつPlanner.ListMyTasksV2もありますが、これは自分が参加しているすべてのプランから、自分に割り当てられたタスクを返します。
どちらもテーブル型で帰ってくるため、Filter関数が使えます。
バケットと昨日以前、未完了の条件で絞って結果を確認します。
Filter(Planner.ListTasksV3("プランID","グループIDは空でok").value,
bucketId="バケットID",dueDateTime<Today(),percentComplete<100
)
この中身が空かをIsEmpty関数で調べれば未完了のタスク有無がわかります。
タスクの削除
調査の結果、空でなかった場合はタスクを削除しなければなりません。
タスクを削除するにはPlanner.DeleteTaskを使います。
本来は削除したいタスクidを指定するのですが、めんどくさいので総当たりさせます。
理論上、1件しかタスクは存在しないはずですが念のためです。
ForAll(
Filter(Planner.ListTasksV3("プランID","グループIDは空でok").value,
bucketId="バケットID",dueDateTime<Today(),percentComplete<100
),Planner.DeleteTask(ThisRecord.id)
)
これできれいさっぱりしますね。
今日のタスクがあるか確認する
二重登録を防ぐため、今日のタスクが登録済みでないか確認します。
やり方は昨日分とほぼ同じで、期限を今日に変えて絞り込むだけです。
同様にIsEmpty関数で調べれば登録済みかわかります。
Filter(Planner.ListTasksV3("プランID","グループIDは空でok").value,
bucketId="バケットID",dueDateTime=Today(),percentComplete<100
)
タスクの作成
ようやくデイリーミッションのタスクが登録されます。
タスクを作成するにはPlanner.CreateTaskV4を使います。
サンプルのようにタスクタイトル、バケット、開始日と期限、割り当てを指定します。
Planner.CreateTaskV4("グループIDは空でok","プランID",
glbDM.Title,
{
bucketId:"バケットID",
startDateTime:Today(),
dueDateTime:Today(),
assignments:Office365ユーザー.MyProfileV2().id
}
)
ちなみに上記コードをSet関数で囲むと作成したタスクの情報を変数に格納できます。
とても便利なのでぜひ使ってみてください。
デイリーミッションの細かい作業
デイリーミッションのカード作成
デザインはなんかよさげなものを適当にあてがいます。
コンテナ使うと扱いが容易ですよ。
表示させる情報はタイトルと期日くらいですね。
タスク作成時の変数から各種情報を抜いてきましょう。
このコンテナをデイリーミッション作成時に表示するとわかりやすいですね。
ポイントの集計
可視化は大切です。
ポイントの集計は完了したタスクをCountRows関数で集計するだけです。
今回はバケットが特定されているので、その中の完了タスクを数えるだけですね。
タスクが完了しているかは、percentCompleteが100であるかで判断します。
次のコードで数えられるはずです。
CountRows(Filter(Planner.ListTasksV3("プラン.id","グループID").value,bucketId="バケットID",percentComplete=100))
これでポイント化できましたね。
注意事項
コネクタの制限で、タスクは最新400件までしか抜いてこれません。
つまり自身の全タスクかプラン内の総タスクが400件を超えると正しく集計されなくなります。
そのため、ポイントの集計が目的の場合は個人ごとにプランを用意してください。
一応、フロー経由なら1000件くらいまではいけますが、そこまでしなくてもいいかなとも思います。
デイリーミッションを作ろう!のまとめ
アプリを使ってもらいたいなら、使いたくなる仕組みづくりが効果的です。
デイリーミッションは若い世代ほど食いつきがいいですね。
追加コストがかからないのもポイント高いですね!
ぜひ職場に導入していただきたいお話でした。おしまい。
RandBetween関数を複数使うと別々の値を返すので正しく計算されないよ。