OmniAICreator/Qiita-1.07M huggingface dataset:
中古PCのWindowsを削除してLubuntuをインストールした話


# インセンティブ

- 新卒1年目も終わりに近づく中、仕事で黒い画面を見る機会が増え、黒い画面のことをちゃんと理解する必要がある（というか入社して１年も経つのにLinuxのこと何も知らないのはヤバくない？）と思ったから。
- 黒い画面をスマートに使えるようになるとかっこよさそうだから。
- 仮想環境を作る~~のがめんどくさい~~となると、ただでさえカオスなメインPCの中身がもっとぐちゃぐちゃになってしまうのが嫌だったから。
- TCP/IPの勉強をしていたから。
- おもしろそうだったから。

# 注意事項
「この記事を見てLubuntuをインストールしてみた結果PCが壊れて使い物にならなくなった！どうしてくれるんだ！」とか、そういうのは対応しかねます。

その辺は自己責任ということでよろしくお願いします。

# 参考にした記事
こちらの記事を大いに参考にさせていただきました。ありがとうございます。
⇒[Windowsを削除してUbuntuをUSBからインストールする](https://yoshinorin.net/2017/04/29/remove-windows-and-install-ubuntu-from-usb/)

# 前準備
上記の記事に従って、まず初めに以下の下ごしらえをしました。

- 中古PCを購入（ThinkPad X240/Windows 10 Home 64bit(MAR)/Corei3-4010U 1.70GHz/ DDR3L-1600 4GB/500GB HDD 17000円也）
- [Lubuntu 20.04.2 LTS (Focal Fossa)](http://cdimage.ubuntu.com/lubuntu/releases/20.04/release/)のISOイメージのダウンロード
- USBメモリ（8GB）（家にあった全然使ってないやつ）

# Rufusを使ってUSBインストールメディアを作成する
新たにPCにOSをインストールするわけなので、インストールメディアが必要ということらしい。
前準備で落としてきたLubuntuのISOイメージとUSBメモリに加えて、[Rufus](https://rufus.ie/)を使いました。「ルーファス」と読むらしい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/eac1cce8-cfd3-36e9-35d3-777d866465b7.png)

- デバイス：使用するUSBメモリを選んで、
- ブートの種類：落としてきたLubuntuのISOイメージを指定して、
- あとはデフォルトのままで、
- 「スタート」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/d7713804-8d9f-e833-a113-3d73384ee4ba.png)

- 「はい」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/6a5557b3-f611-a480-eedb-c0fb8a730d02.png)

- 「OK」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/ee30ec16-ca3d-bd86-a82b-2af4e99f6bd4.png)

- 消去してもよいデータしか入ってないことを確認して、「OK」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/f1ce0680-652a-4422-4d7c-3bc25dba667a.png)

- ちょっと時間がかかるので、コーヒーでも飲みながら待機。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/40e1c6e3-2a25-4545-3a51-b512871d08e2.png)

- バーが埋まったら完了。「閉じる」を選択して終了。

# Lubuntuをインストールする
ここからが本題のLubuntuのインストールです。

残念ながらあまりキャプチャはありません。ところどころスマホで直撮りしたのでそれを貼ります。

まず中古PCに件のUSBを挿し、BIOS起動。
外部デバイスでのブートをEnableに変更（今回はデフォルトでなっていました）し、ブートの優先順位でUSBの名前を一番上にしました。

その後、F12で変更を保存し起動すると、、、
![73852.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/5c7a8c0e-0ba2-0919-3aa2-06027b753bee.jpeg)
無事lubuntuで起動が成功しました。

起動後、Lubuntuのインストーラを選択し、起動。
![73854.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/5e1f9783-0e3a-4010-5248-af354503013a.jpeg)
いろいろと設定項目があるので、適当に設定して進むと、パーティショニングの設定がやってきました。
![73853.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/24d4bf05-332b-65da-8d61-5af46d2ee092.jpeg)
今回はもともと入っていたWindowsを削除して、完全にLubuntuのPCにしたかったので、ディスクを消去を選択し、インストールを完了させました。

そして、PCを再起動させたところ、
![73855.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1099491/e66a5816-49a9-a541-ae0b-ca87a21a0093.jpeg)
うまく起動できました。挙動も今のところ特に問題ありません。

# おわりに
記事の内容は以上となります。
お読みいただきありがとうございました。
npmでTypeScriptをインストールした時のエラー

# エラー詳細
TypeScriptをインストールするために下記コマンドを実行

```
$ npm install -g typescript
```

すると、下記のエラーが発生。

```
npm WARN checkPermissions Missing write access to /usr/local/lib/node_modules
npm ERR! code EACCES
npm ERR! syscall access
npm ERR! path /usr/local/lib/node_modules
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, access '/usr/local/lib/node_modules'
npm ERR!  [Error: EACCES: permission denied, access '/usr/local/lib/node_modules'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'access',
npm ERR!   path: '/usr/local/lib/node_modules'
npm ERR! }
npm ERR! 
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR! 
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/xxx/.npm/_logs/XXXX-XX-XXXXXX_XX_XX_XXXX-debug.log

```

# 解決方法
↓こちらの記事に従ってnpmのデフォルトディレクトリを作成したら解決した
https://qiita.com/NaokiIshimura/items/cc07441939b226e779c6
VS Code 1.53 の新機能 - デフォルトの検索モードの指定

https://code.visualstudio.com/updates/v1_53#_default-search-mode

フォルダやワークスペース内をファイル検索する際の動作のデフォルトを設定する項目が追加された。

設定項目は`search.mode`で選択肢は以下の通り。

- `view` : サイドバーで検索を行う（既定値）。
- `reuseEditor` : 検索用のエディタを使用し、エディタを再利用する。
- `newEditor` : 検索用のエディタを使用し、常に新規にエディタを開く。

サイドバーでの検索の場合は検索条件の入力と検索結果の表示はサイドバーで行われ、結果をクリックするとそのファイルがエディタで開く。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/30c54120-fc5a-9eca-4cef-f4c00c2fb408.png)

これに対し、検索用のエディタを使用する形式にするとこのようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/6df2d4bf-590a-8535-cfb0-edf6826a6c7a.png)

ファイル名のリンクは`Ctrl`を押しながらクリックすると別エディタでファイルが開き、ダブルクリックするとファイルの内容がインライン表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181011/b1fe72e9-6702-ec2b-6f62-2b9986315f27.png)

ファイル名リンクではなく検索結果をダブルクリックしたときの挙動は、設定`search.searchEditor.doubleClickBehaviour`によって異なる。

- `selectWord` : 単語を選択する（通常のエディタと同じ挙動）
- `gotoLocation` : 別エディタでファイルを開く（既定値）
- `openLocationToSide` : 別エディタグループでファイルを開く（サイドバー形式に似た挙動になる）

使う場面によってモードを使い分けすると良さげだが、検索用エディタ＋`openLocationToSide`の設定が検索結果も見やすいしファイルも横に開けるしでいいとこ取りでデフォルト設定としては良さそう。
プログラミングスクール・教室卒業者のレベルをざっくり解説してみました。

私は現在エンジニア就職活動の真っ只中の某有名プログラミングスクール生です。

普段は学習したことのアウトプットにQiitaを使っているのですが、正直なところ、私の記事を読んでいたいている皆さんに何かを与えられているとは到底思えません。

私が普段記事にしていることは、参考書やQiitaの記事で学習した内容そのものです。実務で培った経験ではありません。

そのような内容なんてグーグル検索をすれば、より質の高いものなんていくらでも出てきます。

こんな私でも、何か与えることがしたいと思ったので、これからプログラミングを学習するとか、まだ学習を始めたばかりだとか、そのような人に私の少ない知識を分け与えさせていただきたいなと思います。

時間の無駄にさせないように努力しますので、是非読んでみてください。

## プログラミングスクール・教室卒業者のレベルとは

結論、「おそらく1番有名であろうスクールが作らせるようなフリマアプリよりも、ちょっと難しいオリジナルアプリが作れるくらい」が、プログラミングスクール卒業生の実力の平均値でしょう。

これを読んだら、おそらく「いやいや、そもそもフリマアプリ作るってどのくらいのレベル感だよ？」とツッコミたくなった方もたくさんいるでしょう。

ざっくり説明いたしますと、「メルカリの超主要機能だけを実装したアプリ」と考える良いでしょう。

ユーザー登録機能があって、ログインしたりログアウトしたりすることができます。

そして、商品を載っけたり、編集したり削除したり、クレジットカード決済機能がついていて売ったり買ったりすることができます。

某有名スクールのカリキュラムだと、大体4週間かけて作る超大作ということになっていますが、実際は1週間もかからず作ってしまう人もいますし、2~3週間くらいでは皆さん作り終えることでしょう。

