【Linux】【Laravel】Laravel5.5をインストールする。

オイラのLinux PCにLaravel5.5をインストールしました。

使用ディストリビューションはUbuntu18.04です。

composerのインストール

$ sudo apt-get install composer

Laravelのインストール

$ composer global require "laravel/installer"

プロジェクトの作成

$ composer create-project --prefer-dist laravel/laravel <プロジェクト名> "5.5.*"

実行すると

You can also run php --ini inside terminal to see which files are used by PHP in CLI mode.

というエラーが出たので、PHPのモジュールを追加。

$ sudo apt-get install php7.2-mbstring
$ sudo apt-get install php7.2-xml

Laravelの実行

$ php artisan serve

を実行した状態で、ブラウザから

http://localhost:8000

にアクセスする。

この画面が表示されればOK。

パーミッション変更

これをやらないとダメらしい。

$ chmod 777 storage/
$ chmod 777 bootstrap/cache/

【プログラミング】勇者と魔王の戦い

Tech commitの課題で、面白そうなテーマだったので、挑戦してみました。

https://github.com/takishita2nd/battle_rpg

  • 勇者と魔王が交互に攻撃する
  • 一定確率で攻撃を回避する
  • 一定確率でクリティカルヒット(ダメージ1.5倍)になる
  • どっちが勝利したかを表示する
using System;

namespace battle_rpg
{
    public static class Common
    {
        public static bool roleJudge(int rate)
        {
            bool judge = false;
            Random r = new Random();
            int value = r.Next(0, 100);
            if(value < rate) {
                judge = true;
            }
            return judge;
        }
    }
}

これは乱数を使って、命中やクリティカル判定などの確率判定を行うメソッドです。

引数に確率(%)を受け取り、乱数を0〜100の範囲で発生させて、その値が確率以下ならばtrueを返します。

using System;

namespace battle_rpg
{
    public class Charactor
    {
        private const String Statusformat = "{0}:HP{1} 攻撃力{2}";
        private const String AttackFormat = "{0}の攻撃!{1}に{2}のダメージ";
        private const String CriticalAttackFormat = "{0}の攻撃!クリティカルヒット!{1}に{2}のダメージ";
        private const String EvasionFormat = "{0}の攻撃!{1}は攻撃をかわした";
        public string Name {get;}
        public int Hp {get; set;}
        public int Attack {get;}
        public int evasionRate { get;}
        public int criticalRate { get;}

        public Charactor(string _name, int _hp, int _attack)
        {
            this.Name = _name;
            this.Hp = _hp;
            this.Attack = _attack;
            this.evasionRate = 5;
            this.criticalRate = 5;
        }

        /**
         * ターゲットを攻撃
         * <param>  _target 攻撃対象
         * <return> 与えたダメージ
         */
        public String doAttack(Charactor _target)
        {
            String message = String.Empty;
            if(isHit(_target)) {
                int damage = this.Attack;
                if(isCritical()) {
                    damage = (int)(damage * 1.5);
                    message = String.Format(CriticalAttackFormat, this.Name, _target.Name, damage);
                } else {
                    message = String.Format(AttackFormat, this.Name, _target.Name, damage);
                }
                _target.Hp -= damage;
            } else {
                message = String.Format(EvasionFormat, this.Name, _target.Name);
            }

            return message;
        }

        /**
         * 命中判定
         * <param>  _target 攻撃対象
         * <return> true:命中
         */
        private bool isHit(Charactor _target)
        {
            bool hit = true;
            if(Common.roleJudge(_target.evasionRate)) {
                hit = false;
            }
            return hit;
        }

        /**
         * クリティカル判定
         * <return> true:クリティカル
         */
        private bool isCritical()
        {
            bool critical = false;
            if(Common.roleJudge(this.criticalRate)) {
                critical = true;
            }
            return critical;
        }

        /**
         * 死亡判定
         * <return> true:死亡
         */
        public bool isDie()
        {
            bool die = false;
            if(this.Hp <= 0) {
                die = true;
            }
            return die;
        }

