クソゲーのキャラクターシート登録所みたいなものを作成する3

# おさらい
- [クソゲーのキャラクターシート登録所みたいなものを作成する - Qiita](https://qiita.com/ragingalpaca/items/288869bcf22590783e8c)
- [クソゲーのキャラクターシート登録所みたいなものを作成する2 - Qiita](https://qiita.com/ragingalpaca/items/5bfb457d3fe28abc1f0d)

もう誰も横浜の果てで涙という名の同窓会だけ見えないRPGのキャラシ保管庫を作成しています。

# やりたいことは
前回でダミーデータは表示できるようになったので、あと最低限必要なのは

- 実際の俺表データを格納する
- 俺表を取得できるようにする
- キャラクターデータを保存する

くらいですかね。
保存の方式がちょっとあやふやなんですけど。

ちゃちゃっと進めていきます。

# 製造
## 実際のデータを作る
データをよくよく見たら、「〜〜の〜〜で」が実質１つの項目になっていました。
「会社のエリートで」みたいな感じですね。

なので設定は８つではなく６つになります。
あとで修正せねば……。

https://github.com/takoyakibot/moumienairpg/blob/master/Mienai.rb

idに関しては、「〜〜の〜〜で」がどちらも18種類、表の顔の「。」が12種類、裏の顔の「し・だし・。」が36種類。
ということは3桁でこんな感じで番号を振れば良さそうです。

設定|番号範囲|
:--|:--:|
表の「〜の〜で」|101〜118
表の「。」|201〜212
裏の「〜の〜で」|301〜318
裏の「し・だし・。」|401〜436

データの方は以前に作成したダイスボットから持ってきて、Seederに配列を作り。
foreachで１件ずつinsertしました。
単純。


## 俺表を取得できるようにする
ボタンを押すと、一旦コントローラーに入力情報をpostする。
その後、データを取得したりなんなりして更新した変数を引数として、改めてビューを開き直す。

そんな感じですかね……？

### ビュー
データが無いときにだけ俺表取得ボタンを押せるようにします。

俺表関連のパラメータ（なんでもいい）のemptyを判定する`@if`とかで括ればOKですね。

**やることはそれだけ……と思っていたんですが、魔が差して、気がついたらほぼ１日かけてめっちゃレスポンシブ対応してました。**

![スクリーンショット 2018-05-11 15.45.06.jpg](https://qiita-image-store.s3.amazonaws.com/0/214031/dda608b7-32bc-6a5a-eb60-710af4d270e1.jpeg)

ちなみに配列にしたいとか言ってた部分ですが、軽く調べて『mysqlの型に配列はない』と書いてあってそりゃそうだってなりました（馬鹿）。

というわけで、処理の前段で配列を作るようにしました。

#### 競合対策（気の迷い）
さて、このボタンを押すと現在の入力内容をpostしつつリダイレクトで戻ってくるわけですが。

**保存も当然postなので競合します。**

ボタンのnameで判定して、コントローラー側で分岐すればいいみたいです。

- [LaravelのFormで複数Submitボタンを設置したいときのハンドリング方法 - Qiita](https://qiita.com/okoysm/items/fa3f091aac0eb9ac9dcc)

まあ、今はスルーで。


### ルーティング
```php:web.php
Route::post('/actor/{id_rand}', 'CharacterController@submit');

```

新規作成時点でもid_randは内部的には取得しているので、それをくっつけて渡してやります。




### コントローラー
基本的に入力内容を$characterに格納して、もう一度actorビューに戻るわけですが。
たぶん保存機能も同じことをしそうです。

えっと……

```php:
    protected function submit(Request $request, $id_rand = '')
    {
        $character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);

        // $character情報を更新する
        $character = array_merge($character, $request);

        // 俺表取得の場合
        if (Input::get('createOre'))
        {
            // 取得範囲は決まっているので、ここではore_idを決定するだけ
            //表の「〜の〜で」|101〜118
            //表の「。」|201〜212
            //裏の「〜の〜で」|301〜318
            //裏の「し・だし・。」|401〜436
            $character->omote1_id = rand(101, 118);
            $character->omote2_id = rand(201, 212);
            $character->ura1_id = rand(301, 318);
            $character->ura2_id = rand(401, 436);
            $character->ura3_id = rand(401, 436);
            $character->ura4_id = rand(401, 436);
        }

        // 真実に気付いてしまったので中断

```

嫌なことに気付きました。


## 気付いてしまった
**一回しか押せないボタンとか意味ないですね？**

最初から値が入ってる変数を渡せばいいだけでした。
（あと微妙に、入力内容を持ったまま戻ってくるのが面倒そう……）

というわけで修正していきます。


###　コントローラー
```php:CharacterController.php（修正）
    public function show($id_rand = '')
    {
        $character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);
        if (empty($character->id_rand))
        {
            $character->id_rand = str_random(20);

            //表の「〜の〜で」|101〜118
            //表の「。」|201〜212
            //裏の「〜の〜で」|301〜318
            //裏の「し・だし・。」|401〜436
            $character->omote1_id = rand(101, 118);
            $character->omote2_id = rand(201, 212);
            $character->ura1_id = rand(301, 318);
            $character->ura2_id = rand(401, 436);
            $character->ura3_id = rand(401, 436);
            $character->ura4_id = rand(401, 436);}

        return view('actor')->with([
            'character' => $character,
            'ore' => $this->getOre($character),
        ]);
    }

```

新規作成のときにid_randと一緒に俺表のidを渡してやることにします。

ちなみに、俺表のidはキャラシ画面では表示しないものの、何処かに保存しておく必要があるのでhiddenで持っておくようにしています。


## キャラクターデータを保存する
俺表ができてしまったので、submitというか保存機能を修正します。

### ビュー
```php:actor.blade.php（修正）
<script type="text/javascript">
    function checkPassword ()
    {
        try
        {
            // passwordを取得
            var p = document.f.password.value;

            // 空文字でなければハッシュ値を生成
            if (p != '') document.f.password_hash.value = getHash(p);

            var current_password = '{{ $character->password_hash }}';

            // 現在のパスワードが空なら何が来てもtrue（パスワードは新しいものに変わる）
            if (current_password == '' || current_password == document.f.password_hash.value)
            {
                // パスワードはPOSTさせない
                document.f.password.value = '';
                return true;
            }

            alert('パスワードが違います');
            return false;
        }
        catch (e)
        {
            console.log(e);
            alert('やばたん');
        }
        finally
        {
            return false;
        }
    }

    function getHash(str)
    {
        var shaObj = new jsSHA("SHA-256", "TEXT");
        shaObj.update(str);
        var hash = shaObj.getHash("HEX");
        return hash;
    }
</script>

〜〜〜〜〜

        <div class="row my-5">
            <div class="col-12 px-3">
                <div class="row mb-3">
                    <div class="col-3 col-md-4 mb-1 px-1">
                        <input type="password" class="form-control" id="password" name="password" value="">
                        <input type="hidden" class="form-control" name="password_hash" value="">
                    </div>
                    <div class="col-3 col-md-4 mb-1">
                        <input type="submit" class="btn btn-primary form-control" name="save" value="保存" onclick="return checkPassword();">
                    </div>
                </div>
                <div class="row">
                    <div class="col small">※パスワードは入力しないでも保存ができますが、一度入力するとそれ以降同じパスワードの入力が必要になります。</div>
                </div>
            </div>
        </div>

```
申し訳程度にパスワードをつけました。
SNSログインとはなんだったのか。

パスワードはハッシュなので気軽に持ってきています。
入力された値のハッシュ値と比較します。

- [JavaScriptでSHAハッシュを作りたくなったときに読み返すためのメモランダム | 自主的20%るぅる](https://www.agent-grow.com/self20percent/2017/01/31/articles-for-reference-when-generate-sha-hashes-using-javascript/)

パスワードがなにもない場合は特に変更しないようにしています。
パスワードがない状態でパスワードが入力された場合は、素通しして以降そのパスワードが有効になります。
怖い。

パスワードがある場合は、普通にハッシュ値を比較します。


### マイグレーション
```php:create_characters_table.php
            $table->string('password_hash')->nullable();

```

パスワードの項目を追加します。


### コントローラー

```php:CharacterController.php（修正）
    protected function submit(Request $request, $id_rand = '')
    {
        $character = null_escape(Character::where('id_rand', $id_rand)->first(), new Character);

        // $character情報を更新する
        if (empty($character->id_rand)) $character->id_rand = $id_rand;
        $character->password_hash = $request->password_hash;
        $character->player_name = $request->player_name;
        $character->actor_name = $request->actor_name;
        $character->organization = $request->organization;
        $character->age = $request->age;
        $character->gender = $request->gender;
        $character->photo = $request->photo;
        $character->good = $request->good;
        $character->evil = $request->evil;
        $character->social = $request->social;
        $character->most_important = $request->most_important;
        $character->omote1_id = $request->omote1_id;
        $character->omote1_free = $request->omote1_free;
        $character->omote2_id = $request->omote2_id;
        $character->omote2_free = $request->omote2_free;
        $character->ura1_id = $request->ura1_id;
        $character->ura1_free = $request->ura1_free;
        $character->ura2_id = $request->ura2_id;
        $character->ura2_free = $request->ura2_free;
        $character->ura3_id = $request->ura3_id;
        $character->ura3_free = $request->ura3_free;
        $character->ura4_id = $request->ura4_id;
        $character->ura4_free = $request->ura4_free;
        $character->kill1 = $request->kill1;
        $character->kill2 = $request->kill2;
        $character->kill3 = $request->kill3;
        $character->kill4 = $request->kill4;
        $character->kill5 = $request->kill5;
        $character->memo = $request->memo;

        $character->save();

        return redirect('/actor/'.$character->id_rand);
    }

```

array_mergeとか使えるかなーとか期待したんですが、arrayじゃねーよって怒られました。
地道に全項目をぶち込んでます。


## とりあえず一通りできた……？

画像アップロードとかログインとか、やりたかったけど後回しにしている部分が残ってますが。
とりあえず最低限動くようになりました。

やったー。

最大文字数とかその辺の制御をほっぽってるので何かしらエラーは吐きそうですけど……。

あとはあれですね。

**actor.blade.phpで上昇したbootstrapの知識をもとにしてcharacters.blade.phpを見るとありえん汚い**

という点にどこまで折り合いをつけるかですね……。