※一応自己弁護しておきますが、私はプログラミング学習のハードルをあげるような発言はできるだけしたくないと考えています。これからいくつか「そんな簡単なことではない！」と思うようなところもあるでしょうが、あえてそのような表現を避けているということをご承知ください。

## どうすれば卒業生の人たちと同じようなレベルになれるのか

これは私の個人的な意見として提示させていただきますが、

Rubyをメインで学習する場合であるならば

1.まずはHTMLとCSSを使って、簡単な静的なサイトを作れるようになる

2.JSやjQueryを参考書などで学習しながら、それを使った制作物を作る

3.プロゲートなどを使ってRubyやRailsの基本的なことを学習する

4.チュートリアルや参考書を使ってある程度網羅した学習をしながら、アウトプットとして制作物(例えばTwitterのようなアプリとか)を作成する

5.それが終わったらネットの情報などを参照しながら、フリマアプリなどの実際の卒業生の制作物を参考にしながら、同じようなものを自力で作る

6.そして最後にオリジナルアプリを作成する

ざっくりですが、このようなフローで学習を進めていけばある程度同じレベルにはなれるだろうと思います。

## エンジニアとしての就職難易度

では一番重要な、エンジニアとして就職することについて少し私の意見を述べようと思います。

前提として、私は通っていたスクールの中に私くらいの量と質で学習している人をみたことがありません。

スクールのカリキュラムも、通常の10分の3~4くらいの期間で終えることができました。

残りの時間はオリジナルアプリや周辺知識の学習に割いたので、絶対に他の多くの受講生よりも行動していたはずです。

そんな私のエンジニア就職に対する感想としては、シンプルに「難しい」です。

私はスクールに通ってから、学習期間3ヶ月、就職活動の期間が始まってからは2ヶ月と少し経っています。

そもそも、応募して返事が返ってくる企業は1割にも満たないと言うのがエンジニア未経験転職の現状です。

しかし、3次面接に進めている企業もありますし、就職できる可能性はしっかりあると思います！

## まとめ

ざっくりとプログラミング学習やエンジニア転職について、私なりに知っていてもらいたいことを話してきましたが、参考になったでしょうか。

もし「良かった」とか、「こういうことはどうなの？」というコメントがくるようでしたら、私に可能であれば答えていきたいですし、

必要であれば、記事にしていきたいと思っているので、今後もよろしくお願いいたします！
ToastNootificationを出すアプリケーションをmingwでコンパイルするのは諦めた話

# はじめに

Windows 10には通知システムが搭載されており、Toastと呼ばれている。

利用するには

```cpp
#include <wrl/implements.h>
#include <wrl/event.h>
#include <windows.ui.notifications.h>
```

あたりのヘッダーが必要になる。

# WRLのmingwでのサポート

まず次の2つのヘッダーについてみていく。

```cpp
#include <wrl/implements.h>
#include <wrl/event.h>
```

`/mingw64/x86_64-w64-mingw32/include/wrl`を見てみると

- `wrapper/corewrappers.h`
- `client.h`
- `internal.h`
- `module.h`

のみが存在している。つまりこれらのヘッダーはない。

