【自作PC】自作PCに限っての2019振り返り

全体的な振り返りはこちらにまとめましたが、

ここでは自作PCに限定して振り返ります。

いやーメモリ32GBのRyzenPC、メインPCとしてバリバリ活躍しています。

でもその道も平坦では無くて。

特に躓いたのが、メモリ4枚挿し。

結局諦めましたからね。

拡張性を考慮してメモリスロット4つのマザーボードを購入しましたが、これだったら2枚のマザーボードでも良かったじゃん、って感じです。

2枚差しだったらもっと安いマザーボード買える。

そして、メモリーはショップで相性保証を付ける方が良い。

自作PCで動作しない、という症状は、主にマザーボードとメモリーの相性だったりします。あとは、きちんと刺さってなかったり。

例えばツクモの相性保証を付ければ、相性が合わなくて動作しなかった場合、1ヶ月以内だったらパーツ交換してくれるというやつです。

相性問題が発生してもリスクが少ないので、相性保証付けた方が、結果敵にお得です。

あと、コストのことを考えたら、AMD系の方が圧倒的有利だと思いました。

世代が変わってもソケットの規格が同じ(AM4)なので、マザー自体を変えなくちゃいけない、と言うことが少ないためです。

Intel系は世代毎にソケットの規格が異なったりするので、マザーを変える必要があります。

マザーを変えると言うことは、また相性問題が発生する可能性がある、ということです。

このリスクを考えると、AMD系のほうがかなりお得だと思います。

今Ryzen5 3400Gを使用していますが、これをワンランク上の第3世代Ryzen7に買えるとしても、ソケットの規格が同じAM4なので、CPUを交換するだけで対応出来ます。

まぁ、AMD系CPUの欠点は足が曲がりやすいので取り扱い注意と言うことですかね。

最近大きな買い物をしてしまったのでd、次の収入があるまで我慢ですが、次は第3世代のRyzenにパワーアップさせたいですね。

2019年を振り返る

みなさま、年末いかがお過ごしでしょうか。

お掃除は終わりましたか?

年越し蕎麦とおせちーは準備できましたか?

オイラは準備万端です。

おせちーは注文したものがお昼に届くので、解凍すれば明日には食べられるはずです。

たぶん、年末年始は部屋に篭もってると思います。

寒いもん。

外出したくない。

さて、今年の振り返りですが、一番大きな出来事としては、やはり仕事を退職したことでしょうか。

でも、悪いことだけじゃ無く、時間が十分すぎるほどできたので、いろんなことに挑戦できました。

ブログも頻繁に更新し、自作PCにも挑戦、ジビエ料理にも挑戦、たまーに旅行にも行きました。

ブログは退職前と比べると、アクセス数が増えまして、ようやくマシな額の収益が出るようになりました。

特に良かったのがTechCommitというプログラマーとしてのスキルアップを目指す人達のコミュニティ。

勉強した内容をブログにまとめて、学習日報にリンクを貼り付け、ということをしていたら結構アクセスが伸びました。

でもまだ現金化できないので、まずは、1ヶ月で現金化できるのを目標に頑張ってみようと思います。

時間もたっぷりあるし、お金にも困っていない、まぁ、ぼちぼち頑張ります。

ジビエ料理も良かったっすね。

Twitterの反応が良かった。

動画撮るのも面白かったし。

再生数は伸びないけど。

まだ面白い食材のネタはあるので、今後も続けてみたいと思います。

もっと良いカメラが欲しいなぁ。

逆に後悔していることは、旅行にかかった費用。

特にタイムズカーシェアで留萌に行ったときは失敗した。

長距離ライドしたときは距離料金取られて金額が万超えていたしね。

レンタカー借りた方が安かったよ。

それぐらいかなぁ。

来年もこの調子でいけたら良いなぁ。

あったかくなったらキャンプとかやってみたいですね。

というわけで、良いお年をー

【Laravel】【Vue.js】【ホテル予約管理】チェックアウト一覧を表示

前回までの状況はこちら

予約一覧から本日チェックアウトする部屋を探して画面に表示させます。

View

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">本日のチェックアウト時刻</div>

                <div class="panel-body">
                    <table class="checkout">
                        <tr>
                            <th class="name">部屋</th>
                            <th class="time">チェックアウト時刻</th>
                        </tr>
                    @foreach ($Lists as $list)
                        <tr>
                            <td class="name">{{ $list->roomname }}</td>
                            <td class="time">{{ $list->checkout }}</td>
                        </tr>
                    @endforeach
                    </table>
                </div>
                <div>{{ Html::link('/management', '戻る', ['class' => 'btn']) }}</div>
            </div>
        </div>
    </div>