        public String showStatus()
        {
            return String.Format(Statusformat, this.Name, this.Hp, this.Attack);
        }
    }
}

勇者や魔王を扱うクラスです。

このクラスの中でHPや攻撃力などを保持します。

メインはdoAttack()メソッド。この中で命中判定やクリティカル判定をおこない、攻撃対象(引数)のHPを減らしていきます。

using System;

namespace battle_rpg
{
    public class Battle
    {
        private Charactor yusha;
        private Charactor maou;
        private const String DieFormat = "{0}は倒れた。";
        public Battle()
        {
            yusha = new Charactor("勇者", 300, 15);
            maou = new Charactor("魔王", 400, 9);
        }

        public void execute()
        {
            bool nowBattle = true;
            while(nowBattle) {
                // HP表示
                Console.WriteLine(yusha.showStatus());
                Console.WriteLine(maou.showStatus());
                Console.WriteLine();

                // 勇者の攻撃
                Console.WriteLine(yusha.doAttack(maou));

                // 魔王死亡判定
                if(maou.isDie()) {
                    Console.WriteLine();
                    Console.WriteLine(DieFormat, maou.Name);
                    nowBattle = false;
                    Console.WriteLine("世界に平和が訪れた。");
                }

                if(nowBattle == false) {
                    return;
                }

                // 魔王の攻撃
                Console.WriteLine(maou.doAttack(yusha));

                // 勇者死亡判定
                if(yusha.isDie()) {
                    Console.WriteLine();
                    Console.WriteLine(DieFormat, yusha.Name);
                    nowBattle = false;
                    Console.WriteLine("世界は征服された。");
                }
                Console.WriteLine();
            }
        }
    } 
}

実際にバトルを行うクラスです。

コンストラクタで勇者と魔王のステータスを設定、execute()でどちらかが負けるまでループを行います。

using System;

namespace battle_rpg
{
    class Program
    {
        static void Main(string[] args)
        {
            Battle battle = new Battle();
            battle.execute();
        }
    }
}

メイン関数。Battleクラスをインスタンス化してexecute()を実行しているだけです。

とりあえず、こんな感じで要求されている処理はできました。

カスタマイズすれば色々と拡張できそうですね。

【自作PC】配線汚い問題

前々から感じてはいました。

配線が汚い。

特に問題なのは、電源ケーブルがPCIスロットの上を通っているので、PCIを装着するときに物理的に干渉するんじゃないかということ。

YouTubeの自作PCの動画を見ていると、電源ケーブルをマザーの裏側に通す、と言うことをやっていたので、オイラも実際にやってみようと思う。

電源から出ているケーブルを背面に持っていき、

ここから出す。

この周りごっちゃと見えるのは、ここにマザーの電源ピンがあるため。

ここにさらに各ドライブへの電源と、ケースファンの電源が伸びているので、仕方ありません。

背面のファンのケーブルもちょっと長くて、ファンに当たってしまいそうだったので、ケースに付いてきた結束バンドでまとめました。

全体を見るとこんな感じ。

CPUの電源ケーブル。。。

だいぶスッキリしましたが、CPUの電源ケーブルがまだ邪魔ですね。

あと、ケースファンの電源もブランブランしているのが気になります。

なにかうまい方法は無いでしょうか・・・

身近な物にも使われている相対性理論

再びこの本です。

いや、この本、物理について非常にわかりやすく説明されているので、読んでいて楽しいです。

そして、物理学の中でも難解なのが、相対性理論。

昔、授業で習ったことあるけど、当時は全く理解できなかったけど、今これを読んだら、どういう理屈なのかがわかったのです。

身近な物の応用例としてはGPS

ここまで正確に位置がわかるのは相対性理論の応用によって可能になっているです。

重力は時空の歪みによって発生している

ニュートンの万有引力の法則(質量がある物同士は引きつけあうという物理法則)がありますが、この中では、なぜ重力が発生するのかについては明かされていない。