[MSYS2 / Thread: [Msys2-users] MSYS2 and Windows Runtime Library](https://sourceforge.net/p/msys2/mailman/msys2-users/thread/97e48697-1fd3-911e-ed2a-475db0bb82a1%40gmail.com/)
メーリスに2018年の会話が残っていた。つまるところまだ実装されていないということらしい。

要するにCOMなので、実装するにはIDLを書いて、`widl`でコンパイルしてヘッダーを生成する必要がある。MSが配ってる`wrl/event.h`を見に行くとそんなに難しくなさそうに見えて`wrl/implements.h`に依存している。そして`wrl/implements.h`を生成させるのは結構これがでかいのでだいぶつらそうではある。

> Because 'implements.h' is not available, you have to create one 
yourself. MSVC headers *usually do not* compile verbatim using GCC. It 
will require quite a little time and energy to make a header that is 
both binary-compatible with the MSVC one and source-compatible with GCC.

どのへんがquite a little time and energyの範疇に収まってるのか疑問だが、まあmingw/wineに関わる人は常人ではないのでこれくらいはその範疇なんだろう、知らんけど。

# `windows.ui.notifications.h`

Toastを使うための必須アイテムであるが、これまたmingwでは提供されていない。つまりお決まりのIDLを書いて(ryの作業が必要になるわけだがここでこんな情報があった。

[1495998 - windows.ui.notifications.h is missing on mingw for bug 1155505](https://bugzilla.mozilla.org/show_bug.cgi?id=1495998)

> Yeah, it won't be quick to fix, I'm afraid. winrt mode extends .idl syntax quite a lot. I implemented some of those features in widl, but it's still not up to the task to generate windows.ui.notifications.h. It will be quite a bit of work.

mozillaの連中が「ちょっと実装しようとしたけど生成には至らん、簡単じゃねーよ」と言ってる時点でまあさじを投げ出したい気持ちでいっぱいになる。

ざっとMSが配ってるIDL見てきたけど、

```C#
// Type definition
namespace Windows
{
    namespace UI
    {
        namespace Notifications
        {
            [contract(Windows.Foundation.UniversalApiContract, 3.0)]
            enum AdaptiveNotificationContentKind
            {
                Text = 0
            };
```

[contract属性](https://docs.microsoft.com/ja-jp/uwp/midl-3/predefined-attributes#the-contract-attribute)とかどうすればいいのか検討もつかん。

# まとめ

膨大に時間が有り余っていてCOMを扱えるだけの技術力が有り、ろくなドキュメントもない`widl`を扱える人がいたらぜひ実装してください。私はさじを投げました。


# 追記: 2023/12/19

たまたま業務でコードを読解していて知ったのだが、トースト通知をするだけなら`Shell_NotifyIconW`で行けるらしい。

[\[ 372_フォームを使用しないタスクトレイ常駐アプリ \] - Mr.XRAY](http://mrxray.on.coocan.jp/Delphi/plSamples/372_TrayIconNoForm.htm#05)

`windows.ui.notifications.h`使おうとしたのはあれかな、UWP向けの記事かなにか見て惑わされたのかもしれない。


・・・とかぼやいていたら社内の有識者からこんな情報が

>いつからかバルーンのAPIを呼び出すとトーストで表示されるようになりました。
バルーンに戻した的な話:
https://admx.help/?Category=Windows_10_2016&Policy=Microsoft.Policies.TaskBar2::EnableLegacyBalloonNotifications&Language=ja-jp
https://www.naporitansushi.com/windows11-balloon-notification-enable/
【Go】標準入力 / bufio.Scanner

競プロとかをやっていると標準入力を受け取って処理をすることが多いと思います。
記事も多いので、あまり理解せず書いていたコードをドキュメントを参照しながらまとめようと思います。

Go勉強し始めて日が浅いので色々ご容赦ください...mm

## 標準入力を受け取るよくある書き方。
```go
package main

import (
  "bufio"
  "fmt"
  "log"
  "os"
)

func main() {
  sc := bufio.NewScanner(os.Stdin)
  sc.Scan()

  if err := sc.Err(); err != nil {
    log.Fatal(err)
  }

  fmt.Println(sc.Text())
}
```

## 一つずつみていく
まず、`bufio.Scanner`を[みてみる](https://golang.org/pkg/bufio/#Scanner)。今回使ってるメソッドが大体載ってますね。

```go
// ファクトリ関数
func NewScanner(r io.Reader) *Scanner

func (s *Scanner) Scan() bool
func (s *Scanner) Text() string
func (s *Scanner) Err() error
```
`NewScanner`はファクトリ関数で、Scanner型のポインタを返すので、返り値をレシーバーにメソッドが呼べるんですね。`os.Stdin`は一旦置いておいて、進めます。

それ以下は3つともScannerをレシーバに持つメソッドです。
`Scan`は入力をトークンとして保存します。このトークンを取り出すには、`Text()`か`Bytes()`を呼べと書かれています。戻り値はboolで、falseを返したときは、`Err()`でエラー詳細を参照できるみたいです。

ところで、`NewScanner`の引数は`io.Reader`型なので、`os.Stdin`を[調べてみます](https://golang.org/pkg/os/#pkg-variables)。

```go
var (
  Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
  Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
  Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

func NewFile(fd uintptr, name string) *File
```
`NewFile`の第一引数はfile descriptor（ファイルの識別子）、第二引数がファイル名です。返り値はFile型。
fdは`syscall.Stdin`の返り値を型キャストしています。

つまり、`os.Stdin`はFile型、`NewScanner`の引数は`io.Reader`型なので一致しません。??
[こちらの記事](https://qiita.com/takayukioda/items/edb30c7ba9ca28dba624)で述べられていますが、それぞれドキュメントを再び確認してみます。[os.Stdin](https://golang.org/pkg/os/#File.Read) / [io.Reader](https://golang.org/pkg/io/#Reader)

```go
package io

type Reader interface {
  Read(p []byte) (n int, err error)
}

// ===================
package os

func (f *File) Read(b []byte) (n int, err error)
```
つまり、`io.Reader`はReadメソッドをラップしたinterfaceであり、`os.File`は全く同じReadメソッドを持っているということになります。従って、File型をReader型として引数で渡せる訳ですね。


## 最後にBufferについて
Bufferとは情報を一時的に保存しておく領域のことです。
`bufio.Scanner`のBufferのデフォルト値を[確認してみます](https://golang.org/pkg/bufio/#Scanner.Buffer)。

```go
const (
  MaxScanTokenSize = 64 * 1024
)
```
64KiBつまり、65536byteです。入力サイズが大きい場合は不足する可能性があります。私は問題を解いていてこれでハマりました。

```go
const (
  init = 10 * 1024
  max = math.MaxInt64
)

sc := bufio.NewScanner(os.Stdin)

buf := make([]byte, init)
sc.Buffer(buf, max)

sc.Scan()
```

Scanを呼ぶ前にBufferを指定すれば良さそうです。上記の例はかなり乱暴な例ですが、注意点として第一引数は`[]byte`で、第二引数は`int`です。

以上、読んでいただきありがとうございました！

参考：
https://qiita.com/takayukioda/items/edb30c7ba9ca28dba624
https://mickey24.hatenablog.com/entry/bufio_scanner_line_length
HoloLens 2 エミュレーターで Unity の Debug.Log() の出力を確認する

HoloLens 2 のエミュレーターでアプリを作成しようとしたのですが、
Unity でいつものように [Debug.Log()](https://docs.unity3d.com/ja/current/ScriptReference/Debug.Log.html) を出力したところ、
どこに出力されるのか分からず困ったので書いておきます。

## 確認方法

最初に確認方法を書いておきます。

1. HoloLens 2 エミュレーターの Windows Device Portal を開きます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/657a1259-9d2a-1f79-8310-e642135464e5.png)

2. [System] > [File explorer] を開きます。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/40703143-170b-0d8b-b513-132d0505e507.png)

3. [LocalAppData] > (パッケージ名) > [TempState] を開きます。
4. UnityPlayer.log を Save します。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/312bcbeb-d2d0-3224-9808-33ab3e754060.png)

5. UnityPlayer.log を確認します。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/294bcf5a-d7db-28e8-cd30-a279452883f8.png)

## 環境
- Unity 2019.4.19f1
- Microsoft Mixed Reality Toolkit v2.5.4
- Microsoft.MixedReality.Toolkit.Unity.Foundation.2.5.4.unitypackage
- Visual Studio 2019 Version 16.8.4
- HoloLens 2 Emulator 10.0.19041.1134

## 困るまでの手順

1. Microsoft の HoloLens 2 のチュートリアルの通りに HoloLens 2 向けのアプリを作成します。
  - [プロジェクトの初期化と最初のアプリケーションの配置](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/unity/tutorials/mr-learning-base-02)
2. 適当な Script に [Debug.Log()](https://docs.unity3d.com/ja/current/ScriptReference/Debug.Log.html) を書きます。

    ```csharp:*.cs
        void Start()
        {
            Debug.Log("Hello: Start().");
        }
    ```

3. Microsoft の HoloLens エミュレーターを使用する の通りにエミュレーターにアプリを展開します。
  - [HoloLens エミュレーターにアプリを展開する](https://docs.microsoft.com/ja-jp/windows/mixed-reality/develop/platform-capabilities-and-apis/using-the-hololens-emulator#deploying-apps-to-the-hololens-emulator)
4. Visual Studio で [デバッグ] > [デバッグの開始] を実行すると、Visual Studio の出力に Debug.Log() の出力がされていると思い確認すると・・・

**ない！！！！**
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/9af1fb06-4a66-bbf5-a0ce-55a712629fda.png)

5. 動作確認の方法で UnityPlayer.log を確認すると・・・

**あった！！！！**
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/460904/294bcf5a-d7db-28e8-cd30-a279452883f8.png)

## さいごに

最初はどこに表示されているか分からず困りましたが、
これで何とか動作を確認することができそうです。
LaravelとStripeでWebhookを試す。🥰

手順をサクッとメモっときます。


##httpsでアクセス可能にする

まずはngrokなどを使って、httpsでアクセス可能にします。

やり方が分からない方は[【Mac】Laravelアプリをngrokを使って、外部に公開する。](https://qiita.com/howaito01/items/cd82197643b6e386cc37)通りにやればできます！

##Stripe側でWebhookを設定する。

[こちら](https://dashboard.stripe.com/test/webhooks)からwebhookを設定します。

##envファイルにシークレットキーを設定

webhookのシークレットキーをenvファイルに記述します。

```:.env
STRIPE_WEBHOOK=whsec_自分のやつ。
```

##config/services.phpに追加。

下記を追加。

```php:config/services.php
'webhook' => [
        'secret' => env('STRIPE_WEBHOOK'),
        'tolerance' => env('STRIPE_WEBHOOK_TOLERANCE', 300),
    ],
```

##Laravel cashierのインストール

```
composer require laravel/cashier
```

##ルーティングの記述

```php:web.php
Route::post('stripe/webhook', 'WebhookController@handleWebhook');
```

##コントローラーの作成

アクション名は**「handle+キャメルケース」** の形にする。

例えば、payment.createdというイベントをリッスンする場合は`handlePaymentCreated`というように書く。

```php:WebhookController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use Laravel\Cashier\Http\Controllers\WebhookController as CashierController;

class WebhookController extends CashierController
{
    public function handlePaymentCreated()
    {
       Log::debug($event['data']['object']);
    }
}

```

##CSRFの設定

>Webhookの処理は【POST】メソッドを使いますが、CSRF対策を入れられません。

>そこで、「こういう時は例外にしておいて」とLaravelに設定する必要があります。

>app/Http/Middleware の VerifyCsrfToken.phpを開き、下記を追加しておきましょう。

```app/Http/Middleware/VerifyCsrfToken.php
protected $except = [
        'stripe/*',
    ];
```

##参考
下記の3つを参考にしました。

・[LaravelでStripeのWebhookを利用するための7ステップ【NGROK利用】](https://biz.addisteria.com/larave-stripe-webhook/)
・[【Laravel5.8+Stripe11】Webhookの実装](https://nekorokkekun.hatenablog.com/entry/2019/08/25/213501)
・[Laravel 6.x Laravel Cashier](https://readouble.com/laravel/6.x/ja/billing.html#handling-stripe-webhooks)
【Nuxt】ssgのnuxt.jsでjsonを読み込む

静的サイトジェネレーターでポータルページを作っていた際にapiを作るほどではないけjsonどデータとして持って表示させたいとのことがあった。

# assetとしてnuxtのレポジトリ内にjsonを保つ場合

```sample.vue
<template>
  <div v-for="data in datas">
    {{data}}
  </div>
</template>
<script>
import datas from "@/assets/jsons/datas.json";
export default {
  data() {
    return {
      datas: datas,
    };
  },
};
</script>
```

# 外部サーバーにjsonおいて参照する場合
```sample.vue
<template>
  <div v-for="data in datas">
    {{data}}
  </div>
</template>
<script>
export default {
  async asyncData({ $axios }) {
    const datas = await $axios.get(
      "http://storage.googleapis.com/jsons/datas.json"
    );
    return {
      datas: datas.data,
    };
  },};
</script>
```
Docker+RailsでImageMagickをインストール

##開発環境##

* Docker 20.10.2
* Ruby 2.6.4
* Rails 6.0.3
* PostgreSQL 11.2

##躓いたところ##
webコンテナ上でImageMagickを

```
$ sudo apt-get update 
$ sudo apt-get -y install imagemagick libmagick++-dev
```

でインストールしようとするとupdateの段階で

`sudo: apt-get: command not found`

と言われ,installまで辿り着かない。

##原因##
Dockerのruby 2.5から仕様が変わったため、パッケージのインストールコマンドはapt系ではなく、apkを利用する必要があるとのこと。
##解決方法##

```
$ sudo apk update 
$ sudo apk add --no-cache imagemagick
```

の順に実行するとできた。
railsをやっててsequal proにカラムが表示されなかったときの解決法

sequal proを初めて使ってみて、なんでかしらないけれどもカラムに反映されないっていうトラブルに見舞われましたね。
試しに
`rails db:migrate`
をもう一度やってみたけれども結果変わらなかった
`rails db:migrate:rollback`
をやってみても結果は変わらずでしたね。
もちろんちゃんとリロードもしましたけどね。

そこで、
`rails db:migrate:reset`
をやってみたところ通って解決しました。
良ければ参考にしてみてください
コロン（：）と少しだけ仲良しになったという話（ruby)

#コロン（：）と少しだけ仲良しになったという話

前から思ってたんです。rubyにおける「 ” : （コロン）” がややこしい！」と。
今日は、” : “の位置が原因で起きたエラーのおかげで学んだことをアウトプットします。

結論： **シンボルは「文字列の皮を被った数値」である。trueはシンボルで書かなくていい。**

***

###▼エラー状況

```ruby
rails routesをターミナルで実行した際以下のエラー文が出た（省略してます）
rb:45:in `presence': wrong number of arguments (given 1, expected 0) (ArgumentError)
```

###▼エラー理由

```ruby
user.rb に書いたバリデーションで
正：presence: trueを　→ 誤：presence :trueとしていたため。
（:の位置が間違ってた）
```
参考記事：https://diveintocode.jp/blogs/Technology/ErrorCollection

###▼わかってなかったこと

```
シンボル（:hoge）とは何か？逆に hoge: とするのはどういう意味か？
```

###▼シンボルについてわかったこと

```
・ :hoge ←これがシンボル。
・表面上は文字列っぽいので、プログラマにとって理解しやすい。
・内部的には整数なので、コンピュータは高速に値を比較できる。
　→シンボルは「文字列の皮を被った数値」のこと。
・ハッシュのキーとしてよく使う。
・クラス名/メソッド名/変数名/定数名は定義すると勝手にシンボルを作って検索に備えている。
・メモリの使用効率が良い。
・イミュータブルなので、勝手に値を変えられる心配がない。
```

参考記事：
・https://programming-dojo.com/%E3%80%90ruby%E5%85%A5%E9%96%80%E3%80%91%E3%82%B7%E3%83%B3%E3%83%9C%E3%83%AB%EF%BC%88%E3%82%B3%E3%83%AD%E3%83%B3%E8%A8%98%E5%8F%B7%EF%BC%89/
・https://www.sejuku.net/blog/13094

###▼trueについて深掘りしたこと

```
:trueでエラーが発生した
→ trueはシンボルにする必要がない。
presence:  〇〇←ここでのコロンの意味は
presence「は」〇〇（英語で言う” isとかare “）かなと思った。
今回はpresenceが真か偽かを判別したかったけど、コロンの位置が変でそれができなかったから上記のエラーが出たのかなぁ。
```

***

###▼感想

エラーが出ることで深まることがあるなぁということ。なんとなく「シンボルで表記してるなぁ」「コロンよく出てくるなぁ」くらいで考えてたけど、今回深く考える機会がもらえてよかった。
それにしても、コロンの位置がちょっとずれただけでrails routes出来なくなったりするんだから恐ろしいよね。
あとは、trueをシンボルにしない理由のところはあんまりうまくアウトプットできてないのは悔しい。もっと理解深い人いたら、ぜひ教えて欲しいです。
docker run コマンドで MySQL のコンテナを立ち上げたら Table doesn't exist.

# docker run コマンドで MySQL のコンテナを立ち上げたら Table doesn't exist.
Docker の MySQL ではイメージを作るとき、`/docker-entrypoint-initdb.d`というディレクトリにテーブル作成する`.sql`ファイルをコピーしておくようにすると、コンテナを立ち上げたときに自動的に`.sql`ファイルを実行してくれるという便利な機能があります。
参考: [MySQLのDockerイメージの公式サイト](https://hub.docker.com/_/mysql)

私もその便利な機能にあやかりお手軽にサンプルのデータベースを構築しようとしたのですがそのときにタイトルのような問題が発生したので備忘録として残します。

## 結論: SQL ファイルを順番に実行したかったらファイル名で順番付けするとよさそう
> Files will be executed in alphabetical order.
(ファイルはアルファベット順に実行されます。)
参考: [MySQLのDockerイメージの公式サイトの Initializing a fresh instance
という項目](https://hub.docker.com/_/mysql)

ということで view を作りたい！でも view 作成用の SQL ファイルの中で参照してるテーブルの作成用の SQL ファイルは順番的に後になってしまうぞどうしよう、という場合はファイル名の先頭に`00_`など順番付けできるようなプレフィックスをつけるようにすると良さそうです。

# なにをしようとしたときに起こったか
ここでは私がこの問題にぶち当たるまでの経緯を説明しようと思います。

## まずはテーブルを作成しよう
例えば以下のように好きなもののテーブルがあったとします。

```
docker_ddl/
  ├ cakes.sql
  ├ chocolates.sql
  ├ cookies.sql
  └ pancakes.sql
```

## view があったら便利そうだ、そうに違いない、よし作ろう
そしてそれらを一覧で見れたら便利かもねーということで `my_favorites_view.sql` のような view を作成したとします。

```
docker_ddl/
  ├ cakes.sql
  ├ chocolates.sql
  ├ cookies.sql
  ├ my_favorites_view.sql
  └ pancakes.sql
```
このとき `my_favorites_view.sql` では中で `pancakes.sql` を参照しているとします。(いい感じのが思いつかなかったので中身は省略します。。)

## いでよ docker、パパーっとデータベースを立ち上げておくれ
この SQL ファイルたちを使うべく Dockerfile を書いてイメージを作って`docker run`を実行します。
するとどうでしょう`Table [データベース名].pancakes doesn't exist`となってしまいました。

## なぜなのか
これは`my_favorites_view.sql`の実行時にはまだ`pancakes.sql`が実行されておらず存在しなかったためです。
ですが確かになんとなく言われてみれば上から順番に実行されそうなので「何でやねんっ！」とはなりませんでした。

## どうすればいいか
ここで MySQL のイメージの公式を見るとアルファベット順で実行されますと書かれています。
それ以外で特に順番についての言及はないので結論にも書いたようになにか順番付けできるプレフィックスを決めるのがよさそうですね。

#### 余談1
コンテナ生成するとき`-d`オプションをつけた場合はバックグラウンドで実行されるのでコンテナ氏はスッといなくなってしまいます。
そんな場合は`docker logs [コンテナ名、またはコンテナ ID]`とするとログが見れるので原因追求しやすくなります。

##### 余談2
やっぱり公式読むのは大事ですね、、、
英語ちゃんと読めるようになりたいですね、、、
[PlayCanvas] サウンドの再生終了したタイミングで処理を実行する

# はじめに
* 特定のサウンドの再生が終わった後に処理を走らせたい。
* ザックリと調べてもそういったイベントもなさそうなので、とりあえず自前でどうにかする。
* 重要：これはベストな方法ではない。

# 実装
マウスをクリックしたら音声を再生、その音声終了したらコンソールにログを表示します。

``` javascript:Sample
var Sample= pc.createScript('sample');

// initialize code called once per entity
Sample.prototype.initialize = function() {
    this.app.mouse.on(pc.EVENT_MOUSEDOWN, this.mouseDown, this);
};

Sample.prototype.mouseDown = function(event) {
    var name = 'Sample';
    
    if( this.entity.sound ){
        this.entity.sound.play( name );
        
        if( this.entity.sound.slots[name] ){
            var id = this.entity.sound.slots[name]._asset;
            var asset = this.app.assets.get( id );
            var duration = asset._resources[0].buffer.duration;
            
            setTimeout(()=>{
                console.log('Played audio:', asset.name);
            }, pc.math.clamp(duration * 1000));
        }
    }
};
```

# 解説
前提として、アセットがちゃんと存在していて、Preloadにチェックが入ってるものとします。

## アセットを取得する
SoundのスロットにはAsset IDが格納されています。そのIDと`this.app.assets.get()`を使用してアセットを取得します。

``` javascript
var id = this.entity.sound.slots[name]._asset;
var asset = this.app.assets.get( id );
```

## アセットから再生時間を取得する
取得したAssetがちゃんとAudioであるならば、`_resources[0].buffer`に再生時間やサンプリングレートが格納されています。今回必要なのは再生時間(`duration`)です。

``` javascript
var duration = asset._resources[0].buffer.duration;
```

## 再生終了時に処理を走らせる。
取得した再生時間をミリ秒単位に変換し`setTimeout()`を使って処理を走らせます。
今回は何の音声が再生終了したのかをコンソールに吐き出します。

``` javascript
setTimeout(()=>{
    console.log('Played:', asset.name);
}, pc.math.clamp(duration * 1000));
```

# おわりに
サウンドのダッキングをするために調べていた時の副産物なので、ベストな方法は他者にまかせます。
【備忘録】:nth-of-type(n)の使用例

# はじめに
Sassを使った実装の時によく使われていたので、備忘録として残します。

#　目次
- :nth-of-type(n)とは
- 使用例
- 参考サイト

#　E:nth-of-type(n)とは
ターゲット要素(E)と同じタイプ（タグ）で兄弟関係にある要素に対してスタイルを適用します。

# 使用例

①html

```html
<!DOCTYPE html>
<!-- ここからがhtmlタグ/ルート要素 -->
<html lang="ja">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="style.css">
</head>

<body>
    <div>
        <h1>果物</h1>
        <p>
            りんご
        </p>
        <p>
            バナナ
        </p>
        <div>
            トマト？
        </div>
        <p>
            キウイ
        </p>
        <p>
            パイナップル
        </p>
        <h1>fruits</h1>
        <p>
            オレンジ
        </p>
        <p>
            みかん
        </p>
        <p>
            ぶどう
        </p>
        <p>
            かき
        </p>
    </div>

</body>

</html>
```

②CSS

```css
p:nth-of-type(odd) {
    color: white;
    background-color: black;
}

p:nth-of-type(n + 8) {
    /* p要素で兄弟関係にある8番目の要素からスタイルを適用。 */
    color: blue;
    background-color: yellowgreen;
}

h1:nth-of-type(2) {
    color: red;
    font-weight: 500;
}

div:nth-of-type(2) {
    /* div要素で兄弟関係にある２番目の要素がないため、スタイルはなし。 */
    color: pink;
    font-size: large;
}
```

③結果

![スクリーンショット 2021-02-11 15.54.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/966135/5c9eb271-d48b-5f81-2e1a-65b9f503e895.png)

# 参考サイト
http://www.htmq.com/selector/nth-of-type.shtml
https://developer.mozilla.org/ja/docs/Web/CSS/:nth-of-type
機械学習　第七章　サポートベクターマシン

####サポートベクターマシン（SVM）とは

マージンを最大化という基準をもちいて決定境界を得るモデル。
サポートベクターマシンは分類と回帰のどちらの問題にも利用することができ、このアルゴリズムでは、決定境界は線形になる。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/be12e743-fa50-f108-8694-d4b57500d399.png)

決定境界から一番近いデータまでの距離をマージンと呼び、マージンが最大になるように決定境界の位置が決められている。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/cb74aa63-aea3-51b2-6174-ab0174387247.png)

決定境界の決め方には「ソフトマージン」と「ハードマージン」の２種類がある。

- ハードマージン

データがマージンの内側に入ることを許容しない。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/4e234b92-89b0-da44-0d83-d89fab6dab38.png)

ハードマージンでは一つでも外れ値があるとそのデータの影響を大きく受けてしまう。

- ソフトマージン

データがマージンの内側に入ることを許容する。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/34b1d784-62ae-6a25-c81e-3522b6cc4188.png)

ソフトマージンでは全体のデータの分布を見てバランス良く決定境界を決めるため、外れ値の影響は小さくなる。

####マージン最大化のアルゴリズム

```math

\frac{1}{マージン}+C×誤判別数\\

C:誤判別の許容度

```

Cの値が小さい場合には、決定境界の内側にあるデータ数は増え、Cの値が限りなく大きい場合には、ハードマージンとなる。
機械学習　第五章　アルゴリズム

###k近傍法

分類問題のための機械学習手法

最近傍のデータをｋ個取ってきて、それらがもっとも多く所属するクラスに識別


![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/2ad7ad86-2e3a-01e7-14f3-ee15d8e264e8.png)


kを変化させると結果も変わる

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/053291e6-39b1-b282-9729-ee3f8dfc2ede.png)

kを大きくすると決定境界は滑かになる。

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/640f6e57-03f0-9b70-ab1b-967430f87ddb.png)


###k-平均法(k-means)

- 教師なし学習
- クラスタリング手法
- 与えられたデータをｋ個のクラスタに分類する

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/7f4ae53e-7e9e-d94e-f273-bfb3decb1cf6.png)

アルゴリズム
手順１

- 各クラスタ中心の初期値を設定する

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/dee520ba-38a4-75a0-a443-488952eeb301.png)

手順２

- 各データ点に対して、各クラスタ中心との距離を計算し、最も距離が近いクラスタを割り当てる

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/6bb4455b-f025-664f-cdc4-285bffb59f47.png)

手順３

- 各クラスタの平均ベクトル（中心）を計算する

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/b4354153-de83-13aa-5061-4e50743790b4.png)

