OmniAICreator/Qiita-1.07M huggingface dataset:
OSS開発初めかた (Issueの見つけ方)

この記事は，東京大学工学部電子情報工学科・電気電子工学科(通称EEIC)の3年後期実験の一つである「大規模ソフトウェアを手探る」のレポートとして，書かれたものです。

# Issueの見つけ方
[「大規模ソフトウェアを手探る」](https://doss.eidos.ic.i.u-tokyo.ac.jp/)という実験で私たちの班はOSSのお絵かきソフトであるinkscapeを題材として選択し、バグを修正してマージするところまでできました。環境構築、バグの直しかたについては以下の概要記事から参照してください。
[Inkscapeを手探る](https://qiita.com/momoka_0122y/private/df19a0ff5a993514cc89)


inkscapeを題材にすると決めてから私たちは自分たちでInkscapeを触ってみて付け加えたい機能を探す他に既存のIssueをみて、自分たちにも解決できるバグが報告されていないか探しました。

## Issue 一覧
#### GitLab
Issue一覧は開発したいOSSの左側の項目一覧からIssueという項目から探すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/3f95397b-3cdf-42a1-7361-128a233799b1.png)
#### GitHub
GitHubページなら上の項目の中のIssueから一覧を見ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/8407c3b1-fab5-3782-75ef-14e94ec9a988.png)

## labelでIssueを探す。
初めてだとどれがはじめやすいIssueなのかみてもわからないので、いくつかある初心者用のラベルがついているIssueからみていくとわかりやすいです。
初心者ラベルには```easy-fix```　や```good first issue```などがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/d84c00dc-f5d3-e89c-47e1-f39b73141dc3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/a5f3f474-0861-cf35-afb4-dda419995090.png)

これらのタグがついているIssueは比較的楽だったりします。
### 比較的簡単なIssueの例
実際に```easy-fix```のラベルがついていて簡単に直せそうだと見つけたIssueを紹介したいと思います。 (残念なことに取り掛かる前に別の人にMRを出されてしまった。)
[**Prevent deleting locked guides** - Inkscape](https://gitlab.com/inkscape/inkscape/-/issues/1905)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/f4570fec-9a8e-bfc9-2b81-8224f467c057.png)
これはお絵かきアプリInkscapeのバグについてのIssueで内容としてはguideという機能を使うときにある線をロックした場合deleteボタンでは削除できないはずなのに、削除できてしまうという内容です。実際にこのIssueがまだopenのときに確認したところ確かにロックされているのに削除できてしまう状態でした。

バグの内容を聞いただけだと何がよくないのかわからず直すのが難しいバグに思えますが、InkscapeのdeveloperがこのIssueにコメントをつけておりそれが解決のヒントとなります。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/fdbfb53c-2c30-b1d0-4fcd-9757bb8c0867.png)
わかりやすく言い換えると「desktop-events.cppファイルの中のsp_guide_removeを呼び出すときにlockされているかどうかをチャックすればいいだけだから```easy-fix```だね」

つまりlockされている時だけsp_guide_removeを呼び出すようにすればいいということ。簡単に聞こえてきた。
実際のMRではどのように直されたかコードをみてみる。
[**Prevent locked guides from being deleted**](https://gitlab.com/inkscape/inkscape/-/merge_requests/2371)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279062/1178a624-85e0-71cf-a259-9afd77c6ba09.png)
コメントのとおりにsp_guide_removeが呼び出される前にguide->getLocked()がTrueかFalseかを確かめているだけ。コードにするとif文一つ付け加えただけである。


このIssueは見つけてから取り掛かるまでに時間を置いてしまったこともあり、実際に自分で直すことはできなかったが、if文一つ付け加えるだけでIssueを直すことができるということを学ぶことができたよいIssueであった。


## Issueを見つけた後は？
Issueを見つけた後は実際にコードを変更してバグを直してMRなりPRをだしてOSSに貢献しましょう。
Issueを見つけた後のMRを出すまでの動きは次の記事でまとめました。
[**OSS開発初めかた (GitLabにある本家にマージ) - Qiita**](https://qiita.com/momoka_0122y/items/4d04c8f2d94d591f938a)
スクロール

```javascript

function scrollToTop() {
  scrollTo(0, 0);
 }
```

```javascript

var element = document.getElementById('target'); // 移動させたい位置の要素を取得
    var rect = element.getBoundingClientRect();
    var position = rect.top;    // 一番上からの位置を取得

function scrollToTop() {
  scrollTo(0, position);
 }
```
Android Studio を日本語化する方法

まず、Android Studio を起動します。

`File`メニューから`Settings`を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/4d2ffcb6-632e-95f8-eebd-3e856b362c30.png)

検索欄にJapaneseを入れると、`Japanese Language Pack EAP`が出てくるのでこれを`Install`します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/6bd7c577-0dc6-12fc-6609-82094aecac97.png)

`Restart IDE`でAndroid Studioを再起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/8e202000-744b-cdad-9222-beb749fffed3.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/9e0fb920-d441-c562-7df1-86c3b21fd809.png)

