JavaScriptでおみくじを作ってみた

ポートフォリオ用にJavaScript（以下、JS）でおみくじを作ったときの復習的覚え書きです。

- JSはちょっと勉強したけどポートフォリオをどう作っていいのかわからない
- 配列は分かるけどイマイチ使い方にピンとこない
- if文、switch文は分かるけどイマイチ使い方にピンとこない

こんな方（知識は多少あるけどまだ実行できてない人）向けに、何かしらのヒントになれば幸いです。
誤っている点あればご指摘頂けますと助かります。

この記事の内容を実装したサンプルはこちら→ [GitHub](https://github.com/mayegg4869/Portfolio/tree/master/omikuji/simple) / [GitHub Pages](https://mayegg4869.github.io/Portfolio/omikuji/simple)
色々と応用したものがこちら→ [GitHub](https://github.com/mayegg4869/Portfolio/tree/master/omikuji) / [GitHub Pages](https://mayegg4869.github.io/Portfolio/omikuji/)
【注】使ってる値が同じなので2ついっしょにやるとバグります

# １．仕様を決める
まずは作りたいプログラムが何をするか、どんな動作をするかを決めます。いわゆる要件定義です。
今回はおみくじのプログラムを作りたいので、下記のようになります。

:::note
仕様
①おみくじを引くボタンを押すと、運勢がランダムで出る
②運勢に応じてコメントを出したい
③1日1回だけ引けるようにしたい
:::

上記の機能を実装するために、どのような処理が必要かを洗い出します。

①いくつかの運勢の中からランダムで出したい→ **【配列】**
②出た運勢に応じてコメントを出し分けたい→ **【if文 or switch文】**
③当日引いたかどうかを判定したい→ **【if文】**

使う処理は **配列、if文、switch文** に固まりました。
さっそく要件通りになるようコードを書いていきます。

# ２．おみくじの結果を出す部分を作る

仕様①の部分、おみくじの結果を出力する部分を作ります。
ボタンクリックをトリガーとしたいのでindex.htmlにボタンを作ります。
```HTML:index.html
<!-- おみくじを引くボタン -->
<button id="button" type="button" onclick="buttonClick()">おみくじを引く</button>
```

script.jsにはクリックしたときの関数`buttonClick()`を作ります。
その中の変数omikuji_resultに大吉～小吉までの運勢を配列で格納し、
配列の中からランダム抽出しておみくじの結果を出します。

```JS:script.js
function buttonClick() {
    // 運勢の配列を作る
    const omikuji_result = ["大吉", "中吉", "小吉"];
    // ランダムで運勢を決める
    const random = omikuji_result[Math.floor(Math.random() * omikuji_result.length)];
    // コンソールに出力
    console.log(random);
}
```
コンソールで確認してみましょう。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/e7ca1bac-bdb6-e805-14bb-f343bfa15cc8.png)
index.htmlの「おみくじを引く」をボタンを押すと運勢が表示され、クリックのたびランダムで運勢が出力されます。
これでおみくじの結果部分ができました。

# ３．運勢に応じてコメントを分ける

仕様②、ランダムで出てきた運勢に応じて、コメントを出し分けていきます。
この時使えるのはif文もしくはswitch文ですが、このプログラムではswitch文を使用しています。
下記を`console.log(random);`の下に追加します。
```JS
switch(random) {
case '大吉':
    console.log('大吉！　今日はいい日です。');
    break;
case '中吉':
    console.log('中吉！　ちょっといいこと起こるかも。');
    break;
case '小吉':
    console.log('小吉！　そこそこですね');
    break;
default:
    console.log('Error');
};
```
randomの中身が各caseと一致した時、それに応じた処理を書きます。
これをコンソールで確認すると、先ほどの運勢にプラスして、その運勢に応じたコメントも出てきます。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/e83896ed-afc3-ebd3-f9a0-b72c32d629cc.png)
これで運勢に応じたコメントを出し分けることができました。
# ４．おみくじを1日1回引けるようにするための処理

仕様③、一度引いたらその情報を保持して、翌日まで別の運勢が出ないようにします。
`function buttonClick()`の次の行にDateメソッドで本日の日付を取得しておきます。
```JS
// 本日の日付を取得してtodayに今日の日付を代入
const date = new Date();
const today = date.getDate();
```

ここまでだとページを更新した時にデータが消えてしまうので、localStorageを使用します。
※localStorageとは、ユーザーのブラウザ側にデータを保存する機能です。詳細は下記参照。
参考：https://www.granfairs.com/blog/staff/local-storage-01
参考：https://qiita.com/masuda-sankosc/items/cff6131efd6e1b5138e6