手順４

- クラスタの再割り当てと、中心の更新を繰り返す

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/993cb810-ba37-9ae3-3a55-8afe9f7efe55.png)


- 中心の初期値を変えるとクラスタリング結果も変わりうる


![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/18f21885-3882-9e05-53b5-5538ca2b38bd.png)


- ｋの値を変えるとクラスタリング結果も変わる

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/41801520-7633-41b6-9b5f-6e32b95969de.png)
機械学習　第四章　主成分分析

####アウトライン

- 多変量データの持つ構造をより少数個の指標に圧縮

変量の個数を減らすことに伴う、情報の損失はなるべく小さくしたい。
少数変数を利用した分析や可視化（２、３次元の場合）が実現可能。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/4f9d6cb0-e12e-fddb-522c-54ca6b86cf00.png">

- 学習データ

```math
x_i=(x_{i1},x_{i2},...,x_{im})\in\mathbb{R}^m
```

- 平均ベクトル

```math
\hat{x}=\frac{1}{n}\sum_{i=1}^{n}x_i
```

- データ行列

```math
\hat{x}=\frac{1}{n}\sum_{i=1}^{n}x_i
```

-分散共分散行列

```math
\sum=Var(\overline{X})=\frac{1}{n}\overline{X}^T\overline{X}
```


