taki のすべての投稿

【鬱病】また体調が悪くなってしまいました。

鬱になると体調管理が難しい。

お正月の三が日、年末に買ったビール1箱飲みきってから禁酒生活していましたが、先週水曜日から体調が悪化。

体のだるさは戻ったものの、耳鳴りが止まず辛い生活をしています。

思ったより体重落ちないし。

運動してなかったというのも影響しているかもしれないけど。

とりあえず、禁酒生活7日後にお酒解禁して、落ち込み気味の気分をアルコールの力で相殺していました。

あまりやっちゃいけないことなのかもしれないけど。

仕事復帰のお声もかけてもらってもいるのですが、

今の状態じゃ仕事復帰は難しいかも。

ゴメンナサイしようかな。

明日の朝、耳鳴りが治ってなかったら、ゴメンナサイします。

こんな感じで急に体調悪化するから鬱病は怖い。

体調維持出来るルーティンを見つけなければ。

加齢も加わっているからほんと、体調管理って難しいのよ。

まあ、今日はサウナからの居酒屋ビールで気分をリフレッシュします。

【C#】【数独】マス目のデータをどう持つか、を考える。

前回の状況はこちら。

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/sudoku

前回はファイルからデータを取り出して、int型の二次元配列に取り込む、ということをしましたが、このままでは数独の解析は難しいでしょう。

なので、マス目一つ一つをオブジェクトとして、様々なデータを持つようにしたいと思います。

とりあえず、今考えているのは、

  • 確定した値
  • 確定したかどうか
  • 候補となる数字
  • etc…

とりあえず、これを実装してみたいと思います。

    class Square
    {
        class Candidate
        {
            public bool value1;
            public bool value2;
            public bool value3;
            public bool value4;
            public bool value5;
            public bool value6;
            public bool value7;
            public bool value8;
            public bool value9;

            public Candidate()
            {
                this.value1 = false;
                this.value2 = false;
                this.value3 = false;
                this.value4 = false;
                this.value5 = false;
                this.value6 = false;
                this.value7 = false;
                this.value8 = false;
                this.value9 = false;
            }
        }

        // 確定した数字
        private int _value;
        // 確定したかどうか
        private bool _confirmed;
        // 候補の数字
        private Candidate _candidate;

        public Square()
        {
            this._value = 0;
            this._confirmed = false;
            this._candidate = new Candidate();
        }

        public Square(int val)
        {
            this._value = val;
            if(val == 0)
            {
                this._confirmed = false;
            }
            else
            {
                this._confirmed = true;
            }
            this._candidate = new Candidate();
        }

        public int GetValue()
        {
            return this._value;
        }

        public void SetValue(int val)
        {
            this._value = val;
            this._confirmed = true;
        }

        public bool isConfirmed()
        {
            return this._confirmed;
        }
    }

まずは、こんな感じでマス目のクラスSquareを定義しました。

これで完全とは思っていません。

今後も必要に応じて追加していきます。

これに、ファイルから取得したデータを設定します。

    static class FileAccess
    {
        /**
         * ファイルからデータを取得する
         */
        public static Square[,] OpenFile(string filePath)
        {
            int[,] matrix = new int[9, 9];

            // ファイルを開く
            bool error = false;
            using (var stream = new StreamReader(filePath))
            {
                int row = 0;
                while (stream.EndOfStream == false)
                {
                    string lineText = stream.ReadLine();
                    var val = lineText.Split(',');
                    int col = 0;
                    foreach (var v in val)
                    {
                        int i;
                        if (int.TryParse(v, out i))
                        {
                            matrix[row, col] = i;
                        }
                        else
                        {
                            error = true;
                        }
                        col++;
                    }
                    row++;
                    if (row > 9)
                    {
                        error = true;
                    }
                }
            }
            if (error)
            {
                Console.WriteLine("Illegal format.");
                return null;
            }

            Square[,] ret = new Square[9, 9]; 
            for (int row = 0; row < 9; row++ )
            {
                for(int col = 0; col < 9; col++ )
                {
                    Square sq = new Square(matrix[row, col]);
                    ret[row, col] = sq;
                }
            }

            return ret;
        }

        // debug
        public static void Output(Square[,] sq)
        {
            using (var stream = new StreamWriter(System.Environment.CurrentDirectory + "\\output"))
            {
                for (int row = 0; row < 9; row++)
                {
                    for (int col = 0; col < 9; col++)
                    {
                        stream.Write(sq[row, col].GetValue());
                    }
                    stream.Write("\r\n");
                }
            }
        }
    }