</div>
@endsection

ルーティング

Route::get('/management/checkout', 'RegisterManagementController@checkout');

コントローラー


    /**
     * 当日のチェックアウト時刻一覧を表示
     */
    public function checkout(Request $request)
    {
        return view('register.checkout',
                        [
                            'Lists' => $this->registerManagement->getCheckoutList()
                        ]);
    }

リポジトリ

    public function getCheckoutList()
    {
        $ret = array();
        $index = 0;
        $checkout = ReserveManagement::select('rooms.name as roomname', 'checkout')
                                    ->leftJoin('reserve_management_room', 'reserve_managements.id', '=', 'reserve_management_room.reserve_management_id')
                                    ->leftJoin('rooms', 'reserve_management_room.room_id', '=', 'rooms.id')
                                    ->get();
        date_default_timezone_set('Asia/Tokyo');
        $today = date("Y-m-d");
        foreach ($checkout as $value) {
            $str = explode(" ", $value->checkout);
            if($today == $str[0]) {
                $value->checkout = $str[1];
                $ret[$index] = $value;
                $index++;
            }
        }
        return $ret;
    }

ここまでアップデートする過程で、checkoutがnullになるケースがあったためか、データベースで日付指定でwhereすると、うまく行かないので、結局、全テーブルから日付を全部チェックする、という処理になりました。

もっとうまくできる方法ないかねぇ。

あと、タイムゾーンも考慮しないと、日付の判定がうまく行かないときがあるので、date()関数を使用するときは注意。

こんな感じで最終チェック後、提出します。

【自作PC】メモリ32GBの世界へようこそ

いやー買っちゃいました。

16GBのメモリ2枚です。

4枚差しが上手くいかないものの、32GBの夢が捨てきれず、買っちゃいました。

32GBの世界へようこそ。

念のためベンチマークを走らせます。

念のため、というのは、もう十分メモリがありすぎるので、劇的な変化は期待していないと言うことです。

もはや道楽の世界。

ちなみに、前回のベンチマークの結果はこちら。

PCMARKでのスコアは若干アップ。

FF14、FF15は誤差のレベルなので、ほとんど変化無しですね。

予想通り。

メモリが4GB→8GBに増やした場合は、プログラム実行時にメモリに空きが無い場合、一番使用されていないメモリのデータをストレージに吐き出して、メモリの容量を確保します。

そして、吐き出したデータが必要になったときにメモリに読み込みます。

この一連の処理をページング、またはスワッピングといいます。

情報処理の試験に出ます。

このときのストレージへのアクセスが、メモリ不足によってPCが遅くなる最大の要因なのです。

でも、16GB以上になると、ほとんどページングが発生することがない。(それだけ十分過ぎるメモリがあるので)

じゃあ、なぜメモリを32GBに増やしたかというと、

道楽ですよ。

とはいえ、このメモリだけでそれなりのお金を使ってしまったので、当分の間は大きな買い物できないな。

次は・・・CPUかな。

パーツ型番価格
CPURyzen 5 3400G20680
マザーボードPRIME A320M-A7544
メモリCT2K16G4DFD822614280
電源KRPW-L5-750W/80+6256
ケースCC-9011086-WW5099
SSDGH-SSDR2SA1202178
M.2SSDSCKKW480H6X15980
グラフィックボードSAPPHIRE PULSE RADEON RX 570 8G GDDR514800
DVDドライブIHAS324-17/A2020
OSWindows 10 Pro3259
電源ユニットネジ200
合計82298

【Laravel】【Vue.js】【ホテル予約管理】予約の削除を実装する

前回までの状況はこちら

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

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

予約詳細画面に削除ボタンを設置します。

                <button @click="closeModal">close</button>
                <button v-if="edit_flg == false" @click="onClickEdit">編集</button>
                <button v-else @click="onClickSave">保存</button>
                <button v-if="edit_flg == false" @click="onClickDelete">削除</button>
            onClickDelete: function() {
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                this.param.id = this.contents.id;
                axios.post('/api/delete', this.param).then(function(response){
                    self.registers = [];
                    self.updateRegisters(self, response.data.registerLists);
                    self.closeModal();
                }).catch(function(error){
                    self.error_flg = true;
                    self.error_message = error.response.data.errors;
                });
            },
            updateRegisters: function(self, registerLists){
                registerLists.forEach(element => {
                    self.registers.push(
                        {
                            id:element.id, 
                            name:element.name,
                            address:element.address,
                            phone:element.phone,
                            num:element.num,
                            roomid:element.roomid,
                            room:element.room,
                            days:element.days,
                            start_day:element.start_day, 
                            checkout:element.checkout
                        }
                    );
                });
            }