使い方は`localStorage.setItem`に値：キーの形式で、switch文の下に記入します。
今回は特に複雑な運用はしないのでどちらも同じ名前に統一させました。
```JS
// lastDayに今日の日付を、lastFortuneに今回の運勢を代入
const lastDay = today;
const lastFortune = random;
// localStorageにそれぞれ日付と運勢を代入
localStorage.setItem('lastDay', lastDay );
localStorage.setItem('lastFortune', lastFortune );
```
これでlocalStorageにおみくじを引いた日付と運勢が記録されました。
これをif文で参照して、当日すでに引いていたら結果を再度出し、引いていなければ新たにランダムで運勢を出すようにします。

```JS
// ifの判定用にlocalStorageのlastDayを変数に代入
const storageLastday = localStorage.getItem('lastDay');
// 最後におみくじを引いた日付＝今日のとき、storage内の運勢を表示する
if (today == storageLastday) {
    // localStorage内の運勢をもってくる
    const storageLastFortune = localStorage.getItem('lastFortune');
    // 当日の結果を再表示する
    document.querySelector('#omikuji_result').innerHTML = ('今日の運勢は' + storageLastFortune + 'です。また明日占いましょう。');
} else {
    // 最後に引いた日＝今日でなければ通常通りおみくじを引く
    // ～中略～
    // おみくじを引いた後に日付と結果を保存する
    const lastDay = today;
    const lastFortune = random;
    // localStorageに保存する
    localStorage.setItem('lastDay', lastDay );
    localStorage.setItem('lastFortune', lastFortune );
    }
```

![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/bfaefcc3-5ebb-d164-e895-d8b8f95af678.png)
ボタンを数回クリックしてみて、2回目以降「今日の運勢は○○です。また明日占いましょう。」と出ていれば成功です。
これで仕様①～③を実装できました。
あとは`console.log`の部分を`innerHTML`にして、ページ上に結果を表示できれば完成です。

# ５．まとめ
下記が完成版のコードになります。

```HTML:index.html
<!DOCTYPE html>
<html lang="jp">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>おみくじ</title>
</head>
<body>
    <!-- おみくじを引くボタン -->
    <button id="button" type="button" onclick="buttonClick()">おみくじを引く</button>
    <!-- 結果出力エリア -->
    <div id="result_area"></div>
    <!-- JS読み込み -->
    <script src="script.js"></script>
</body>
</html>
```

```JS:scriptt.js
// ボタンがクリックされた時に呼び出される関数
function buttonClick() {
    const date = new Date();
    const today = date.getDate();
    // localStorage内の日付をもってくる
    const storageLastday = localStorage.getItem('lastDay');
    if (today == storageLastday) {
        // localStorage内の運勢をもってくる
        const storageLastFortune = localStorage.getItem('lastFortune');
        document.querySelector('#omikuji_result').innerHTML = ('今日の運勢は' + storageLastFortune + 'です。また明日占いましょう。');
    } else {
        // 運勢の配列を作る
        const omikuji_result = ["大吉", "中吉", "小吉"];
        // ランダムで運勢を決める
        const random = omikuji_result[Math.floor(Math.random() * omikuji_result.length)];

        // 運勢に応じてコメントを出す
        switch(random) {
        case '大吉':
            document.querySelector('#omikuji_result').innerHTML = ('大吉！　今日はいい日です。');
            break;
        case '中吉':
            document.querySelector('#omikuji_result').innerHTML = ('中吉！　ちょっといいこと起こるかも。');
            break;
        case '小吉':
            document.querySelector('#omikuji_result').innerHTML = ('小吉！　そこそこですね');
            break;
        default:
            document.querySelector('#omikuji_result').innerHTML = ('Error');
        };
        const lastDay = today;
        const lastFortune = random;
        localStorage.setItem('lastDay', lastDay );
        localStorage.setItem('lastFortune', lastFortune );
    }
}
```

実行してみると、ボタンクリック1回目は画像1枚目、2回目以降は画像2枚目のようになります。
当日中はlocalStorageを削除しない限り、ページを更新しても2枚目のような文言が出るかと思います。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/b2054442-1e37-a3be-984e-3d36b71e575e.png)
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/ae5c7b55-8993-45ae-94f6-1dea5cb99c39.png)
これで仕様①～③を満たしたおみくじプログラムの完成です。
今回はシンプルな作例を紹介しましたが、おみくじの結果を画像にしたりCSSを使用したり等の装飾をするとリッチなポートフォリオになるので、お好みで色々やってみるのも面白いかもしれません。
自分だけのオリジナルおみくじを作りましょう！