前回のファイルリード、ライト処理をクラス化しました。やっていることに大きな変更はありません。

これで、Main関数もスッキリするはずです。

    class Program
    {
        static void Main(string[] args)
        {
            // パラメータチェック
            if (args.Length != 1)
            {
                Console.WriteLine("usage : sudoku.exe [input file]");
                return;
            }

            // ファイルの存在を確認
            string filePath = Environment.CurrentDirectory + "\\" + args[0];
            if (File.Exists(filePath) == false)
            {
                Console.WriteLine("File not found.");
                return;
            }

            var sq = FileAccess.OpenFile(filePath);
            if(sq == null)
            {
                return;
            }

            // debug
            FileAccess.Output(sq);
        }
    }

前回と同じ結果を取得することができました。

取り込みが美味く機能していることが言えます。

とりあえず、今日はここまで。

実際にロジックを考えてみます。

【Laravel】【ホテル予約管理】予約情報を変更、削除する

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

今回は、予約の編集処理と削除処理を修正します。

まず、UIですが、氏名、住所、電話番号はユーザー登録情報を使用するため、編集画面では、編集不可にします。

                    <tbody>
                        <tr>
                            <th>名前</th>
                            <td>{{ contents.name }}</td>
                        </tr>
                        <tr>
                            <th>住所</th>
                            <td>{{ contents.address }}</td>
                        </tr>
                        <tr>
                            <th>電話番号</th>
                            <td>{{ contents.phone }}</td>
                        </tr>

編集処理では、氏名、住所、電話番号のカラムはテーブルから削除しましたので、パラメータに含めないように修正します。

ログイン中のユーザー情報はAuth::user()を使用します。

予約情報の変更のみなので、ユーザーと予約情報の紐付けは変える必要ありません。

    public function update(Request $request)
    {
        \Log::debug(print_r($request->contents, true));
        if($this->registerManagement->checkScheduleForUpdate($request->contents["start_day"], 
                                                            $request->contents["days"], 
                                                            $request->contents["id"], 
                                                            $request->contents["roomid"]) == false)
        {
            \Log::debug("スケジュールが重複しています");
            return response()->json([
                'errors' => "スケジュールが重複しています"
            ], 400);
        }
        $param = $this->registerManagement->getParam();
        $this->registerManagement->updateById($request->contents["id"],
        [
            $param[0] => $request->contents["num"],
            $param[1] => $request->contents["days"],
            $param[2] => $request->contents["start_day"],
            $param[3] => false,
            $param[4] => date('Y-m-d H:i', strtotime($request->contents["start_day"].' + '.$request->contents["days"].' day') + $request->contents["checkout"])
        ], $request->contents["roomid"]);
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room,
            Auth::id()
        )]);
    }

削除処理は、予約情報の削除と同時に予約情報との紐付けを解除する必要があります。

    public function delete(Request $request)
    {
        $this->registerManagement->deleteById($request->id, Auth::user());
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room,
            Auth::user()
        )]);
    }
    public function deleteById($id, $user)
    {
        $model = $this->getItemById($id);
        $this->detachToUser($model, $user);
        $this->detachToRoom($model, $model->rooms()->first()->id);
        $this->detachToSchedule($model);
        $model->delete();
    }

これでユーザーログインでの修正は完了しました。

次は、管理者ログインでの処理を修正します。

【C#】【数独】ファイルからデータを取り込む

なんか、とあるプログラミングスクールの入学試験でこういう問題は出題されたらしい。

合格できると、スクールの費用が全額無料ということなのですが、やはり、その門のハードルは高いようです。

