Power Apps で鍋ガチャを作る

# 「鍋ガチャ」とは
具材や調味料をランダムで選出するルーレットのことを指しています。
完成図は以下のTwitterをご覧いただければと思います。

https://twitter.com/eigogakuto/status/1605538072010952705

## 背景
　このアプリは遡ること半年前の友人の一言がキッカケになっています。
　「先生（＝筆者のあだ名）、鍋ガチャをしよう」という友人の狂気に満ちたひとことから生まれました。

　曰く「５つの具材をランダムにピックアップする」のだそうで、当初はExcelのRand関数を使って発生させた乱数をフィルターでソートし、単純に上から５つの具材を抽出するだけのものを考えていたのですが、凝り性の筆者は「エンタメ要素が少ないな…」という欲が出てきました。

　そこでアイディアとして浮かんできたのが「ルーレットアプリ開発」と「具材の擬人化」でした。10分くらいでプロトタイプを見せたところ、とても気に入った様子でしたので完成まで持っていくことにしました。

　…が、このアプリを完成させるためにはコンテンツとなるデータが必須でした。つい先日まで手付かずだったのですが、去る2022年12月20日に行われた「年忘れアプリ発表会」にお招きいただいたことをキッカケに再度着工。100件分だけ暫定的に作ってみました（詳細はデータにて）

　今回は、この鍋ガチャ（以下、鍋娘）の制作背景やデータなどを公開致します。
　皆さんも Let's 鍋ガチャ。

## 画面詳細
### Top Screen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/5d5b36d7-2fc2-7cd2-ca3f-3371c7f68665.png)
　各画面に遷移するためのトップ画面です。
　Navigate関数を用いて各画面に飛ばします。「ガチャる」というボタンには、画面遷移と同時に①鍋ガチャがスタートするように、②SEが再生されるように、OnSelectプロパティに以下の数式を入力しています（...コレクションの数式は不要な気がしますね）

```
ClearCollect(
    colResult,
    Shuffle(NabeMusume)
);
UpdateContext({locValue:!locValue});
Navigate(
    'Main Screen',
    ScreenTransition.Fade
)
```

　また、アプリ側からSharePointリストのデータソースを編集したり新規入力したりもできるように工夫しています。ヘッダー右側の鍋の画像をクリックすると、パスワード入力を求められます。パスワードを入力して確定ボタンを押したら Config Screen に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/8d8ce2f3-1554-e854-7d44-8d0156bfd3bc.png)
鍋画像のOnSelectプロパティ
```
Reset(txtPassWord);
SetFocus(txtPassWord);
UpdateContext({locPass:!locPass})
```
確定ボタンのOnSelectプロパティ
```
UpdateContext({locPass: !locPass});
If(
    txtPassWord.Text = "任意のパスワード",
    Navigate(
        'Config Screen',
        ScreenTransition.Fade
    ),
    Notify("パスワードが違います")
)
```
　なお、コンテクスト変数のlocPassは、パスワード入力画面に関わる各コントロールのVisibleプロパティを操作しています。

### Main Screen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/6f5fc00c-5389-0b56-71dc-b03b0a98b90d.png)

　メイン画面です。
　主なコントロールは、①タイマー、②音源（ドラムロールとドラムロールエンド）、③音源を切り替えたり再生したりするためのトグル、④シャッフルしたデータを上から５つ抽出して表示するためのギャラリー、⑤鍋娘の紹介文を表示するためのギャラリー、の５つです。

　タイマーコントロールのDurationプロパティを1/100秒くらいにセットし、タイマーの自動再生と繰り返しをtrueに切り替えます。また、タイマーが終了したタイミングでコレクション（colResult）にシャッフルした結果が格納される仕組みを作ります。OnTimerEndプロパティに以下の数式を入力しています。
```
ClearCollect(colResult,Shuffle(NabeMusume))
```
　ボタン（タイマーコントロール）を押したらトグルが切り替わり、音源と共にタイマーも止まる仕組みになっています。
　まずは音源を再生したり止めたりするトグルを制御する数式をタイマーコントロールのOnSelectプロパティに入力します。
```
UpdateContext({locValue:!locValue})
```
　再生するオーディオのStartプロパティにそれぞれ以下の数式を入力します。
```
【ドラムロール】
　If(tglSwitch.Value=false,true,false)
【ドラムロールエンド】
　If(tglSwitch.Value=true,true,false)
```
　さらに、このトグルコントローが切り替わるごとに音源がリセットされるようにも設定しました。OnCheckプロパティとOnUnCheckプロパティにそれぞれオーディオをリセットする関数を入力します。

