OmniAICreator/Qiita-1.07M huggingface dataset:
Introducing SwiftUI: Building Your First App ・Roomsのパート2の続き

# WWCD2019のセッション204を再現しての話　その2 続き?

# SwiftUI Canvasでは作動するがSimulatorや実機ではCamvas同様に作動しない ?

> 編集2019/11/2 : 解決しました、「Introducing SwiftUI: Building Your First App ・Rooms 解決編」をみてください

[Introducing SwiftUI: Building Your First App ・Rooms 解決編](https://qiita.com/papassan/items/d530f87f7db28f9ae992)

[その他のコードは Introducing SwiftUI: Building Your First App ・Rooms](https://qiita.com/papassan/items/6fd131ebc39ad2585ae8)

> やっと実機やSimulatorで作動するようになったのに ? でも、ある機能が作動しません ? なんで ?

それは ?

- ContentView1.swiftのForEach(store.rooms) { room inの部分を変更するとSimlatorや実機でもCanvasと同じ挙動になりますが
- Addや削除や移動や編集ができなくなります ?
- 対象のファイルは動画で案内しているContentView.swiftです

# コードを見た方が早い ?

# ContentView.swift

```ContentView.swift

//変更箭
 ForEach(store.rooms) { room in
                        RoomCell(room: room)
                    }
//変更後
ForEach(testData) { room in
                        RoomCell(room: room)
                    }

```

ここまで

# 私の感想

> 私の感想ですが ?
やっぱり、SwiftUIは一から学ぶ言語のようですね ?
早く頭の良い人の詳しい情報がネットに出ることを願います ? 研究は続きますが ? Appleの当時の動画の環境では実機やsimulatorで作動していたのでしょう ? しかし ? 証拠はありません ? 私はベータは使いませんのでわかりません、多分 ? バグと思います、Canvasで表示したのに実機で表示しないのはパグです、それは私の意見ですがね ? しかし努力して解決してみます、多分、セルの変更を更新する部分に原因があると思うし ? その部分を無視して直接配列を指定するとセルが表示するけど更新する部分は無視するから削除とか移動とか追加ができないのでしょうね ? 結局、私が無知なだけです、毎日が勉強です
[ゼロから作るDeep Learning]ニューラルネットワークの高速化　逆伝播処理について解説してみた

#はじめに
この記事は**ゼロから作るディープラーニング 6章誤差逆伝播法**を自分なりに理解して分かりやすくアウトプットしたものです。
文系の自分でも理解することが出来たので、気持ちを楽にして読んでいただけたら幸いです。
また、本書を学習する際に参考にしていただけたらもっと嬉しいです。

#逆伝播処理とは
前回も少し話しましたが、逆伝播処理とは計算グラフを右から左に解いていく処理のことで、各変数の微分を求めることができます。

前章で実装したニューラルネットワークの勾配式は数値微分という変数に微小な値を加えて微分を求める方法を使っていました。
数値微分は単純でわかりやすいのですが、処理時間が長いという欠点があります。
そこで使うのが**逆伝播処理**です。
ニューラルネットワークの処理に逆伝播処理を実装してあげることで勾配を今までよりも高速に効率よく求めることができます。

それでは手始めに、簡単な計算グラフの順伝播処理と逆伝播処理をpythonで実装したいと思います。
<img width="678" alt="スクリーンショット 2019-10-31 20.35.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510602/065d7768-99aa-4523-2850-a398e7d1531b.png">


```python
a = 100
as = 3
o = 50
os = 4
t = 1.1

# 順伝播処理
az = a * as #　リンゴの合計金額
oz = o * os #　みかんの合計金額
z = az + oz #　リンゴみかんの合計金額
y = z * t #　合計金額

# 逆伝播処理
dy = 1 # 順伝播処理の答えyの微分

# z * tは掛け算なので各変数の値をそれぞれ入れ替えて前の微分をかける
dz = t * dy = 1.1 #　zの微分
dt = z * dy = 500 #　tの微分

# az + oz は足し算なので前の微分をそのまま継承する
daz = dz = 1.1 # azの微分
doz = dz = 1.1 # ozの微分

# o * osは掛け算なので各変数の値をそれぞれ入れ替えて前の微分をかける
do = os * doz = 4.4 # oの微分
dos = o * doz = 55 # osの微分

# a * asは掛け算なので各変数の値をそれぞれ入れ替えて前の微分をかける
da = as * daz = 3.3 # aの微分
das = a * adz = 330 # asの微分
```

上のように掛け算と足し算の逆伝播処理は簡単にできるので、これを用いてニューラルネットワークに逆伝播処理を実装する。
firestoreのルールは存在しないレコードに対するクエリにも効く

たとえば、対象となるレコードに`claim`というフィールドがある場合、
そのCustomClaimがないとreadできないというようなルールを書くとする。

```
allow read :if request.auth.uid != null && ((!resource.data.keys().hasAll(['claim']) || request.auth.token[resource.data.claim] == true))
```
ここで上記のように書くと、大体のケースではうまくいくのだが、
存在しないレコードに対してクエリを投げると、権限不足でエラーになってしまう。
感覚的にはclaimというカラムがないのだから権限無しでもOKにして欲しいものだが、ruleの仕様上NGである。

# 対応策

```
    match /hoge/{hogeId} {
      allow read :if request.auth.uid != null && !exists(/databases/$(database)/documents/hoge/$(hogeId))
    }
```
上記のように、「存在しなければread許可」の条件を足してやればOK。
Rapberry pi 個人的環境構築まとめ

ラズパイを触ることになったので、初期設定、環境構築方法をまとめておきたいと思う。

2021/09/12追記
月日が経って見直したら、コマンドが変わっていたりするものもあったので再編集した。

#まずは以下の記事を参考にSSH接続ができるまでの初期設定
##いきなりWifi接続

```$ cd /Volumes/boot```

wpa_supplicant.confを作る


```wpa_supplicant.conf

country=JP
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
    ssid="abc"
    psk="paaaaassssss"
}

```

起動時にsshを有効にする

```$ touch ssh
```

まぁこれだけ

[Raspberry Pi Zero W 環境構築ことはじめ MacOS編](https://qiita.com/hiesiea/items/67ead05a4c3aa5d47ce7)
[RaspberrypiでSSHができなくて試したこと](https://qiita.com/hayate242/items/0de7a98f6fea0dabf04c)

#そしてアプデ
sudo apt update
sudo apt full-upgrade -y
sudo apt autoremove -y
sudo apt clean
sudo reboot

#ラズパイをアクセスポイント化。
[RaspberryPiでルーターを自作し無線AP化](https://qiita.com/wannabe/items/a66c4549e4a11491f9d5)
ここで、apt-get updateとupgradeをサボったら詰まった。

#ラズパイをファイルサーバー化、Apacheを導入してPHPによるアクセスを可能にする。

ここでSMBをインストール時にDHCPについて何か聞かれる。
ここはいいえを選択しないと今後接続できなくなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/524479/c8d94145-3ec8-e5be-3726-6a339be57cae.png)


[raspberry piをファイルサーバー化](https://qiita.com/ryuichi1208/items/4420d40cac451a93228e)
[Raspberry PiにPHPをインストールする](https://raspi.taneyats.com/entry/install-php)
[Raspberry Pi 3 に Apache 2.4 + PHP 7.0 をインストール](https://blog.smallserver.jp/raspberry-pi-3-%E3%81%AB-apache-2-4-php-7-0-%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB/)
[RaspbianにおけるApache2の設定](https://qiita.com/takey/items/75e6984468f0f6870a97)
[Raspberry PiにApacheをインストール～ドキュメントルートの変更まで](http://tomokiit.hatenablog.jp/entry/raspberrypi-apache)


###この時、apache2をインストールしても、PHPをインストールしていなかったせいで、詰まった。PHPが実行されずにソースコードだけが表示されていた。

###※phpによるファイル操作を許可するためのパーミッションの設定を忘れてはいけない。

[パーミッションなどを設定する！chmodコマンドの詳細まとめ【Linuxコマンド集】](https://eng-entrance.com/linux-command-chmod)

ここまでで、ラズパイにwifi接続し、ラズパイ内のファイルをiOSのファイルアプリなどから、アクセス可能になり、PHPによるファイル実行を可能になった。

#時刻合わせをNTPからchronyに変更する。
一つのラズパイをサーバにして、複数台のラズパイを接続する形を想定しているため、ローカルでの時刻の同期をする必要が出てきたためである。

まずは[raspbianでchrony](https://www.isoroot.jp/blog/2844/)でchronyを導入する

[2017/10/19(ROSにおけるchronyを使ったオフライン時刻同期)](http://mozyanari.hatenablog.com/entry/2017/10/20/005418)に書いてあるように、サーバー側とクライアント側に数行のコマンドを打つだけで、時刻同期が可能になった。

###ここで注意なのは、これらは設定した後に
```sudo /etc/init.d/chrony restart
```
上記のコマンドをターミナルに入力しなければ、適応されない。
サーバー側もクライアント側も必要。

#やっとラズパイ上でプログラムを実行する段階になる。

[Raspberry Pi に Python 3.7.0 をインストールする](https://qiita.com/GuitarBuilderClass/items/d6d2798bebf7b916c5c6)
[Raspberry PiでPythonのRPi.GPIOを使ってLチカする](https://qiita.com/masato/items/715e28e0c0c945a54297)
[Raspberry Pi で systemd を使ってプログラムを自動実行する](https://qiita.com/molchiro/items/ee32a11b81fa1dc2fd8d)

あとは個人的にPANDASを入れておきたいので下記の記事を参考にした。
すなおにライブラリをダウンロードできないので、参考にしたほうが良い。
https://qiita.com/Avocado/items/ba800e5afffc2bd98dc6

これで、ラズパイ起動時にpyファイルが実行されGPIOに接続したセンサー類の値を取得することができる。

#最後に忘れてはいけないバックアップとリストア方法

[RaspberryPiのバックアップ＆リストア方法 for Mac](https://simple-was-best.com/blog-entry-raspberrypi-backup-restore-for-mac.html)
[Raspberry PiのmicroSDバックアップとリストア for Mac](http://jeana.hatenablog.jp/entry/2018/03/20/004703)

以上で、個人的な環境構築をすることができた。
PythonでPDFからPNGに変換する + α

# 概要

- `PDF => PNG(画像)`に変換するAPIを作りたかったのでPython3でやってみました
- `pdf2image`を使えばサクッとできます
- ソースは[こちら](https://github.com/nakamura-yohei-fixer/pdf-to-image)にあるので試したい方はどうぞ

# Packages

パッケージ以外にOS側に`poppler`が入ってないと動かないと思うので[こちら](https://texwiki.texjp.org/?Poppler#tafa7455)からインストールしておいてください

```txt:requirements.txt
pdf2image
Pillow
wheel
```

以下のコマンドで一気にインストールできます

```shell
pip install -r requirements.txt
```

# 実装

`PDF => PNG`と 必要になったので`PDF => PNG => Base64`もやってみました

## PDF => PNG

```python
import base64
from pdf2image import convert_from_path, convert_from_bytes


images = convert_from_path('sample.pdf')

for index, image in enumerate(images):
    name = str(index) + '.png'
    image.save(name, 'png')
```

## PDF => PNG => Base64

```python
import base64
from io import BytesIO
from pdf2image import convert_from_path, convert_from_bytes


images = convert_from_path('sample.pdf')


def base64pdf_to_base64png(image):
    buffer = BytesIO()
    image.save(buffer, format="PNG")
    return base64.b64encode(buffer.getvalue()).decode().replace("'", "")


base64Pngs = list(map(base64pdf_to_base64png, images))
print(base64Pngs)
```
【資格試験対策】ディープラーニングG検定【キーワード・ポイントまとめ】

※ [継続的に更新のため移設しました](https://sik-bug.hatenablog.com/entry/2020/05/30/103038)。

#はじめに
+ ディープラーニングG検定に向けた情報整理を行う。  
[JDLA Deep Learning for GENERAL 2019 #3](https://www.jdla.org/business/certificate)
+ 構成はシラバスに従い、該当項目には「📘」を付す。  
[JDLA Deep Learning for GENERAL 2019 #3 シラバス](https://www.jdla.org/business/certificate/#G)
+ 参考図書  
[ディープラーニング G検定(ジェネラリスト) 公式テキスト](https://www.amazon.co.jp/dp/4798157554)
+ 【参考】模擬テスト  
[Study-AI G検定 模擬テスト](http://study-ai.com/generalist/)
+ 注意事項！  
自分自身の知識の確認と整理を目的に作成しています。  
テスト前のキーワード確認などでご活用ください。  
この記事だけで十分な知識をつけることはできませんので、必ず公式テキスト等を活用して自ら学習を行うようにしてください。

#１．📘人工知能（AI）とは（人工知能の定義）

##AIの定義
+ 専門家の間で共有されている定義はない。
+ 人工知能であるかどうかは「人によって違う」という状況。
+ 定義の例
    + 「推論、認識、判断など、人間と同じ知的な処理能力を持つ機械（情報処理システム）」
    + 🎩**松尾豊**「人工的につくられた人間のような知能、ないしはそれをつくる技術」
    + 🎩**アーサー・サミュエル**「明示的にプログラムしなくても学習する能力をコンピュータに与える研究分野」
    + 「周囲の状況（入力）によって行動（出力）を変えるエージェント（プログラム）」という定義もある。

##人工知能レベル
| レベル   | 説明 | 
|---------:|:------------------|
| レベル１  | シンプルな制御プログラム。<br>**ルールベース**。|
| レベル２  | 古典的な人工知能。<br>**探索・推論**を行う。知識データを利用する。 | 
| レベル３  | **機械学習**を取り入れた人工知能。<br>多くのデータから入力・出力関係を学習する。 | 
| レベル４  | **ディープラーニング**を取り入れた人工知能。<br>特徴量による学習を行う。 | 

##AI効果
人工知能の原理がわかると「単純な自動化である」とみなしてしまう人間の心理のこと。

##ロボットとの違い
+ 人工知能では「考える」という、目に見えないものを中心に扱っている。
+ 人工知能ではロボットの「脳の部分」を扱っている。（脳だけ、というわけではない）
+ ロボットの研究者は人工知能の研究者というわけではない。

##歴史
###✅ 💻ENIAC
+ **1946年**、アメリカ ペンシルバニア大学
+ 世界初の汎用電子式コンピュータ

![ENIAC](https://upload.wikimedia.org/wikipedia/commons/6/6c/ENIAC_Penn1.jpg)

###✅ ダートマス会議
+ **1956年**、アメリカで開催
+ 🎩**ジョン・マッカーシー**が初めて「人工知能（AI）」という言葉を使った
+ 世界初の人工知能プログラムといわれる💻**[ロジック・セオリスト](https://ja.wikipedia.org/wiki/Logic_Theorist)**のデモを実施

![](https://miro.medium.com/max/1000/0*8MW8iP2QC_WNhmiW)

※ [以降はこちら](https://sik-bug.hatenablog.com/entry/2020/05/30/103038)。
Aurora MySQL の failover への追従

# 注意

AWS の人に Aurora について色々質問する機会があり、コネクションプールを実装するために failover への追従について話を聞けました。

まだ自分で実装して検証したわけではないので間違っている部分があるかもしれません。


# 背景

通常、Aurora MySQL の Cluster endpoint に接続すると、書き込み可能なサーバーに接続することができます。

しかし、 failover が発生するとこのサーバーが replica に降格することがあります。長時間接続を維持するコネクションプールを使っている場合、ちゃんと書き込み可能なサーバーにつなぎ直さなければなりません。

# innodb_read_only

接続先が Read replica だった場合、 `innodb_read_only` という変数が On になっています。 クエリを投げる前、あるいはトランザクションを開始する前に `select @innodb_read_only` というクエリで 1 が返ってきたら再接続するというのが素朴な実装です。

更新クエリを投げたときに "The MySQL server is running with the --read-only option ..." というエラーになるので、それが発生したら再接続するという手もあります。

しかし、autocommit なら簡単に（アプリに手を加えなくてもコネクションプール側で）クエリの再実行ができますが、トランザクションを使ってる場合はリトライが面倒なので、その場合は `select @innodb_read_only` の方がいいでしょう。


# mysql.ro_replica_status

failover が発生して再接続する時、 cluster endpoint に再接続すると、DNSの反映が遅くてまた古い writer に接続してしまうことがあります。

もっと早く failover に追従するために、古い接続を切る前に `SELECT SERVER_ID FROM mysql.ro_replica_status WHERE SESSION_ID = 'MASTER_SESSION_ID'` することができます。

このテーブルはDNSよりも failover への追従が早いので、 Aurora Cluster の member のリストを持っておけば、この SERVER_ID から member を選択して接続することができるはずです。 (ro_replica_status からIPアドレスかホスト名が取れればいいのに...)

この方法を使った高速な failover 対応がすでに MariaDB Connector/J の ODBC ドライバで実装されているようなので、自分で実装するときに参考にすることができるはずです。

# 追記

ちょうどローカルのDNSを使って高速 failover 対応をする方法を DeNA さんが公開してくださっていたのでリンクしておきます。

https://engineer.dena.jp/2019/10/management-migration-aurora.html
JS直書きでGoogle DoodleのCanvasを録画してGifに

# 導入
今日はハロウィンなので、GoogleのHPではまた新たな[Doodle](https://www.google.com/doodles/halloween-2019)が更新しました。
今回のDoodleは~~ハスキー~~オオカミがバスケをやっているのがあって、とても面白いと思って、つい録画しようと思いました。

![Webp.net-gifmaker (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87438/733955e1-c2f8-7833-4786-457d293650a3.gif)

# 方法
## DOM要素の調査
調査してわかったのは、このアニメーションは`id="hpcanvas"`というCanvasが出しているのがわかりました。

![2019_年ハロウィン_🔊.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87438/4bb04192-c636-dcd2-ba4a-34be22cb40a8.png)


## キャプチャーを撮る
CanvasからGifに変換するライブラリーは多数ありますが、私がいくつか試したところ、Chrome Consoleでの操作がには適していないようで、いっそう直書きにしました。
動画とは静止画の連続なので、Canvasアニメをサンプリングして静止画のフレームをキャプチャーして、繋げていけば目的が達成できると考えていました。

今回はそんなに大量に作成しなくていいと思い、100ms間隔で100枚(10fps * 10s)キャプチャーを撮り、blob urlをリストに保存するよう作りました。

```js
const array = []
let i = 0
const recorder = setInterval(() => {
  if (i < 100) {
    canvas.toBlob(blob => {
      array.push(window.URL.createObjectURL(blob));
    })
    i ++;
  } else {
    console.log(array);
    clearInterval(recorder);
  }
}, 100);
```

上記SnippetをChrome Consoleに流した瞬間、アニメーションのスタートボタンを押せば、録画が開始します。
録画が終ったとき、キャプチャーのURLリストが出力されます。

## キャプチャーをダウンロード
今回は100枚のフレーム(キャプチャー)をローカルにダウンロードして、Gifとして繋ぎ直す予定でしたので、まずダウンロード用のダミー`<a>`タグを作ります。

```js
const a = document.createElement("a");
a.style = "display: none";
document.body.appendChild(a);
```

そして、先ほどできたblob urlから、キャプチャーをダウンロードします。ブラウザが劇重いになりそうなので、一枚ダウンロードして100ms Sleepをさせています。
また、ファイル名を連番つけないと、後ほどいろいろ苦労しちゃうので、ちゃんと連番もつけます。

```js
(async () => {
  let i = 0
  for (const url of array) {
    a.href = url;
    a.download = `google-${i}.png`;
    a.click();
    i ++;
    await new Promise(r => setTimeout(r, 100));
  }
})();
```

ダウンロード終えた時、ローカルに100枚のキャプチャーがあるはずです。
![名称未設定フォルダ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87438/a28795e9-c79b-be56-a4a5-077641a5dc25.png)

## Gifに変換
PNGをGifに繋ぐサービスは多数存在しますが、私は適当に[こちらのサイト](https://gifmaker.me/)を使いました。
不要のフレームを削除して、サイトにアップロードします。先ほどサンプリングする際は100msごと一枚(10fps)でしたので、`Animation speed`を `100 milliseconds` にすればいいです。

以上、今回のレポートでした。

# 参考
- [JavaScriptでcanvasを録画して動画ファイルに保存する方法](https://blog.ver001.com/javascript-canvas-mediarecorder/)
- [[悪用禁止] ブラウザだけでカメラ、キャプチャ、VideoやCanvasを録画してダウンロード](https://qiita.com/jerrywdlee/items/60934ca7b89cfe7baf13)
【Rails】resourcesメソッド

# resourcesメソッド

## 意味
CRUD (Create, Read, Update, Delete) 操作に対応付けられるルール
index, show, new, edit, create, update, destroy の
７つのアクションへのルーティングを一挙に宣言する

## 使用法
``` routes.rb
resources :users
```

| HTTPリクエスト | URL | アクション | 名前付きルート | 用途 |
|:--|:--|:--|:--| :-- |
| GET | /users | index | users_path | すべてのユーザーを表示するページ |
| GET | /users/1 | show | user_path(user) | 特定のユーザーを表示するページ |
| GET | /users/new | new | new_user_path | ユーザーを新規作成するページ (ユーザー登録) |
| POST | /users | create | users_path | ユーザーを作成するアクション |
| GET |	/users/1/edit |	edit | edit_user_path(user) | id=1のユーザーを編集するページ|
| PATCH | /users/1 | update | user_path(user) | ユーザーを更新するアクション |
| DELETE | /users/1 | destroy | user_path(user) | ユーザーを削除するアクション |

## 参考
[Rails のルーティング - Rails ガイド] (https://railsguides.jp/routing.html#crud%E3%80%81%E5%8B%95%E8%A9%9E%E3%80%81%E3%82%A2%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3)

[第7章 ユーザー登録 - Railsチュートリアル] (https://railstutorial.jp/chapters/sign_up?version=4.2#table-RESTful_users)
画像(複数)アップロードにCarrierWaveを使ったRspec

複数の画像のRspecテストでつまずいたので備忘録です！

###参考
>URL:(https://github.com/carrierwaveuploader/carrierwave/wiki/How-to:-Use-test-factories)

>[画像アップロード CarrierWaveを使ったmodelのRSpecを通す](https://qiita.com/motty93/items/5cbc46ce79a502fcaa65)

###動作環境
- Ruby 2.6.0
- Rails 5.2.3
- Mysql 5.7
- macOS Mojave 10.14.6

##モデルのアソシエーション
``` post.rb
class Post < ApplicationRecord
  belongs_to :user
  mount_uploaders :pictures, PictureUploader

  validates :title, presence: true, length: { maximum: 30 }
  validates :description, length: { maximum: 150 }
  validates :pictures, presence: true
end
```
``` user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable

  has_many :posts, dependent: :destroy
  mount_uploader :image, ImageUploader
  validates :name, presence: true, length: { maximum: 10 }
end
```

###postsテーブル
``` schema.rb
ActiveRecord::Schema.define(version: 2019_10_28_043606) do

  create_table "posts", options: "ENGINE=InnoDB DEFAULT CHARSET=utf8", force: :cascade do |t|
    t.string "title", default: "", null: false
    t.string "description"
    t.json "pictures"   #複数画像のときはjson型(Mysqlのバージョンによって違うらしい)　配列で保存する・これを忘れるとデータ作成のときにエラーが出る
    t.bigint "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["user_id"], name: "index_posts_on_user_id"
  end
 #下記省略
end
```

###Factory_Botでデータを準備
テスト用画像はspec/factoriesに保存しておく

``` spec/factories/posts.rb
FactoryBot.define do
  factory :post do
    sequence(:title) { |n| "this is a test#{n}"}
    sequence(:description) { |n| "this place is one of my favarite place#{n}"}
    pictures { [ Rack::Test::UploadedFile.new(Rails.root.join('spec/factories/test.jpg'), 'spec/factories/test.jpg') ] }  #json型で画像を保存するときは[]でデータを囲む・配列にしていないと入力エラーが発生する
    association :user  #アソシエーションを定義
  end
end
```

###postモデルのテストをする
画像の配列の中身の数変更してテストしたいときはletで先に
定義していると楽にテストを書くことができる.

今回はお題の画像の部分のみ

``` post_rspec.rb
require 'rails_helper'

RSpec.describe Post, type: :model,do: true  do
  let(:image_path) { Rails.root.join('spec/factories/test.jpg') }
  let(:image) { Rack::Test::UploadedFile.new(image_path) }

  it "タイトル、説明、画像があれば有効" do
    post = create(:post)
    expect(post).to be_valid
  end

  it "タイトル、説明、画像(2数)でも有効" do
    post = create(:post, pictures: [image, image])
    expect(post).to be_valid
  end
  it "タイトル、説明、画像(3数)でも有効" do
    post = create(:post, pictures: [image, image, image])
    expect(post).to be_valid
  end

  it "写真が空だと無効" do
     post = build(:post, pictures: nil)
     post.valid?
     expect(post.errors[:pictures]).to include("を入力してください")
   end
end
```

###最後に
カラムの型を忘れていて結構な時間を浪費しました！
みなさんはカラムの型をしっかりと把握しておけば、無駄なエラーが減ると思います。
至らない点もあったと思いますが、勉強の手助けになればなと思います！！
任意の個数の整数をソートするプログラム（C言語）

ソートは基本選択法で行います。


```
#include <stdio.h>
#include <stdlib.h>

void sort_ary(int a[], int n);

int main(void) {
	int *head,*p;
	int i,m;

	printf("いくつの整数を並び替えますか？");
	scanf("%d",&m);

	head = (int *)malloc(sizeof(int) * m);

	if(head == NULL){
		perror("メモリが確保できません");
		exit(1);
	}

	p = head;

	for(i = 1; i <= m; i++,p++){
		printf("%d個目の整数----->",i);
		scanf("%d",p);
	}

	printf("\n");

	sort_ary(head,m);	

	free(head);

	return 0;
}

void sort_ary(int a[], int n) {

		int i;
		int j;
		int min;
		int temp;

	printf("並び替え前\n");
	
	for(i = 0; i < n; i++) {
		printf("x[%d] = %d\n",i, a[i]);
	}

	printf("\n");
	
		//ここからソート処理
		for(i = 0; i < n-1; i++) {
			min = i;
			for(j= i+1 ; j < n; j++) {
				if(a[min] > a[j]) {
					min = j;
				}
			}
				temp = a[min];
				a[min] = a[i];
				a[i] = temp;
					
	 	}

		//ソート処理はここで終わり

		printf("並び替え後\n");

			for(i = 0; i < n; i++) {				

			printf("x[%d] = %d\n",i, a[i]);
		}
}
```
以前投稿した、
[基本選択法によるソートプログラム](https://qiita.com/ryo_ka/items/335b57d2c2d7ec8d12ac)
を少し発展させたものです。
swift removeAtIndex() について　備忘録

備忘録
自分で調べてもなかなか出てこなかったので書いておく

```swift
var HogeHoge[String] = ["foo","bar"]
HogeHoge.removeAtIndex(0)
```
と書くと

```swift
Value of type '[String]' has no member 'removeAtIndex'
```
と怒られた

調べていくと

```swift
var HogeHoge[String] = ["foo","bar"]
HogeHoge.remove(at:0)

print(HogeHoge) //["bar"]
```

この書き方で良いそうだ

初心者なので間違っているかもしれないが、誰かの役に立てれば嬉しい。
ディスク容量を減らす際のsyslogの削除について

#syslogを削除してもディスク容量が減らない

ある時サーバ内のディスク容量が切迫し、syslogの容量がとても大きいのでrmコマンドで削除をしたのだが、削除後にdfコマンドを入力しても容量に変化がない、

経験が浅い私は焦ったのだが、どうやら参照カウンタが関係しているらしい。
参照カウンタはGC(ガベッジコレクション)の一種でオブジェクトを参照している数をカウントする。

そもそもrmコマンドはファイルを削除するものだと思っていたが、厳密にいうとそうではないらしい。簡単にいうとファイルを参照から外すイメージだそう。

UNIX系OSではファイルの実体にinodeというものがつけられ、inodeを使ってファイルを参照する。しかしinodeだけでは人間が管理しずらい為inodeを参照するリンクを作って管理している。

rmコマンドとはこのリンクを解除して参照カウンタを0にする事なのです。
平たく言うとファイル名のみの削除、あとの削除はGCが行ってくれる。

GC(ガベッジコレクション)の働きとして、参照が０になったものをゴミと判断し、ファイルの削除処理が発生する。この時初めて削除が発生するのです。

ではなぜ冒頭で述べたようにログファイルをrmコマンドで参照を０にしても削除がなされないかというと

rmコマンドでログファイル削除。
↓
デーモン再起動コマンド
↓
結果が返ってこない
↓
プロセスをkillしても死なない

逆に参照を０にしてしまった事によって大きいファイルの削除に時間がかかり、デーモン再起動プロセスがファイル削除を待ってしまっている事が原因であるよう。


正しいログファイルの削除はデーモン再起動時に参照を０にしないことである。

mvコマンドでファイル名変更
(過去のファイル名は削除され、参照から外れるが、新しい名前が参照される。参照は０にならない)
↓
デーモン再起動
↓
rmコマンドでファイル削除(ここで初めて参照が０になる。)

この手順であればデーモン再起動時には参照が０になっていない為、
再起動後にrmで参照を０にすることによって正しく削除が行われる。
CodePipeLineからLambda呼び出しを行うCloudFormationテンプレートの定義

# はじめに
CodePipeLineが終わったらSlackに通知を送るために、最後にLambda呼び出したかった。
作成したものを備忘として記録。

# テンプレート

```yaml
  # CodePipeLine
  Pipeline:
    Type: AWS::CodePipeline::Pipeline
    Properties:

      ・・・(lambda以外は省略)

      Stages:

      ・・・(lambda以外は省略)

        - Name: lambda
          Actions:
            - Name: lambda
              ActionTypeId:
                Category: Invoke
                Owner: AWS
                Version: 1
                Provider: Lambda
              Configuration:
                FunctionName: slack-function # 呼び出したいLambdaの関数名
                UserParameters: 'lambda' # Lambdaにパラメータを渡したいときだけ設定する
              RunOrder: 1
```

# LambdaでUserParametersを取得する方法(Python)
けっこう深いところにいます。。

```python
def lambda_handler(event, context):
  # paramにテンプレートで設定した文字列lambdaが取得されます。
  param = event['CodePipeline.job']['data']['actionConfiguration']['configuration']['UserParameters']
```

# LambdaからCodePipeLineに結果を返す方法
Lambdaから結果を返さないとCodePipeLine上でLambdaがずっと実行中のままとなり、1時間のタイムアウトまで実行中になってしまいます。

## コード

```python
import boto3

# CodePipeLineのクライアント
code_pipeline = boto3.client('codepipeline')
# job_idの取得
job_id = event['CodePipeline.job']['id']

try:
  # 成功したとき
  code_pipeline.put_job_success_result(jobId=job_id)
except:
  # 失敗したとき
  code_pipeline.put_job_failure_result(jobId=job_id, failureDetails={'message': "任意の文字列", 'type': 'JobFailed'})


```

## IAMポリシー
成功/失敗を返す権限が必要です。
下記の2つの許可が必要です。

```json
        {
            "Action": [
                "codepipeline:PutJobSuccessResult",
                "codepipeline:PutJobFailureResult"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
```
next.jsでabsoluteなpathをインポートしたい

`../../`とかやらずにimportしたいなと思ったので、調べた。

こういうやつ

```diff
-import { InjectStoreContext, initializeData } from '../../../../../src/stores';
+import { InjectStoreContext, initializeData } from 'src/stores';
```

next.config.jsでwebpackに設定注入して、
eslintの設定も追記するとだいたいOK
雑にdiffも置いとく。

```diff
diff --git a/.eslintrc.js b/.eslintrc.js
index 5594d79..84bc5b3 100644
--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -8,13 +8,18 @@ module.exports = {
     ecmascript: 6,
     jsx: true,
   },
-  extends: ['airbnb', 'prettier', 'prettier/react'],
+  extends: ['airbnb', 'prettier', 'prettier/react', 'plugin:import/errors', 'plugin:import/warnings'],
   settings: {
     react: {
       createClass: 'createReactClass',
       version: 'detect',
     },
     'import/core-modules': ['styled-jsx/css'],
+    'import/resolver': {
+      'node': {
+        'paths': ['.']
+      },
+    },
   },
   parser: 'babel-eslint',
   plugins: ['react', 'react-hooks', 'prettier'],
diff --git a/next.config.js b/next.config.js
index bd98df1..d461392 100644
--- a/next.config.js
+++ b/next.config.js
@@ -1,4 +1,5 @@
 const webpack = require('webpack');
+const path = require('path');
 const withBundleAnalyzer = require('@next/bundle-analyzer')({
   enabled: process.env.ANALYZE === 'true',
 });
@@ -25,6 +26,13 @@ module.exports = withSass(
       withSourceMaps({
         webpack(config) {
           config.plugins.push(new webpack.ContextReplacementPlugin(/moment[/\\]locale$/, /ja/));
+          config.resolve.alias.src = path.join(__dirname, 'src');
           return config;
         },
         serverRuntimeConfig: {
diff --git a/pages/_app.js b/pages/_app.js
index a006c3f..4538e0e 100644
--- a/pages/_app.js
+++ b/pages/_app.js
@@ -3,13 +3,13 @@ import Router from 'next/router';
-import '../src/styles';
-import { InjectStoreContext, initializeData } from '../src/stores';
-import InjectThemeProvider from '../src/components/InjectThemeProvider';
+import 'src/styles';
+import { InjectStoreContext, initializeData } from 'src/stores';
+import InjectThemeProvider from 'src/components/InjectThemeProvider';
```
Auth0 Deploy CLIを使ってテナント情報をディプロイしてみた

# はじめに
この記事は[Auth0 Deploy CLI](https://auth0.com/docs/extensions/deploy-cli)を使ってローカルのPCで作成したAuth0のテナント情報をリモートの本番テナントにディプロイする手順をまとめています。

# 検証環境
- **OS** : `macOS Mojave 10.14.6`
- **node** : `10.15.3`
- **npm** : `6.12.0`

# 検証内容
Auth0のダッシュボードにログイン、左ペインの"Applications"をクリックして右上の"CREATE APPLICATION"を押します。
<img src="https://i.imgur.com/ZtGP5PL.png" width=70%>

"Name"に任意の名前を入力して"Choose an application type"で"Machine to Machine Applications"を選択、"CREATE"を推します。
<img src="https://i.imgur.com/iToIkRd.png" width=70%>

"Select an API..."で"Auth0 Management API"を選択して"Select all: All"をクリックして全てのScopeをチェック、"AUTHORIZE"を押します。**Deploy CLIは[Auth0 Management API](https://auth0.com/docs/api/management/v2/)をコールするため設定しています。本番環境では用途に合わせてScopeを限定しますがこの記事は検証目的のため全てのScopeをチェックしています。**
<img src="https://i.imgur.com/MVSAd51.png" width=70%>

Auth0 Deploy CLIをPCにインストールします。

```console
$ npm i -g auth0-deploy-cli
```

任意の作業ディレクトリを作成して移動します。

```console
$ mkdir auth0-deploy-cli-demo
$ cd auth0-deploy-cli-demo
```

config.jsonを作成して編集します。**"AUTH0_CLIENT_ID", "AUTH0_CLIENT_SECRET"には先のステップで作成したMachine to Machine ApplicationのID/Secretを指定します。"Applications"->"Settings"から確認できます。**

```console
$ touch config.json
```

```json:auth0-deploy-cli-demo/config.json
{
  "AUTH0_DOMAIN": "kiriko.auth0.com",
  "AUTH0_CLIENT_ID": "xxxx",
  "AUTH0_CLIENT_SECRET": "xxxx",
  "AUTH0_ALLOW_DELETE": true
}
```

Auth0のテナント情報(ex/設定、Custom Script, Rules)をPCにエクスポートします。

```console
$ a0deploy export -c config.json -f yaml -o ./tenant
```

**auth0-deploy-cli-demo/tenant/tenant.yamlにテナント情報が出力されています。確認してみます。**

```yaml:auth0-deploy-cli-demo/tenant/tenant.yaml
emailProvider:
  name: smtp
  credentials:
    smtp_host: smtp.mailtrap.io
    smtp_port: 2525
    smtp_user: xxxx
    smtp_pass: YOUR_SMTP_PASS
  default_from_address: Travel0 Accounts <accounts@travel0.net>
  enabled: true
rules:
  - name: Account-Linking-Extension
    script: ./rules/Account-Linking-Extension.js
    stage: login_success
    enabled: false
    order: 120
--省略--
```

ローカルPCにエクスポートされた任意のRulesを変更してみます。**auth0-deploy-cli-demo/tenant/rules配下の任意のJSを変更してみます。**

ローカルPCの変更内容をリモートのテナントにインポートします。

```console
$ a0deploy import -c config.json -i ./tenant/tenant.yaml
```

**Auth0のテナントを確認してローカルPCの変更が反映されていれば成功です。**

# おわりに
"全ての企業がソフトウェア企業"と言っていいほどソフトウェアの重要性は増すばかりで、新しいソフトウェア機能を迅速に市場に投入するためにはDevOpsのような文化醸成、CI/CDツールを利用した自動的・継続的なソフトウェアデリバリーは不可欠かと思います。CI/CDツールが管理するソフトウェアデリバリーパイプラインに乗せるには、デリバリー対象が人が読めるコードになっていることが前提ですが、"as Code"化されてきたインフラストラクチャに比べてID領域のコード化はこれからかと思います。Auth0はID領域をコード化して、お客様がご利用されているCI/CDツールと連携してソフトウェアデリバリーパイプラインに簡単に組み込むことが可能です。
【Rails】Provideメソッド

# Provideメソッド

## 意味
供給する, 与える, 規定する

## 使用法
provideメソッドでパラメータを引き渡し

``` erb:home.html.erb
<% provide(:title, "Home") %>
```
yieldメソッドで受け取る

``` erb:application.html.erb
<title><%= yield(:title) %></title>
<!-- <title>Home</title> -->
```
AWS re:Invent チケット売り切れの歴史

#はじめに
2012年から毎年年末にラスベガスで開催しているAWSの年次イベント AWS re:Invnet のチケットは毎年売り切れるほど人気があるプレミアチケットです。
2019年のチケット（Full conference pass）代は1799USDです。
購入を迷っていると売り切れてしまうことがありますので、例年の売り切れ傾向を調べてみました。

# 売り切れ年表
確認できる範囲でいつ売り切れたのか調べてみました。
なお、ソースとなる情報は公式もしはそれに準じるものを優先しています。公式情報が見つからなかった場合は個人/企業のブログ記事の日付を参考にしております。

| 開催年 | 開催期間 |売り切れ日|ソース|
|---|---|---|---|
|2012 | 2012/11/27～11/29 | 2012/11/09 |https://twitter.com/awsreinvent/status/266626817362911232 |
|2013 | 2013/11/12～11/15 | 不明 |N/A |
|2014 | 2014/11/11～11/14 | 2014/10/28 |https://twitter.com/awscloud/status/526856194108178434 |
|2015 | 2015/10/06～10/09 | 2015/07/24 |https://twitter.com/Werner/status/624308060933074944 |
|2016 | 2016/11/28～12/02 | 2016/11/11 |（Not Official）https://www.afonza.com/ready-for-aws-reinvent-2016/ |
|2017 | 2017/11/26～12/01 | 2017/11/16 |https://twitter.com/awsreinvent/status/930978983067508737 |
|2018 | 2018/11/25～11/30 | 2018/11/20 |（Not Official）https://twitter.com/matt_traverse/status/1064810922324230144 |

参加人数情報もあるとより興味深い表になったのですが、余裕があれば調べてみます。

今年（2019年）はいつ売り切れるのでしょうか。
参加予定の方は急いで登録しましょう。

# 参考
AWS re:Invent公式サイト　https://reinvent.awsevents.com/
なぜnullは良くないと言われるのか

<!--
author's note

この記事の内容自体はひどく初歩的なのだけど、初心者から質問されたときに口頭で説明しようとすると根拠をぱっと言えなかったりサンプルコードでわかりやすく説明できなかったりするので、説明品質を一定にしつつ何度でも読み返せるように文章にしました。
またそこそこ経験のある人でもすっぽりこの辺りの理解が抜けていることもあるため、知識のベースラインを合わせる目的でも有用だと思います。

-->

# 前提

* nullまたはそれに当たる機能を持つ静的型付け言語の知識がある
* null非許容型、null許容非安全型、null許容安全型の定義については次の記事を参照
    * [null安全の観点から見たnull非許容型、null許容非安全型、null許容安全型の比較 \- Qiita](https://qiita.com/bigwheel/items/c4d60d91b3bbd7e6e130)

# 問題

なぜnullは良くないと言われるのか

# 短い回答

nullそのものは悪くありません。
null許容非安全型も限定的な利用であれば便利なケースもあると言えます。
悪いのはnull許容非安全型をデフォルトの型にしてしまっている言語です(例: Java, C#, Objective-C)。
このような言語はnull許容非安全型を濫用した結果、不要に実行時例外の危険を招いています。

[^10]: ほぼほぼ次の記事と同意見です [null安全でない言語は、もはやレガシー言語だ \- Qiita](https://qiita.com/koher/items/e4835bd429b88809ab33)

# 長い回答

TBW

<!--

## null安全な言語でもnullは使用される

ときどき「nullは悪い文明。破壊する」といったような発言を目にしますが、これは正しくありません[^11]。
null自体は「存在しない」という状態を表す単なる概念で基本的に良くも悪くもないです。
実際にnull安全を実装したモダンな言語[^12]でもnullまたはnull代替の概念(None, nil)は出てきますし、null概念自体が排除されたわけではありません。

[^11]: こういった発言をする人はnullとnull許容安全型を混同しているかあるいはわかっていてあえてnullといっているのかのどちらかだと思いますが、どちらにしろ初学者に誤解を与えかねないので「null許容安全型」が悪いと言ったほうが良いです

[^12]: Swift, Kotlin, Scala, TypeScriptなど。Kotlin, Scalaは(多分TypeScriptも)null安全性に関しては厳密には微妙

ではなぜnullは良くないの言われるのかと言うと、nullの使い方に問題がある言語が存在するためです。

## なぜ**null安全でない型**はあまり良くないのか

中身がnullだったときに発生しうる実行時例外が良くない、これにつきます。






-->


# 参考

* [アントニー・ホーア \- Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%A2%E3%83%B3%E3%83%88%E3%83%8B%E3%83%BC%E3%83%BB%E3%83%9B%E3%83%BC%E3%82%A2) Null参照の発明者
* [null安全でない言語は、もはやレガシー言語だ \- Qiita](https://qiita.com/koher/items/e4835bd429b88809ab33)
ソースコードを確認する時に便利な機能

#はじめに
開発しているソースコードを解析する際に、
・動的：実機等で実際に動かして確認する方法
・静的：ドキュメントやソースコードを直接確認する方法
の2種類の方法があります。
それぞれ、メリット/デメリットがあるのですが、
今回、自分が実際に使用している、Android Studioでの基本的な方法、
便利な機能を紹介いたします。

#動的解析
##ブレイクポイントを使おう
Android Studioでは、下記の画像のようにブレイクポイントを入れて置くことで、
アプリを一時停止しながら1行ずつ処理を動かすことができ、
変数等の動きを確認することができます。
![スクリーンショット 2019-10-28 18.15.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472891/331d2100-c449-9c1f-f0cc-c70b85dd8125.png)

##今開いているActivityがわかる
実機等で確認している時にandroid studioのTerminalに

```
adb shell dumpsys activity | grep mFocusedActivity | cut -d ' ' -f6 |rev | cut -d '.' -f1 | rev
```
と記入することで、実機等で開いている画面のActivityを知ることができます。
出力としては、

```
MainActivity
```
と表示されます。

##レイアウトの範囲が見える
android端末の開発者向けオプションのレイアウト範囲を表示をオンにすることで、
各Viewごとに線が表示され、レイアウトがわかりやすくなります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472891/8e1a88ca-1260-57c6-9f6c-abbdd252ae3f.png" width="150" height="250">

#静的解析
##Find in Path
command + shift + f と押すことで、全ファイルの中から入力した文字を含む文字列を検索してくれます。
![スクリーンショット 2019-10-30 19.40.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472891/ccf422ae-f7ee-06b7-94fb-b521e618a28e.png)
Find in Pathを使用することで、気になっているコードをすぐに見つけることができます。

##変数名や関数名の意味を調べる
変数や関数等の名前をきちんと調べたほうがいいです。
関数名を理解することで、調べていることに関係がある関数なのかすぐに知ることができます。
そのため、いちいち中身を見なくても処理が想像でき、時間短縮になります。
自分は英語翻訳を使って意味を調べるようにしています。

#おわりに
今回、自分がソースコードを確認するときに実際にやっていることを載せてみました。
他人のソースコードを確認する時に上記で記した機能を使用したことで、
処理を探す時間がだいぶ短くなりました。
便利なものはジャンジャン使っていきましょう！

他にもこれを使えばもっとわかりやすいよー！などあれば、
教えていただきたいです！
【mysql】ssh接続したさくらサーバー上からmysqlをコマンドラインで実行

## 前提

- 環境：さくらレンタルサーバースタンダードプラン
- 目的：terminalからssh接続した状態でコマンドラインからmysqlをいじりたい！

## 方法

```:
$  mysql --host=mysqlxxx.db.sakura.ne.jp --user=foobar --password=xxxxxxxxxxxxxxxxx
```

> [さくらのレンタルサーバでmysqlをコマンドラインから使う](http://unkillonline.hatenablog.com/entry/2017/06/17/152011)

この`--host`オプションをつけてなくて、ずーっとエラーが吐かれてて焦ったので、メモがわりに書いておきます。
Markdownのあると便利なコピペ記法まとめ

初投稿になります。
この記事は、Markdownの記法に関する備忘録になります。

## 経緯

Markdownで文章を書いている際に、ちょくちょくHTMLで書くことがあり、そのたびに調べ、別々のページからコピペしてたのでHTMLの記法だけまとめたのが欲しいと思い記事にしてみました。（すでにそいう記事はあるかもですが・・・）

記載する記法は、私自身がよく使っているものやあると便利だなと思うものを載せています。

## 動作環境

実際の表記を確認したツールは以下になります。

- visual studio code
    - Markdown Preview Enhanced を使用
- Typora


## テキスト関連
#### アンダーラインを引く
```
<u>こんにちは</u>
```

#### テキストを右寄せ、中央、左寄せにする

- 右寄せ

```
<div style="text-align: right;">
こんにちは
</div>
```

- 中央

```
<div style="text-align: center;">
こんにちは
</div>
```

- 左寄せ

```
<div style="text-align: left;">
こんにちは
</div>
```

#### テキストの色を変更する

- <font color="Red">こんにちは</font>```<font color="Red">こんにちは</font>```

- <font color="Blue">こんにちは</font>```<font color="Blue">こんにちは</font>```

- <font color="Gold">こんにちは</font>```<font color="Gold">こんにちは</font>```

- <font color="Green">こんにちは</font>```<font color="Green">こんにちは</font>```

#### フォントサイズを変更する
```
<div style="font-size: 300%"> sample text </div>
```

## 画像関連
#### 挿入する画像サイズを変更する

```
<img src="画像のPATH" width=***>
```
※ ***は、パーセント表記でも可(例：width=50%)

#### 画像を右寄せ、中央、左寄せにする

```
<div align="right">
<img src="画像のPATH">
</div>
```
```
<div align="center">
<img src="画像のPATH">
</div>
```
```
<div align="left">
<img src="画像のPATH">
</div>
```

## その他

#### PDF変換時の改ページ挿入

```
<div style="page-break-before:always"></div>
```

## 最後に
他にも、コピペできるとサクッと書いていけそう記法ありましたら、
追記していこうと思います。
GCE, Docker環境でSegmentation faultの対処法

# Segmentation fault
GCEインスタンスでDockerを立ち上げて[OpenNMT](http://opennmt.net/)を実行していたのですがSegmentation fault (core dumped)が出ました。
初めにOpenNMT, PyTorchあたりのエラーを疑ってたんですがDockerが原因で解決したので記録として残しておきます。
# 解決方
Dockerのオーバーコミットメント設定を変更する
ホストマシンで

```bash
sysctl vm.overcommit_memory
```

を確認して0なら

```bash
sysctl vm.overcommit_memory=1
```

に変更の上、新しく立ち上げたコンテナでプログラムを実行したら解決しました。

# 原因を探すことの難しさ
[Segmentation fault in preprocess](https://github.com/OpenNMT/OpenNMT/issues/547)
OpeNMTのイシューで同様のエラーが出た人がいるんですが、開発者は「俺たちのエラーじゃない。PyTorchの実装が悪い」と説明してて「PyTorch Segmentation fault」でも[ググった](https://discuss.pytorch.org/t/segmentation-fault/23489)ところ、この問題は解決されてましたが、それ以前のDockerのエラーでした。GCE,Docker,フレームワークの上で実行されたプログラムはエラーの原因を探すことが難しいですね。

## 参考
[Segmentation fault when running in docker container](https://github.com/soedinglab/hh-suite/issues/104)
毎週起動する RDS を毎週停止させる CodeBuild

# 背景

RDSの停止ができるようになりましたが、停止してから1週間経過すると、ふたたび起動してきます。停止したのは、停止しておきたい理由があるから停止したのに、おまえ何で起動さした？

毎週手作業でやるのも微妙。Lambdaでbotoするのを書くのもダルい。

CodeBuild で毎週実行させて awscli でやるのが究極に簡単でした。

# buildspec.yml

コンテナイメージは awscli が入るなら何でも良いです。作例では `amazonlinux:2` を使っています。

```yaml
version: 0.2

env:
  variables:
     RDS_NAME: "RDSインスタンス名"

phases:
  install:
    commands:
      - yum install -y awscli
  build:
    commands:
      - aws rds stop-db-instance --db-instance-identifier ${RDS_NAME}
 ```

# IAM

CodeBuildに付けてるIAMロールに  `StopDBInstance` 権限を付与します。Resourceの範囲はお好みの塩梅で。ほんとうにStopDBInstanceしてよいものだけに絞るのが安全かと思います。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "rds:StopDBInstance",
            "Resource": "arn:aws:rds:*:*:db:RDSインスタンス名"
        }
    ]
}
```

CodeBuild内でawscliを実行するので `iam:PassRole` も付けてください。

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Action": [
        "iam:PassRole"
      ],
      "Effect": "Allow",
      "Resource": "*"
    }
  ]
}
```


# 実行周期

CodeBuildの「ビルドのトリガー」で実行周期の設定ができますね。毎週1回実行などとしておきます。

# 参考

* https://docs.aws.amazon.com/cli/latest/reference/rds/stop-db-instance.html
* https://dev.classmethod.jp/cloud/aws/iam-pass-role/
* [いますぐ使うCodeBuild](https://qiita.com/sasasin/items/6e5f7001cba350851d49)
"Xcodeが予期しない理由で終了しました。" （The Xcode build system has crashed.）解決方法

# 環境
Xcode 10.3

#現象

どのプロジェクトも"Xcodeが予期しない理由で終了しました。"となる。

・`rm -r ~/Library/Developer/Xcode/DerivedData/`
・`rm -r myapp.xcworkspace
pod install`
どちらも試したが、解決せず。

#解決方法

メニュー>File>Project Setting から
「Legacy Build System」を選択

<img width="552" alt="スクリーンショット 2019-10-31 18.20.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344603/08c56f87-cb29-3338-1c1b-1f2086df1581.png">

#参考URL
https://stackoverflow.com/questions/50870787/xcode-9-4-unexpected-service-error-the-xcode-build-system-has-crashed
https://qiita.com/KosukeOhmura/items/bb6986d723a36633411b
アメリカの小学校〜中学校で AIプログラミング教育が始まっていた件（無料AIツールの紹介）

#無料の画像解析のモジュール？
MIT App Inventor2 で最近リリースされた LookExtension というエクステンションモジュールがあるのを発見。画像解析のAIのようだが、ほとんど資料がなくどのように使うのが調べていたら小学生や中学生向けのAI、プログラミング教材の一貫でもあることがわかった(App Inventor "LookExtension" how to use という検索キーでヒットした件数は10件)。教室内にある時計などをカメラで撮影して、それが時計であるかなどをAIで判定させ、正確性の確率まで画面に表示される。MIT App Inventor2はブロックでアプリが作成できるが、ボタンを押したら画像をキャプチャし、分析ボタンを押したら解析を開始するといったプロセスについては児童・生徒に作らせる仕組みだ（作らせると言っても１０分もあれば終わってしまうが）。この一連の教育が「beginner」、４５分２回のセッションという位置付けだから驚きだ。 この時点ですでに日本が出遅れていることを実感。
このような教育を受けた世界の子供たちが5年〜10年もたてば就業年齢になるわけで、特にIT系の仕事をしているオッサンらは（私は）今の子供達が何を勉強しているかアンテナはって基礎教養で負けないように覚悟しておいた方が良さそう（人生100年時代というが、10年も経てば用無し、使い者にならないか？）。
なお、スマホの種類で動くものと動かないものがあり（そういう意味では商用利用は厳しい）いくつか動作確認済の機種が掲載されていた：Samsung Tab S2, Android 7.0、Amazon Fire HD 8, Fire OS 6.3.0.1、Amazon Fire HD 10、ASUS Zenpad 3s 10, Android 6.0、Chromebookのいくつか。

#教材の場所
2019/10/16付の紹介資料：https://www.i-programmer.info/news/105-artificial-intelligence/13174-ai-with-app-inventor.html
教材のトップページ：
https://appinventor.mit.edu/explore/resources/ai/image-classification-look-extension
Complete Teacher Unit Outline / 教師用資料：
https://drive.google.com/open?id=1RQMs_bF2MBIb5agGYY-no4dpyi5zABr
Lesson 1 teacher slides / 教師用スライド集1 ：
https://drive.google.com/open?id=1XEDDxgiC9Hvna7pjYSsrRUHrhhhlhvOsIZQpUVP053k
Lesson 2 teacher slides / 教師用スライド集2 ：
https://drive.google.com/open?id=1sAzNEdKQyR5Lv0cbI3r1msLoWJbAlS7t6YMIy7Fv8Uo
Lesson 2 student guide (pdf) / 児童・生徒用資料：
https://drive.google.com/open?id=1YS0w_tDo20afucM33sJ_qb117-E0olNh
Tutorial (opens in ai2.appinventor.mit.edu) / App Inventor 2 (AI2上の)オンライン教材：
http://ai2.appinventor.mit.edu/?locale=en&repo=http://appinventor.mit.edu/yrtoolkit/AI/aiaFiles/imageClassification/WhatIsIt.asc
よく使うMySqlコマンド

# はじめに
「よく使う」シリーズ。
私がよく使うMySqlコマンドをメモしておきます。

# 使用ツール
今回も略。

# よく使うMySqlコマンド
## MySql起動

```
sudo systemctl start mysqld.service
```
## MySql再起動

```
/usr/sbin/mysqld restart
```
## MySql接続

```
mysql -u root -p
```

この後パスワード入力。
## MySql切断

```
quit
```
## mysql バックアップ取得
```
mysqldump --single-transaction -u ユーザ名 -p DB名 > `date "+%Y%m%d_%H%M%S"`.sql
```

この後パスワード入力。ファイル名に現在日時が入ります。便利。
## mysql バックアップより復元
```
mysql -u ユーザ名 -p DB名 --default-character-set=utf8 < (filename).sql
```

この後パスワード入力。
## mysql テーブル一括削除

下記で指定する「テーブル名に含まれる文字列」を持つテーブルを一括削除できます。
予め-pの後パスワードを入力しておけばこのコマンド打った後のパスワード入力が不要になります。

```
mysql -u ユーザ名 -p パスワード -e 'SHOW TABLES FROM DB名' | grep テーブル名に含まれる文字列* | xargs -I "@@" mysql -u ユーザ名 -p パスワード -e "DROP TABLE DB名.\`@@\`"
```

# よく使うわけじゃないけどたまに発生するやつ
## MySql文字コード確認
```
show variables like "chara%";
```
## MySql文字コード変更
```
sudo vi /etc/my.cnf
character-set-server = utf8
```
# 参考サイト
[mysqlでの文字コード関連がわかってなくてワロタ](http://www.aipacommander.com/entry/2014/12/20/130551)
サーボモータ を別電源で動かすときに暴れだす現象について

導入文をここに書く
MG996Rなどの大型のサーボだとラズパイやマイコンの電圧では動かないため
直接DC電源のプラスとマイナスを差し込んで使うことがあると思う。
自分はこの際、サーボモータ が暴れだすというトラブルに陥いった


# 対象読者 
マイコン で大型のサーボモータ を動かしたいとき。


# 結論
DC電源のマイナスは直接サーボモータのGNDにつないではいけない。

ブレッドボードを利用して、
直列に

DC電源（ー）　→　サーボ （GND)　→　マイコン （GND)
このように繋ぐ。

一応参考に他は

DC電源（＋）　→　サーボ（VCC)

マイコン （PIN)　→　サーボ（PWM)

このように繋ぐ。



# 参考

https://www.youtube.com/watch?v=YjARfu1ukv4&t=181s
この動画を参考にした。


# あとがき

原因は専門が電気ではないため不明。
知ってるかたいたら教えて欲しいくらい。
（いつか火事になりそう）
我が家はレンガなので燃えません。
TidalCycles TIPS パート1「乱数を用いる」

TydalCyclesで乱数を用いた楽曲の制作方法について紹介します。

まず、一般的な乱数を用いる方法として、以下のような例が挙げられます。

```haskell
d1 $ s "bd" # n (irand 5)
d2 $ s "cp" # pan rand
d3 $ s "arpy" # up (choose[0,4,7])
```

上記のような方法を取る場合、課題として、1サイクル（1小節）以下の短いスパンでしか、乱数を適用できない、という点があります。

例えば、任意のタイミングで音色をランダムに変えたい、という場合、TydalCyclesで用意された記法では実現不可能です。
　参考：https://tidalcycles.org/index.php/Randomness

<br>


そこで、別の方法で乱数を生成し、生成した値を変数を経由して楽器(d1,d2等）に適用することにします。

Haskellは[副作用](https://ja.wikipedia.org/wiki/%E5%89%AF%E4%BD%9C%E7%94%A8_%28%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%29)を許容しない言語なので、乱数を用いる場合は以下の工夫が必要です。

- System.Randomモジュールをインポートする
- アクション（<-）を用いる

例えば、以下の記述により、変数randnumに0～10のランダムな整数を格納できます。

```haskell
import System.Random

randnum <- randomRIO (0, 10)

randnum
```

import文は1度のみ実行してください。
次のアクションの行を実行する度に、取得する値が変わります。
（randnumのみの行を実行することで取得した値を確認できます）

次にrandnumを先ほどのキックの楽器（d1）の音色に適用します。

```haskell
d1 $ s "808" # n randnum -- エラーとなる
d1 $ s "808" # n (fromIntegral randnum) -- 成功
```

素直に1行目のように書くと、n関数の引数はDouble型ですが、変数randnumはInteger型であるためエラーとなります。（厳密には、Num型であるべきだがIntegral型のためにエラー）

2行目のようにfromIntegral関数を使うことで、Num型へ型変換が行われ、エラーを解消できます。

これで、キックの音色を好きなタイミングでランダムに変更することができました！

次回は、リストを使ったもう少し複雑な例を紹介します。
【Capybara】Rails rspecシステムテストのScreenshot全画面表示設定

## 概要
アプリケーションを作ってごりごりシステムスペックを書いているわけですが。
テストコードはちゃんとテストとして成立しているかチェックしながら書いていくことが多いと思います。

そこでcapybaraを使った統合テストでは、failedが出るとスクリーンショットを取ってくれます。
このスクリーンショットと照合しながらテストコードの性能をチェックしていくことになるのですが・・・

しかしこのスクリーンショット、デフォルトだと小さい！
画面の下の方にリンクを置いてるのに上の方しか表示されねえ！

ってことで、設定方法をまとめとこうかなと思います。

## 設定方法

```ruby:spec/spec_helper.rb
require 'capybara/rspec'


Capybara.register_driver :selenium_chrome_headless do |app|
  options = Selenium::WebDriver::Chrome::Options.new

  [
    "headless",
    # ここの倍率を変更すれば、スクリーンショットサイズが変わります。
    "window-size=2880x2000",
    "disable-gpu" # https://developers.google.com/web/updates/2017/04/headless-chrome
  ].each { |arg| options.add_argument(arg) }

  Capybara::Selenium::Driver.new(app, browser: :chrome, options: options)
end

RSpec.configure do |config|
  ....
(省略)

```

コメントアウトにも書いてますが、倍率を変更すればスクリーンショットのサイズが変わります。
ちなみに2880x2000はかなり大きいです。
諸事情により、大きめのサイズでテストしたかったので変えました。
結構カジュアルに設定を変えることができるのも魅力かなと思います。

## ちなみに

Mac bookProのRetinaディスプレイで1680x1050くらいらしいですよ
PCの入力でn乗を打つ方法

# n乗
n乗はUnicode文字でちゃんと用意されています😆
http://uhyohyo.sakura.tv/uni/index.html

Google日本語では、コードポイントを打つことで、特定のUnicode文字を呼び出すことができるます
なのでそれを使って呼び出してみましょう❗

# 打ち方
Google日本語入力を使います
全角で「U+00B2」と打ちます

すると変換候補の中に「²」が出てくるのでそれを選択すればOKです😁
同様に他のUnicode文字も呼び出せるので覚えておくと便利です

こんな式もかけちゃいます😋

```
x = v₀t + (at²)/2
```

ちなみに₀は「U+2080」です
EC2 AutoScaling を初めて試そうとした場合にスケーリングが動かなかった話

# 経緯

- EC2 AutoScaling の検証のために自分のAWSアカウントに初めてScaling Groupを生成
- コンソールから実施していたが、この時生成に失敗
- しばらく経過して再生成すると成功
- CPUを `yes >> /dev/null` で 100% にしてみたものの、待てども待てどもスケーリングが開始されない

# 理由

- 初回生成時のエラーは初回IAM Roleの生成エラーによるもの
- 結果、スケーリングルールに紐づくCloudWatch 系列が一切作成されない状態でスケーリングポリシーが作成されてしまっていた
- インスタンス数の増減のイベントはCloudWatchのアラームベースなので、当然インスタンス数の増減も発生しない (手動でterminateすると元の希望数に保ってくれる動きは見せてくれたが)

# まとめ

AWS Management Consoleは便利ですが、ちょくちょくこういったリソース生成の順序周りでエラーが発生する気がします（忘れたけど、何回か遭遇した気がする）。
生成時にエラーが出た場合、そのタイミングで生成されたリソースが不完全な状態で作成されている可能性もあるので注意しましょう。
Rails6.0でactiverecord-mysql2spatial-adapterを使う

静岡市でWeb開発しているkazuomatzです。

弊社では、開発するモノとして位置情報を扱うサービスが比較的多いです。

Rails開発において、MySQLで位置情報を扱うGemである[activerecord-mysql2spatial-adapter](https://github.com/rgeo/activerecord-mysql2spatial-adapter)にお世話になってきましたが、このGem、開発がほぼ止まっているようで、最後の更新が2017年の7月で、サポートされているRailsのバージョンは4.1です。

ただ、いろいろな開発者の方が元のリポジトリーをforkしてRailsのバージョンに追随しており、[こちら](https://github.com/sebastianiorga/activerecord-mysql2spatial-adapter)のリポジトリで、[Rails4.2](https://github.com/sebastianiorga/activerecord-mysql2spatial-adapter/tree/rails-42) と [Rails5.1](https://github.com/sebastianiorga/activerecord-mysql2spatial-adapter/tree/rails-5)に対応したGemが公開されています。

過去手がけてきた位置情報を扱うRailsのアプリケーションのGemfileを並べてみると、こんな感じ。

### 2023年9月更新

MySQL8.0を使用する場合は、これだと動かないので、[こちら](https://qiita.com/kazuomatz/items/6954bfba1fb1ae837c27)を参考にして下さい。

## Rails 4.2の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'sebastianiorga/activerecord-mysql2spatial-adapter', branch: 'rails-42'
```

## Rails 5.0の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter' , github: 'sebastianiorga/activerecord-mysql2spatial-adapter', branch: '3f03ce772959e80797e5913682b3b4aff8847fd8'
```

Rails5.0の場合はいたってシュールですね・・・。

## Rails 5.1の場合

```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'sebastianiorga/activerecord-mysql2spatial-adapter', branch: 'rails-5'

```

これらすべてのバージョンが本家にmergeされてません。

たまたま、自分はRails 5.2での位置情報を扱うWeb開発を行う機会がなかったのですが、恐らくRails5.2に対応したバージョンはなかったかと思います。

で、時代はRails 6です。Rails4系のものは、6系に移行したいところです。

そもそも、Rails + MySQLで位置情報を扱う需要が少ないんでしょうか、緯度経度をDecimalか何かで保存すればそれでOKなのでしょうか、Rails 6 + MySQLで位置情報を扱えるGemって必要ないんでしょうか、それともPostgreSQLなの・・・？　いろいろ探しても見つかりません。

というわけで、上記のrails-5のGemをforkして改造すれば動くのではないかと思いたち、Rails 6で動作する[activerecord-mysql2spatial-adapter](https://github.com/kazuomatz/activerecord-mysql2spatial-adapter/tree/rails-6)を作ってみることにしました。

やったことといえば、ひたすらコードをトレースしながら、ActiceRecord 5と6の差を埋める作業をコツコツとやりました。引数の違いを吸収したり、宣言されていなかったものがなくなっている部分を埋めたりそんな感じ。

マイグレーションとデータの読み書きができるようになったので、多分使えるでしょう。

## Rails 6.0の場合
```ruby:Gemfile
gem 'activerecord-mysql2spatial-adapter', github: 'kazuomatz/activerecord-mysql2spatial-adapter', branch: 'rails-6'
```

これで動くハズです。
ただ、これを本家にmergeして欲しいのだけど、PRも放置されているようで、何ともなりません。
こういう場合は、どうしたらいいんでしょうかね。

一昔前は、Railsに乗ってるだけで幸せな日々が送れていたはずなのに、開発が止まってしまうGemがいろいろと出てきて、辛い時代になったきたなぁと思うのは自分だけでしょうか・・？
StandardScalerを試してみる

[sklearn.preprocessing.StandardScaler](https://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.StandardScaler.html)について簡単に調べたのでメモとして残します。

`StandardScaler`はデータセットの標準化機能を提供してくれています。
標準化を行うことによって、特徴量の比率を揃えることが出来ます。

例えば偏差値を例にすると、100点満点のテストと50点満点のテストがあったとして
点数の比率、単位が違う場合でも標準化を利用することでそれらの影響を受けずに点数を評価できます。

標準化は集合の各データから平均を引き、標準偏差で割ることで求めることが出来ます。

```math
z_i = \large{\frac{x_i- \mu}{\sigma}}
```

`μ`は平均、`σ`は標準偏差、`i`は任意な自然数を表します。

平均は集合の総和を個数で割ることで求められます。

```math
\mu = \frac{1}{n}\sum ^n_{i}x_i
```

標準偏差は分散を平方根で割ることで求められます。

```math
\sigma = \sqrt{s^2}
```

また分散は集合の各データから平均を引いたものを二乗和し、個数で割ることで求められます。

```math
s^2 = \dfrac 1n\sum ^n_{i}(x_i - \mu)^2
```

まずは機械学習ライブラリなどを利用せず、自分で実装してみたいと思います。
標準化を行う対象として、`iris`データセットを利用します。

```py
from sklearn.datasets import load_iris

iris = load_iris()
X = iris.data
print(X[:1]) # array([[5.1, 3.5, 1.4, 0.2]])

import math

def standardize(x):
    """
    Parameters
    ----------
    x: 標準化を行う配列、1次元のベクトルを期待.

    Returns
    -------
    mean: 平均
    var:  分散
    std:  標準偏差
    z:    標準化された配列
    """
    mean = None
    var = None
    std = None
    z = None

    # 平均を算出、集合の総和 / 特徴数
    mean = sum(x) / len(x)

    # 分散を算出、集合の平均 - 特徴の差を2乗和したものを個数で割る
    var = sum([(mean - x_i) ** 2 for x_i in x]) / len(x)

    # 分散を平方根で割る
    std = math.sqrt(var)

    # 各特徴から平均を引き、それを標準偏差で割る
    z = [x_i / std for x_i in [x_i - mean for x_i in x]]
    
    return [mean, var, std, z]

# データセットの1次元の先頭から7個のデータ
sample_data = X[:, :1][:7] 
print(sample_data.tolist()) # [[5.1], [4.9], [4.7], [4.6], [5.0], [5.4], [4.6]]

mean, var, std, z = standardize(sample_data)

print(mean) # [4.9]
print(var)  # [0.07428571]
print(std)  # 0.2725540575476989
print(*z)   # [0.73379939] [3.25872389e-15] [-0.73379939] [-1.10069908] [0.36689969] [1.83449846] [-1.10069908]
```

`sample_data`変数が加工され、浮動小数点に変換されていることが確認できます。

次に`sklearn.preprocessing.StandardScaler`を利用してみます。

```py
from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
scaler.fit(sample_data)

print(scaler.mean_) # [4.9]
print(scaler.var_)  # [0.07428571]
print(math.sqrt(scaler.var_)) # 0.2725540575476989
print(*scaler.transform(sample_data))  # [0.73379939] [3.25872389e-15] [-0.73379939] [-1.10069908] [0.36689969] [1.83449846] [-1.10069908]

# 値は同一
print(scaler.mean_ == mean) # [ True]
print(scaler.var_ == var)   # [ True]
print(math.sqrt(scaler.var_) == std) # True
print(*(scaler.transform(sample_data) == z)) # [ True] [ True] [ True] [ True] [ True] [ True] [ True] 
```

このように`StandardScaler`を利用することで少ない分量で標準化を実現できます。

また`mean_`、`var_`などの標準化の際に算出した値を保持しているため、機械学習モデルの学習時に`fit`しておけば、モデルの推論時に利用するデータ[^1]に対しても`processed_query = (np.array(query) - scaler.mean_) - np.sqrt(scaler.var_)`と出来るので、とても便利だと思います。

[^1]: モデル推論時に与えるベクトルが学習時に使用したデータセットの集合に属すると仮定した場合。
hostsを設定してもChromeで反映されない

# 状況

* DNSキャッシュの問題ではない
* `*.localhost`などのドメイン名を`127.0.0.1`以外に割り当てようとしている

# 原因

cf. https://stackoverflow.com/a/51801611
cf. https://webmasters.stackexchange.com/a/110737

どうも`localhost`を特殊なTLDとして一括ループバックにすれば良かろうという風潮であるらしい。VMに名前でアクセスしたい場合など困るのだが

事情はやや異なるが、予約されたドメイン名の`.test`や`.example`、またGoogle所有の`.app`や`.dev`も避けた方がいいとのこと。

# 対処

- `local.mydomain.com`など自分の管理下のサブドメインを用いる
- 他のブラウザを使う

cf. https://lubtech.geo.jp/2017-09-16/?p=3126
cf. https://support.apple.com/ja-jp/HT207511

`.local`はいろいろ問題があり、かと言って今後使われる可能性のあるドメインも困るので、自分のドメインを使うのが手っ取り早い。
emacs forge の操作メモ

[forge](https://github.com/magit/forge) は Github やそれに類似する Git サービスを Emacs 上で利用するためのプラグイン。使い方などは後々追記するとして、自分に必要なことを書き残していく。以下は 20191007.1416 のバージョンで確認。

# プルリクエスト


`M-x forge-create-pullreq` または `' c p` でプルリクエストの source ブランチと dest ブランチを選ぶ。すると new-pullreq バッファが表示される。これがプルリクエストの本文となる。

このとき冒頭に draft: true を与えると draft 状態のプルリクエストを作成できる。たとえば下のようにする。

```md
---
title: xxxxxxx
draft: true
---

pull request description ...
```

プルリクエストの本文は markdown なので `[ ]` とすればチェックボックスになる。チェックボックスの中にカーソルを移動させて return キーを押すと ON/OFF ができる。

プルリクエストの編集が終わったら `C-c C-c` でプルリクエストを Github に送信する。