で、オイラも腕試しで数独(ナンバープレイス)を解くプログラミングをやってみようと思いました。

まずは、問題を読み取るところから。(そこからかよ!)

とにかく、今回はUIは気にしないで、

こんな感じのファイルを取り込んで、デバッグ機能としてそのまま出力するところまでやります。

コードはこんな感じになりました。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace sudoku
{
    class Program
    {
        static void Main(string[] args)
        {
            int[,] matrix = new int[9, 9];

            // パラメータチェック
            if (args.Length != 1)
            {
                Console.WriteLine("usage : sudoku.exe [input file]");
                return;
            }

            // ファイルの存在を確認
            string filePath = Environment.CurrentDirectory + "\\" + args[0];
            if (File.Exists(filePath) == false)
            {
                Console.WriteLine("File not found.");
                return;
            }

            // ファイルを開く
            bool error = false;
            using (var stream = new StreamReader(filePath))
            {
                int row = 0;
                while(stream.EndOfStream == false)
                {
                    string lineText = stream.ReadLine();
                    var val = lineText.Split(',');
                    int col = 0;
                    foreach(var v in val)
                    {
                        int i;
                        if(int.TryParse(v, out i))
                        {
                            matrix[row, col] = i;
                        }
                        else
                        {
                            error = true;
                        }
                        col++;
                    }
                    row++;
                    if(row > 9)
                    {
                        error = true;
                    }
                }
            }
            if (error)
            {
                Console.WriteLine("Illegal format.");
                return;
            }

            // debug
            using (var stream = new StreamWriter(System.Environment.CurrentDirectory + "\\output"))
            {
                for(int row = 0; row < 9; row++)
                {
                    for(int col = 0; col < 9; col++)
                    {
                        stream.Write(matrix[row, col]);
                    }
                    stream.Write("\r\n");
                }
            }
        }
    }
}

実行結果

引数でファイル名を取得する

Main()の引数args[]の中にコマンドパラメータが入っています。

今回使用する引数は、ファイル名1個だけですので、args.lengthが1以外の場合は、usageを表示して終了します。

ファイルの存在を確認する

今回はカレントフォルダに存在するファイルを対象にすることにします。

おそらく相対パスなら大丈夫かもしれませんが、絶対パスならエラーになるでしょう。

対策は後で考えます。力を入れるべきところはここじゃないので。

Environment.CurrentDirectoryにカレントフォルダが入っているので、これにファイル名をくっつけて、完全なファイルパスを作成します。

そして、File.Exists()でファイルの存在を確認します。存在しなければfalseが返るので、エラーメッセージを表示して終了します。

ファイルのデータを取り込む

テキストのデータ読み取りならStreamReaderを使うのが簡単でしょう。

StreamReaderでファイルを開いて、ファイルストリームを取得します。

usingを使うと、usingの中でExceptionが発生しても、適切なtry/catch処理をやってくれます。

まぁ、エラーが起こってもプログラムがファイルを掴んだままにならない、ということです。

usingの中でwhileループをおこない、ReadLine()でファイルから1行ずつ取り出します。

取り出した1行データをsplit()を使って、”,”(カンマ)で分割します。結果はstring[]になります。

これをさらにtryParse()でint型に変換します。

これで読み込んだ文字列が数字に変換されて取り込むことができます。

これを全てのデータに対して行います。

念のためフォーマットエラーも確認します。

まぁ、クラス構成はもうちょっと考えるとして、とりあえずはこんな感じで。

【Laravel】【ホテル予約管理】ユーザーアカウントで予約登録

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

今回はユーザーアカウントでログインした状態で予約登録する場合を作成していきます。

予約登録画面。