APIへのルーティング

Route::post('/api/delete', 'ApiController@delete');
    public function delete(Request $request)
    {
        $this->registerManagement->deleteById($request->id);
        return response()->json(['registerLists' => $this->registerManagement->getListByMonth(
            $request->year,
            $request->month,
            $request->room
        )]);
    }

実際に削除したら、レスポンスで予約一覧を返し、一覧を最新の状態で表示してもらいます。

あとは、一覧更新処理が共通しているので関数化。

難なく設置できました。

・・・追加処理もモーダル化する?

【Laravel】【Vue.js】【ホテル予約管理】予約の編集を行う

前回までの状況はこちら

前回の予約詳細画面。

これに、編集ボタンを追加して、予約編集できるようにします。

これが思いの外大変だった。

まずはテンプレートを編集。

        <div id="overlay" v-show="showContent">
            <div id="content">
                <p v-if="error_flg == true" class="error">{{error_message}}</p>
                <table class="edit">
                    <tbody>
                        <tr>
                            <th>名前</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.name /></td>
                            <td v-else>{{ contents.name }}</td>
                        </tr>
                        <tr>
                            <th>住所</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.address /></td>
                            <td v-else>{{ contents.address }}</td>
                        </tr>
                        <tr>
                            <th>電話番号</th>
                            <td v-if="edit_flg == true"><input type="text" v-model=contents.phone /></td>
                            <td v-else>{{ contents.phone }}</td>
                        </tr>
                        <tr>
                            <th>人数</th>
                            <td v-if="edit_flg == true">
                                <select v-model=contents.num>
                                    <option v-for="num in nums" v-bind:value="num.value">{{ num.text }}</option>
                                </select>
                            </td>
                            <td v-else>{{ contents.num }}</td>
                        </tr>
                        <tr>
                            <th>宿泊部屋</th>
                            <td v-if="edit_flg == true">
                                <select v-model="contents.roomid">
                                    <option v-for="room in rooms" v-bind:value="room.id">{{ room.name }}</option>
                                </select>
                            </td>
                            <td v-else>{{ contents.room }}</td>
                        </tr>
                        <tr>
                            <th>宿泊日数</th>
                            <td v-if="edit_flg == true"><input type="number" v-model=contents.days /></td>
                            <td v-else>{{ contents.days }}</td>
                        </tr>
                        <tr>
                            <th>宿泊日</th>
                            <td v-if="edit_flg == true"><input type="date" v-model=contents.start_day /></td>
                            <td v-else>{{ contents.start_day }}</td>
                        </tr>
                        <tr>
                            <th>チェックアウト</th>
                            <td v-if="edit_flg == true">
                                <select v-model="contents.checkout">
                                    <option v-for="time in timeList" v-bind:value="time.key">{{ time.value }}</option>
                                </select>
                            <td v-else>{{ contents.checkout }}</td>
                        </tr>
                    </tbody>
                </table>
            <p>
                <button @click="closeModal">close</button>
                <button v-if="edit_flg == false" @click="onClickEdit">編集</button>
                <button v-else @click="onClickSave">保存</button>
            </p>
            </div>
        </div>

edit_flgという状態変数を見て、これがtrueならば、タグをinputに置き換える、という作りになっています。

では、データの方はというと、

        data() {
            return {
                error_message: "",
                error_flg:false,
                errors: {},

 中略

                nums: [
                    {text:'1', value:1},
                    {text:'2', value:2}
                ],
                timeList:[],
                selectRoom: 0,
                rooms: [],
                result: [],
                param: {
                    year: 2019,
                    month: 1,
                    room: 1
                },
                registers: [],
                showContent: false,
                contents: {
                    name: "",
                    address: "",
                    phone: "",
                    num: 0,
                    roomid: 0,
                    room: "",
                    days: 0,
                    start_day: "",
                    checkout: "",
                },
                edit_flg: false
            }
        },

ポイントはedit_flg。これをtrueにすることで、テンプレートが編集用に置き換わります。

