登録した英単語をランダムにプッシュ通知して出題

#概要
- PowerPlatformの学習にはまだまだ英語情報しかないものも多く、最新の情報を仕入れるには英語資料の読解が不可欠です。(これに限らずですが)
- 以前から知らない英単語がでてきたら意味を調べ、OneNoteに記録していました。
- ただ、普段出てこないものや復習しないものは忘れてしまいます。
- そこで、PowerAutomateを使ってOneNoteに記録した英単語をランダムに出題し、覚えているかどうか確認できるようなものができないかと考えました。　※最終的にPowerAppsとなりました。
- 出題方法はプッシュ通知で、スマホアプリをインストールすることでPowerAutomateから通知を送ることができるので、これを活用してみました。

#OneNote編(失敗)
SharePoint+PowerAppsもありでしたが、手軽で今ある英単語をそのまま使えるOneNoteを選択しました。
プッシュ通知とNoteの表示はスマホなのでスマホアプリもインストールします。

完成版のフロー全体全体は↓のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/e0ff5c85-fa1b-e6e9-c40c-f2abd6928378.png)

###フローの説明
1. トリガーは「スケジュール済みクラウドフロー」で、毎朝、晩に実行するように設定。

2. OneNoteの構造はノートブック→セクション→ページなのでまずセクションを取得。
すると、ページのId、タイトル、Urlといった情報が配列となって出力されます。
※一旦テストを実行してどのようなjsonが返されるか確認します。

3. 各変数の部分は以下の通りです。

▼ページ数(配列のサイズ)を取得

``` JavaScript:ページ数(数値)
length(body('特定のセクションのページを取得')?['value'])
```


▼乱数を生成(0～ページ数-1)

``` JavaScript:取得するページインデックス(数値)
rand(0,variables('CountPages'))
```
※'21/1/18修正：randの第二引数の-1を削除しました。rand関数はrand(0,10)とすると0～9を返すため。

▼先程の乱数を使用して、ページ配列から一ページを取り出します。

``` JavaScript:対象ページ(オブジェクト型)
body('特定のセクションのページを取得')?['value'][variables('ページインデックス')]
```


▼先程の対象ページオブジェクトからタイトルを取り出します

``` JavaScript:ページタイトル(文字列)
variables('対象ページ')?['title']
```

▼対象ページ.links.oneNoteClientUrl.hrefを取り出します

``` JavaScript:oneNoteClientUrl(文字列)
variables('対象ページ')?['links']?['oneNoteClientUrl']?['href']
```
.
4. スマホへのプッシュ通知は以下のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/a6732985-b8d8-318c-bd20-a20a68f65203.png)

ページタイトル(英単語)で通知して、アプリ画面でOneNoteへのリンクを開いて答え合わせを行うような流れです。
Androidの場合oneNoteClientUrlを渡せばOneNoteのアプリで開けました。
※ただ、OneNoteを事前に起動していないとなぜか違うページが表示されてしまいます・・

とりあえずこれで上手くいったように見えました。

ページが増えていったとき、何ページまで取得できるのかが気になり色々調べました。
結果、OneNoteのコネクタは最新20ページしか取得できないことが判明／(^o^)＼
[OneNote GetPagesInSection returns only 20 results](https://powerusers.microsoft.com/t5/Building-Flows/OneNote-GetPagesInSection-returns-only-20-results/td-p/302446)

せめて100とかならセクションを分けてセクションもランダムにするなどの対応が考えられるのですが・・・
GraphAPIを呼び出せば対応できるようですが、プレミアムが必要なため断念。

素直にSharePointとPowerAppsで作ります。

#PowerApps編
###①SharePoint
1. 英単語の記録はSharePointリストで、列構成は以下のように設定。

|  列名  |    データ型    |       備考      |
|:------:|:--------------:|:---------------:|
| 英単語 | 1行テキスト    | Title列名を変更 |
| 意味   | 複数行テキスト |                 |
| 習熟度 | 整数           | 0～3            |
| 出題数 | 整数           |                 |

###②PowerAutomate
1. 「複数項目の取得」は2000アイテム程度取得できるようにします。
2. ランダム部分はOneNoteのときと同じです。
3. ここで出題数を加算しておきます。
4. PowerAppsにパラメータ付きでプッシュ通知を送信します。
5. パラメータは`{"ItemID": variables('ItemID')}`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/ab0413d2-8a34-3cdf-3d45-2ecc6fca25b3.png)

###③PowerApps
1. パラメータはAppのOnStartで取得。
2. `Set(ParamID,Value(Param("ItemID"))`で一旦変数に入れ、1以上の場合はパラメータありとして英単語画面にNavigateします。
3. 英単語画面のEditFormのItemは以下のようにし、ホーム画面のギャラリーから移動する画面と共通化しました。

 ``` JavaScript:
 If(ParamID > 0,
  LookUp(英単語リスト,ID = ParamID),
  Gallery_Words.Selected
 )
 ```
_
4. 英単語画面のOnHiddenでParamIDを0に戻しギャラリーのアイテムを表示できるように。

作成したアプリ画面。左がホーム画面、右が単語画面。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/912a06c2-95db-972e-efdf-febbeb52ce3b.png)　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293667/d865de5b-aecb-3cf0-6b84-18fe2a15b865.png)

これでAutomateからにプッシュ通知が届き、スマホの通知バーをタップするとアプリが開いて英単語の意味を確認できます。
覚えたと思ったら編集画面にして習熟度を設定します。

ただ、これもPowerAppsが裏で起動していると前回の画面が表示され、パラメータが取得できません・・・
今の所一日一回くらいならPowerAppsが上手くキルされてちゃんと表示されます。

#あとがき
覚えたかどうかを感覚で表す「習熟度」はスターで表示できるコンポーネントを作成しました。タップで設定も可能です。(後日記事に)
出題数や習熟度の数値があるので、これを使ってアプリから問題を出すこともできそうです。

PowerApps版はOneNoteでのやり方に問題があることを知ってから半日足らずで作成できました。
このようなアプリが短時間で作成できるPowerPlatform素敵ですね。