今までは宿泊者の情報を入力していますが、今回の仕様変更で、現在ログインしているユーザーの情報を表示させます。

                <table class="edit">
                    <tr>
                        <th>名前</th>
                        <td>{!! $user->name !!}</td>
                    </tr>
                    <tr>
                        <th>住所</th>
                        <td>{!! $user->address !!}</td>
                    </tr>
                    <tr>
                        <th>電話番号</th>
                        <td>{!! $user->phone !!}</td>
                    </tr>
                    <tr>
                        <th>人数</th>
                        <td>{!! Form::select('num', ['1' => 1, '2' => 2]) !!}</td>
                    </tr>
                    <tr>
                        <th>宿泊部屋</th>
                        <td>{!! Form::select('room', $rooms) !!}</td>
                    </tr>
                    <tr>
                        <th>宿泊日数</th>
                        <td>{!! Form::number('days', 1) !!}</td>
                    </tr>
                    <tr>
                        <th>宿泊日</th>
                        <td>{!! Form::date('start_day', \Carbon\Carbon::now()) !!}</td>
                    </tr>
                    <tr>
                        <th>チェックアウト</th>
                        <td>{!! Form::select('checkout', $timelist) !!}</td>
                    </tr>
                </table>
    /**
     * 入力フォーム
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('register.create',
                    [
                        'user' => Auth::user(),
                        'rooms' => $this->roomRepository->getRoomList(),
                        'timelist' => $this->registerManagement->getTimeList()
                    ]
                );
    }

ログイン中のユーザー情報はAuth::user()で簡単に取り出すことができます。

予約登録処理。

まずは、バリデーションルールを修正します。

    public function rules()
    {
        return [
            'num' => 'required|numeric|digits_between:1,2',
            'room' => 'required|numeric',
            'days' => 'required|numeric|digits_between:1,4',
            'start_day' => 'required|date',
        ];
    }

登録するデータを変更します。

class RemoveCalumnReserveManagementTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('reserve_managements', function (Blueprint $table) {
            $table->dropColumn('name');
            $table->dropColumn('address');
            $table->dropColumn('phone');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('reserve_managements', function (Blueprint $table) {
            $table->string('name')->befor('num');
            $table->string('address')->after('name');
            $table->string('phone')->after('address');
        });
    }
}
class AddReserveManagementUserTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('reserve_management_user', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('reserve_management_id')
                  ->foreign('reserve_management_id')
                  ->references('id')->on('reserve_managements')
                  ->onDelete('cascade');
            $table->integer('user_id')
                  ->foreign('user_id')
                  ->references('id')->on('users')
                  ->onDelete('cascade');
            $table->timestamps();
            $table->engine = 'InnoDB';
            $table->charset = 'utf8mb4';
            $table->collation = 'utf8mb4_unicode_ci';
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('reserve_management_user');
    }
}
    private $paramNames = ['num', 'days', 'start_day', 'lodging', 'checkout'];

予約データとユーザーを結びつけます。

データベースの構成はこんな感じになります。

    public function add($param, $room, $user)
    {
        $model = new ReserveManagement;
        foreach($this->paramNames as $name)
        {
            $model->$name = $param[$name];
        }
        $model->save();
        $this->attachToRoom($model, $room);
        $this->attachToSchedule($model);
        $this->attachToUser($model, $user);
    }
    public function attachToUser($model, $user)
    {
        $model->users()->attach($user);
    }

    public function detachToUser($model, $user)
    {
        $model->users()->detach($user);
    }
    public function store(ManagementRequest $request)
    {
        if($this->registerManagement->checkSchedule($request->start_day, 
                                                    $request->days, 
                                                    $request->room) == false)
        {
            return redirect('management/create')
                        ->with(['error' => 'スケジュールが重複します'])
                        ->withInput();
        }
        $param = $this->registerManagement->getParam();
        $this->registerManagement->add([
            $param[0] => $request->num,
            $param[1] => $request->days,
            $param[2] => $request->start_day,
            $param[3] => false,
            $param[4] => date('Y-m-d H:i', strtotime($request->start_day.'+'.$request->days.' day') + $request->checkout)
        ], $request->room, Auth::user());
        return redirect('management');
    }

最後に、登録した情報を予約一覧に表示させます。

ユーザーでログインしているときは、他のユーザーの情報が見えないようにしないといけません。

    public function getList()
    {
        $select = ['reserve_managements.id as id', 'num', 'rooms.id as roomid', 'rooms.name as room', 'days', 'checkout', 'start_day'];
        return ReserveManagement::select($select)
                                    ->where('lodging', false)
                                    ->orderBy('start_day')
                                    ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                    ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                    ->get();
    }

    public function getListByMonth($year, $month, $room, $userId)
    {
        $select = ['reserve_managements.id as id', 'users.name as name', 'users.address as address', 'users.phone as phone', 'num', 'rooms.id as roomid', 'rooms.name as room', 'days', 'checkout', 'start_day'];
        return ReserveManagement::select($select)
                                ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                ->leftJoin('reserve_management_user', 'reserve_managements.id', '=', 'reserve_management_user.reserve_management_id')
                                ->leftJoin('users', 'reserve_management_user.user_id', '=', 'users.id')
                                ->where('start_day', '>=', date('Y-m-d', strtotime('first day of '.$year.'-'.$month)))
                                ->where('start_day', '<=', date('Y-m-d', strtotime('last day of '.$year.'-'.$month)))
                                ->where('reserve_management_room.room_id', $room)
                                ->where('lodging', false)
                                ->where('users.id', $userId)
                                ->orderBy('start_day')
                                ->get();
    }
    public function registers(Request $request)
    {
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room,
            Auth::user()->id
        )]);
    }

まだ十分ではないけれど、そこそこ形になってきました。

【Laravel】【ホテル予約管理】ユーザーアカウントにユーザー情報を含める

前回までの状況はこちら

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

さて、これからどんな形にしていこうかというと、

  • ユーザー登録時にユーザー情報を入力する(フルネーム、住所、電話番号)
  • 予約登録時にはログインユーザーの情報を使用するので、ユーザー情報の入力を省く
  • 部屋ごとに利用できる(空きのある)日と、利用できない(ほかユーザーが予約済み)日をわかるようにする

というのが必要かなと。

まずは、ユーザー登録処理を修正しましょうか。

というわけで、データベースのカラムを追加します。

$ php artisan make:migration move_column_name_address_phone_to_users_table --table=users
class MoveColumnNameAddressPhoneToUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->string('fullname')->after('email');
            $table->string('address')->after('fullname');
            $table->string('phone')->after('address');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('fullname');
            $table->dropColumn('address');
            $table->dropColumn('phone');
        });
    }
}
$ php artisan migrate

これで、usersテーブルにフルネーム、住所、電話番号のカラムが作成されました。

Viewを書き換えます。

                        <div class="form-group{{ $errors->has('fullname') ? ' has-error' : '' }}">
                            <label for="fullname" class="col-md-4 control-label">Full Name</label>

                            <div class="col-md-6">
                                <input id="fullname" type="text" class="form-control" name="fullname" value="{{ old('fullname') }}" required autofocus>

                                @if ($errors->has('fullname'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('fullname') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('address') ? ' has-error' : '' }}">
                            <label for="address" class="col-md-4 control-label">Address</label>

                            <div class="col-md-6">
                                <input id="address" type="text" class="form-control" name="address" value="{{ old('address') }}" required autofocus>

                                @if ($errors->has('address'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('address') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group{{ $errors->has('phone') ? ' has-error' : '' }}">
                            <label for="phone" class="col-md-4 control-label">phone</label>

                            <div class="col-md-6">
                                <input id="phone" type="text" class="form-control" name="phone" value="{{ old('phone') }}" required autofocus>

                                @if ($errors->has('phone'))
                                    <span class="help-block">
                                        <strong>{{ $errors->first('phone') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

register.blade.phpに上の部分を書き足しました。

登録処理も書き換えます。

app/User.phpを以下のように書き換えます。

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'name', 'fullname', 'address', 'phone', 'email', 'password',
    ];

これは、usersテーブルのカラムを設定している箇所です。

これを実際のカラム名に合わせなければ、正しくデータベースに反映されません。

次に、パラメータチェックです。

registerController.phpのバリデートルールを書き足します。

    protected function validator(array $data)
    {
        return Validator::make($data, [
            'name' => 'required|string|max:255',
            'fullname' => 'required|string|max:255',
            'address' => 'required|string|max:255',
            'phone' => 'required|digits:11',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:6|confirmed',
        ]);
    }

そして、実際にユーザーを作る処理。

    protected function create(array $data)
    {
        return User::create([
            'name' => $data['name'],
            'fullname' => $data['fullname'],
            'address' => $data['address'],
            'phone' => $data['phone'],
            'email' => $data['email'],
            'password' => bcrypt($data['password']),
        ]);
    }

これで、ユーザー情報を追加することができました。

【Laravel】【ホテル予約管理】ユーザーの権限管理を行う

最新ソースはこちら(gitHub)

https://github.com/takishita2nd/hotel-mng

さて、お次の課題は、

  • 一般ユーザーからでも予約登録ができる
  • レスポンシブ対応にする

です。

で、そのために必要になるのが、ユーザーの権限管理というものです。

具体的には、管理者用のアカウントを登録して、管理者アカウントからは今までのフル機能が使用できる。

その一方で、通常ユーザーの場合は、一部の機能だけが使用できる、という感じです。

Laravelの権限管理の方法は色々あるようですが、今回は一番簡単なGATEを使用した方法を採用しようと思います。

この方法なら、新たに特別なプラグインを使用する必要がないためです。

では、Userテーブルに還元を管理するカラムroleを追加します。

$ php artisan make:migration add_column_role_users_table --table=users
class AddColumnRoleUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->tinyInteger('role')->default(0)->after('password');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('users', function (Blueprint $table) {
            $table->dropColumn('role');
        });
    }
}
$ php artisan migrate

単純にrole=0が一般ユーザー、role=1が管理者アカウントとします。

では、Seederを使用して、管理者アカウントを予め追加しておきます。

(これを行わないと、管理者権限を与えるユーザーが存在しないことになるので、運用できません!)

$ php artisan make:seeder UsersTableSeeder
class UsersTableSeeder extends Seeder
{
    /**
     * Run the database seeds.
     *
     * @return void
     */
    public function run()
    {
        DB::table('users')->insert([
            'name' => 'manager',
            'email' => 'manager@gmail.com',
            'password' => bcrypt('manager'),
            'role' => 1,
        ]);
    }
}
$ composer dump-autoload
$ php artisan db:seed --class=UsersTableSeeder