日本語化されたAndroid Studioが起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184382/16ca926e-59b8-2d6d-a0ae-fe7dce34317f.png)
IBM CloudのVPC環境で時刻同期(Private Service Endpointを利用）

#1. はじめに

VPC環境ではデフォルトではNTPは構成されていない。

```
[root@syasuda-tok1-vpc1 ~]# timedatectl
      Local time: Tue 2020-11-03 17:32:33 JST
  Universal time: Tue 2020-11-03 08:32:33 UTC
        RTC time: Tue 2020-11-03 08:32:46
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: n/a
NTP synchronized: no
 RTC in local TZ: no
      DST active: n/a
```


[IBM Cloud docs](https://cloud.ibm.com/docs/vpc?topic=vpc-service-endpoints-for-vpc#network-time-protocol-ntp-servers)には、Private NWからアクセス可能なNTP endpoint情報として`161.26.0.6`が提供されているため、この情報を利用してNTPを構成する。今回はCentOS7+chronyを利用した。

#2. chronyの導入と設定


```txt:chronyの導入
# yum install -y chrony
```

`/etc/chrony.conf`はとりあえず接続先情報さえ変えたらそのままでも動くので、（細かいカスタマイズは行うことなくデフォルトの設定をそのまま採用し）、今回は接続先のみを変更。

```txt:/etc/chrony.confの設定変更
# vi /etc/chrony.conf
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
↓
server 161.26.0.6 iburst
```

```txt:chronydの起動
# systemctl start chronyd
```

#3. 動作確認

```txt:NTPが有効になった。
# timedatectl
      Local time: Tue 2020-11-03 17:41:13 JST
  Universal time: Tue 2020-11-03 08:41:13 UTC
        RTC time: Tue 2020-11-03 08:41:12
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
```
```
# chronyc tracking
Reference ID    : A11A0006 (mirrors.adn.networklayer.com)
Stratum         : 4
Ref time (UTC)  : Tue Nov 03 08:39:36 2020
System time     : 0.000035592 seconds fast of NTP time
Last offset     : +0.000036951 seconds
RMS offset      : 0.000421925 seconds
Frequency       : 19.302 ppm slow
Residual freq   : +0.012 ppm
Skew            : 0.823 ppm
Root delay      : 0.145885363 seconds
Root dispersion : 0.048914578 seconds
Update interval : 64.2 seconds
Leap status     : Normal
```


```txt:アスタリスク（＊）が付いている行が実際に同期しているNTPサーバ
# chronyc sources
210 Number of sources = 1
MS Name/IP address         Stratum Poll Reach LastRx Last sample
===============================================================================
^* mirrors.adn.networklayer>     3   6   177    34    +15us[  +52us] +/-  125ms
```
【Java】デザインパターンのまとめ

<h1>目的</h1>
Javaのデザインパターン全23種を学んだので、その備忘録として記載する。
本記事では、全デザインパターンの概要について記載する。

<h1>デザインパターンとは</h1>
より効率的で汎用的な設計ができるように考案された、代表的なクラス設計のパターン集。
再利用性が高くコード全体の見通しが良くなるだけでなく、メンテナンスする際にも影響範囲を最小限に抑えることができる。

<h1>デザインパターンの種類</h1>
デザインパターンは、
・オブジェクトの生成
・プログラムの構造
・オブジェクトの振る舞い
に関する3つのパターンに大きく分類される。

<h2>オブジェクトの生成</h2>
オブジェクトの生成に関するパターンの一覧と概要です。全5種。

<table><thead><tr>
<th>パターン名</th><th>概要</th>
</tr></thead><tbody>
<tr><td>Factory Method</td><td>複数のサブクラスをペアにして生成する。</td></tr>
<tr><td>Abstract Factory</td><td>Factory Methodを専門にするクラス。</td></tr>
<tr><td>Builder</td><td>コンストラクタをビルダクラスとディレクタクラスに分け、複雑な初期値のオブジェクトを生成する。</td></tr>
<tr><td>Prototype</td><td>クローンをプールしておくことで、オブジェクトの生成を簡単にする。</td></tr>
<tr><td>Singleton</td><td>システムの起動から終了までの間に、そのクラスのオブジェクトが1個しか生成されないことを保証する。</td></tr>
</tbody></table>

<h2>プログラムの構造</h2>
プログラムの構造に関するパターンの一覧と概要です。全7種。

<table><thead><tr>
<th>パターン名</th><th>概要</th>
</tr></thead><tbody>
<tr><td>Adapter</td><td>既存クラスを修正することなく、適切なメソッドを追加することができる。</td></tr>
<tr><td>Bridge</td><td>関連の強い2つのクラスについて、それぞれのクラスを継承することで拡張しても影響のないようにする。</td></tr>
<tr><td>Composite</td><td>階層構造をなすオブジェクト全体に共通のインターフェスを持たせることで、一連の操作を簡単に実行することができる。</td></tr>
<tr><td>Decoraror</td><td>共通のインターフェスを実装させることで、クラスの継承よりも幅広く機能を追加できる。</td></tr>
<tr><td>Facade</td><td>汎用性の高いクラスのオブジェクトをまとめることで、開発者間で共有しやすくする。</td></tr>
<tr><td>Flyweight</td><td>生成済みのオブジェクトをプールしておくことで、オブジェクトの生成・保持に必要な負荷を小さくする。</td></tr>
<tr><td>Proxy</td><td>共通のインターフェスを持たせることで、メソッドが呼ばれたときにそれをフックして処理を加える。Decoratorと似ている。</td></tr>
</tbody></table>


<h2>オブジェクトの振る舞い</h2>
オブジェクトの振る舞いに関するパターンの一覧と概要です。全11種。

<table><thead><tr>
<th>パターン名</th><th>概要</th>
</tr></thead><tbody>
<tr><td>Chain of Responsibility</td><td>リクエストの種類（引数の値）によって、複数のオブジェクトの中から適切なオブジェクトを選択して処理する。</td></tr>
<tr><td>Command</td><td>リクエストの処理自体をオブジェクト化し、複雑な内容のリクエストを送る。</td></tr>
<tr><td>Interpreter</td><td>構文解析の結果として得られるオブジェクト構造をそのまま使ってインタプリタを実行できるので、構文を拡張しやすくなる。</td></tr>
<tr><td>Iterator</td><td>Iteratorインターフェスを使用して、オブジェクト群の構造に関係なく簡単にアクセスできるようになる。</td></tr>
<tr><td>Mediator</td><td>相互作用の内容の変更や部品オブジェクトの追加が簡単にできる。</td></tr>
<tr><td>Memento</td><td>オブジェクトのある瞬間での状態のスナップショットを取り出して保存しておき、それを使って元の状態を復元できる。</td></tr>
<tr><td>Observer</td><td>チェックする側とされる側のクラスを切り替えたり増やしたりすることが簡単にできる。</td></tr>
<tr><td>State</td><td>状態が複雑に変化しても処理内容の切り替えがシンプルに行え、コード内での状態遷移の見通しがよくなる。</td></tr>
<tr><td>Strategy</td><td>プログラムの実行中に、その中で使われるアルゴリズムを簡単に切り替えることができる。</td></tr>
<tr><td>Template Method</td><td>ある1つの大きな処理を複数のステップに分解し、ステップの実行順序は守りつつ、各ステップごとに処理内容を変更する。</td></tr>
<tr><td>Visitor</td><td>オブジェクトの集合の中に何種類かのクラスが混在していても、それらのクラスを修正することなく処理を追加することができる。</td></tr>
</tbody></table>

<h1>最後に</h1>
デザインパターンは、再利用性やメンテナンス性を考えると非常に優秀だが、無理にデザインパターンに当てはめようとすると、かえって複雑なコードになってしまうケースもあるので注意する。
強いアトムのチャットルーム

### プロジェクトの概要
😛項目は全スタックtypescriptを用いた
全typescript
😈プロジェクトを開発し、以後の機能が超のんびりするためだ。もちろん、私自身もtypescriptが好きです。
🧐現在チャットルームが完全なチャット機能を備え、今後多く酷鍱の機能が、続々と開発の好きな友人のスターに私を励ましてみましょう!
### プロジェクトインターフェース
![v6_pc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849336/fab0b849-2f70-0e3b-871a-280e63e513fb.png)
![v6_m1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849336/bb44c1ee-2bd9-d826-5d83-b607501b3990.png)
### プロジェクトデータベース設計
![database.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849336/f831d5f4-091a-ae91-bf18-13e66bce7f74.png)

### 機能紹介
- モバイル端兼用
- ユーザー情報の改正(石塔/ユーザー名/パスワード)
- 群话/私の话
- 創設群/加入群/退群あいまい検索群
- 削除添加/友人の友人/あいまい検索ユーザー
- メッセージページ
- emoji
- 写真を送る/写真プレビュー
- オンライン数を集計
- カスタムテーマ
- 重に注意さえ

### github
[鉄腕アトム](https://github.com/genaller/genal-chat)
### url
[www.genal.fun](https://genal.fun/)
[OCI] OCIのログイン画面をカスタマイズする

OCIのログイン画面はカスタマイズ可能です、ここではCI (Corporate Identity)的な意味で、ログイン画面をカスタマイズしてみます。

OCIのIDCSのlogin画面の出来上がりのイメージはこちらです。
なんとなく青ヶ島の写真にしてみました、実際には何かのサービスに関連した画像を貼ることになると思います。
![rapture_20201103165511.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/d70465d3-9a15-7654-d3bd-8aefe9be1172.jpeg)
これがカスタマイズされたIDCSのログイン画面です。
### 設定手順
アイデンティティ -> フェデレーション　を選択
![rapture_20201103165744.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/0b33762f-d5f3-bcdf-49ce-90e5b57b0049.jpeg)
OracleIdentityCloudService を選択
![rapture_20201103165755.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/fd220540-64ed-54d7-131c-2411aee08024.jpeg)
IDPに移動したら、Oracle Identity Clouse service Console のURLをクリック
![rapture_20201103165805.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/45592736-3562-e4a3-8e1c-d8c043381a0c.jpeg)
IDPの 設定 -> ブランディング　に移行してIDCSのカスタマイズの画面に移行します。
![rapture_20201103165814.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/65ab2872-28b7-896c-5818-ef93d64fb823.jpeg)
ここで各種ブランディングの設定をします。

サインインページのアイコンとテキスト
コンソール左上のアイコン
eメールのアイコン
が設定できます。
![rapture_20201103165829.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/f8d8de3e-a0d6-ecb8-9dd8-f06fa7ebc6e2.jpeg)

ここで設定可能なのはIDCS側の画面のみでIAM側の画面ではありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3968/c64e586a-68be-1351-b6f6-8768f8c4614b.png)
ここから先は、私の解釈ですが、
IAM側の画面はIaaS専用で、この画面を使用するのはインフラ管理者という裏方なのでファンシーな設定はありません。
デパートにたとえて言うなら、IAMは従業員出入口、IDCSは正面玄関です。
IAMはサービスを提供する為の出入り口なので、使う人は従業員、アクセス権が権限分掌されており食品売り場には食品担当者しか入れません、掃除担当の人はどこにも入れますが、レジスターには触れません、警備の人は24時間いつでも出入りできます。
逆に、IDCSはサービス利用者のための出入り口なので、まず、大勢の人が出入りします。
またサービス時間外はアクセスできません。他店からやってくる人もいます。
一般ユーザーが多いですが、会員制の高度なサービスを受けられる人もいます。
入会、脱会の頻度と数が多いです。
入口がおしゃれでないと、入ってきません。

つまりIDCS画面は、PaaS,SaaSのための画面であり、エンドユーザーも接することのある画面なので、このようなアイコンの追加も可能なものとなっています。
つまりエンドユーザーが見る可能性があるかないかの違いです。
OCIのコンソールは2系統あって、複雑に感じますが、逆に、その目的の違いを理解すれば、IaaSの多くのユーザーが使うIDCSシステムを構成することが楽になるのではないかと思います。
link_toの引数がnil(null)で想定していないリンクが生成れたので検証してみた

# 前提
インスタンス変数を引数にして、link_toでリンクを生成する際、指定した覚えのないリンクが生成されました。
生成されたのはそのページのリンクで、どうやら引数にnilを渡していると発生するようだ。
関連するページを発見できなかったので、検証結果と解決策を記載してみる。
なお、当方は初学者なので、見当違いであればコメントをいただけると幸いです。
# 環境
ruby 2.6.5
Ruby On Rails 6.0.0

# TL;DR
```erb
http://localhost:3000/hoge/3というページ内で以下の記載をした場合
以下のように、そのページのリンクが生成される。(誰が使うねん）
<%= link_to nil,nil %>

=> <a href="/hoge/3">/hoge/3</a>

渡ってくるデータにnilが入る可能性がある場合は、以下のようにすると、nilの場合はブランクとなる。
@hoge・・・urlデータかnil

<%= link_to_if @hoge, @hoge, @hoge %>
空文字やスペースを入る可能性があるなら（そのへんはバリデーション対応するべき？）
<%= link_to_unless @hoge.blank?, @hoge, @hoge %>

```

# 詳細（検証と解消方法）
```erb
link_to（使い方）
link_to(リンクテキスト, パス [, オプション, HTML属性 or イベント属性])

リンクテキストがnilの場合は、パスに入れた内容がリンクテキストとして表出する

<%= link_to nil, "https://twitter.com/" %>

=> <a href="https://twitter.com/">https://twitter.com/</a>

パスがnilだった場合（http://localhost:3000/hoge/というページに記載）
カレントページのリンクが生成される

<%= link_to "hoge", nil %>

=> <a href="/hoge/">hoge</a>

なのでリンクテキストにもnil,パスにもnilが入っていると、
パスがnilなのでカレントページのリンクが生成される
→リンクテキストがnilなのでカレントページのリンクが表出されると思われる。

解消方法
使い方
link_to_if(条件式, リンクテキスト, url [, オプション, HTML属性 or イベント属性])

@hoge・・・urlデータかnil

<%= link_to_if @hoge, @hoge, @hoge %>

↑のようにすれば、@hogeがnilの場合は何も生成されず、データばあるときのみ生成される。

```
# 参考文献
https://railsdoc.com/page/link_to
https://railsdoc.com/page/link_to_if
nilを入れたときの動きが↓に書いてある。（link_toは結局url_forを呼ぶので）
https://github.com/rails/rails/blob/f33d52c95217212cbacc8d5e44b5a8e3cdc6f5b3/actionview/lib/action_view/routing_url_for.rb#L79
初めてvimにプラグインを入れてみた

駆け出しエンジニア兼プロゲーマーのガリレオです。
ゴリラ先生を習いvimを使い始めて7ヶ月が経ちましたが、自分でvimのプラグインを入れたことが無かったので入れてみました。

内容としてほぼ（というか全部？）ゴリラ先生の記事と一緒になってしまいましたが・・・

プラグインを入れるのは思ったより簡単だったのでどんどんカスタマイズしていきたい。

## 参考記事
* [ゴリラ先生のvimプラグイン導入記事](https://knowledge.sakura.ad.jp/23248/)
* [今回導入するプラグイン](https://doruby.jp/users/dera_memo/entries/_scala___vim__vim_SnakeCase_camel_case_)

## 導入方法

 `vim ~/.vimrc`

```
" dein.vim settings {{{
" install dir {{{
let s:dein_dir = expand('~/.cache/dein')
let s:dein_repo_dir = s:dein_dir . '/repos/github.com/Shougo/dein.vim'
" }}}

" dein installation check {{{
if &runtimepath !~# '/dein.vim'
  if !isdirectory(s:dein_repo_dir)
    execute '!git clone https://github.com/Shougo/dein.vim' s:dein_repo_dir
  endif
  execute 'set runtimepath^=' . s:dein_repo_dir
endif
" }}}

" begin settings {{{
if dein#load_state(s:dein_dir)
  call dein#begin(s:dein_dir)

  " .toml file
  let s:rc_dir = expand('~/.vim')
  if !isdirectory(s:rc_dir)
    call mkdir(s:rc_dir, 'p')
  endif
  let s:toml = s:rc_dir . '/dein.toml'

  " read toml and cache
  call dein#load_toml(s:toml, {'lazy': 0})

  " end settings
  call dein#end()
  call dein#save_state()
endif
" }}}

" plugin installation check {{{
if dein#check_install()
  call dein#install()
endif
" }}}

" plugin remove check {{{
let s:removed_plugins = dein#check_clean()
if len(s:removed_plugins) > 0
  call map(s:removed_plugins, "delete(v:val, 'rf')")
  call dein#recache_runtimepath()
endif
" }}}

```

* プラグインの追加

今回はキャメルケースとスネークケースを変換するプラグインを導入します。
今まで手動でやっていたけど量が多いと面倒なのでプラグイン導入を決意。

`vim ~/.vim/dein.toml`

```
[[plugins]]
repo = 'tyru/operator-camelize.vim'

[[plugins]]
repo = 'kana/vim-operator-user'
```

* プラグインの設定

`vim ~/.vimrc`

```
vmap <leader>c <plug>(operator-camelize)
vmap <leader>C <plug>(operator-decamelize)
```

* vimの再起動
`:source ~/.vimrc`

*  動作確認

1. ビジュアルモードで選択
2. スペース+Cでスネークケースに変換
3. スペース+cでキャメルケースに変換

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849291/e0b4f6ef-8c73-42c1-c1ba-44744c04aa34.gif)
UDPのチェックサムを理解する

## この記事について
[マスタリングTCP/IP](https://www.amazon.co.jp/%E3%83%9E%E3%82%B9%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0TCP-IP-%E5%85%A5%E9%96%80%E7%B7%A8-%E7%AC%AC5%E7%89%88-%E7%AB%B9%E4%B8%8B/dp/4274068765)の本で勉強していたんですが、UDPのチェックサムの部分がやや難しかったので自分なりにまとめてアウトプットします。

## UDPのヘッダフォーマット

UDPは次の4つのヘッダを持ちます

- 送信元ポート番号
- 宛先ポート番号
- パケット長
- チェックサム

**[図1]**
![udp1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/0130e700-8d23-95ca-b2dd-3abe98dbdc64.png)


チェックサム以外の説明は不要かと思うので省略します。
### チェックサム
チェックサムはUDP以外にもIT分野では一般的に利用される単語です。

[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%81%E3%82%A7%E3%83%83%E3%82%AF%E3%82%B5%E3%83%A0)には
>チェックサム（英: checksum）とは、ワード列の各ワードの総和を利用した誤り検出符号の一種である。他の誤り検出符号と比べて信頼性は低いものの、単純計算[注釈 1]で99.6%以上の検出率があるうえにアルゴリズムが簡単であることから、簡易な誤り検出に用いられる

とあります。
簡単に言うと、送信データにある規則性を持たせ、受信時にその規則性が保たれているかどうかで誤り検出を行う。といったものです。

このUDPのチェックサムの役割としても同じです。
このチェックサムの値を用いて、UDPのデータの誤りを検出します。

### UDP通信の流れ

#### 送信側
まず送信側において、UDPのデータ全体(UDPヘッダ＋UDPボディ)の前に疑似ヘッダを付けます。

**[図2]**
![udp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/72f68bda-3132-1bcd-2170-bdc6e88bb998.png)

この疑似ヘッダの中身は次のようなものです。
**[図3]**
![udp3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137041/4da19554-edd8-d3d0-22e4-74002a227b5c.png)


また、図2の全体(疑似ヘッダ＋UDPヘッダ＋UDPボディ)の全長が16ビットの倍数となるように最後に「0」を追加します。
なお、**UDPヘッダのチェックサムの値はすべて0を入れておきます。**

この状態で全体(疑似ヘッダ＋UDPヘッダ＋UDPボディ)を16ビットごとに1の補数を算出し、それらの和を求めます。
またその和の1の補数の値をUDPヘッダのチェックサムの値に挿入します。

そして疑似ヘッダを取り除いた状態で送信します。

#### 受信側

受信側においてはこれと逆の処理を行います。

まず受信したデータのIPヘッダから、送信元IPアドレス宛先IPアドレスを取得します。
このIPアドレスの情報と、受信したデータ長から、送信側で作成した疑似パケットと同じも復元可能となります。

その疑似パケットを用いて、送信側と同じようにチェックサムを計算します。
ただ、この時計算される値は、チェックサムにデータが含まれている状態で計算されるものです。
(送信時には、チェックサムの初期値を0として計算している。)

「受信したデータから計算したチェックサム」の値は、「送信時に計算したチェックサムの値」と「送信時のデータのチェックサム以外の和」との和を求めていることになります。
そして「送信時に計算したチェックサムの値」は「送信時のデータのチェックサム以外の和」の1の補数をとったものです。
そのため、1の補数の性質から、これらの和は16ビットすべてが1の値になるはずです。(=1111111111111111)

つまり、受信側で計算されたチェックサムのビットがすべて1であれば、誤りなく通信が行われたと判断可能となります。

## まとめ
送信側、受信側でチェックサムがどういう値なのか、どういった意味を持つか着目すると理解しやすいですね。


理解がまちがっていたらご指摘お願いします。
【StereoDepth】PytorchでSADの実験

<h1>背景</h1>
画像の類似性を計算する代表的な方法にSAD(Sum of Absolute Difference)という手法がある。
とりあえずどんな感じなのか視覚的に理解したいと思う。

<h2>比較対象</h2>
左の画像
![left.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/e01e49ad-52e4-99f1-cb26-ecd43dc8212e.png)

右のイメージを左のDisparityを使ってwarpさせた画像
![estLeft.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/0d244ddb-21f5-d5dd-b6db-b6e0f1dd45c3.png)

<h2>SAD</h2>
Red
![SAD_R.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/50a227a2-8090-b184-4d53-dcd82c920522.png)

Green
![SAD_G.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/df8a2020-ab03-6a35-fb16-e5a0dbf51fe6.png)
Blue
![SAD_B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/10bd28c9-807a-d687-02ef-f6445004b5c6.png)


赤いフェンスのerrorがちゃんと検知されてる
車の周りも推定がうまく行ってないのをlossがきちんと出ている。
<h2>ソースコード</h2>

```
        SAD_left = torch.mean(torch.abs(left - estLeft))
        SAD_right = torch.mean(torch.abs(right - estRight))
```

<h2>結論</h2>
シンプルに優秀！
【GAS】集計した値を最終行の次に追加する

```javascript
function myFunction() {
 function getUsedRowCount(sheet, rowName) {
   var values = sheet.getRange(rowName + ':' + rowName).getValues();
   return values.filter(String).length;
}
var ss_copyFrom = SpreadsheetApp.getActiveSpreadsheet();
var ss_copyTo = SpreadsheetApp.openById('スプレッドシートのID');
var sheet_copyFrom = ss_copyFrom.getSheetByName('コピーするタブ名');
var sheet_copyTo = ss_copyTo.getSheetByName('コピペするタブ名');
var copyValue = sheet_copyFrom.getRange('コピーする範囲').getValues();
var targetRow = getUsedRowCount(sheet_copyTo, 'コピペしたい列名') + 1;
sheet_copyTo.getRange('コピペされた値の先頭の列名'+targetRow+':コピペされた値の最後の列名'+targetRow).setValues(copyValue);
}
```
## 自分の場合
### コピーするタブ

| 日付 | 商品A | 商品B | 商品C | 商品D | 商品G |
|:-:|:-:|:-:|:-:|:-:|:-:|
|=today()|=countif(集計の範囲,商品A)|=countif(集計の範囲,商品B)|=countif(集計の範囲,商品C)|=countif(集計の範囲,商品D)|=countif(集計の範囲,商品G)|

### コピペのタブ

| 日付 | 商品A | 商品B | 商品C | 商品D | 商品G |
|:-:|:-:|:-:|:-:|:-:|:-:|

毎日、最終行の次の行にコピペして日別のデータを作成する。
同じ日付でも更新ではなく、重複になるので、トリガーは１日１回まで。
STM32L010F4P6のボードの作り方(STM32L010)

シリーズはSTM32L010でパッケージはSTM32L010F4で20P

部品(全て秋月で購入)
STM32L010F4P6->I-15689
SSOP20変換->P-10497
リードフレーム(SHP-001)->C-14182
基板->P-08242
[P1]ICソケット->P-10682
[P2,P3]1列ソケット2個->C-10298
[C1]コンデンサー0.1uF->P-07935
[R1,R2]カーボン抵抗10kΩ->R-16103

作り方
1.STM32L010F4P6をSSOP20変換に半田付けする。
一番難しい作業、セロハンテープは、使った方がいいらしい。
フラックスと半田線を使って一気に1回で仕上げる。
2,3個だめにしていい気分で行う。
導通チェックとショートのチェックをテスターで行う。
2.SSOP20変換にリードフレームを半田付けして、20,30回まげて
バリをとる。
3.10kの抵抗R1をリセットに取り付ける。位置は7b-8d(プルアップ)
4.アナログ電源用のジャンパーJ1を位置4f-4gに取り付ける
5.10kの抵抗R2をBOOT1に取り付ける。位置は4e-9g(プルダウン)
6.電源用パスコンC1を位置f8-9gに取り付ける。片一方は、ジャンパーJ1の上に半田する。
7.ICソケットP1を位置4eに取り付ける
8.1列ソケットP1を位置4aに取り付ける
9.1列ソケットP2を位置4lに取り付ける

![l010ボード.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/7bccb8ca-d4db-38b2-8087-43a9e5d5858e.jpeg)


![stm32_bord1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/66be1f6c-ccf4-d77d-8cea-78bfd2ab3869.jpeg)

-link_4-

![中華link_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/54941c0e-1181-3210-cae8-a3f2d075f65b.jpeg)
【ELB】ELBとは

## ELBとは
**Elastic Load Balancing** の略
受信したアプリケーションまたはネットワークトラフィックを、EC2インスタンス・コンテナ・IPアドレス・複数AZなど、複数のターゲットに分散させる機能

- マネージド型サービス
- 従量課金制
- アプリケーションの可用性と耐障害性の向上の為に使用
- VPC上に構成する
- 必ず2つ以上のAZを指定する

## ELBの特徴
- インターネットからのみアクセス可能なELB（**Internet-Facing ELB**）とVPC内やオンプレミス環境からのみアクセス可能なELB（**Internal ELB**）を選択可能

- ELB自体もプライベートIPアドレスを利用
→ ELBを配置するサブネットは最低でも /27ビットのCIDRブロックを持つ必要がある

- ELB作成時に自動的に生成されるエンドポイントと呼ばれるURLに独自ドメイン名を指定可能
→ 自社のDNSサーバーにCNAMEレコードを追加する、またはRoute 53にALIASにレコードを追加する

- アクセスログをS3に出力可能

## ELBの仕組み
- クライアントからの受信トラフィックを受け入れ、リクエストを1つ以上のAZにある登録済みのターゲット（EC2インスタンスなど）にルーティングする

- ヘルスチェックによって異常なターゲットを検出すると、そのターゲットへのトラフィックのルーティングを中止する

- その後ターゲットが再び正常になったことを検出すると、そのターゲットへのトラフィックのルーティングを再開する

## スケーラビリティ
負荷の増減に応じてELB自体が自動でスケールする機能
→ スケーリングが間に合わない場合はクライアントに対してHTTP503を返す

### Pre-Warming （暖機運転）
トラフィックの急増が予測される場合に事前にELBをスケールさせておくことで、通信トラフィックの急増に伴うエラーを回避すること

- AWSコンソールからの設定ではなく、AWSサポートに事前申請が必要
- AWSサポートプランのビジネスまたはエンタープライズに加入している必要がある

## ヘルスチェック
ターゲットのインスタンスに対してTCP/HTTP/HTTPSのプロトコルで応答確認を行い、正常に動作しているかどうかをチェックする機能

- 異常状態（Unhealty）に遷移した場合、そのターゲットのインスタンスを負荷分散対象から切り離し、リクエストの転送を停止する
→ **転送を停止するだけで、インスタンスの再起動はしない**

- 異常を検知するとCloudWatchに通知される

## SSL Termination
クライアントとELBの間をSSL通信（443ポート）、ロードバランサーとターゲットのインスタンス間をHTTP通信（80ポート）として、SSL通信処理の負荷を軽減する

- 外部公開するWebサーバーなどを構成して通信する場合、セキュリティ確保の為に外部との通信をSSLで暗号化することが一般的

- スケールアウトによってターゲットのインスタンス数が多くなった場合、インスタンス側でSSL/TLS証明書を構成すると証明書管理が煩雑になるが、SSL Terminationを利用することで証明書管理の手間を軽減可能

- ロードバランサーにSSL/TLSサーバー証明書を少なくとも1つ以上構成する必要がある

## スティッキーセッション
ELBによってクライアントからのリクエストを毎回同一のインスタンスに送信する機能

- セッションを引き継いで、アプリケーションがCookieに設定した値を利用しながら動作するようなケースに使用

**1. 任意の有効期限を指定する方法**
任意に設定された有効期限までの間、同一インスタンスとのセッションを維持する（有効期限を指定しない場合、Cookieをクライアント側で意図的に削除しない限り永続的にセッションを維持する）

**2. アプリケーションのCookieに従う方法**
セッションの維持を行うCookie名を指定することにより、そのCookie名を含むリクエストがクライアントからあった場合、同一インスタンスとのセッションを維持する

## Connection Draining
ヘルスチェックに失敗したEC2インスタンス切り離しのタイミングで、新規のリクエストの振り分けを停止しつつ、処理中のリクエストがあればその処理が完了するまで切り離しを待機する機能（デフォルトで有効化されている）

## 連携可能なサービス
- **Amazon EC2**：EC2 インスタンスへのトラフィックをルーティングするようにロードバランサーを設定可能

- **Amazon EC2 Auto Scaling**：ELBでAuto Scalingを有効にすると、Auto Scalingによって起動・終了されたインスタンスは自動的にロードバランサーに登録・登録解除される

- **AWS Certificate Manager**：HTTPSリスナーを作成するには、ACMで提供された証明書を指定可能

- **Amazon CloudWatch**：ロードバランサーを監視し、必要に応じてアクションを実行することが可能

- **Amazon ECS**：EC2インスタンスのクラスターで実行されるDockerコンテナにトラフィックをルーティングするようにロードバランサーを設定可能

- **AWS Global Accelerator**：Acceleratorを使用することで、1つ以上のAWSリージョンの複数のロードバランサーにトラフィックを分散することが可能

- **Route 53**：ロードバランサーなどのリソースには、AWSによりURLが割り当てられ（任意のURLを使用することも出来る）、ドメイン名をロードバランサーにマッピングすることが可能

- **AWS WAF**：ALBでAWS WAFを使用することで、ウェブアクセスコントロールリスト（ウェブACL）のルールに基づいてリクエストを許可またはブロックすることが可能
OpenCV「画像の横幅、縦幅の調べかた」

##Mark3　画像の横幅、縦幅の調べかた
```
#include <opencv2/opencv.hpp>
#include<iostream>

#if _DEBUG
#pragma comment(lib,"opencv_world430d.lib")
#else
#pragma comment(lib,"opencv_world430.lib")
#endif

using namespace cv;	
using namespace std;

int main(void) {


	Mat img = imread("C:\\opencv\\sources\\samples\\data\\lena.jpg");

		cout<<
		"横幅=" << img.cols																
		<< "," <<
		"縦幅=" << img.rows
		<< endl;

	imshow("View", img);

	waitKey();

	return 0;


}

```
このよう出てくればOKです。
![rena.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/843242/78c13f02-9995-8155-ad5b-9a73b1b6f891.png)


######解説①
c++をしてる人ならわかると思うが、cout<<" "<<endl;はc言語でいうprintfに当たるものです。endlは改行です。文字は"　"中に入れましょう。
######解説②
ここでの肝はimgについている、「.cols 」と「.rows」です。画像は小さな窓のような□の集まりでできています。これをピクセルと呼びます。聞いたことぐらいはあると思いますが、これらはすべて行列で表せます。「.cols 」はMatクラスの変数を参照することで画像の幅(行列の列数)を取得できます。「.rows」はMatクラスの変数を参照することで画像の高さ(行列の行数)を取得できます。
##最後に
本日の内容は短いですがここで終わりです。最近とんかつがおいしすぎてそればかり食べています。とんかつ最高！！
音楽チャートをスクレイピングした（ほぼ日記）

ただコードをおいておくためだけに。

```{python}
import pandas as pd
import time
from selenium import webdriver
from datetime import date
from datetime import timedelta

driver = webdriver.Chrome("****/chromedriver")
driver.implicitly_wait(30)

url = "http://www.billboard-japan.com/charts/detail?a=sales&"
data = pd.DataFrame(columns = ["year", "title", "artist", "num"])
for i in range(60):
  d = date(2020, 10, 5) - timedelta(days = 28*i)
  day = d.strftime("year=%Y&month=%m&day=") + str(int(d.strftime("%d")))
  driver.get(url + day)
  title = driver.find_elements_by_class_name("musuc_title")
  artist = driver.find_elements_by_class_name("artist_name")
  num = driver.find_elements_by_class_name("num")
  if num == []:
      break
  for j in range(50):
    r = len(data.index)
    data.at[r, "year"] = d.strftime("%Y/%m/%d")
    data.at[r, "title"] = title[j].text
    data.at[r, "artist"] = artist[j].text
    data.at[r, "num"] = num[j].text
  print(">>> " + d.strftime("%Y/%m/%d") + " 読み込み完了")
  time.sleep(1)
driver.quit()

data.to_csv("****/data.csv")
```
TCP/IPについて小学生でもわかるように説明してみた

## 通信プロトコル
TCP/IPを語る上で必要なので軽く紹介
ネットワークに接続された機器同士が通信をする時、予め決められた共通のルールや手順のこと
![スクリーンショット 2020-11-03 17.03.03（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/eead524b-d4ee-2d18-38ce-6149662e3a70.png)

## TCP/IP
インターネットにおける様々なサービスを実現するための通信プロトコル(ルール)が集まったもの。
インターネットに接続可能なPC、スマホ、タブレットなどは全てTCP/IP対応してる。
TCP/IPにおける階層モデルは下記の4階層で構成。
それぞれざっくり説明すると下記のような感じ。

|アプリケーション層|
|:--|:---:|--:|
|例)ホームページのファイルを受け渡しするときの決まりは事前に決めましょう

|トランスポート層|
|:--|:---:|--:|
|例)データを受け取った時、失敗した時の決まりを事前に決めましょう

|インターネット層|
|:--|:---:|--:|
|例)通信失敗した時はちゃんと知らせましょう

|ネットワークインターフェース層|
|:--|:---:|--:|
|例)情報がルーターに届いたらどこのPCに送信するか事前に決めましょう



## アプリケーション層
利用者が操作するアプリケーションが提供する機能についての仕様や通信手順、データ形式などのルール。
例えば Webサイトの閲覧や電子メールの送受信、ファイルの送受信などができるのは、
アプリケーション層がPCと利用者の間で通信プロトコル(ルール)を提供しているからです。
アプリケーション層で使用される主なプロトコル(ルール)の一例を紹介します。

**(アプリケーション層の一例)**

- Webサイトを見る時のルールであるHTTP
- 暗号や認証の技術を利用して安全にデータを送るのルールSSH
![スクリーンショット 2020-11-03 17.04.37（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/43a83fb6-00b0-149b-5f3a-68d6d0455c8b.png)



## トランスポート層
通信の信頼性（データが正しく渡るための方法）について定めているのがトランスポート層です。
今回はトランスポート層の1つであるTCPを紹介します。
これはデータを受け取った相手が、正常にデータが届いたことを送信元に返信するシステムです。
送信側は、受信側からの「受け取った」という返信を確認することで、確実にデータが送られたことを確認することが出来ます。そして、仮にデータの送信に失敗した場合は、一定時間後に再送する仕組みがあります。
このようにTCPは、まるで会話をしているような信頼性の高い通信プロトコルです。
![スクリーンショット 2020-11-03 17.05.59（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/03482eea-c909-e86d-c86c-29f1e013a7b4.png)
![スクリーンショット 2020-11-03 17.13.40（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/c6ad3fe1-ca75-0c75-98b5-072f5e402ff9.png)



## インターネット層
今回はインターネット層の１つであるICMPを紹介します。
ICMP通信エラー発生時には、その場所からデータの送信元に対してICMPによってエラー情報が通知されます。
その結果、データの送信元は発生した障害内容を知ることができるわけです。
![スクリーンショット 2020-11-03 17.07.20（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/1dc21f4b-1d2c-f267-14ce-19bde7c1e7d5.png)


## ネットワークインターフェイス層
この「隣り合う機器同士のやり取り」に関するルールがネットワークインターフェイス層です。
ざっくりに言えば隣の機器は、どんな線を使って、どのような手段でデータを送受信するかが定められています。
メジャーなのだとwifiがそれにあたります。
![スクリーンショット 2020-11-03 17.07.53（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840696/deab4ce3-6115-edea-1574-90a62b8142b5.png)
pythonによる機械学習(1)　全体的分類

備忘録として学習した内容を記していきます。


#(1)AIと機械学習、ディープラーニングの関係性について


AIとはArtificial Intelligence(人工知能)の略であり、人間のような情報を処理を行えるようにしたもの(簡単にいうならロボット)


知覚情報や与えられた情報を数値化し、それを処理するものが機械学習。つまりAIをAIたらしめるものにするのが機械学習。


機械学習の中にディープラーニングなどの手法がある。

したがって大まかに言えばAI(人工知能)<機械学習<ディープラーニング。








#(2)機械学習の種類について
機械学習には様々な手法があり行いたいものによって使い分けが必要です。
主に3つに分けることができます。


###教師あり学習
教師あり学習とは学習するデータが既に存在しており、そのデータを解析した結果を用いて未知の値を評価するものです。
例えば、季節によるアイスクリームの売り上げ予想(来月はどのくらい売れるか、など)
一番身近なものかと思います。

教師あり学習はまた「回帰」「分類」が代表的です。
・回帰：先ほどのアイククリームの例のような連続する数値からの予想をするもの

・分類とはあるデータがどの分類に分けることができるかを処理するものになります。
例としては身長、体重などの具体的数値から男女を分類する、などが挙げられます。



###教師なし学習
教師なし学習とは教師がない、つまり与えられるデータの答えをなしに複数の未知データからその特徴を掴む学習をさせて分類する手法です。

例えば筆跡の認識(同じ人が書いたものを見つける)などです。

googleが2012年に猫を見つけ出すAIを開発し話題になりましたがこれはこの教師なし学習を用いたものです。

子供が生活していくうちにだんだんいろいろなことを覚えていくのと同じイメージです。

こちらは主に「クラスタリング」「次元削減」に代表されます。

・クラスタリング：先ほど述べたような正解のないデータから共通する特徴をもつグループを見つけるもの


・次元削減：高次元のものを扱う際に次元を減らすことでデータをより理解しやすいものにする(低次元にする)もの。
掴みにくいですが、必要なデータのみで分類すること、と言えます。
これを行うことで教師あり学習の精度をあげることができたり、計算速度を向上させたりすることができます。




###強化学習
データがないもしくはほとんどないものに対しての学習となります。
例としてはお掃除ロボット。部屋の大きさやものの配置などはそれぞれで最初は何もデータがない状態から学習を行い、最終的にその部屋を効率よく掃除するようにプログラムされています。

またAlpha Goが世界一の棋士を負かしたことで有名になった手法です。





#最後に
次回は実際に単回帰分析を行ってみたいと思います。
今後の展開としてはコーディング、エラー処理などのプログラミング関連だけでなく、神経科学と結びつけたものも投稿していきます。
rsync使い方メモ

## 基本
```
Local:  rsync [OPTION...] SRC... [DEST]

Access via remote shell:
  Pull: rsync [OPTION...] [USER@]HOST:SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST:DEST

Access via rsync daemon:
  Pull: rsync [OPTION...] [USER@]HOST::SRC... [DEST]
        rsync [OPTION...] rsync://[USER@]HOST[:PORT]/SRC... [DEST]
  Push: rsync [OPTION...] SRC... [USER@]HOST::DEST
        rsync [OPTION...] SRC... rsync://[USER@]HOST[:PORT]/DEST
```

`host:path` でリモートシェルを使い、`rsync:://` や `host::path` を使うとrsync daemonを使うことになる模様。

## 使用例

### ローカルからリモートに同期
```
rsync -a --delete /local/path example.com:/remote/path
```

* `-a`, `--archive`: archive mode; equals -rlptgoD (no -H,-A,-X)
  * `-r`, `--recursive`: recurse into directories
  * `-l`, `--links`: copy symlinks as symlinks
  * `-p`, `--perms`: preserve permissions
  * `-t`, `--times`: preserve modification times
  * `-g`, `--group`: preserve group
  * `-o`, `--owner`: preserve owner (super-user only)
  * `-D`: same as --devices --specials
     * `--devices`: preserve device files (super-user only)
     * `--specials`: preserve special files
* `--delete`: delete extraneous files from dest dirs

### 出力を見やすくする

```
rsync -hv --progress /local/path example.com:/remote/path
```

* `-h`, `--human-readable`: output numbers in a human-readable format
* `-v`, `--verbose`: increase verbosity
* `--progress`: show progress during transfer

### dry-run

```
rsync --dry-run /local/path example.com:/remote/path
```

* `-n`, `--dry-run`: perform a trial run with no changes made

### 特定パスの無視

```
rsync --exclude=.git --delete-excluded /local/path example.com:/remote/path
```

* `--exclude=PATTERN`: exclude files matching PATTERN
* `--delete-excluded`: also delete excluded files from dest dirs
VagrantでLAMP環境を構築する(Linux+Apache+MySQL+PHP)

## 前提
・個人で開発したいなーと思う時は基本Vagrantでゴニョゴニョ環境を作っています。(マンネリ化してきたんで今度からDockerとかにしようかな・・)
・その時の備忘録です、自分用。さくっと作りたい人向け。

## Vagrant
・適当なディレクトリで

```
vagrant init centos/7
```
```
# vi Vagrantfileで以下コメントアウト
config.vm.network "private_network", ip: "192.168.33.10"
```
```
vagrant up
```
```
vagrant ssh
# sshd_configやSELinuxはやりたい人はやる
```
## Apache
```
# Apacheインストール
sudo yum install httpd
```
```
# Apache起動と確認
service httpd start
service httpd status
```
## PHP5.4
```
# PHPインストール、モジュールは必要に応じて
sudo yum install --enablerepo=remi,remi-php56 php php-mbstring php-mcrypt php-mysql php-pdo php-xml php-mysql
```
## MySQL
```
# MySQLインストール
sudo yum -y install http://dev.mysql.com/get/mysql-community-release-el6-5.noarch.rpm
sudo yum -y install mysql-community-server
```
## 入ってるか確認
```
# Apache
httpd -v
# PHP
php -v
# MySQL
mysql -v
```
## ブラウザで確認
```
http://192.168.33.10/
こんな感じで設定したIPでブラウザでも確認、Apacheの画面やPHPの画面に遷移できたらOK
```
Golang - Github ActionsでDocker ImageをBuild & Push

# 内容

Golangで作ったアプリのDockerイメージを作成し、Dockerレジストリにpushする。
Golangアプリ用のDockerfileは[こちら](https://qiita.com/Yuuki557/items/3d088de91ab86bc71600)

[Github Actionsのyaml構文のドキュメント](https://docs.github.com/ja/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions)

# 目次

- ワークフローファイル
- 内容の捕捉

## ワークフローファイル

```ci.yaml
name: CI
on:
  push:
    tags:
      - "v*.*.*"

jobs:
  test:
    runs-on: ubuntu-18.04
    strategy:
      matrix:
        go: ["1.15"]
    steps:
      - name: Check out source code
        uses: actions/checkout@v1
        
      - name: Set up Go v${{matrix.go}}
        uses: actions/setup-go@v2
        with:
          go-version: ${{matrix.go}}

      - name: Install dependent packages
        run: go mod download

      - name: Run all test
        run: go test -v ./...

  docker-build:
    needs: ["test"]
    runs-on: ubuntu-18.04
    env:
      DOCKER_IMAGE_NAME: docker-app
    steps:
      - name: Check out source code
        uses: actions/checkout@v1

      - name: Build and push docker image
        run: |
          TAG=$(echo $GITHUB_REF | grep -o "[0-9][\.].*")
          DOCKER_IMAGE=${{ secrets.DOCKER_REGISTRY }}/${DOCKER_IMAGE_NAME}:$TAG
          echo "Docker image: ${DOCKER_IMAGE}"
          docker login --username ${{ secrets.DOCKER_USERNAME }} --password ${{ secrets.DOCKER_PASSWORD }}
          docker build -t $DOCKER_IMAGE .
          docker push $DOCKER_IMAGE
```

## 内容の捕捉

### ワークフローのトリガー - on.push.tags

Github Actionsのトリガーはonの後に書くことでトリガーとして登録されます

今回は、タグ v1.0.0 のような形式のタグがpushされた時にCIパイプラインが実行されるようにしています。

push以外にもPRのオープンなどの多くの[Github Actionsのトリガー](https://docs.github.com/ja/free-pro-team@latest/actions/reference/events-that-trigger-workflows)があります。

### テスト - jobs.test

jobsという単位でジョブを作成していきます。
ここではテストのジョブを実行しています。

1. ソースコードのチェックアウト
2. Golangのバージョンを指定 (今回は1.15を指定)
3. *go modules*に従って依存パッケージをインストール (go mod download)
4. ワーキングディレクトリ内のすべてのテストを実行 (go test -v ./...)

### イメージのビルドとプッシュ - jobs.docker-build

jobsという単位でジョブを作成していきます。
ここではビルドとプッシュのジョブを実行しています。

認証情報はsecretを使っています。
secretに関しては、下のドキュメントが参考になります。
https://docs.github.com/ja/free-pro-team@latest/actions/reference/encrypted-secrets

1. イメージtagをgit refから作成している (例 v1.0.0 -> 1.0.0)
2. Dockerイメージ名を作成 (レジストリ名はsecret,イメージ名はenv,タグ名は1で作成したもの)
3. dockerにログイン (usernameとpasswordはsecret)
4. docker build (Dockerイメージ名は2で作成したもの)
5. docker push
【Ruby】selfはクラスとインスタンスのどちらを指す？

## 結論
selfはクラスとインスタンスのどちらも指すことができます。

## 背景
自分としては、インスタンスを指すイメージの方が強かったのですが、最近クラスを指すのを知ったのでまとめました。
「rubyはjavaでいうthisと同じだよ」って聞いた気がするのですが、完全に同じなのか今もわからないです。今はJavaのthisを忘れてしまったので。

## 実験

```ruby
class ClassA
  def foo       # インスタンスメソッド
    puts "ins_foo"
    puts self #このselfはインスタンス(ClassAのインスタンス)を指す
  end

  def self.foo  # クラスメソッド(このselfはクラス自身(ClassA)を指す)
    puts "self_foo"
    puts self # このselfはクラス自身(ClassA)を指す
  end
end
ClassA.foo
# self_foo
# ClassA # クラスを指している
ClassA.new.foo
# ins_foo
# #<ClassA:0x00007f93108144d0> # インスタンスを指している
```

クラスメソッドを定義するときは`self.`をつけるって読んだことあるのですが、そのselfはクラスを指していたんですね。
Go を docker で動かす時の tips

## docker image

### go mod を利用するパターンの参考
```dockerfile
# buildイメージ
FROM golang:1.13 AS builder

WORKDIR /go/src

## 依存ライブラリをダウンロードする(キャッシュを使いたいので、これを先にやる)
ENV GO111MODULE=on
COPY go.mod go.sum ./
RUN go mod download

ADD . /myapp
WORKDIR /myapp

## main.goをコンパイルし、実行バイナリを保存
RUN CGO_ENABLED=0 GOOS=linux go build -o server ../myapp/cmd/main.go

# run-timeイメージ
FROM alpine:3.10
COPY --from=builder /myapp/server /app
EXPOSE 50051
ENTRYPOINT ["/app"]
```

### dep を利用するパターンの参考
```dockerfile
# buildイメージ
FROM golang:1.13 AS builder
ADD . /go/src/github.com/myself/myapp
WORKDIR /go/src/github.com/myself/myapp

## depのインストール と依存関係の解決
RUN go get github.com/golang/dep/cmd/dep
RUN dep ensure

## main.goをコンパイルし、実行バイナリを保存
RUN CGO_ENABLED=0 GOOS=linux go build -o server /myapp/cmd/main.go

# run-timeイメージ
FROM alpine:3.10
COPY --from=builder /go/src/github.com/myself/myapp/server /app
EXPOSE 50051
ENTRYPOINT ["/app"]
```

## 詰まったポイント

### go buildで `cannot find package` エラー
- パスが間違っているか、ファイルがないかどっちかの可能性が高い

### go build で `packages founded A and B` エラー
- 同一ディレクトリの中に複数個のパッケージがある
- 以下はコンパイルエラー
    - 対象ディレクトリ配下に複数のmainパッケージのモジュールを置く
    - 異なる名前のパッケージ宣言を持つモジュールを同じディレクトリの中に置く
    - 末尾が`_test`で終わるファイルはテストコードとして解釈されるので例外的に複数個目として配置できる
- ちなみに、ディレクトリと異なる名前でパッケージ宣言するのはセーフ
    - パッケージ名ではなくパスベースで import するから

### go getで、`XX is not using a known version control system` エラー
- https://github.com/gobuffalo/buffalo/issues/694#issuecomment-337032375
- 上記を元に `/vendor` 以下の対象のファイル群を消したらなぜかうまくいった

### dep ensure で `/hoge is not within a known GOPATH/src` エラー
- よくわからんがディレクトリ構成がダメっぽい
- Goのディレクトリ構成の特徴として、すべてのソースコードを環境変数 `$GOPATH/src` 配下に置く
- 解決法は以下の二つ
    - コンテナ内の `/go/src` 以下にリポジトリを配置する
    - シンボリックリンクを貼る

### dep ensure で `root project import: dep does not currently support using GOPATH/src as the project root` エラー
- workdir を `GOPATH/src` に指定していたところを `GOPATH/src/app` にしたら直った

### docker build 時の dep ensure で  `fatal: could not read Username for 'https://github.com'~` みたいに、githubにアクセスできなくて怒られる
- private リポジトリから資源を取る時は github token などを使わないとダメ
- ただ、自分のリポジトリの資源を取る時はローカルパスでいけるはず。それが取れない場合はパスが間違っている可能性大
    - 実際、docker の workdir を`go/src/app`から`/go/src/github.com/myself/my-app`にしたらいけた

### docker run した時に `exec user process caused "no such file or directory"` と怒られる
- 最近の Go のバイナリは Dynamic link を行うらしく、これはそのリンク対象が存在しないために発生しているらしい
- ビルド時に `CGO_ENABLED=0` をつけるといける
    -  `CGO_ENABLED=0 go build`
[Python]所要時間で見るDataFrameの強さと弱点

[本記事は、自分サイトのこの記事と同一内容です。](https://hagiayato.github.io/my-site/jekyll/update/2020/11/29/Python-Speed.html)
<h1>はじめに</h1>
Pythonではpandas.DataFrameで二次元の表データを扱うことができます。
他言語の配列相当であるlist,tuple以上に表データを扱いやすいのですが、その処理速度も基本的にはlist,tuple以上に速いのです。
そんなDataFrameの強さと弱点を実際にプログラムを動かしながら見ていきましょう。
<p>実行環境・条件</p>
実行環境
・windows10 Home 64bit
条件
・使用データ：10000行のCSVデータ
・使用データの列：index,学生ID,A-E 5教科の点数(0-10000)
　※ある試験を受けた学生10000人の成績一覧をモデルとしています
<h1>DataFrameの強さ</h1>
DataFrameの強さは簡単な処理で、かつ高速でデータを処理できる点です。
<h5>平均値を求める場合</h5>
後ろに列を追加して、平均値を代入する処理を実装します。
listだと下記の処理を組むことになります。

```python
for idx, row in enumerate(list):
	row.extend('0')
	row[7] = str((float(row[2]) + float(row[3]) + float(row[4]) + float(row[5]) + float(row[6]))/5.0)
```
他の言語と書き方が似ています。
これでもいいのですが…DataFrameで実装すると以下の1行で済みます。

```python
# オリジナル
df['average'] = (df['subjectA'] + df['subjectB'] + df['subjectC'] + df['subjectD'] + df['subjectE'])/5
# 編集後
df['average'] = (df[['subjectA', 'subjectB', 'subjectC', 'subjectD', 'subjectE']].sum(axis=1))/5
```
※編集リクエスト者：[siruku6](https://qiita.com/siruku6)さん
1行分操作のイメージで書けるためコーディングミスのリスクが少ないです。
<h5>ソートする場合</h5>
上記の平均値降順でソートを行う場合、listだと下記の処理を組むことになります。

```python
list = sorted(list, key=lambda x: x[7], reverse=True)
```
ソートに関しては、listでも1行で実装できますね。
これをDataFrameで実装するとこちらも1行で済みます。

```python
df.sort_values('average', ascending=False)
```
<h5>条件で絞り込みをする場合</h5>
平均点が50点以上のデータのみを絞り込む場合、listだと下記の処理を組むことになります。

```python
list2 = []
for idx, row in enumerate(list):
	if 50 <= float(row[7]):
		list2.append(row)
```
平均算出時と同様に、forループを使います。
これをDataFrameで実装すると、…予想がつくと思いますが1行で済みます。

```python
df2 = df[50 < df['average']]
```
<h5>各処理の速度は…</h5>
これら各処理の速度を計測し、10回平均を取ると以下の通りとなります。

| 処理名 | 10回平均所要時間(list)[sec] | 10回平均所要時間(DataFrame)[sec] |
|:--|--:|--:|
| 平均計算 | 0.764768385887146 | 0.01179955005645752<br/>コード変更後 : 0.007805347442626953 |
| ソート | 0.030899477005004884 | 0.011399650573730468 |
| 絞り込み | 0.04529948234558105 | 0.006699275970458984 |
DataFrameによる実装はコードが簡潔なだけでなく、その速度が速いこともわかります。
<h1>DataFrameの弱点</h1>
DataFrameの弱点はforループです。
もし平均値をforループで作成する場合は下記のコードを使います。

```python
for idx in range(len(df)):
	df.iat[idx, 6] = str((float(df.iat[idx, 1]) + float(df.iat[idx, 2])
		+ float(df.iat[idx, 3]) + float(df.iat[idx, 4]) + float(df.iat[idx, 5])/5.0))
```
その所要時間は10回平均2.33[s]で、listの場合よりも遅いです。
従ってDataFrameを扱う際は、極力forを使わないことが望ましいです。
<h3>どうしてもDataFrameでforを使うなら</h3>
それでもDataFrameでforを使う場面はあります。
そんなときは、forを使う部分のみlistやndarrayにする、あるいは下記投稿のような方法を使うことで処理を高速化できます。
[[Python3 / pandas] DataFrameをどうしても1行ずつ処理したいときの速度改善策](https://qiita.com/siruku6/items/0633db690283a0f525ad)
<h2>サンプルデータ作成について</h2>
今回使ったサンプルデータは、下記URLのコードで作成しました。
https://github.com/HagiAyato/PythonTests/blob/main/make10000data.py
[Rails6]Scaffoldで生成した投稿機能とdeviseで生成したユーザー機能を結びつける方法

# はじめに
Railsで記事投稿アプリを作ろうと思い、手順をカットするためにScaffoldを導入したところ、投稿とユーザーを結びつけるのに躓いたので知見を共有
詳しく知りたい人は[こちらのドキュメント](https://railsguides.jp/association_basics.html)をどうぞ

# 前準備
## Scaffoldで投稿機能生成
まずはScaffoldで投稿機能を生成。めちゃくちゃ簡単。db:migrate忘れずに

```
$ rails g scaffold Post content:string
$ rails db:migrate
```

## devise
[こちらの記事](https://qiita.com/cigalecigales/items/16ce0a9a7e79b9c3974e)を参考に。めっちゃ分かりやすい


# 紐づけ
## belongs_toとhas_many


```app/models/user.rb
class User < ApplicationRecord

  # 以下を追加.複数形のsを忘れずに
  has_many :posts,  dependent: :destroy
end
```

```app/models/post.rb
class Tip < ApplicationRecord
  # 以下を追加.念のため、空の投稿は拒否されるようにする
  belongs_to :user
  validates :content, presence: true
end
```

## user_idカラムの追加
```
$ rails g migration add_user_id_to_posts user_id:integer
$ rails db:migrate
```

***これで仕組み上はUserモデルとPostモデルの紐づけが完了した***

## controllerに追加
```app/controllers/posts_controller.rb
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def post_params
      params.require(:post).permit(:content)
    end
end
```
Scaffoldによって自動生成された上のコードを以下のように変更する。

```app/controllers/posts_controller.rb
  private
    # Use callbacks to share common setup or constraints between actions.
    def set_post
      @post = Post.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def post_params
      params.require(:post).permit(:content).merge(user_id: current_user.id)
    end
end
```

これで完成。実行してlocalhost:3000/posts に移動し投稿してみよう‼‼
Sorceryのサブモジュール追加する際にdb:migrateできない問題


Sorceryで認証機能を作る際、各機能を追加するには都度サブモジュールをインストールしていくのですが、公式のチュートリアル通り進めようとして出だしでつまづいたので解決方法を記します。

##問題に当たるまで
User Activation機能を追加する場面を例に使います。
*ここではgemのインストールやUserモデルの作成、基本的な認証機能は実装済みであることを前提に進めます。

まずはサブモジュールのインストール

```
$ rails g sorcery:install user_activation  --only-submodules
```

すると以下のマイグレーションファイルが作られます。

```[timestamp]_sorcery_user_activation.rb
class SorceryUserActivation < ActiveRecord::Migration
  def change
    add_column :users, :activation_state, :string, :default => nil
    add_column :users, :activation_token, :string, :default => nil
    add_column :users, :activation_token_expires_at, :datetime, :default => nil

    add_index :users, :activation_token
  end

end
```

そしてマイグレート

```
$ rails db:migrate
```

ここでエラー発生！

```
rails aborted!
ArgumentError: To use user_activation submodule, you must define a mailer (config.user_activation_mailer = YourMailerClass).
```

エラーメッセージは「このサブモジュールを使うならメーラーを書いとけ！」 と言っていますが、従ったところで別のエラーが発生し先には進めません。

##原因

この問題は、最初にサブモジュール追加のコマンドを打った際、あとで自分で追記するべき箇所に自動的に追記されることで発生します。

```config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [:user_activation, :他のサブモジュール ...]
```

チュートリアルの通りに進めると、あとで上の`:user_activation`を追記せよとの指示がありますが、今これが記載されていると先に進めなくなるので一旦削除します。

```config/initializers/sorcery.rb
Rails.application.config.sorcery.submodules = [(:他のサブモジュール )...]
```

やっとマイグレートできるようになりました。

```
$ rails db:migrate
```

あとはチュートリアル通り進めると`:user_activation`を追記する指示があるのでそこで追記し解決です。

##参考
[Sorcery/wiki/User-Activation](https://github.com/Sorcery/sorcery/wiki/User-Activation)
[Vuetify]v-tabsの選択中タブをscriptで変更する

Vuetifyのv-tabsは、以下のように利用するタブ型UIコンポーネントです。

```vue
<template>
  <v-tabs>
    <v-tab>Item One</v-tab>
    <v-tab>Item Two</v-tab>
    <v-tab>Item Three</v-tab>
  </v-tabs>
</template>
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352532/956e2a52-e338-046c-7787-457409923534.png)
(※[公式](https://vuetifyjs.com/en/components/tabs/)より引用)

タブをクリックすると、以下のように選択されている`ITEM xxx`が変わります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352532/9184d26c-017d-e0a6-5e17-efa54a623a86.png)

この「**どのタブが選択されているか**」という状態をscriptから制御してみます。

##v-modelでバインドする
まず、scriptから操作するための前提として、v-modelでv-tabsを適当な変数でバインドします。

```vue:template
  <v-tabs v-model="tab">
    <v-tab>Item One</v-tab>
    <v-tab>Item Two</v-tab>
    <v-tab>Item Three</v-tab>
  </v-tabs>
```
```javascript:script(data)
  data() {
    return {
      tab: null,
    }
  },
```

ここで、タブを切り替えたときの変数`tab`の動きを見てみましょう。
`@change`を使って、v-tabsに変化が起きたときに`tab`の中身を出力します。

```vue
  <v-tabs v-model="tab" @change="log">
    <v-tab>Item One</v-tab>
    <v-tab>Item Two</v-tab>
    <v-tab>Item Three</v-tab>
  </v-tabs>
```
```javascript
  methods: {
    log() {
      console.log(this.tab)
    },
  },
```

この状態でタブを順に押すと……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352532/6b736ed6-896f-a545-dec4-723d5138a624.png)

つまり、「v-tabs内のどのタブが選択されているか」という状態は、0から順に数字で管理されていることがわかりました。今回の例だと、0が"Item One"、1が"Item Two"、2が"Item Three"です。

##scriptから選択中のタブを変更する
あとは簡単、先程バインドした変数'tab'を更新するだけです。
今回はcreatedフックで更新することで、初期表示時から選択中のタブを制御してみます。

```javascript
  created: function () {
    this.tab = 1
  },
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/352532/4fe87815-45e2-7ca3-a7ef-c4d3f503ad4a.png)

初期表示時から"Item Two"が選択されています。
無事、scriptからタブの選択状態を更新することができました。
Railsチュートリアル備忘録（3章 3.1）

## 環境
macOS Catalina 10.15.5
Rails 6.0.3

Railsチュートリアルとそれに付随するいろいろを書いていきます。
Githubに慣れたいので、チュートリアルは第6版に準拠しています。

## 3.1 セットアップ
リスト 3.2に沿ってGemfileを変更。
前回の反省を生かして`gem 'puma'`を`'4.3.4'`から`'4.3.6'`にしました。

```php:Gemfile
source 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

gem 'rails',      '6.0.3'
gem 'puma',       '4.3.6'
gem 'sass-rails', '5.1.0'
gem 'webpacker',  '4.0.7'
gem 'turbolinks', '5.2.0'
gem 'jbuilder',   '2.9.1'
gem 'bootsnap',   '1.4.5', require: false

group :development, :test do
  gem 'sqlite3', '1.4.1'
  gem 'byebug',  '11.0.1', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  gem 'web-console',           '4.0.1'
  gem 'listen',                '3.1.5'
  gem 'spring',                '2.1.0'
  gem 'spring-watcher-listen', '2.0.1'
end

group :test do
  gem 'capybara',                 '3.28.0'
  gem 'selenium-webdriver',       '3.142.4'
  gem 'webdrivers',               '4.1.2'
  gem 'rails-controller-testing', '1.0.4'
  gem 'minitest',                 '5.11.3'
  gem 'minitest-reporters',       '1.3.8'
  gem 'guard',                    '2.16.2'
  gem 'guard-minitest',           '2.4.6'
end

group :production do
  gem 'pg', '1.1.4'
end
```
`$ bundle update`しましたが下記のエラーが出ました。

```
An error occurred while installing pg (1.1.4), and Bundler cannot
continue.
```

エラーに下記の内容があったため、`pg_config`がないのが問題ではないか？と考えました。
（こちらを参考にしました。→ https://elastictechdays.info/rails-postgresql-bundle-install-error/ ）

```
current directory:
/Users/user/.rbenv/versions/2.7.0/lib/ruby/gems/2.7.0/gems/pg-1.1.4/ext
/Users/user/.rbenv/versions/2.7.0/bin/ruby -I
/Users/user/.rbenv/versions/2.7.0/lib/ruby/2.7.0 -r
./siteconf20201103-5783-kv6db3.rb extconf.rb
checking for pg_config... no
No pg_config... trying anyway. If building fails, please try again with
 --with-pg-config=/path/to/pg_config
```
`pg_config`はどこにあるのか？といろいろ調べましたが、
`$ brew install postgresql`で`postgresql`を作るのが最適なようです。
（こちらを参考にしました。→ https://qiita.com/youcune/items/5b783f7fde45d0fd4b35 ）

さっそく`$ brew install postgresql`を実行して再度`$ bundle update`しましたが、やはり同様のエラーが出ました。
先ほどの参考サイトを確認したところ、`postgresql`をビルドする時に参照するパスを変更していたので、
`$ brew install postgresql`の内容を確認したところ
下記のように、`/usr/local/Cellar/postgresql/13.0`がインストールされていました。

```
==> Installing postgresql
==> Pouring postgresql-13.0.catalina.bottle.tar.gz
==> /usr/local/Cellar/postgresql/13.0/bin/initdb --locale=C -E UTF-8 /usr/local/
```
そのため以下のように`$ bundle config build.pg`を実行し、パスを変更しました。

```
$ bundle config build.pg --with-pg-config=/usr/local/Cellar/postgresql/13.0/bin/pg_config
You are replacing the current global value of build.pg, which is currently "--with-pg-config=/usr/pgsql-9.3/bin/pg_config"
```

無事`$ bundle install`が通りました。