それを論理づけたのが相対性理論。

時空の歪みとは、この本では、トランポリンの上にボーリングの玉を乗せているようなイメージとしています。

ボーリングの玉が地球だとすれば、その重さによってトランポリンの面が沈んでいると思います。

これが時空の歪みのイメージです。

ここにもう一個トランポリンの上にボーリングの玉を置くと、その重さによって、二つのボーリングの玉が引き寄せられると思います。

これが万有引力のイメージです。

時空の歪みから離れるほど時間の流れが遅くなる

例えば、地球上の時間の流れる速度と、地球の周りを回っている人工衛星の時間の流れは少し異なります。

人工衛星のほうが時間の流れが少し遅い。

とはいっても、ほんの数ミリ秒にも満たない微妙な誤差ですが。

GPSの位置測定では、電波の送信時間と到着時間の差分で測定しているのですが、このとき、時間の誤差を計算に入れないと、位置情報の計算結果が狂ってしまうのです。

そう考えると、GPSってスゴイよね。

この本は本当にオススメ。

物理学って難しいと思われがちですが、身近な物を例に取ればわかりやすくなるんですね。

量子コンピュータってすげぇっていう話

お酒を飲みながらこの本を読んだのですが、改めて、量子コンピュータってすげぇなって思いました。

この本はKindle Unlimitedを利用していれば読み放題で読むことができます。

こちらでも量子コンピュータにも触れましたが、この本を読むと、さらに量子コンピュータについて理解することができます。

量子コンピュータの概念としては、こちらの記事で間違いないようです。

しかし、0と1を重ね合わした状態というのは、正確には、0でもあり、1でもある状態、ということみたいです。

これは、通常のコンピュータでは値は0か1というふうに定まっているけど、量子になると0と1が共存している状態。この値は確率で決められるため、参照するタイミングによって、0でもあり、1でもある状態を指します。

これを応用した量子コンピュータでは並列処理が得意になる。

(いや、この概念を理解するには量子とは何かについて理解しないとダメかもしれない。)

なぜ暗号の解読が困難か?

暗号化には素因数分解の計算が応用されているためらしい。

素因数分解を計算するには、いろいろな値で割って割りきれるかどうか、の計算を行わなくちゃいけない。

小さい数字なら簡単に解を求めることができますがこれが1万桁ぐらいになると、スーパーコンピュータでも数年以上もかかると言われています。

しかし、量子コンピュータなら、並列処理が得意なので、こういった計算も数時間で解くことができる(らしい)。

現在の暗号化技術にも、素因数分解の仕組みが利用されているため、量子コンピュータでは数時間で暗号を解読できる、と言われているためだそうです。

うん、まだまだわからないところはたくさんあるな。

量子→並列処理のところと暗号の仕組みだね。

自分ももっと勉強します。

しかし、そう考えると、物理は面白い。

【プログラミング】美人時計のようなもの(Android編)

Tech commitの挑戦状課題で「美人時計のようなもの」があったので、Androidアプリで作成しました。

http://taki-lab.site/meshitero/app_debug.apk

https://github.com/takishita2nd/meshitero_timer_android

コード解説

まずはマニフェストファイルから

  
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.meshitero">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-permission android:name="android.permission.INTERNET" />
</manifest>

<uses-permission android:name=”android.permission.INTERNET” />

この一行を書き足します。

これが無いと、AndroidアプリはWebアクセスできません。