- 線形変換後のベクトル

```math
S_j=(S_1j,...,S_nj)^T=\overline{X}a_j\\
a_j\in\mathbb{R}^m

```

- 係数ベクトルが変われば線形変換後の値が変化

情報の量を分散の大きさと捉える。
線形変換後の変数の分散が最大となる射影軸を探索

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/fd45de4a-30e5-4b06-00aa-7e9b00ab8669.png)
機械学習　第三章　ロジスティック回帰モデル

#####分類問題（クラス問題）
ある入力（数値）からクラスに分類する問題

#####分類で扱うデータ
- 入力（各要素を説明変数または特徴量と呼ぶ）

m次元のベクトル（ｍ次元の場合はスカラ）

- 出力（目的変数）

0 or 1の値

- タイタニックデータ、IRISのデータなど


#####シグモイド関数

- 入力は実数、出力は必ず0～1の値
- （クラス１に分類される）確率を表現
- 単調増加関数

```math
\sigma (x)= \frac{1}{1+\exp(-ax)}

```

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/86dca22a-75ae-0141-ff1b-c65c735301b8.png)

- シグモイド関数の性質

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/1527b1ca-c409-194a-6a20-dd943e14c8b5.png" width=60%>


シグモイド関数の微分はシグモイド関数で表せる。

- シグモイド関数の出力をY=1になる確率に対応させる

```math
P(Y=1|x)=\sigma (w_o+w_1x_1+...+w_mx_m)

```

データYは確率が0.5以上ならば1、未満なら0と予測


- ベルヌーイ分布

数学において、確率ｐで１、確率１－ｐで０をとる、離散確率分布（例；コイン投げ）

- 同時確率

あるデータが得られた時、それが同時に得られる確率
確率変数は独立であることを仮定すると、それぞれの確率の掛け算となる。

- 尤度関数とは

データは固定し、パラメータを変化させる
尤度関数を最大化するようなパラメータを選ぶ推定方法を最尤度推定という

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/136a0d73-ed0c-0733-d388-bd4276593a51.png" width=80%>

- ロジスティック回帰モデルの最尤推定

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/0e052a93-95b9-a94f-c13c-34e0b14cd38f.png" width=80%>


![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/a3942eeb-580b-3f90-d7e6-3ac72704affa.png)

- 尤度関数を最大とするパラメータを探す（推定）



対数をとると微分の計算が簡単

対数をとるのは桁落ちしないため


- 勾配降下法

```math
w(k+1)=w^k-\eta\frac{\partial E(w)}{\partial w}

```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/da375f8e-2862-9885-b57b-c14993e88908.png" width=70%>


- 勾配降下法では、パラメータを更新するのにN個全てのデータに対する和を求める必要がある。

ｎが巨大になったときにデータをオンメモリに載せる容量が足りない、計算時間が莫大になるなどの問題がある
確率的勾配降下法を利用して解決

- 確率的勾配降下法(SGD)

```math
w(k+1)=w^k+\eta (y_i-p_i)x_i

```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/9ebcc4a0-1139-c3a1-bae2-fefbc81eb0fc.png" width=70%>
機械学習 第二章 非線形回帰モデル 

#####単回帰/重回帰

```math
y=w_0+w_1x+w_2x_2+...+w_mx_m

```
→非線形な回帰を考えたい
→xの代わりにΦ(x)を用いる。