なお、編集中のテンプレートは、予約追加時と同じくらいの機能を持たなくてはいけません。

もう、予約追加処理も、この中に入れてしまってもいいのかもしれない。

実際の処理は、

        created: function() {
            this.getRooms();
            this.getTimeList();
        },
        methods: {
            getRooms: function() {
                var self = this;
                axios.post('/api/rooms').then(function(response){
                    response.data.roomLists.forEach(element => {
                        self.rooms.push({id:element.id, name:element.name});
                    });
                }).catch(function(error){
                    console.log("失敗しました");
                });
            },
            getRegisters: function() {
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                axios.post('/api/registers', this.param).then(function(response){
                    self.registers = [];
                    response.data.registerLists.forEach(element => {
                        self.registers.push(
                            {
                                id:element.id, 
                                name:element.name,
                                address:element.address,
                                phone:element.phone,
                                num:element.num,
                                roomid:element.roomid,
                                room:element.room,
                                days:element.days,
                                start_day:element.start_day, 
                                checkout:element.checkout
                            }
                        );
                    });
                }).catch(function(error){
                    console.log("失敗しました");
                });
            },
            onClickEdit: function(){
                this.edit_flg = true;
                var checkoutTime = this.contents.checkout.split(" ")[1];
                this.timeList.forEach(element => {
                    if(checkoutTime == element.value+":00"){
                        this.contents.checkout = element.key;
                    }
                });
            },
            onClickSave: function(){
                var self = this;
                this.param.year = this.selectYear;
                this.param.month = this.selectMonth;
                this.param.room = this.selectRoom;
                this.param.contents = this.contents;
                axios.post('/api/update', this.param).then(function(response){
                    self.registers = [];
                    response.data.registerLists.forEach(element => {
                        self.registers.push(
                            {
                                id:element.id, 
                                name:element.name,
                                address:element.address,
                                phone:element.phone,
                                num:element.num,
                                roomid:element.roomid,
                                room:element.room,
                                days:element.days,
                                start_day:element.start_day, 
                                checkout:element.checkout
                            }
                        );
                    });
                    self.closeModal();
                }).catch(function(error){
                    self.error_flg = true;
                    self.error_message = error.response.data.errors;
                });
            },
            openModal: function(id){
                for(var i = 0; i< this.registers.length; i++){
                    if(this.registers[i].id == id){
                        this.contents.id = this.registers[i].id;
                        this.contents.name = this.registers[i].name;
                        this.contents.address = this.registers[i].address;
                        this.contents.phone = this.registers[i].phone;
                        this.contents.num = this.registers[i].num;
                        this.contents.roomid = this.registers[i].roomid;
                        this.contents.room = this.registers[i].room;
                        this.contents.days = this.registers[i].days;
                        this.contents.start_day = this.registers[i].start_day;
                        this.contents.checkout = this.registers[i].checkout;
                        break;
                    }
                }
                this.showContent = true;
                this.edit_flg = false;
            },
            closeModal: function(){
                this.showContent = false;
                this.edit_flg = false;
            },
            getTimeList: function(){
                var self = this;
                axios.post('/api/timelist').then(function(response){
                    for (let [key, value] of Object.entries(response.data.timelist)){
                        self.timeList.push({key: key, value: value});
                    }
                }).catch(function(error){
                    console.log("失敗しました");
                });
            }

onClickEdit()で、詳細画面から、編集画面に切り替わります。

そして、onClickSave()で、入力したデータをLaravel側のAPI処理にデータを渡します。

うん、予約追加もこの中でいいよね。

あと、サーバ側でエラーが発生した場合のメッセージ表示も追加しています。

error_flgがtureになったらテンプレートにもその要素が表示され、API側で送られたメッセージが画面に表示されます。

では、API側の処理。

ルーティングに以下を追加します。

Route::post('/api/update', 'ApiController@update');
Route::post('/api/timelist', 'ApiController@timelist');

処理は、

    public function timelist(Request $request)
    {
        return response()->json(['timelist' => $this->registerManagement->getTimeList()]);
    }

    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["name"],
            $param[1] => $request->contents["address"],
            $param[2] => $request->contents["phone"],
            $param[3] => $request->contents["num"],
            $param[4] => $request->contents["days"],
            $param[5] => $request->contents["start_day"],
            $param[6] => false,
            $param[7] => 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
        )]);
    }