package com.example.meshitero;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.util.Log;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownloadTask extends AsyncTask<String, Void, Bitmap> {
    private Listener listener = null;

    @Override
    protected Bitmap doInBackground(String... param) {
        return downloadImage(param[0]);
    }

    @Override
    protected void onProgressUpdate(Void... progress) {

    }

    @Override
    protected void onPostExecute(Bitmap bmp) {
        if (listener != null) {
            listener.onSuccess(bmp);
        }
    }

    private Bitmap downloadImage(String address) {
        Bitmap bmp = null;

        HttpURLConnection urlConnection = null;

        try {
            URL url = new URL( address );

            // HttpURLConnection インスタンス生成
            urlConnection = (HttpURLConnection) url.openConnection();

            // タイムアウト設定
            urlConnection.setReadTimeout(10000);
            urlConnection.setConnectTimeout(20000);

            // リクエストメソッド
            urlConnection.setRequestMethod("GET");

            // リダイレクトを自動で許可しない設定
            urlConnection.setInstanceFollowRedirects(false);

            // ヘッダーの設定(複数設定可能)
            urlConnection.setRequestProperty("Accept-Language", "jp");

            // 接続
            urlConnection.connect();

            int resp = urlConnection.getResponseCode();

            switch (resp){
                case HttpURLConnection.HTTP_OK:
                    try(InputStream is = urlConnection.getInputStream()){
                        bmp = BitmapFactory.decodeStream(is);
                        is.close();
                    } catch(IOException e){
                        e.printStackTrace();
                    }
                    break;
                case HttpURLConnection.HTTP_UNAUTHORIZED:
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            Log.d("debug", "downloadImage error");
            e.printStackTrace();
        } finally {
            if (urlConnection != null) {
                urlConnection.disconnect();
            }
        }

        return bmp;
    }

    void setListener(Listener listener) {
        this.listener = listener;
    }

    interface Listener {
        void onSuccess(Bitmap bmp);
    }
}

AndroidでWebアクセスするには、本体スレッドでは動かすことはできないので、非同期タスクをつかって、こちらで動かす必要があります。

AsyncTaskインターフェースを実装したクラスを新規に作成して、こちらに実際に画像をダウンロードする処理を作成します。

doInBackground()では、実際に行うタスク処理を書きます。ここでは実際に画像ファイルをダウンロードする処理を記載します。

onProgressUpdate()では、タスク状態が変わったときに実行される処理を書きます。ここでは特に何もしていません。

onPostExecute()では、タスク処理終了後に実行する処理を書きます。ここでは、setListener()にて設定したコールバック処理を実行させています。

package com.example.meshitero;

import androidx.appcompat.app.AppCompatActivity;

import android.graphics.Bitmap;
import android.os.Bundle;
import android.util.Log;
import android.widget.ImageView;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

public class MainActivity extends AppCompatActivity {
    private DownloadTask task = null;
    private ImageView imageView = null;
    private Timer timer = null;
    private String url = "https://taki-lab.site/meshitero/img/time_%02d_%02d.jpg";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imageView = findViewById(R.id.imageView);
        timer = new Timer();
        timer.schedule(new MyTimerTask(), 0, 60000);
    }

    @Override
    protected void onDestroy() {
        task.setListener(null);
        super.onDestroy();
    }

    private DownloadTask.Listener createListener() {
        return new DownloadTask.Listener() {
            @Override
            public void onSuccess(Bitmap bmp) {
                imageView.setImageBitmap(bmp);
            }
        };
    }

    private String getTimer() {
        Calendar cTime = Calendar.getInstance();
        int min = cTime.get(Calendar.MINUTE);
        if(min < 30) {
            min = 0;
        } else {
            min = 30;
        }
        Log.d("debug",String.format(url, cTime.get(Calendar.HOUR_OF_DAY), min));
        return String.format(url, cTime.get(Calendar.HOUR_OF_DAY), min);
    }

    class MyTimerTask extends TimerTask {

        @Override
        public void run() {
            task = new DownloadTask();
            task.setListener(createListener());
            task.execute(getTimer());
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:srcCompat="@android:color/background_light" />
</androidx.constraintlayout.widget.ConstraintLayout>

MainlyActivityでは、内部クラスにTimerTask を実装したMyTimerTaskクラスを作成しています。

タイマー処理はこれがないとダメらしい。

run()に、実際にタイマー処理で実行される処理を書きます。ここでは、DownloadTask()を実行させています。

onCreate()では、timerクラスを使って MyTimerTask をスケジューリングしています。第二引数は初回実行までの時間、第三引数には、実行間隔を指定します。

setListener()にcreateListener()メソッドを渡すことで、 MyTimerTaskのタスク処理が実行されたあと、 createListener()が実行されるように設定しています。

ここでは、ImageViewに読み込んだ画像を設定しています。

時間取得はCalendarクラスを使用します。こちらの方が推奨された処理らしいです。

【プログラミング】美人時計のようなもの(Web編)

Tech commitの挑戦状課題で「美人時計のようなもの」があったので、まずはJavascriptで作成しました。

飯テロ時計

http://taki-lab.site/meshitero/meshitero.html

https://github.com/takishita2nd/meshitero_timer

30分おきに画像が変わり、時間を教えてくれます。

コード解説

まずは、html本体。

<!doctype html>
<html>
    <header>
        <meta charset="utf-8">
        <title>飯テロ時計</title>
        <script src="jquery-3.4.1.min.js"></script>
    </header>
    <body>
        <img id="image" width="640" height="480" src="" />
        <script src="meshitero.js" ></script>
    </body>
</html>

ライブラリはjQueryを使用。これを使うと、IDやclass指定した要素の取得が簡単になります。

本体は画像を表示するimgタグのみ。

そのあとにjs本体を読み込ませます。

jsは最後に書かないと、きちんと動いてくれないっぽい。

続いて、js本体。

function getImageName() {
    var date = new Date();
    var hour = ("00" + date.getHours()).slice(-2);
    var min = "00";
    if(date.getMinutes() >= 30) {
        min = "30"
    }
    var imageFormat = "time_{0}_{1}.jpg";
    return imageFormat.replace("{0}", hour).replace("{1}", min);
}

function imageUpdate(force = false) {
    var date = new Date();
    if(force = false &&
       (date.getMinutes() % 30) != 0) {
        return;
    }
    var imageName = getImageName();
    var image = $("#image")[0].src = "img/" + imageName;
}

document.onload = imageUpdate(true);
setInterval(imageUpdate, 60000);

まず、用意する画像のファイル名は「time_hh_mm.jpg」で統一します。

ファイル名フォーマットとして”time_{0}_{1}.jpg”というのを用意し、あとは実際の時間に合わせて{0}と{1}の部分をリプレースして、ファイル名を作成します。

画像の置き換えはimgタグの要素srcの値を書き換えるだけです。

で、setInterval()で一定時間後周期的にヶ同読み込みが行われるのですが、初回ロード時にも画像を読んで貰わないと行けないので、onload(html読み込み終了時)に強制的に読み込みを実行します。

imageUpdate(force = false) {}とは、引数を指定しなければforceの値は初期値falseが適用されます。

imgタグを書き換えるだけでいいので、思ったほど簡単なコードになりました。

【自作PC】3Dベンチマークの比較

3D ゲームをするつもりはないのですが、ついでなので、1年前に購入したノートPCと自作PCの3Dベンチマークを測定してみました。

ベンチマークソフトは3DMARKを使おうと思いましたが、何故か動かなかったので、ファイナルファンタジー14のベンチマークソフトを使用しました。

まずは、ノートPCの測定結果はこちら。

動作困難!

わかってた。

測定中も動作カックカクで、とてもゲームができる状態ではないと思いました。

続いて自作PCの測定結果。

やや快適!

動作はやや滑らか、でも時々違和感がある程度で、これくらいならまだ許容できる範囲。

そもそもスペックを比較すると、ビデオRAMのサイズが全然違ってて、ノートPCの方は128MBに対して自作PCの方は2GB。

全然違う。

Intel内蔵のグラフィックチップとRYZENに内蔵しているグラフィックチップにはかなり違いがありますね。

Intelの方は、本当に必要最低限の機能しかないって感じ。

ADMのCPUは、基本的にはグラフィックチップは搭載していないのですが、一部のCPUにはかなり高性能(?)なグラフィックが搭載されているようです。

但し、グラフィックチップを搭載しているAMDのCPUはごく一部なので、本来はグラフィックボードを使用しなければいけません。

Intelを選ぶか、AMDを選ぶかは、その辺りも考慮しなければいけませんね。

全く考えないでパーツ買ってた。

みんなは必ず、意識するように。

【自作PC】ついでにケースも交換、スタイリッシュに?

前回の様子はこちら

なぜケースを交換するに至ったかというと、

フロントパネルのUSB端子が一個壊れてた。

まぁ、オークションで仕入れた中古だから仕方ないね。

ケースを交換するに当たって、もう一つ、DVDドライブも新しいものにしました。

音楽CDを取り込もうとしたら、CDを認識してくれなかったため。

これも中古PCに付いてきた物だから仕方ない。

なので、Amazonで購入しました。

なんか、中身が見えるってかっこよくない?

配線汚いけど。

あと、本体上部にファンを二つ取り付けられるので、古いPCケースからファンを頂きました。

ついでに言うと、前面と、本体下部にも取り付けられるようです。

そんなに冷却能力はいらない。

3個で十分過ぎるので、いま、PCの周りはファンの風で少し寒いです。

現在のPC構成とコストはこちら。

パーツ型番価格
CPURyzen 5 3400G20680
マザーボードPRIME A320M-A7544
メモリHX426C16FW2K2/16 6980
電源KRPW-L5-400W/80+3278
ケースCC-9011086-WW5099
SSDGH-SSDR2SA1202178
M.2SSDSCKKW480H6X15980
DVDドライブIHAS324-17/A2020
OSWindows 10 Pro3259
電源ユニットネジ200
電源延長ケーブル×2300
二股電源ケーブル300
合計57818

みんなも自作PCやろう。

睡眠改善を目的に、GABA for sleepを食べてみた結果

GABA for Sleepというチョコレートが売られており、これを寝る前に食べると、睡眠の質が良くなるらしい。

Amazonで買えました。

買ってみた

中身はこんな感じ。

寝る前に3個食べれば良いらしい。

食べて寝てみた

fitbitの睡眠スコア測定結果はこんな感じ。

食べて寝たのは月曜日の夜なので、確認するのはその前後、火曜日と水曜日です。

火曜日→睡眠スコアが悪化(たぶん過去最低)

水曜日→午前3時に起床、その後二度寝

悪化してない?

裏面の注意書きを確認しました。

たぶんなんですけど、自分は鬱病を持っていて睡眠薬を飲んでいて、それが疾病に当たるから、実は食べちゃいけない物じゃないかと思いました。

GABA(γ-アミノ酪酸)とは

そもそもこの食品に含まれるGABAとは何でしょうか。

GABAという言葉を持ったチョコレートはかなり昔からありましたよね?

GABAとは天然アミノ酸の一つで、またの名をγ-アミノ酪酸と呼びます。

これを摂取すると、神経伝達物質として働き、以下のような効果があるとされています。

  • リラックス効果
  • ストレスの緩和
  • 抗ストレス作用
  • 学習にも良い効果がある
  • 脳細胞破壊の抑制
  • 寝付きを良くする

なるほど、体にいろいろと良い効果があるのですね。

GABAを摂取するには

一般的にGABAは一日に30mg必要とされています。

GABA自体は様々な食物に含まれています。

  • 発芽玄米
  • 白米
  • トマト
  • なす
  • アスパラガス
  • かぼちゃ
  • きゅうり
  • メロン
  • みかん
  • 漬物
  • キムチ

特に、発芽玄米には100gにGABAが10mg含まれているようです。

ちなみに、GABA for sleepには1粒に100mg含まれているようです。

多くね?

要はGABAの取り過ぎでは無かろうか

そんな気がしました。

とにもかくにも、睡眠に悪影響が出ている以上、睡眠薬飲んでいる人は、寝る前の摂取は辞めた方が良いかも。

さて、

これ、どう処理したら良いですかね?

自分、ぼっちですが何か?