登録できました。

次は、AuthServiceProviderのboot()に処理を追加して、GATEによる権限の定義を記入します。

    public function boot()
    {
        $this->registerPolicies();

        Gate::define('manager', function ($user) {
            return ($user->role == 1);
        });
        Gate::define('user', function ($user) {
            return ($user->role == 0);
        });
    }

これで、role=1(manager)、role=0(user)がGATEによって定義されました。

では、Viewを書き換えて、一般ユーザーには不要なメニューを表示させないようにします。

<div class="panel-body">
    <detail-component></detail-component>
    <div>{{ Html::Link('/management/create', '追加', ['class' => 'btn']) }}</div>
</div>
@can('manager')
<div>{{ Html::link('/management/schedule', 'スケジュール', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/management/total', '集計', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/room', '部屋一覧へ', ['class' => 'btn']) }}</div>
<div>{{ Html::link('/management/checkout', '本日のチェックアウト', ['class' => 'btn']) }}</div>
@endcan

ポイントは@can(権限)〜@canend。

@can(権限)に権限の名前を入れることで、ユーザーの権限に対して@can(権限)〜@canendの表示を切り替えることができます。

manager権限

一般ユーザー

こんな感じで、表示の切り替えができました。

では、次回からは一般ユーザーの使い勝手がいいように修正していきましょうか。