*ｘからΦ(x)に代えてもwについては線形のまま

予測model;

```math
\hat{y}= w_0+w_1\phi_1(x) +w_2\phi_2(x)+...+w_m\phi_m(x)
```

これは重みwについて線形

#####基底展開法

- 回帰関数として、基底関数と呼ばれる既知の非線形関数とパラメータベクトルの線形結合を使用
- 未知パラメータは線形回帰モデルと同様に最小二乗法や最尤法により推定

多項式

```math
\phi_j=x^j
```

ガウス型基底

```math
\phi_j(x)=\exp\biggl(\frac{(x-\mu_j)^2}{2h_j} \biggr)

```


基底展開法も線形回帰と同じ枠組みで推定可能

- 説明変数

```math
x-i=(x_i1,x_i2,...,x_im)\in \mathbb{R}^m
```

- 非線形関数ベクトル

```math
\phi(x_i)=(\phi_1(x_i),\phi_2(x_i),...,\phi_k(x_i))^T\in \mathbb{R}^k
```

- 非線形関数の計画行列

```math
\Phi^(train)=(\phi(x_1),\phi(x_2),...,\phi(x_n))^T\in \mathbb{R}^{n×k}
```

- 最尤法による予測値

```math
\hat{y}=\Phi(\Phi^{(tarin)T}\Phi^{(train)})^{-1}\Phi^{(train)T}y^{(train)}

```

#####未学習(underfitting)と過学習(overfitting)

- 学習データに対して、十分小さな誤差が得られないモデル→未学習
- 小さな誤差は得られたけど、テスト集合誤差との差が大きいモデル→過学習

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/968c5594-4c73-3318-5dbf-b186860abd01.png" width=60%>

- 不要な基底関数を削除
基底関数の数、位置やバンド幅によりモデルの複雑さが変化
解きたい問題に対して多くの基底関数を用意してしまうと過学習の問題が起こるため、適切な基底関数を用意(CVなどで選択)