```
【ドラムロール】
　Reset(audDrum)
【ドラムロールエンド】
　Reset(audDrumEnd)
```
　要点をまとめると、トグルコントロールの切り替えで音源を制御するようにしています。
　そのトグルスイッチのtrue/falseを切り替えるのにlocValueをタイマーコントロールのOnSelectプロパティに入力しています。
　
　ギャラリーの設定については割愛させてもらいます。FirstN関数で上から５つ取ってくるものと、そのギャラリーで選択されているデータが中心のギャラリーに表示されるようにItemsプロパティを設定しました。

### List Screen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/5892f95e-69a0-c382-6bd4-c5ba3440a43b.png)
　鍋娘のデータが一覧で確認できるスクリーンです。垂直ギャラリーの折り返しの数を4に設定しただけのものです。＞ アイコンを押したら画面遷移し、任意の鍋娘のデータを確認できるようになっています。
```
Navigate('View Screen');
Set(glbCount,ThisItem.ID);
ClearCollect(colCount,NabeMusume)
```
　ここでグローバル変数を用いた理由とデータソースのNabeMusumeをcolCountとして配列化した理由は、次のViewScreenで明らかになります。

### View Screen
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/de1536b4-5d8a-d0d1-a151-73a4efc1b6d2.png)
　List Screenに戻らなくても、ページ送りで鍋娘のデータを確認できるようにしました。
　一応ユーザーのことを考えています。

　前ページに戻るボタンには、先ほどのグローバル変数から-1するように、次ページに進むボタンには、先ほどのグローバル変数に+1するようにOnSelectプロパティに数式を入力しています。図鑑（List Screen）に戻った時には変数を0とし、きちんと選択されたデータが表示されるようにしておきます。
```
【前】
　Set(glbCount,glbCount-1)
【次】
　Set(glbCount,glbCount+1)
【図鑑に戻る】
　Set(glbCount,0);
　Navigate('List Screen',Fade)
```
　中央のギャラリーのItemsプロパティは、LookUp関数を使ってIDと変数が一致したものを表示する仕組みとなっています。
```
LookUp(colCount,ID=glbCount)
```
　あとはDisplayModeプロパティに条件分岐をかけて終いです。前ボタンにはglbCountが1だったらDisabled、次ボタンにはレコードが増えていくことを見越してglbCountとcolCountのレコード数が一致していたらDisabledとなるようにしました。

```
【前】
　If(glbCount=1,Disabled,Edit)
【次】
　If(glbCount=CountRows(colCount),Disabled,Edit)
```
　なお、List Screen のコレクション（colCount）は委任回避で入れました。~~こんなアプリのくせに…。~~

### Config Screen 以下
　残りは~~面倒だったので~~フォームコントロールを使ってSharepointリストのデータソースを編集できるようにしたものです。特別なことはしていません。SubmitForm関数、EditForm関数、NewForm関数を組み合わせてフォームコントロールを操作するだけで作業終了です。

## データ
　「紹介文を読みたい」という方々が多くいらっしゃったのですが、全体に向けた公開は現時点で考えていません。ただ、記事の反応が良かったら考えてみようかな…というところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2952933/59f29898-7722-0372-7bdf-a68e4dd9702f.png)
　食べ物で遊ぶのは良くないという理性は持ち合わせていたようなので、全ての食材は「鍋として成立しそうな具材」に限定しています。SharePointリストの「Name（名前）」フィールドには一意の値が入るようにしておいて重複を避けられるようにしています。

　余談ですが、体感的にExcelよりもSharePointリストを使うとアプリ作成が楽になりますね。もちろん作るアプリによって向き不向きはあるのですが、登録者や時間が自動で入りますし、精度の高いデータを気楽に作れるような気がします。なんとなくですが、今後はSharePointとTeamsが業務を支える基幹になっていくのかもしれません。

# 今後の課題
　Power Apps の良いところは、こういうアイディアを形にしやすくなったところだと改めて感じます。これ以上、このアプリケーションに力を費やすことはしませんが、自分が「こんなアプリがあったらいいな」と思ったものを色々と作ってみたいですね。