ゲーム・ワールドフリッパーを辞めた理由

最初はピンボールを元にできたゲームとして、おっ、新しいな、と思って、楽しんでプレイしていました。

しかーし。

どうしても許せない欠点がありまして。

それは、協力プレイのマッチングが全然成立しない、と言うことです。

このゲームのマッチングシステムはというと、

まず、プレイヤーがルームを作成します。

これだけでは他のプレイヤーはそのルームに入ることはできません。

なので、ルームの建て主が他のプレイヤーを「招待」する必要があります。

招待対象はフォロワー、ランダムなどありますが、

招待を受けたプレイヤーはゲームのプレイ中に割り込み通知があり、参加するかどうかを選択できます。

このシステムがよろしくない。

結局招待できるプレイヤーが少ないから全然人が集まらないし、招待された側も自分の都合があるから断られることが多い。

なので、ルームに人が集まらず、協力プレイができない。

これは重大なシステムの欠陥と言えます。

そして、デイリーミッションに「協力プレイをする」というのが含まれています。

デイリーミッション完了できません。

運営はマッチング成功率とかのデータを取っていないのだろうか。

これじゃあ、ただのオート周回放置ゲーじゃないですか。

それに気づいて、アプリを消しました。

終了。

Ps4のリモートプレイを試す(PC編)