- 正則化法(罰則化法）
「モデルの複雑さに伴って、その値が大きくなる正則化項(罰則項)を課した関数」を最小化
正則化（平滑化）パラメータ

```math
S_\gamma = (y-\Phi w)^T(y-\Phi w)+\gamma R(w)

```

- 正則化項（罰則項）の役割
無い→最小２乗推定量
L2ノルムを利用→Ridge推定量
L1のノルムを利用→Lasso推定量

- 正則化パラメータの役割
小さく→制約面が大きく
大きく→制約面が小さく

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/9221d433-3e08-e1c9-adf8-50e4ffeecbd6.png" width=80%>

- 手元のモデルがデータに未学習しているか過学習しているか

訓練誤差もテスト誤差もどちらも小さい→汎化しているモデルの可能性
訓練誤差は小さいがテスト誤差も大きい→過学習
訓練誤差もテスト誤差もどちらも小さくならない→未学習
回帰の場合には陽に解が求まります（学習誤差と訓練誤差の値を比較）

- ホールドアウト法

有限のデータを学習用とテスト用の２つに分割し、「予測精度」や「誤り率」を推定する為に使用

・学習用を多くすればテスト用が減り学習精度は良くなるが、性能評価の精度は悪くなる
・逆にテスト用を多くすれば学習用が減少するので、学習そのものの精度が悪くなることになる。
・手元にデータが大量にある場合を除いて、良い評価性能を与えないという欠点がある。

基底展開法に基づく非線形回帰モデルでは、基底関数の数、位置、バンド幅の値とチューニングパラメータをホールドアウト値を小さくするモデルで決定する。

- クロスバリデーション（交差検証）

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/ada1f60a-ff0d-406f-745a-17c4404c883a.png" width=70%>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/6a3b12ff-8534-8789-27cb-6fd8a00b19b8.png" width=70%>
機械学習 第一章 線形回帰モデル 

####線形

- ざっくり比例

- 回帰問題

ある入力（離散あるいは連続地）から出力（連続値）を予測する問題

直線で予測→線形回帰
曲線で予測→非線形回帰

- 回帰で扱うデータ

入力（各要素を説明変数または特徴量と呼ぶ）
 - ｍ次元のベクトル（ｍ＝１場合はスカラ）
出力（目的変数）
 - スカラー値(目的変数）

説明変数　

```math
X=(x_1,x_2,...,x_m)^T \in \mathbb{R}^m

```
目的変数

```math
y\in\mathbb{R}^1
```


### 線形回帰モデル

- 回帰問題を解くための機械学習モデルの一つ
- 教師あり学習（教師データから学習）
- 入力とｍ次元パラメータの線形結合を出力するモデル

パラメータ

```math
X=(x_1,x_2,...,x_m)^T \in \mathbb{R}^m

```

線形結合

```math
\hat{y} = w^Tx+w_0=\sum_{j=1}^{m}w_jx_j+w_0
```

- 説明変数が１次元の場合（m=1)の場合

単回帰モデルと呼ぶ

- データへの仮定

データは回帰直線に誤差が加わり観測されていると仮定

-連立方程式

それぞれのデータをモデル式へ当てはめるとｎ個の式が導出される。


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/15a331bc-7a52-f086-f92c-8186d1382153.png" width=50% >


- 説明変数がm次元の場合

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/59630b01-d069-dc4a-ae30-ff122f6d8fb8.png" width=50%>

- データの分割

学習用データ：機械学習モデルの学習に利用するデータ
検証用データ：学習済みモデルの精度を検証するためのデータ

- なぜ分割するのか

モデルの汎化性能(Generalization)を測定するため

データへの当てはまりの良さではなく、未知のデータに対してどれくらい精度が高いかを測りたい。

#####線形回帰モデルのパラメータは最小二乗法で推定
- 平均二乗誤差（残差平方和）

データとモデル出力の二乗誤差の和

パラメータのみに依存する関数
データは既知の値でパラメータのみ未知

- 最小二乗法
学習データの平均二乗誤差を最小とするパラメータを探索

学習データの平均二乗誤差の最小化は、その勾配が０になる点を求めれば良い

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653571/4a8c77c5-cbff-704f-51e6-87474d64821d.png" width=50%>


*二乗損失は一般に外れ値に弱い→Huber損失,Tukey損失

- MSEを最小にするようなW(m次元)

```math
\hat{w}=\underset{w \in \mathbb{R}}{\textrm{arg minMSE_tarin}}

```

MSEをWに関して微分したものが０となるWの点を求める

```math
\frac{\partial}{\partial w}MSE_{tarin}=0

```
回帰係数

```math 
\hat{w} = (X^{(train)T}X^{(train)})^{-1}X^{(train)T}y^{(train)}


```

予測値

```math
\hat{y} = \underset{n_{new×m+1}}{X}(X^{(train)T}X^{(train)})^{-1}X^{(train)T}y^{(train)}


```

####ハンズオン
ボストンの住宅データデットを線形回帰モデルで分析
AndroidのBillingLibrary2.1.0未満はjcenterにしかない

先日、mavenリポジトリの一つである[jcenterが停止するアナウンス](https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/)がされましたよね。

現時点でのjcenterの停止日は2022/02/01となっていますが、当初は2021/05/01とアナウンスがあり、焦った方も多いのではないでしょうか。

ということで、ずっと放置してた個人プロジェクトのbuild.gradleから試しに`jcenter()`を削除し`mavenCentral()`に置き換えたところ、エラーの中に以下を発見

```
Could not find com.android.billingclient:billing:1.0.
     Searched in the following locations:
       - https://dl.google.com/dl/android/maven2/com/android/billingclient/billing/1.0/billing-1.0.pom
       - https://repo.maven.apache.org/maven2/com/android/billingclient/billing/1.0/billing-1.0.pom
     Required by:
         project :app
```

(BillingLibraryがいまだ1.0なのは置いといて。。。)

**え、googleのMavenリポジトリにも、CentralリポジトリにもBillingLibraryのアーティファクト置いてないの！？**

**どうすりゃいいの!?** 

とビビりました。

結論から言うと、BillingLibraryは**2.0.3まではjcenterに、それ以降最新版(2.1.0~3.x.x)はgoogleのリポジトリ**にアーティファクトがあるようです。
なので、2.1.0以降にアプデすれば、`google()`の記述だけでよくなります。

なお、そもそも、**jcenterの停止の前にBillingLibraryを3.0にアプデしないといけないので問題になることはない**はずです。

> 2021 年 8 月 2 日以降、すべての新規アプリでは Billing Library バージョン 3 以降を使用する必要があります。2021 年 11 月 1 日までに、既存のアプリのアップデートはすべて Billing Library バージョン 3 以降を使用する必要があります



以下、参考スクショ。

![スクリーンショット 2021-02-11 15.38.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214755/a31631cd-04ba-6fd4-9d11-b8702fbf85e8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/214755/57e84e66-b0ed-e08a-93d4-29517cf5bd37.png)
【Rails】text_areaで改行・段落の表示方法

form_withで作成したtext_areaのフォームに改行や段落を入れたい場合があると思いますので、自分への記録も兼ねてこちらでその方法をシェアします。

```ruby:new.html.erb
<%= form_with(model: @recipe, local: true) do |f| %>
  <div class="col-md-8">
    <%= f.text_area :catchcopy, class: "form-control" %>
  </div>
<% end %>
```

上記のようにフォームを作成し、それを表示しようとすると、以下のようになります。

```show.html.erb
<div>
  <%= @recipe.catchcopy %>
</div>
```

ただ、このようにすると、入力フォームで改行や段落を加えた場合でも、それが反映されません。

以下のようにコードを書けば、改行・段落が反映されます。

```ruby:show.html.erb
<div>
  <%= safe_join(@recipe.catchcopy.split("\n"),tag(:br)) %>
</div>
```

参考になりましたら、幸いです。
【AWS】スナップショットが削除できない

備忘録
リージョン変更の時に作ったスナップショットが削除できないという事象が発生してしまった為、その解決方法について以下に記載しました。

リージョン変更についてはこちら↓
https://qiita.com/yvichrou211/items/c85aacdc45ea1811387b

### これから流れ
1.スナップショット削除で出たエラー文を見る
2.AMIとは
3.AMIの登録解除
4.スナップショットの削除
5.スナップショットについて

## 概要
スナップショットはAWSの課金対象だという事で、削除を試みる。

## 1.スナップショット削除で出たエラー文を見る
EC2左側のメニュー Elastic Block Store のスナップショットをクリック
不要になったスナップショットを削除しようと、スナップショットの アクション -> 削除をクリック
スナップショットを削除してもいいですかと、表示になり「はい、削除する」をクリックしても
スナップショット削除中のエラーが出る。

エラー文をよく見ると
 is currently in use by ami-”AMI名”　　＝　現在、ami-”AMI名"によって使用されています
との文字が、記載されていたので、AMIを見る。

## 2.AMIとは
AMIとは、 正式名称”Amazon Machine Image" 
何をする機能か
AMIはソフトウェア構成（オペレーティングシステム、アプリケーションサーバー、アプリケーションなど）を記録したテンプレートの事。
使い方・・・インスタンスのバックアップ

リージョン変更の時に、使ったインスタンスのコピーはAMIによって作成され、
バックアップとして保存。
リージョン変更した後に、スナップショットからインスタンスとして復元され
リージョン変更できたかと思います。


## 3.AMIの登録解除
EC2左側のメニュー　AMIをクリック
AMIを確認してみると、スナップショットのエラー画面と同一のAMI名が。
エラー表示→　is currently in use by ami-”AMI名”
AMIをクリックして、アクション -> 登録解除 　を選択。
イメージの登録を削除してもよいですか　→ 次へ　を選択し登録解除になった。

>>参照記事
 https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/deregister-ami.html
AMI の登録を解除しても、AMI から既に起動したインスタンスに影響を与えることはありません。そのようなインスタンスの使用に対しては引き続き課金されます。そのため、使用が終わったら、インスタンスを終了することをお勧めします。


## ４.スナップショットの削除
AMIの登録解除になったので、スナップショットの アクション -> 削除をクリック

## 5.スナップショットについて
AMIを作られている方は、スナップショットは自動作成される事があるようですのでご注意を。


>> 参考情報
https://dev.classmethod.jp/articles/error-remove-snapshot-ec2/
Xiaomi Redmi 9T に乗り換えた話。


前回スマホを購入しは話はこちら。
[iPhone6sからZenFone Max M1に乗り換えた話。](https://qiita.com/suezawan/items/2c8b22b454c74ff79c18)

今回、Xiaomi Redmi 9Tを購入したので、スペック比較でもしていきます。
全体的にスペックアップしているにも関わらず、価格が1万円台なのがいいですね。

[Xiaomiの「Redmi 9T」が登場　4眼カメラやSnapdragon 662搭載で1万5900円（税別）](https://www.itmedia.co.jp/mobile/articles/2102/02/news078.html)

| 端末名| Xiaomi Redmi 9T| ZenFone Max (M1) |
|:-----------|------------:|:------------:|
|cpu|Qualcomm® Snapdragon™ 662|Qualcomm® Snapdragon™ 430 (オクタコアCPU)|
|メモリ|4GB| 3GB|
|ストレージ|64GB|32GB microSD™256GB利用可能|
|リアカメラ|4800万画素| 1,300万画素カメラ内蔵 (メインカメラ)800万画素広角カメラ内蔵 (2ndカメラ)|32GB|
|インカメラ|800万画素 F値 2.05|800万画素|
|画面サイズ|高さ:162.3mm、幅:77.3mm、厚み:9.6mm|5.5インチ|
|重さ|198g|150g|
|生体認証|サイド指紋センサー/AI顔認証|指紋センサー|
|simカード|デュアルSIM + microSDカード|nanoSIMスロット×2|
|バッテリー|6,000mAh|4,000mAh|
|OS|MIUI12（Android 10準拠）|Android™ 8.0|
|発売日|2021年2月5日|2018年9月21日|
|費用|15,180円|21,800円|
PHPUnitの導入

早いうちにPHPUnitを学習して、１つ１つの機能を実装するたびにテストコードを追加していきたい。
RSpecよりかは準備が楽だった。

##準備

mysql等でテスト用のDBを作成した後、
.env.testingという名のファイルを作成し、.envファイルからコピペしてDB名だけテスト用に書き換える。

``` php:.env.testing
DB_DATABASE=hoge_test  #作成したテストDB名
```
その後、

```
$ php artisan migrate --env=testing
```
を実行してテストDBに対してmigrateする。

composerのインストールを行なっていない人はインストールする。

```
$ composer install
```

Laravel のプロジェクトディレクトリ下で

```
$ ./vendor/bin/phpunit
```
を実行。

```
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:01.199, Memory: 22.00 MB

OK (1 test, 1 assertion)
```

こんな感じで表示されればOK(下の数字はテスト数などで変わる)。


テストメソッドは、
・メソッド名の接頭辞に “test” をつけること
・メソッドのコメントに@testアノテーションをつけること
のどちらかが必要になる。
また、パブリックメソッドであることも必要。

##実践
ユーザー登録のテストを行う。

###テストファイルの作成

```
php artisan make:test UserTest
```

###テストコードの記述

``` php:UserTest.php
<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;

class UserTest extends TestCase
{

    use RefreshDatabase;

    /**
     * @test
     */
    public function createUser()
    {
        $user = new \App\Models\User;
        $user->name = "test";
        $user->email = "test@example.com";
        $user->password = \Hash::make('password');
        $user->save();

        $readUser = \App\Models\User::where('name', 'test')->first();

        // データが取得できたか
        $this->assertNotNull($readUser); 

        // パスワードが一致している
        $this->assertTrue(\Hash::check('password', $readUser->password));
    }
}

```

###実行結果

```
$ ./vendor/bin/phpunit
PHPUnit 9.5.2 by Sebastian Bergmann and contributors.

.                                                                   1 / 1 (100%)

Time: 00:01.774, Memory: 26.00 MB

OK (1 test, 2 assertions)
```

##参考
https://php-junkie.net/framework/laravel/first-testing/
https://qiita.com/kuriya/items/4c9dbefc19514f415374
https://techacademy.jp/magazine/19301
Laravelのアプリケーション全体でCarbonImmutableを使用したい

# はじめに
こんにちは。Laravelで日に日に新しいもの出てきて(見つけて)、追いつくのに必死の筆者です :sob:

さて、`Carbon`使っていますでしょうか？

Eloquentの返り値等々、`CarbonImmutable`だったらいいなと感じました。

# CarbonImmutableにできます :ok_hand:
AppServiceProviderにたった1行書くだけ :+1:

```php:AppServiceProvider.php
class AppServiceProvider extends ServiceProvider
{
    public function register()
    {
        // アプリケーション全体でCarbonImmutableを使用する.
        DateFactory::use(\Carbon\CarbonImmutable::class);
    }
}
```

# おわりに
業務委託でぼそっと言われたのをしれっと対応した備忘録でした:pray:
それでは！
【Nuxt.js】layoutsを使い分けたい 

## 悩んだこと
Nuxt.jsで開発を進めている時に、ユーザー画面と管理者画面で別のヘッダーとフッターを使用したい。思った。

## やったこと
layouts配下には、default.vueがもともと存在するが、そこにadmin.vueというファイルを作成してた。

そして、そのレイアウトを使用したいpageに次の記述を追記した。

```index.vue
<script>
export default {
  layout: 'admin',
  data() {
    return {
    }
  },
}
</script>
```

これで、layouts/admin.vueをレイアウトとして使用することができるようになった。

[参考記事](https://ja.nuxtjs.org/docs/2.x/components-glossary/pages-layout/)
Attention Is All You Need のQuery, Key, Valueは、Query, Query, Queryぐらいの解釈でも問題ない(と思う。)

#概要

以下の記事などで示しているように、単なる興味で、論文「Attention Is All You Need」を理解しようとしている。

[Attention Is All You Need の 『Attention』を、段階を踏んで、理解する手段](https://qiita.com/enoughspacefor/items/394b9473254ff5d7dfca)

第一段階の目標として、

|query,key,value:tada:に慣れる |
|:---:|

を設定していたが、
いまさらのように、ちょっと、気づいたことがあるので、記事にする。

#Query, Key, Valueは、Query, Query, Queryぐらいの解釈でも問題ない(と思う。)

##本来のQuery, Key, Valueとは

本来のQuery, Key, Valueとは、以下の論文等にあるように、
**Key-Value**のペアを利用して、Queryに対応するValueを得る（上手く検索したりする）ものだと思う。

https://arxiv.org/pdf/1606.03126.pdf
Key-Value Memory Networks for Directly Reading Documents

##attentionのQuery, Key, Valueとは
**全然、違う！**
何が違うとかというと、

* 準備されたkey-valueのペアがあるわけではない。

とにかく、全然、違う。
keyとvalueの値が同じ特殊形と考えることができるのか？？？

##参考
以下の記事などは、参考になるかも。
この記事は、粛々と説明がされている。
「**What exactly are keys, queries, and values in attention mechanisms?**」

https://stats.stackexchange.com/questions/421935/what-exactly-are-keys-queries-and-values-in-attention-mechanisms

##結論
Attention Is All You Need のQuery, Key, Valueは、**Query, Query, Query**　:tada:ぐらいの解釈でも問題ない(と思う。)


#まとめ
特にありません。

#参考（自分の関連記事）


[自己注意Self-Attention の解説でわかりやすいと思った記事N選　(まだ、N＝8）](https://qiita.com/enoughspacefor/items/c9810d1065741a7f461c)
10年前のノートPCで4K表示ができました。

2011年製のノートPCで外付けディスプレイの4K対応が確認できました。
【PCスペック】
PC : VOSTRO 3750(カスタマイズモデル)
CPU : Core i5-2410M @2.30GHz
RAM : 6GB
Graphic : HD Graphics 3000, GeForce GT 525M
I/F : USB 3.0

使用したアダプタは以下です。
【USB-HDMI アダプタ】
製品 : plugable USB 3.0 4K HDMI Adapter UGA-4KHDMI
スペック : 最高4K(UHD/3840x2160@30Hz)
![DSC_1237.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919305/c808680c-762f-3a58-cb0a-8d0f317958d8.jpeg)

下記の通り4K対応できました。USB Type-Cを持たない古いPCだったので、4K対応は諦めていたのですが、快適な表示が実現できて大変満足しています。さすがに4K全画面動画はフリーズしてしまいますが、投稿者の用途はソフトウェア開発がメインなのでVisualStudio, VSCode, Excel, ロジアナなど一通り試してみて実使用上問題ありませんでした。

![dispsettings.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919305/7af1486b-0f93-1e4a-225c-ba0ee724543d.jpeg)

![vsc__.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919305/e3ddb239-a495-e8b4-0fcb-05da4220b4c4.jpeg)

何もしなくてもメモリを5GBほど消費します。
![res.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919305/2d2513c5-f731-da0f-652b-758f7e3a8f83.jpeg)
【Godot】CSVファイルの読み込み方法

# 概要
この記事では Godot Engine で CSVファイルを読み込む方法について解説します。

# CSVファイルの作成
今回は以下のデータを扱うとします。

```data.txt
hero,100,20
fighter,150,0
magician,50,80
```

ファイル名は data.txt とします。
拡張子は .csv としたいところですが、 .csv は翻訳データと扱われて実行時にエラーメッセージが表示される（実行はできるのが今後問題が起きるかも……？）ので、念のため .txt としました。

# ファイル読み込み
ファイル読み込みは File オブジェクトを使うことで簡単にロードできます。

```gd
extends Node2D

func _ready():

  # ファイルオブジェクト作成
  var f = File.new()

  # "data.txt" ファイルを開く
  f.open("res://data.txt", File.READ)

  # テキストの内容を出力
  print(f.get_as_text())

  # ファイルを閉じる
  f.close()
```

## CSVを1行ずつ読み込む
Fileオブジェクトの `get_csv_line()` を使用すると、指定の区切り文字(デフォルトは ",")で区切った配列を返してくれます。

```gd

extends Node2D

func _ready():

	# ファイルオブジェクト作成
	var f = File.new()

	# "data.txt" ファイルを開く
	f.open("res://data.txt", File.READ)

	# CSVを1行ずつ読み込む
	var line = f.get_csv_line()
	while line.size() >= 3: # 横方向の項目数が足りない場合は終了
		print("name: %s"%line[0])
		print("hp:   %s"%line[1])
		print("mp:   %s"%line[2])
		line = f.get_csv_line()

	# ファイルを閉じる
	f.close()
```

実行結果

```
name: hero
hp:   100
mp:   20
name: fighter
hp:   150
mp:   0
name: magician
hp:   50
mp:   80
```

`get_line()` で1行ずつ読み込んで、split() で分割しても良いですが、少し楽できます。

### 空行を読み飛ばす判定による実装
なお、ファイル(データ)の終了を `File.eof_reached()` で判定する方法もありますが、その場合は最後の行が空行（改行文字だけ）かどうかを判定する処理が必要となります。

```gd:空行を読み飛ばす判定による実装
extends Node2D

func _ready():

	# ファイルオブジェクト作成
	var f = File.new()

	# "data.txt" ファイルを開く
	f.open("res://data.txt", File.READ)

	# CSVを1行ずつ読み込む
	while f.eof_reached() == false: # ファイルの終端チェック
		var line = f.get_csv_line()
		if line[0] == "":
			continue # 空行を読み飛ばす
		
		print("name: %s"%line[0])
		print("hp:   %s"%line[1])
		print("mp:   %s"%line[2])

	# ファイルを閉じる
	f.close()
```

# 参考

* [Docs » Godot API » File](https://docs.godotengine.org/ja/stable/classes/class_file.html)
【Mac】Laravelアプリをngrokを使って、外部に公開する。

Webhookを試したいという時は、一時的に外部に公開することが多いですが、わざわざサーバーにアップするのは面倒。

そんな時は「ngrok（エングロック）」を使えば簡単に実現出来ちゃいます。

ということで、今回はLaravelアプリを一時的に外部に公開する方法をサクッと書いていきます。

（Laravel以外ももちろん可能ですが、今回はLaravelです。）

##ngrokのインストール

まずはhomebrewでインストールします。（homebrewなのでどこで下記コマンドを実行してもOKです。）

```
brew cask install ngrok

//最近は下記のコマンドになったっぽい。
brew install ngrok --cask   
```

##Laravelでサーバーを立ち上げる

続いて、Laravel側で簡易サーバーを立ち上げます。

```
php artisan serve

//実行結果
Laravel development server started: http://127.0.0.1:8000
```

こんな感じでポート8000でサーバーが立ち上がるはず。

##ngrokを使用して外部に公開

Laravel側のサーバーは立ち上げたまま、別のターミナルで、外部に公開したいポート番号を指定してコマンドを実行してください。

```
ngrok http 8000

//実行結果
ngrok by @inconshreveable                                                                                                           (Ctrl+C to quit)
                                                                                                                                                    
Session Status                online                                                                                                                
Session Expires               1 hour, 59 minutes                                                                                                    
Version                       2.3.35                                                                                                                
Region                        United States (us)                                                                                                    
Web Interface                 http://127.0.0.1:4040                                                                                                 
Forwarding                    http://edf06440561a.ngrok.io -> http://localhost:8000                                                                 
Forwarding                    https://edf06440561a.ngrok.io -> http://localhost:8000                                                                
                                                                                                                                                    
Connections                   ttl     opn     rt1     rt5     p50     p90                                                                           
                              0       0       0.00    0.00    0.00    0.00                                                                                                                                                                                                                                                                                                     
```

上記みたいな感じで、色々表示されますが、`Forwarding`の部分のURLでアクセスできるようになっています。

`http`と`https`のどちらでもアクセス可能なのが便利な点。

これでwebhookのテストが簡単だぁ〜〜〜〜


##【余談】

PC自体のスペックが低いと、ファンがうるさかったり、表示が遅いとかあるらしい。
AppleシリコンMacだと特に何も感じませんでした。

ご使用はほどほどに。