timelist()というのは、データベースで処理するtick値と画面に表示する時刻のテーブルです。

これがあるためにつまずいた。

tick: “時刻(00:00)”

という形でデータを持っていたために、これがうまくVueで処理されないので、JavaScriptで形を変換したのですよ。

このやり方を見つけるのに苦労した・・・。

            getTimeList: function(){
                var self = this;
                axios.post('/api/timelist').then(function(response){
                    for (let [key, value] of Object.entries(response.data.timelist)){
                        self.timeList.push({key: key, value: value});
                    }
                }).catch(function(error){
                    console.log("失敗しました");
                });
            }

ここの処理ね、

[{tick: “時刻(00:00)”},{ },・・・]

このフォーマットを

[{key:tick, value:”時刻”},{ },・・・}

に変換したのですよ。

これを導き出すのに苦労しました。

でも、これができれば今までのサーバ側の処理が、ほぼ、そのまま使えるわけで、

編集画面でも、予約追加と同じことができるようになりました。

っていうか、追加処理もこの形にしよう。

ってなことで次回。

【ジビエ】イノシシのアバラ部分を焼いてみた結果。

前回、イノシシ解体したときにできた、この部分。

アバラの部分です。

これを、ヨシダソースで食べようかと思ったわけです。

ソースに漬けて

焼く。

味は、あんまりおいしくなかった。

なんかいろいろと残念な焼豚って感じで。

そもそも、可食部が少ないので、ボリューム不足と感じたのと、表面の膜を取らなかったので、歯ごたえがぐにょぐにょしていた。

まぁ、こういうときもあるさ。

どんどんいろんな料理を試してみよう。

【自作PC】どうしてもメモリ4枚挿して動かしたい。

前回の様子はこちら。

前回の様子から、電力不足ではないか、と推測して、電源ユニットを購入しました。

玄人志向のATX電源ユニット750W。6200円。

電源容量が400Wから約2倍になりました。

マザーとCPUの電源以外はリバーシブルになっています。

必要ないところは取り外すことができるんですね。

設置。

各線を接続しました。

元々の電源ケーブルが長かったので、延長ケーブルは取り外しました。

メモリも4枚挿してます。

では動作確認。

・・・何も表示されず。

んー、せっかくメモリ2セット買ったのに、もったいない。

いろいろググってみたりして、BIOSの設定(メモリ仕様からタイミングの設定値を調整してみたり、動作周波数を落としてみたり)とかも弄ってみたけど、動く気配無し。

2枚なら動くんですけどね。

こうなったら、4枚挿しは諦めるしかあるまい。

16GBのメモリを2枚購入しましょうかw

32GBは遠いなぁ。

とにもかくにも、電源容量が増えたので、今後も拡張しやすくなったと思います。

現在の構成。

パーツ型番価格
CPURyzen 5 3400G20680
マザーボードPRIME A320M-A7544
メモリHX426C16FW2K2/16 6980
電源KRPW-L5-750W/80+6256
ケースCC-9011086-WW5099
SSDGH-SSDR2SA1202178
M.2SSDSCKKW480H6X15980
グラフィックボードSAPPHIRE PULSE RADEON RX 570 8G GDDR514800
DVDドライブIHAS324-17/A2020
OSWindows 10 Pro3259
電源ユニットネジ200
合計74998

iPadをサブディスプレイに使いたい

2台目のディスプレイを買おうかどうか、悩んでました。

これがオイラのホームポジションの風景。

セカンドディスプレイを設置すると、テレビが見えなくなるのです。

そこで、ふと思いました。

このiPad Proをサブディスプレイにすれば良いのでは?

調べてみると、このアプリを使用すると、iPadをサブディスプレイ化できるようです。

https://ja.duetdisplay.com/

有料アプリで1220円しますが、ディスプレイをもう一台買うに比べれば安い物です。

Windows側にも公式サイトからアプリをダウンロードしてインストールします。

アプリのインストールが終わったら、USBで接続してiPad側のアプリを立ち上げればOK。

自動的にiPadを認識してセカンドディスプレイが現れます。

完全にサブディスプレイです。

しかも、iPad Proって2Kぐらいの解像度にできるんですよ。

文字が小さくて読めないよ。

さらに課金すれば無線LANでサブディスプレイ化できちゃいます。

ワイヤレスにすれば、充電しながらの使用も可能です。

まぁ、有線でも十分ですけどね。

いやでもこれホント便利。

1220円の投資なんて安い物です。