こちらではiOSの場合についてまとめたんですが、

実はリモートプレイって、PCでもできるんですね。

対応OSはWindowsとMacOSです。

https://remoteplay.dl.playstation.net/remoteplay/lang/jp/

やり方は上のサイトからアプリをダウンロード、インストールして、アプリを起動して、PSアカウントでログインする。

ここはiOSと同じ。

PC版で何が違うかというと、PS4のコントローラーはUSBケーブルで優先接続できるというところ。

PS4本体じゃないですよ、PC本体にですよ。

(逆にPCにコントローラーを接続しないと操作ができない)

もちろん、PCにBluetoothのレシーバがあればBluetoothでも接続できるのですが、ペアリングすると、iOSと同じようなペアリング問題が発生します。

でもPCに優先接続なら、優先接続中はPCに、ケーブルを外せばPS4本体に接続されます。

なので、ペアリング問題とは無縁。

まぁ、ネットワークを通じて画面を転送しているので、フレームレートが落ちるので、動きはなめらかじゃないですけどね。

でも、無双OROCHI3とかは問題なくプレイできた。

いいね。悪くない。

PS4のリモートプレイを試す(iOS編)

PS4のリモートプレイは、元々Xperia端末のみで可能でしたが、ちょっと前のアップデートで、他の端末でも利用可能になりました。

しかも、Android端末だけで無く、iOSやPCでも可能になっています。

というのは、今自分はPixel3を使用しているのですが、Pixel3でリモートプレイをしようと思ったら、画面縦置き固定でゲーム画面は上1/3以下のサイズで、画面タップでプレイする、というものでした。

たぶん、PS4コントローラーをベアリングすれば使えると思いますが。

でももっと大きな画面でプレイしたい。

Androidタブレットだとどうなるんですかね?

そもそもAndroidタブレットって、いまそんなに需要無い?(しらんけど)

オイラはiPad Proを持っているので、これに表示できれば、まだマシになるんじゃないかと思いました。

なので、検索。

ありました。

仕組みは、Androidのリモートプレイと同じで、LAN/Wifi経由で画面を表示させます。

アプリを起動して、PSアカウントでログインすると、自動的にネットワーク上のPS4を探してくれます。

ゲーム画面がほぼ全画面に表示され、コントローラーと同じ位置に、各ボタンに対応するタッチエリアがあります。

しかも、PS4コントローラーをBluetoothでiPadとペアリングすれば、PS4コントローラーでプレイできます。

リモートプレイを使用すると、PS4とペアリングしているコントローラーは切断されて使用できないので、コントローラーをiPadとペアリングして使用する必要があります。

ただ、これを元に戻すのが面倒で、まず、iPad側からペアリングを削除する必要があり(コントローラーの電源を入れると、勝手にiPadに接続されます)、PS4とペアリングするにはUSBケーブルで接続する必要があります。

この接続が面倒で、純正ケーブルか、充電・通信ケーブルを使用する必要があります。(充電専用ケーブルではPS4本体とペアリングできない)

まぁ、充電専用ケーブルはケーブル自体が細いから、ケーブルの太さで区別はできるのですが。

まぁ、ややこしい、ということです。

まぁ、こういうリモートプレイもできるんだぞってことで。

Wifi経由で画面に表示させているので、フレームレートはちょっと低い感じがします。