OmniAICreator/Qiita-1.07M huggingface dataset:
REST APIってなに？

## 勉強前イメージ

webでjson形式で取れるAPIってイメージ

## 調査

### REST APIってなに？

REST API(RESTful APIともいう)は
Representational State Transfer の略で、Webサービスの設計モデルです。
RESTを使用したWebサービスは、そのサービスのURIにHTTPメソッドでアクセスすることでデータの送受信を行います。
APIを使用すれば、リソースがどのように取得されるのか、どこから取得されるかというのを気にしなくて良くなります。

### REST APIを作る条件

#### URLの例

- QiitaのAPIの例

```
https://qiita.com/api/v2/users/miyuki_samitani
```

こちらはQiitaのAPIになります。
`https://qiita.com/api/v2` が提供している `/users` の中のアカウントを見ることができます。

#### URLのバージョンを含める

URLにはバージョンを含めるようにするのが良いです。
下記のQiitaのAPIも
`v2` とバージョニングされています。

```
https://qiita.com/api/v2/users/miyuki_samitani
```

また、バージョンを含めるメリットとしては下記になります。

- 開発者としてはAPIのバージョンを選択しやすい
- 切り分けもしやすい

#### 作成/取得/更新/削除のメソッドを使用する

- 作成 : POST

リソースを作成する際に使用します。

- 取得 : GET

リソースを取得する際に使用します。
結果は何度行っても同様になります。

- 更新 : PUT

リソースを更新する際に使用します。
リソースが存在する場合はデータの置き換え(更新)を行いますが、
リソースが存在しない場合は登録を行います。

- 削除 : DELETE

リソースを削除する際に使用します。

- まとめ

| 処理 | メソッド |
|:-:|:-:|
| 作成  | POST  |
| 取得  | GET  |
| 更新  | PUT  |
| 削除  | DELETE  |

## 勉強後イメージ

なんとなくイメージどおりだった。
ただ、いろいろ開発元によってメソッドって作れると思ってた。
調べるだけじゃ結局よくわからないので、次はREST API触ってみたい。

## 参考

- [REST APIとは？ – API設計のポイント！](https://wp.tech-style.info/archives/683)
- [REST API とは](https://www.redhat.com/ja/topics/api/what-is-a-rest-api)
- [REST入門 基礎知識](https://qiita.com/TakahiRoyte/items/949f4e88caecb02119aa)
- [RESTful APIとは？](https://blog.api.rakuten.net/ja/jp-restful-api/)
- [REST (API)が理解できないのでまとめてみる](https://www.subthread.co.jp/blog/20160506/)
【PHP】配列Aの並び順を正として、配列Bを並び替える

# 本記事の趣旨
PHPの配列について、備忘のためメモします。
誰かの何かの役に立てれば幸いです。

# 要件
配列A（以下”見本”）の要素の並び順を正として、配列B（以下”要並び替え”）の要素を並び替える。

ただし、
要並び替え配列の中身そのものを並び替えるのではなく、
要並び替え配列の各要素が見本配列に存在するか、をチェックしたうえで、
存在していたら、その要素は見本配列内では何番目にあるのか、という情報を取得し、
その情報をもとに、別な配列に要素を入れ直す。

**単純な配列の場合**

```
$mihon = ["りんご", "みかん", ”バナナ”]; // 見本

$temoto = ["バナナ”, "りんご", "みかん"]; // 要並び替え

$checked_array = []; // 並び替え後に格納する用の配列

foreach($mihon as $key => $fruit){
   // 見本配列をループしつつ、要並び替え配列の$key番目の要素が、見本配列内に存在するかチェック
   if(in_array($temoto[$key], $mihon)){
       $index = array_search($fruit, $mihon); // 見本配列の要素の添字情報を変数に代入
       $checked_array[$index] = $fruit; // 並び替え（というか別な配列に詰め直し）
   }
}

var_dump($checked_array); // 見本配列と同じ順番になっている
// array(3) {
  [0]=>
  string(9) "りんご"
  [1]=>
  string(9) "みかん"
  [2]=>
  string(9) "バナナ"
}


```
「foreachでは$key => $valueはワンセット」というのを強く意識しないと混乱します。
もっと良いやり方があるような気もしますが、現状思いつきません。

**多次元配列の場合**

追って記載
Dynamic DO!.jpで無料ドメインを取得しよう

# はじめに
　どうもこんにちは、連休＋ちょっと課題少なめ（？？？？）な時期なので、記事を書きたくなりました。今回は、無料ドメインを取得する方法をまとめていきたいと思います。簡単と思う人はたくさんいると思いますが、なんか引っかかったのでまとめます。
　自分でWEBサーバーを作ったけど、ドメイン持ってない。。。とか、サーバーレンタルしているけど、ドメインを変更したいなぁとか思っている人向けです。やることとしては、

1.Dynamic DO!.jp でドメイン取得
2.取得したドメインへのIPアドレスの登録

# 必要なもの
* 現在運用しているサーバーのグローバルIPアドレス
* ドメイン管理用のメールアドレス

# 1.Dynamic DO.jpで無料ドメインを取得する
ここでは、”ドメインの取得”のみを行います。この作業のみではIPアドレスとは紐づかないので注意してください。
まず、[Dynamic DO!.jp](http://ddo.jp/)へアクセスし、下のほうの”ddo.jp サブドメイン DDNS無料登録”に、ドメイン管理用にしても良いメールアドレスを入力してください。そして無料登録ボタンを押します。
![図1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/de69fe44-8f3b-bef2-147c-7c47575c0a51.png)
すると、↓のように、パスワードとか設定しますので、入力して登録内容確認ボタンを押してください。
![図2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/4ce14522-a1a4-1bec-5ea4-00e208311115.png)
進めていくと、入力したメールアドレスにこんなメールが届きます。登録確認のメールなので、確認用URLを押すと、
![図3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/44501ae0-755c-4c18-409b-157302c021e8.png)
こんな感じで、登録が完了していることが分かります。以上でドメイン取得が完了しました！
![図4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/0ee16f98-5be9-ac2f-643a-e0e9c33b7482.png)
# 2.取得したドメインへのIPアドレスの登録
　1.で”ドメイン”を取得しました！しかし、IPアドレスが設定されていません。空っぽですね。なので、運用しているサーバーのグローバルIPアドレスを紐づけしてあげましょう！
同じく、[Dynamic DO!.jp](http://ddo.jp/)へアクセスして、上のほうの”無料サービスのIP更新”をクリックします。
![図5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/4fa4b71d-675d-7c5d-ba0c-67cd089bb07a.png)
するとフォームが無料登録者向けのものになるので、先ほど取得したドメイン名と、紐づけしたいグローバルIPアドレス、ドメイン取得時に設定したパスワードを入力して、”IPアドレス更新”ボタンを押します。
![図6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/ba0f857e-ebfe-f23a-3856-523c2569281a.png)
すると、こんな感じでグローバルIPの登録が完了しました！
![図7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/554112/079f9268-047d-fddb-e916-e14879c4bb6f.png)

# おわりに
　最近、自分でサーバーを構築する事にチャレンジしています。基本の原理的なことはわかっているのですが、それを実現するための操作は結構つまずきますねｗ
ちなみに私は、1.の操作だけでグローバルIPとドメインの紐づけが完了したと思い込んで、（かつ、IPアドレスの反映には時間がかかるとの記事を見かけた）ので、結構躓いていました。
記事の順番的には、「自宅のPCをサーバー化する」が先に来るといいんでしょうが、忘れないうちに書きたかったので、勢いで書いてます。
　Webサイト構築するって楽しい！それでは。
深層学習 Day 3 - Section 7 Attention Mechanism のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 3

Section 1 再帰型ニューラルネットワークの概念
Section 2 LSTM
Section 3 GRU
Section 4 双方向RNN
Section 5 Seq2Seq
Section 6 Word2vec
**Section 7 Attention Mechanism**　←　これ

# 講義

## Attention Mechanism

seq2seqの課題
単語の数がいくつであれ、固定次元ベクトルに入れる必要がある。
文章が長くなるほどシーケンスの内部表現の次元が大きくなる。

解決策
Attention Mechanism
「入力と出力のどの単語が関連しているのか」の
関連度を学習する。


## 具体例

「私」「は」「ペン」「を」「持って」「いる」
「I」「have」「a」「pen」

「a」の関連度は低い。
「I」は「私」との関連度が高い。



# 実装演習

なし。

# 確認テスト

### seq2seqとseq2seq＋Attention Mechanismの違い

Attention Mechanismは入力と出力の単語の関連度で判断する。

模範解答
seq2seqは固定次元ベクトルの学習
Attention Mechanismは重要度、関連度の概念あり。長い文章での翻訳が成り立つ。


# 修了テスト～練習問題～

Attention Mechanismの問題は無い。
代わりに赤本２でお勉強。

### Attention Mechanism

注意機構（Attention Mechanism）

Encoder内の各時刻の隠れ状態をすべてDecoderに引き継ぐ。
Decoderはその隠れ状態の末尾をinitial stateとして使う。
残り隠れ状態はDecoder内で重みを計算して確率として出力する。
確率の高い値は出力されやすい。
深層学習 Day 3 - Section 6 Word2vec のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 3

Section 1 再帰型ニューラルネットワークの概念
Section 2 LSTM
Section 3 GRU
Section 4 双方向RNN
Section 5 Seq2Seq
**Section 6 Word2vec**　←　これ
Section 7 Attention Mechanism

# 講義

RNNの課題
可変長の文字列をNNに与えられない。（固定長のみ可能）

## word2vecの処理

単語のボキャブラリを作成する。（単語の重複なし）

I want to eat apples. I like apples.
 ⇒ {apples, eat, I, like, to, want}

one-hotベクトルにする。
「apples」が入力の場合。
1...apples
0...eat
0...I
0...like
0...to
0...want

## word2vecのメリット

大規模データの分散表現の学習を
現実激な計算速度とメモリ量で実現できる。

以前の方法：ボキャブラリ数 × ボキャブラリ数
word2vec：ボキャブラリ数 × 単語ベクトル

重みの数を減らせるようになった。

## 演習チャレンジ

```python
def traverse(node):
  if not isinstance(node, dict):
    v = node
  else:
    left = traverse(node['left'])
    right = traverse(node['right'])
    v = _activation(W.dot(np.concatenate([left, right]))
  return v
```

np.concatenate関数：ndarrayを結合する
　　　　　　　　　　　上のソースでは1次元ベクトル同士を連結しているので結合の方向は気にしなくていい。

これは選択肢を見れば正解はわかる。
W の形状が (embed_size, 2*embed_size) であることからも明らか。

# 実装演習

なし。


# 確認テスト

### RNNとword2vecの違い

word2vecは単語をone-hotベクトルで計算する。

模範解答
word2vecは重みの計算が現実的な計算速度で可能。
少ないリソース消費量。

RNNはボキャブラリ数 × ボキャブラリ数の重み
word2vecはボキャブラリ数 × 単語ベクトルの重み


# 修了テスト～練習問題～

修了テスト内にword2vecの問題は無い。
代わりに赤本２でお勉強。

- 入力層は扱う単語の数だけ、中間層を経て、出力層へ
- それぞれが全結合層
- 入力層に与える単語はone-hot表現
- 入力層から中間層への重みは分散表現を表す行列、学習によって更新される
- 出力層によって出力されるのはスコア
- スコアをSoftmax関数で確率に変換
- 複数の単語を入力として与えると、確率として推測結果が出力される

例：「you」と「goodbye」から推測される単語の中で最も確率が高いのは「say」
深層学習 Day 3 - Section 5 Seq2Seq のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 3

Section 1 再帰型ニューラルネットワークの概念
Section 2 LSTM
Section 3 GRU
Section 4 双方向RNN
**Section 5 Seq2Seq**　←　これ
Section 6 Word2vec
Section 7 Attention Mechanism

# 講義

## Seq2seq

Encoder-Decoderモデルの一種。

用途
・機械対話
・機械翻訳

### Encoder RNN

1. テキストデータをトークンに区切る。（「食べた」「刺身」「大丈夫」「でしたか」）
2. トークンを入力としてRNNに与えて重みを掛けて次々と渡していく。


Taking     ：文章をトークン分割し、トークンごとのIDに分割
Embedding  ：IDから、そのトークンを表す分散ベクトルに変換
Encoder RNN：ベクトルを順番にRNNに入力

Encoder RNNは主にRNNとして処理するが、普通のRNNと違う点
・データは出力しない。
・隠れ状態(hidden state)の最後の隠れ状態(final state)を出力する。
　through vectorとも。
　このfinal stateに、入力した文章の意味が詰まっているということか。

### Decoder RNN

デコード時の処理（学習時の処理ではない。事前に学習しておく）

1. Encoder RNNのfinal stateをDecoder RNNのinitial stateにする。  
次に出力される候補の単語ごとに確率が出力される。  
（出力される可能性の高い単語は、確率が高い）
2. Sampling：生成確率に基づいてトークンをランダムに選ぶ。
3. Embedding：2で選ばれたトークンをEmbeddingしてDecoder RNNの次の入力にする。
4. Detokenize：1～3を繰り返し、2で得られたトークンを文字列に直す。

Decoder RNNの入力：Encoder RNNによって出力されるfinal state
Decoder RNNの出力：予測された文章

### 演習チャレンジ

```python
def encode(words, E, W, U, b):
  hidden_size = W.shape[0]
  h = np.zeros(hidden_size)
  for w in words:
    e = E.dot(w)
    h = _activation(W.dot(e) + U.dot(h) + b)
  return h
```

h：hidden state
　　return 時の h は final state
vocab_size：語彙数、文字の種類

行列の形状を元に正解を導いた。
b の形状 (h,)
W.dot(e) の形状は b の形状と同じ (h,)
W の形状は (h,h) であることから、e の形状は (h,)
E の形状は (h,v)、また、w の形状は (v,) であることから、
これらを掛けた e (h,) の形状になるには
E.dot(w) しかない。

メモ
一次元のベクトルは、(h,) のように表現する。

ただし、これはソースコード内のコメントを頼ったためであり、正攻法ではない。
本来なら解説にあるように本来行いたい処理を考慮して正解を導く必要がある。

解説
単語 w は one-hot ベクトルであり、それを単語埋め込みにより別の特徴量に変換する。
これは埋め込み行列 E を用いて、E.dot(w) と書ける。

w が one-hot ベクトルのとき、E.dot(w) を計算すると、E の特定の列だけを抜き出せる。


## HRED

Seq2seqの課題
一問一答しかできない。
人間っぽさが出せない。

### HREDとは

Hierarchical Recurrent Encoder-Decoder
過去のn-1の発話から次の発話を生成。

システム：インコかわいいよね
ユーザー：うん
システム：インコかわいいのわかる

Seq2seq + Context RNN

Context RNN:
Encoderのまとめた各文章の系列をまとめて、
これまでの会話コンテキスト全体を表すベクトルに
変換する構造

### HREDの課題

・会話の流れがない。
・短いよくある答えを選びやすい。

## VHRED

Latent Variable Hierarchical. Recurrent Encoder-Decoder
HREDの課題を解決
HREDに、VAEの潜在変数の概念を追加

正直なところ、講義だけでは全く理解できない。
こちらのページを参照、ということか。

DeepLearning における会話モデル： Seq2Seq から VHRED まで
https\://qiita.com/halhorn/items/646d323ac457715866d4

## VAE


### オートエンコーダ

- 教師なし学習
- 例：画像を読み込むと同じような画像を出力する
- 次元削減できる（無意味な特徴量が削除される）
- Encoder によって潜在変数 z が作成される
- Decoder は潜在変数 z を参照する

### VAE

Variational Autoencoder、変分自己符号化器
読み方は、バエ？

潜在変数 z に確率分布 z～N(0,1) を仮定したもの。
これにより、文脈に応じて確率的に応答ができるようになる。

# 実装演習

なし。


# 確認テスト

### Seq2seqの説明

(1)は双方向RNNの説明
(2)はSeq2seqの説明
(3)未学習
(4)LSTMやGRU


### Seq2seq,HRED,VHREDの違い

Seq2seq：一問一答ができる。
HRED：文脈を理解して会話できる。同じ回答。
VHRED：HREDに加えて、異なる回答ができる。


### VAEの説明

自己符号化器（オートエンコーダ）の潜在変数に
確率分布を導入したもの。

# 修了テスト～練習問題～

Seq2seqの問題は無い。
代わりにone-hotベクトルを含めた行列の計算を復習。

one-hotベクトルを使った行列の掛け算
one-hotベクトルを c 、重み行列を W とすると

・c.dot(W) は、W の特定の行を抜き出すという意味
・W.dot(c) は、W の特定の列を抜き出すという意味

1次元ベクトルは掛ける側（右から掛ける、左から掛ける）によって、
行ベクトルであったり列ベクトルであったりと変換するのか。
深層学習 Day 3 - Section 4 双方向RNN のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 3

Section 1 再帰型ニューラルネットワークの概念
Section 2 LSTM
Section 3 GRU
**Section 4 双方向RNN**　←　これ
Section 5 Seq2Seq
Section 6 Word2vec
Section 7 Attention Mechanism

# 講義

## 双方向RNN

過去の情報だけでなく、未来の情報を加味することで
精度を向上。

例
・文章の推敲
・機械翻訳

## 演習チャレンジ

```python
def bidirectional_rnn_net(xs, W_f, U_f, W_b, U_b, V):
  xs_f = np.zeros_like(xs)
  xs_b = np.zeros_like(xs)
  for i, x in enumerate(xs):
    xs_f[i] = x
    xs_b[i] = x[::-1]
  hs_f = _rnn(xs_f, W_f, U_f)
  hs_b = _rnn(xs_b, W_b, U_b)
  hs = [np.concatenate([h_f, h_b], axis=1) for h_f, h_b in zip(hs_f, hs_b)]
  ys = hs.dot(V.T)
  return ys
```

変数名について。
f は forward（順方向）であり、b は backward（逆方向）の頭文字か。

順方向で求めた隠れ状態と、逆方向で求めた隠れ状態を右方向(axis=1)に連結し、
その値を隠れ状態とする。

# 実装演習

なし

# 確認テスト

なし

# 修了テスト～練習問題～

修了テスト内に双方向RNNに関する問題なし。
代わりに赤本2で勉強。

双方向RNNは、周囲の情報をバランスよく含ませる仕組みのこと。
順方向と逆方向のそれぞれで学習して、それぞれの隠れ状態を求め、
これらの隠れ状態を連結することで最終的な隠れ状態とする。
連結以外にも、和や平均がありうる。
深層学習 Day 3 - Section 3 GRU のまとめ

この記事は個人的なお勉強用のメモです。

# このお勉強の位置

深層学習 Day 3

Section 1 再帰型ニューラルネットワークの概念
Section 2 LSTM
**Section 3 GRU**　←　これ
Section 4 双方向RNN
Section 5 Seq2Seq
Section 6 Word2vec
Section 7 Attention Mechanism

# 講義

## LSTMの課題

LSTMはパラメータ数が多く、計算負荷が高い。
⇒ GRUで解決

## GRUとは

Gated Recurrent Unit
LSTMに比べてパラメータが少なく、計算負荷が低い。
精度は同等またはそれ以上。

## 演習チャレンジ（GRU）

```python
def gru(x, h, W_r, U_r, W_z, U_z, W, U):
  r = _sigmoid(x.dot(W_r.T) + h.dot(U_r.T)
  z = _sigmoid(x.dot(W_z.T) + h.dot(U_z.T)
  h_bar = np.tanh(x.dot(W.T) + (r * h).dot(U.t))
  h_new = (1 - z) * h + z * h_bar
  return h_new
```

赤本2の C.2 節にある図を見ながら答えを書いたら正解だった。

## GRUの構造

- 隠れ状態 h あり、記憶セル c なし
- resestゲート：過去の隠れ状態 h を無視する割合
- updateゲート：隠れ状態 h を更新する割合  
 - LSTMのforgetゲートとしての動作は、(1-z) * zの部分。
 - LSTMのinuputゲートとしての動作は、z * h_bar の部分。
 - z が大きいと、inputゲート側に傾いて動作する。
 - z が小さいと、forgetゲート側に傾いて動作する。
- 隠れ状態が更新されるとき、過去の隠れ状態を 2 つの方面から参照する  
  - h_bar の作成と参照
  - 新しい隠れ状態の作成のために直接参照


# 実装演習

なし。


# 確認テスト

### LSTMとCECが抱える課題

LSTMの課題：
パラメータ数が多く、計算負荷が高い。

CECの課題：
重みが一律になってしまい、NNの学習特性が無い。


### LSTMとGRUの違い

LSTMはパラメータ数が多く計算負荷が高い。
GRUはパラメータ数が少なく計算負荷が低い。


# 修了テスト～練習問題～

### 問題18（GRUとLSTM）

- GRUとLSTMはゲートを使用する。ゲートによって防ぐのは勾配爆発ではなく勾配消失である。
- どちらが性能がいいとは言えない。使い分ける。
- GRUに記憶セルはない。LSTMには記憶セルがある。
- LSTMには3つのゲート(input,forget,output)が、GRUには2つのゲート(reset,update)がある。

### 問題19、問題20、問題21（GRU）

※ 図 1 内の r の左付近の矢印の向きが逆になっている。


```python
def GRU:
  def __init__(self, input_size=input_size, hidden_size=hidden_size):
    self.w_z, self_w_r, self.w_c = \
      np.random.randn(input_size + hidden_size, hidden_size) for i in range(3)
    self.b_z, self.b_r, self.b_c = \
      (np.random.randn(hidden_size) for i in range(3)

  def forward(self, x, h_prev):
    inputs = np.concaterate([x, h_prev], axis=0)
    z = sigmoid(np.matmul(inputs, self.w_z) + self.b_z)
    r = sigmoid(np.matmul(inputs, self.w_r) + self.b_r)
    _c = np.concatenate([h_prev * r, x], axis=0)
    c = np.tanh(np.matmul(_c, self.w_c) + self.b_c)
    h_next = (z * c) + ((1 - z) * h_prev)
    return h_next
```

np.random.randn関数：標準正規分布の乱数を返す。引数にはサイズを指定する。

#### 問題19

第一引数を、重みに掛ける入力と考える。
第二引数を、次の計算時の重みに掛ける入力と考える。
図 1 によると、x (input) と h (hidden) を入力にしている。
また、図 1 によると、r を求めた後の次の計算対象は h (hidden) である。

#### 問題20

h_prevの列数：hidden_size
x の列数：input_size
\_c の列数 ＝ h_prev と x を axis=1 で連結した列数：input_size + hidden_size

また、self.w_c の行数が input_size + hidden_size であることからも明らか。

#### 問題21

1 - z は隠れ状態 h に影響する。
z は入力 x から tanh で得られた値 c (変数名は h_bar とも) に影響する。
新しくなった基本情報技術者試験についてメモ（2020/12/10）

#メモ
基本情報技術者試験はPBT（紙ベース）からCBT（コンピュータベース）へ形式移行

申し込み手続きとしては、午前試験と午後試験をプロメトリックのサイトにて予約する

「午前試験」と「午後試験」の内容は基本的にはそのままでただの名称として扱うらしい
「午前試験」と「午後試験」は別日でもよい、順番はどちらが先でもよい、「午前試験」を午後に受けてもよい（もちろんその逆も）
受験時間が150分と長いので、それぞれの試験時間が被らないように注意

1月から3月分については今年10月に受けられなかった人が優先的に予約できる（今日まで知らなったよ俺は、、）

#今日の名言

恋人は裏切るが、資格は裏切らない。

-前やっていたなんかのCM
リモート会議中であることを電子ペーパーで伝えるラズパイの作成

#みなさん在宅勤務楽しんでますか？

###はじめに

一気に普及した在宅勤務。始業時間ギリギリに起きてもOK、通勤時間なし、タスクに集中できるといいことばかりです。

が、日本の住宅事情からは、リモート会議中に子どもが乱入して会議に出席してしまったり、マイクが喧嘩の声を拾ってしまったり、なかなか悩み深いですね。我が家でもルーター近くのコンセントで掃除機を使うと、通信品質が悪化するという症状を抱えています。

最初は「会議中だから静かにして！」と言っていたものの、「ここは生活する場所で仕事をする場所ではない」と言われ喧嘩になってしまいます。お互いの平和を望むなら、互いに配慮できる仕組みがあるといいですね。

ということで、解決策としてラズパイの登場です。 

###こんなのが欲しい

1. それとなく会議中を伝えられる
2. 会議中であることが一目見ただけでわかる

###こんなのができました

仕事部屋のドアに ↓ の電子ペーパー付きラズパイゼロを張り付けました。

|  MTG前  |  MTG中  |
|----|----|
|  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/925749/e7a9ecf6-96d9-a634-9471-c943083aa835.png)  |  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/925749/5348f3d1-79dd-b0d4-059b-9dc18b1e7e48.png)  |

###なにを使ったか

1. Raspberry Pi ZERO WH
2. 電子ペーパー  https://www.sengoku.co.jp/mod/sgk_cart/detail.php?code=EEHD-58WK
3. その他ラズパイを動かすのに必要なmicroSD、USBケーブル、USB電源等

###どうやって動かしているか

サンプルコードは ↓ を参考にしてください。
https://github.com/sat128/showing_mtg_shcedule

電子ペーパーのメーカーであるWaveshareがサンプルコードを公開しています。Pythonのサンプルコードと同じ階層に上記コードを保存して実行すると、MTGのスケジュールが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/925749/bbc9ebaa-9cf4-075e-07d8-6714eb031e92.png)


###ラズパイ＋電子ペーパーのセットアップについて

こちらの記事では、セットアップの詳細は省略しますが、先人たちがさまざまな素晴らしい知見を共有してくれていますので、参考にしてください。

>電子ペーパーモジュール入門
>https://qiita.com/ryosukeeeee/items/0416257387e4fa810edd



###番外編：スケジュール設定めんどくさいよね。

毎日毎日直接コードをいじって、スケジュールを設定するのは面倒なので、これを省力化したいと思います。

上記Gitのコードでは、ラズパイがファイルサーバとして動いていることを前提に、PCからスケジューラ（今回の例は`.ics`ファイル）をラズパイに保存するだけで、勝手にスケジュールを反映してくれるようにしています。`get_schedule_list()`という関数です。

夜翌日のスケジューラファイルを保存したら、あとはcronを使って、翌朝上記Pythonサンプルコードを実行し、営業時間終了になったらプロセスを`kill`するだけです。ラクチン！！

```bash
kill -9 $(ps -ax | grep "show_mtg_schedule.py" | awk '{ print $1 }')
```
Cognitive Services のエンドポイントへのアクセス制限 ~ ファイアウォール機能を試す

Cognitive Services の各サービスを Web API として利用するためにはサブスクリプションキーが必要、とは言っても、自分が所有しているエンドポイント(Web API リクエスト先 URL) に誰からでもアクセスされるのは気になります。
一番単純な方法として、Cognitive Services のエンドポイントにファイアウォールを設定し、Azure Virtual Network で設定する IP アドレス、または Private Endpoint 接続 (Azure の他のサービスとの接続) のみからのアクセスに制限することが可能です。

今回はこのファイアウォール機能を有効にして、ひとまず指定する IP アドレスのみアクセス可能にする手順を紹介します。
※ Face API を例としていますが、他の Cognitive Services のサービスでも手順は同じです。

# Azure Portal からネットワーク設定

利用している Cognitive Services のサービスを Azure Portal で表示します。
左バナーから [ネットワーク] を選択します。

**Firewall and virtual networks** タブの内容を編集していきます。
 - **許可するアクセス先** : **選択したネットワークとプライベートエンドポイント** を選択します。
 - **ファイアウォール** : 現在アクセスしているデバイスのグローバルアドレスが表示されますので、**クライアントIPアドレス** に ☑ (チェック) をつけます。

**[Save]** をクリックして設定内容を保存します。

![20201210_CognitiveServices_Firewall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117583/1ca2c445-93c4-e9f2-2e47-8866836e7c00.png)


# 指定した IP アドレスからアクセス

それでは、Face API へのアクセス制限を設定した PC から (＝設定した IP アドレスを使って)、Face API に HTTP リクエスト を送信してみます。

[送信画像](https://cdn.pixabay.com/photo/2016/10/06/18/22/couple-1719679__340.jpg)
↓
![20201210_CognitiveServices_RegisteredIP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117583/6f96a82f-89ac-dda2-844d-6c3814d308d8.png)

これまで通り顔が検出されています。

# 指定外の IP アドレスからアクセス

今度は IP アドレスを変更して(Wifi再起動など)、同様に HTTP リクエストを送信します。
Access Denied (403) が戻ることが分かります。Virtual Network/Firewall のため、と理由が書かれていますね。(現在の自分の IP アドレスまで記載してくれていますね)

![20201210_CognitiveServices_OtherIP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117583/e9bab295-f4aa-5ce5-6222-5b19206846f5.png)


# ドキュメント

[Microsoft Docs > Azure Cognitive Services 仮想ネットワークを構成する](https://docs.microsoft.com/ja-jp/azure/cognitive-services/cognitive-services-virtual-networks?tabs=portal)
ポートとポート番号とは何？【初心者でもわかりやすいようにまとめてみた！】

こんにちは、うったむです。今日はポートについてまとめてみました。Webエンジニアを目指している人には必須のことなので理解しておきましょう！

![ポート.pages.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/437473/6ef2f631-cf52-c1b1-646b-46a767eaf49d.jpeg)


##ポートとは何？

ポートは__受付窓口__、もしくは__ドア（扉）__、__ビルの一つ一つの部屋__と例えられることがあります。

病院にはいくつかの科があって、いろいろな症状に合わせて治療を受ける場所が異なります。

同じように、Webサーバーにも機能に応じて異なるポートが用意されています。「〜をする時にはこの受付窓口」という具合にポートが設定されています。通信に関して受け渡しの作業をしてくれます。

##機能とポート番号が決まっている

インターネットは「__IPアドレス＋ポート番号__」で通信を行っています。さらに「よく使う機能」にはすでにポート番号が決まっています。以下のように、用途別でポートがあります。

* HTTP 80
* HTTPS 443
* SSH 22
* FTP（ファイルを送受信する） 20,21
* telnet（ほかのコンピュータを遠隔操作する） 23

クライアントがPCとかスマホでURLなどを使って、何かに接続したいとします。URLもしくはIPアドレスとポート番号から、サーバーに対して「何をしたいのか」リクエストします。

サーバーに「〜ということをしたいので処理して」とポートを選んで指示します。サーバーも役割毎に「〜は受け付けるけど、〜は受け付けない」という感じにポートを用意したり、閉じたりします。

##ポートの開放とは

大抵の場合、サーバーはどのポートを開くか、制限をかけています。

例えば、80と443、つまりHTTPとHTTPSのみ開くといった具合です。この二つだけ開放している状態を「ポートの開放」と言います。開いていないポートに対してリクエストをしても、何もできません。

サーバーの場合は、使わないポートを開くとセキュリティのリスクがあります。例えば、SSHの機能がないのに、開いておくとハッキングされる危険あります。最悪、サーバーを乗っ取られることも...

どのポートを開いているのか、使っていないポートを開いていないか確認すべきですね。

##ポートを自由に割り当てられる

よく使う機能に関してはポート番号が決まっていますが、自由にポートを割り当てることもできます。しかし注意も必要です。自由にポートを割り当てると「ポートの競合」という問題が起きる可能性あり。

一つのポートに二つの機能を割り当てると、一つの機能が動かなくなることも。機能が十分に使えないこともあるので「一つのポートに一つの機能」といった風に制限すると良いですね。

##まとめ

__ポート__とは、ネットワークにおいて「データを通信するための部屋」ということがわかりましたね。__ポート番号__は「その部屋の番号」みたいなものです。

プログラムの種類や機能によって、使うポートが異なります。通信には「__IPアドレス＋ポート番号__」が必要だということがわかりましたね。
地図が移動した時のイベントで任意の移動メソッドによる移動を識別する

MapBox GL JS で、地図をスクロールさせたり拡大縮小させると、``moveend`` イベントにより移動が完了したことが通知されます。

![cap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8227/b25875a4-a144-08cb-5feb-f97464fb6200.gif)

```javascript
const map = new mapboxgl.Map({
  container: 'map',
  center: [139.8108103, 35.7100069],
  zoom: 12,
  fitBoundsOptions: { padding: { bottom: 150, top: 150, right: 150, left: 150 } },
  style: {
    version: 8,
    sources: {
      OSM: {
        type: "raster",
        tiles: [ "https://a.tile.openstreetmap.org/{z}/{x}/{y}.png" ],
        tileSize: 256,
        attribution: "OpenStreetMap",
      },
    },
    layers: [
      {
        id: "BASEMAP",
        type: "raster",
        source: "OSM",
      },
    ],
  },      
});

map.on('load', e => {
  console.log('load', map.getBounds().toArray());
});

map.on('moveend', e => {
  console.log('moveend', map.getBounds().toArray());
  console.log('moveBy', e.moveBy);
});

document.getElementById('jump').addEventListener('click', () => {
  
  const eventData = { 
    moveBy: 'flyTo',
  };

  map.flyTo({ 
    center: [138.679699, 35.3578708],
    essential: true,
  }, eventData);

});
```

``moveend`` イベントは初回の地図表示時には通知されないようです(``load`` イベントを使うとよいでしょう)。
マウスジェスチャでも、``flyTo`` や ``fitBounds`` などの移動系メソッドを呼び出しても、``moveend`` イベントは発生します。
移動系メソッドでは、最終引数に任意の ``key: value`` を設定しておくと、移動の完了時に、``moveend`` イベントの引数から呼び出し時に設定した ``key: value`` を取り出せます。
これにより、マウスジェスチャーでの移動と識別することができ、アプリ内の特別な位置変更として取り扱うことができます。
また、``flyTo`` を同じパラメータで2度呼ぶなど、位置が変わらない場合でも ``moveend`` イベントは発生するようです。

## 完全なコード

- [MoveEnd event and EventData - JSFiddle - Code Playground](https://jsfiddle.net/amay077/Lkqynr03/)

## 参考

- [Fly to a location | Mapbox GL JS | Mapbox](https://docs.mapbox.com/mapbox-gl-js/example/flyto/)
NuxtでSSRやっててプロダクションビルドでだけ画面初期表示時に一瞬ページコンポーネントのCSSがあたっていなくても泣かないために

## まず結論
[vue-style-loader](https://github.com/vuejs/vue-style-loader) はSFC（拡張子 .vue） ファイルの`<style />`タグしか、SSRレンダリングしてくれない。
だもんで多分、Nuxtに限った話でなく、VueでSSRしたい時にぶつかる問題。
てっとり早く解決したければSFCでstyleタグに書くべし。

## 事の経緯
最近、Nuxtのページコンポーネントもjsx（tsx）で書くようになった。
だもんで、ページ毎のスタイルは全部ページコンポーネントの冒頭で、

```ts

import './hoge.scss';
```
みたいなやりくちで読み込む事にしていた。
ローカル開発中はまったくこれで問題なかった。
だけど、どういう事でしょう。本番ビルドでNuxtがレンダリングするhtmlにはどこにもこのstyleの記述が見当たらない。

## こういう事らしい
[manualInject オプション](https://github.com/vuejs/vue-style-loader#options)

> 斜め翻訳 by わたし
非vueファイルからスタイルを読み込む時は、単純にjsのバンドルにスタイルが埋め込まれるだけだから、手動でssrコンテキストにぶちこんでね。

ほうほうそういう事か。ばっちこい！、、と思って importしたstyleにきっと `__inject__` っていうメソッドがSSR側ではあるんだろうなぁ、と思ってやってみたものの、、ない。

```ts

import hoge from './hoge.scss';
console.log(hoge); // >>> {}
```

なんだこれ。

どうもこれ、流れとしては、
- Nuxtの内部のwebpackデフォ設定ではスタイルのimportは必ず `vue-style-loader` を通るようになっている
- `vue-style-loader` はデフォでは必ずjsバンドルにスタイルを埋め込んで終了する
- `__inject__` を自前で使いたければ `manualInject` オプション設定しなさい。

って事みたい。
で、Nuxt.jsのローダー設定オプションで `manualInject` をtrueで設定してみる。すると、、
まあ、もう、当たり前なんですけどページコンポーネント以外の全てのコンポーネントファイル内でimportしていたスタイルが全て撲滅で読み込まれない形となる。
で、、 `~/components` 配下のスタイルimportだけはmanualじゃなくてautoで読み込んでね、ってしたいけどそんなオプションはない。
プロジェクト自前で一個、「tsxファイル、かつvueコンポーネントみたいなものをexportしているファイルでスタイルをロードしようとしていたら、beforeCreateに強制的にスタイルインジェクトをさせる」webpackのローダーを書くべきか悩んで、
「それって、そのts(x)ファイルが本当にvueコンポーネントファイルなのかどうかって、怪しいよな」と思って、今時点では素直にSFCで書いて、SFCからexportして他ファイルで参照したい情報はSFCの外部に書いてシェアする事にした。
これ機会は少ないけどもろに発生するのが「親ページコンポーネントの何かを子ページにinjectするパターン」

```parent.tsx
import Vue from 'vue';
import { Component } from 'nuxt-property-decorator';

interafce SomeParentInfo {
  hoge: string;
  fuga?: number;
}

@Component<ParentView>({
  provide() {
    const { info } = this;
    return {
      parentInfo: info,
    }
  },
  render() {
    return (
      <div>
        ...親コンテンツ
      </div>
    );
  },
})
export default class ParentView extends Vue {
  info: SomeParentInfo = { ... };
}
```

```child.tsx
import Vue from 'vue';
import { Component } from 'nuxt-property-decorator';
import { SomeParentInfo } from './parent.tsx';

@Component<ChildView>({
  inject: ['parentInfo'],
  render() {
    return (
      <div>
        {JSON.stringfy(this.parentInfo)}
        ...子コンテンツ
      </div>
    );
  },
})
export default class ChildView extends Vue {
  readonly parentInfo!: SomeParentInfo;
}
```

こういう時に `SomeParentInfo` がsfcの中でコーディングされていると、TypeScriptはそでその中身を抽出しようとするとvue → d.ts のコンバータを利用する以外手がなくなる。
ただもって、今時点で割とビルドパフォーマンスがヘビーなのもあってそのコンバーター用意するよりかは、
素直に `SomeParentInfo` を外だしして、親と子で双方そのインターフェースを参照する方が早いかなと思い、それで解決した。

## ちょっとうっすら思っている事
ページコンポーネントのtsxファイルの中で、

```ts

import '!hoge-loader[xxxxx]./hoge.scss';
```

みたいにして、いい感じにmanualInjectを渡したらページコンポーネント側でだけmanualInjectしたい、、ってのは解決しそうな気も少しする。
、、けど、ページ毎に個別にwebpackのloaderオプション書くのもそれはそれで大変だし、
「そのファイルvueコンポーネントですか？」は結局解決しない。（そもそもVue sfcはdefault export = vueコンポーネントって思想）なので、素直にSFC書く事にした。
【Vue2 →Vue3】Vue-Router&Vuex導入時の違いを比較する

Vue2のプロジェクトとVue3のプロジェクトをそれぞれ用意し、
Vue-RouterとVuexの初期状態にどのような記述の違いがあるのか比較します。

各プロジェクトは`vue create`時に`Manually select features `で
Vue-Router、Vuexを導入するものとします。

**`create`時にVue 3を選べるのは、Vue CLI 4.5以上となります。**

##package.json


**Vue３**では各バージョンが**４**になっています

####Vue2



```javascript:package.json
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0",
    "vuex": "^3.4.0"
  },
```
####Vue3
```javascript:package.json
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^3.0.0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
```

##main.js
####Vue2

```javascript:main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

Vue.config.productionTip = false

new Vue({
  router,
  store,
  render: h => h(App)
}).$mount('#app')
```

####Vue3

```javascript:main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'

createApp(App).use(store).use(router).mount('#app')
```

##router/index.js


####Vue2

```javascript:router/index.js
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'

Vue.use(VueRouter)

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  }
]

const router = new VueRouter({
  mode: 'history',
  base: process.env.BASE_URL,
  routes
})

export default router
```

####Vue3

```javascript:router/index.js
import { createRouter, createWebHistory } from 'vue-router'
import Home from '../views/Home.vue'

const routes = [
  {
    path: '/',
    name: 'Home',
    component: Home
  },
  {
    path: '/about',
    name: 'About',
    component: () => import('../views/About.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

export default router
```

##store/index.js

####Vue2

```javascript:store/index.js
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})

```

####Vue3

```javascript:store/index.js
import { createStore } from 'vuex'

export default createStore({
  state: {
  },
  mutations: {
  },
  actions: {
  },
  modules: {
  }
})
```

#まとめ
大きく変わっているのはVue2は`new`でインスタンスを作成しているのに対し、
Vue3ではメソッド（createRouter/createStore）を使っている点ですね。
対話できるQAになること

★この記事を読むのにかかる時間：約7分程度
★この記事の主な対象者：QAリードや折衝業務などに携わる方々

#1.はじめに
みなさまはじめまして。
今年もあっという間にアドベントカレンダーの時期ですね。

私は普段はゲームQAとして、
プロダクトとの折衝業務や障害・費用の削減などの推進を行っています。

今回は開発チームとの折衝業務や、いくつかのタイトルのQAを担当した経験から、
業務を行うにあたり必要だと感じた**『対話』**というスキルの重要さについて、
実際に体験したことを織り交ぜながらお話をしようと思います。
※あくまで私自身の解釈ですので、その点を留意してお読みください。

#2.対話とは？
普段もコミュニケーションを取りながら仕事や生活を行っていると思いますが、
そもそも「対話」とは、辞書ではどのような意味が定義されているでしょうか。

**対話：向かい合って話し合うこと。また、その話。**
このように記されているようです。[[goo辞書参考]](https://dictionary.goo.ne.jp/word/%E5%AF%BE%E8%A9%B1/)

辞書の意味にもある通り、話し合うこと　が対話です。
QA業務を行っていく際に開発チームと「**向かい合って話し合うこと**」は、
お互いの目的達成のために、とても重要な要素だと考えています。

・なぜ重要なのか？
・どういう点を意識してプロダクトとの対話へ取り組んでいるか
次項から、上記2点の項目に絞ってお話をしていきたいと思います。

#3.QAとして対話する
なぜ対話が重要なのか、その理由を私は以下のように考えています。

相手に向き合い、対話することで、
**「相手の置かれている立場や伝えたいことの意図などをより深く理解できる」**と考えており、
現在の状況など、より解像度高く相手のことを把握することで、
**事情を踏まえた最適な提案の選択肢を設けられる**ことなどが挙げられると考えます。
また、コミュニケーションをしっかり取り、相手を知ろうとするため、
**チームビルディング**の側面でもより大きな効果が出ると思います。

実際の体験に基づいた簡単な例をご紹介します。
※前職での経験談を簡単にアレンジさせていただいてます。
![アドベント会話用2020_001_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540789/e9510518-38c0-6090-5ac2-3c579447fafc.png)
![アドベント記事会話2020_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540789/14c3807d-26b9-b029-d0ee-57c8b9fab5fd.png)


どうでしょうか。
だいぶ脚色が入ってるように見えますが、割とホントにあった話です。

【例その1】の場合は、
全く向き合ってもらえておらず、相手の方は、一方的に伝えたいことだけ伝えておしまいでした。
（そもそもQAの意見は取り合ってもらえるような雰囲気ではなかった）
お互いどういう立場でどう考えているか、深く理解しようとしなかったことが、
上手く対話できていなかった原因ではないかと今では考えています。
ちなみに、割と一方通行なコミュニケーションが多かったため、検証工数は肥大化していく一方となっていました。

【例その2】の場合は、お互い対話する姿勢でのやり取りだったので、しっかり提案までできましたね。
こちらも実際にあった話を元にしていますが、
一番無駄も少なく、全体の雰囲気もよいプロダクトだったと記憶しています。

このように、実際にお互い向き合って対話しながら仕事をしていくことで、
チーム形成や工数の削減など、得られるメリットはとても大きいと考えています。

では、どういう部分に気をつけながら対話を進めていけばよいのでしょうか。

#4.対話のポイント
私が対話をするにあたり意識していることがこちら。
話す内容により、考える要素は増えていきますが、
最低限、以下の2点は考慮しながら対話を行っています。

**①相手を尊重すること（立場の違いを理解する）
②自分が最低限押さえておきたいポイント（妥協しない部分）をしっかり決めておくこと**

####**①相手を尊重すること**について
基本的に調整業務などの場合、相手の方は別の職掌や立場であることが多いです。
相手の考え方などは自分たちの立場とは全然違うこともあります。
決めつけることなく、しっかり相手の話を聞いて理解をしていくことが大事だと思います。
**わからないことは、調べたり空気を読みつつ聞いていくことも大事。**

たとえば、**開発チームの仕様書や実装の癖を理解しておくこと**など。
先ほどの対話例のAさんも「△△だけ見ればいいんじゃないの？」と言っていましたが、
実はこのチーム、**毎回仕様書から考慮漏れが多い傾向にあるチームだった**という可能性も。
そういう背景があり、確認観点が大幅に食い違っていた可能性も考えられます。
相手のことを理解していれば、その点を踏まえて対話をしやすいですね。

また、立場の違いを理解するという意味でも、
**チームの座組を把握しておく**ことはしておいた方がよいと思います。
（どういう組織構成なのか、相談してきた方はどんな立ち位置なのかなど）
先ほどの「相手と向き合えてない話」の例で出てきたAさんも、
実は強引に話を通さざるを得ないやむを得ない事情がなにかあった可能性も。
話を受けたQA側も上記のようにチーム側の背景を知っていれば、
もう少し何かお互い向き合えるアプローチができたかもしれません。



####**②自分が最低限押さえておきたいポイント（妥協しない部分）**について
相手と対話をすることで、お互いここは譲れるポイント、譲れないポイント　みたいな部分が出てくると思います。
QAとしての立場であれば、プロダクトと定めている最低限の品質の担保ができることが前提ではあるので、
お互いの意見の折衷案で、担保する対象や範囲などが曖昧になってしまうことのないよう、
しっかり押さえておきたいポイントを念頭に置いたうえで話を進める必要があります。
（本来守れるはずの品質まで話の流れの中で落とさないように気をつけたいですね。）

上で記載したようなポイントをおさえて、
相手の考えを尊重しつつ、関係性を構築していきながら、
お互いの意識を合わせたゴールへ向かって仕事を進めていけば、よい形で着地できると考えています。

#5.まとめ
いかがでしたでしょうか。
実際の業務では他にも色々と難しい要素も考慮しながら仕事を進めていく必要があるかと思いますが、
まず大前提として、**一緒に仕事をする相手も人間です。**
お互いの考える**「よりよい製品や品質」**を目指すためには、
**「リスペクトを忘れずに」**信頼関係をしっかりと構築していくことがまずは大事だと思っています。
そのためにも、**お互いを理解するための対話**はずっと続けていく必要があると考えています。
もし取り組んでいないことがありましたら、少し気にかけてみてはいかがでしょうか。

この記事が明日からの業務に少しでもお役に立てば幸いです。
テスト自動化の学習用の練習サイトHOTEL PLANISPHEREをForkしてGitHubPagesで動かせるようにした

この記事は[ベリサーブ Advent Calendar 2020 - Qiita](https://qiita.com/advent-calendar/2020/veriserve)の10日目です。

昨日は[vHidetoshiSuhara](https://qiita.com/vHidetoshiSuhara)さんの[VSCodeのPlantUMLプラグインでER図を書いてみた - Qiita](https://qiita.com/vHidetoshiSuhara/items/8fd0eb0a2c2ced0aea60)でした。

<hr>

HOTEL PLANISPHEREという素晴らしいサイトがあります。

[HOTEL PLANISPHERE - テスト自動化練習サイト](https://hotel.testplanisphere.dev/)

Seleniumなどのテスト自動化ツールをちょっと試してみたいな、勉強してみたいなというときに使えるありがたいサイトなのですが、ひたすらここにアクセスさせていただくのも悪いなぁという気持ちになったので、（インフラ的には結局一緒だと思うんですけれども）自分のGitHubPagesで動かしてみようと思いました。

結果がこちらです。

[HOTEL PLANISPHERE - テスト自動化練習サイトのコピー](https://yoshikiito.github.io/hotel-example-site/)

単純にForkするだけだと動かなかったので、そのへんの対応も含めています。

※暫定対応的なやり方なので、もし「まだここが動かないぞ」的なポイントがあったら教えてください。

## 手順

### 1. Forkする

[testplanisphere/hotel-example-site: Sandbox website for learning test automation (hotel reservation)](https://github.com/testplanisphere/hotel-example-site)からリポジトリをForkします。

![ScreenShot 2020-12-10 13.17.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/161982dd-7ea5-87e5-48b8-1b6b58d8f259.png)

どこで？って聞かれるので、自分のリポジトリを選択。

![ScreenShot 2020-12-10 13.17.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/6cf128f7-2353-37d0-ec92-e75ac47b4e8d.png)

Forkはこれだけです。

![ScreenShot 2020-12-10 13.17.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/82cfaeca-8d3e-6cb5-69c7-679f392a36aa.png)

### 2. 一部のソースを変更する

私はこのままGitHubPagesを公開したのですが、２つ問題がありました。


１つはCNAMEまわりでエラーになったこと。
もう１つはJavaScriptまわりが動かず、ロードが終わらなかったり、金額がNaNで表示されたりしたことです。


#### 2-1. CNAMEのファイルを削除

何も考えずにGitHubPages公開しようとしたら、このようなメールが届きました。

>The page build completed successfully, but returned the following warning for the `master` branch:<br>
The CNAME `hotel.testplanisphere.dev` is already taken. Check out https://docs.github.com/articles/troubleshooting-custom-domains#cname-errors for more information.<br>
For information on troubleshooting Jekyll see:<br>
  https://docs.github.com/articles/troubleshooting-jekyll-builds

おそらくCNAMEファイルが残っているのが原因だろう、とアタリを付けてファイル消しました。

![ScreenShot 2020-12-10 23.20.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/4dfd85e0-9f4c-7198-443f-b23fbdfe3dd6.png)

### 2-2. jsの編集

よくよく調べてみると、一部ファイルの読み込みに失敗している様子。

`https://yoshikiito.github.io/hotel-example-site/data/ja/plan_data.json~~~`

という場所にファイルがあるはずのところ、

`https://yoshikiito.github.io/data/ja/plan_data.json~~~`

を見に行っているようでした。


- plans.bundle.js
- plans.bundle.js.map
- reserve.bundle.js
- reserve.bundle.js.map

中に登場する、以下の箇所を変更しました。

`t=location.origin+"/data/"+Object(a.f)()+"/plan_data.json?"+Date.now()`

↓

`t=location.origin+"/hotel-example-site/data/"+Object(a.f)()+"/plan_data.json?"+Date.now()`

## 3. GithubPagesの公開

リポジトリのSettingsタブから、Optionsを開きます。

![ScreenShot 2020-12-10 13.18.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46492/2d944386-1f25-bfe3-84ac-a3e737bb64bf.png)

GitHub Pagesのところのプルダウンを変更して、画像のように合わせてSave。

即時反映ではないので、しばらく待ったうえでアクセスしてみましょう。


## おわりに

「とりあえず動かす」を目標にやったので、繰り返しになりますがあくまでも暫定対応ですので正しいやり方ではないです。
Haskellのためモノイドを学ぶ

# はじめに
* こんにちは ! KDDI アジャイル開発センターの小板橋です。
* この記事は、[KDDI Engineer Advent Calendar](https://qiita.com/advent-calendar/2020/kddi_engineer) 2020の10日目の記事となります。
* Haskell初心者の備忘録としてこの記事を残します。

## 半群とは
抽象代数学であるモノイドを学ぶ前に半群について学びます。
次の条件を満たす集合を**半群**と呼びます。

* 結合法則を満たす下記のような演算が定義されている。なお、この時のa, b, cはある集合Gの要素として含む。

```
( a · b ) · c = a · ( b · c )
```

## モノイドとは
モノイドとは、ひとつの二項演算と単位元をもつ代数的構造です。
例えば、整数の集合は加算演算子と単位元0に対してモノイドを形成します。
もう少し詳しく説明すると、
結合法則を満たす下記のような演算が定義されている。なお、この時のa, b, cはある集合Gの要素として含む。

```
( a · b ) · c = a · ( b · c )
```
且、下記のような単位元がある構造を指します。なお、この時のaはある集合Gの要素として含み、eもある集合Gの要素として含む。

```
e · a = a = a · e
```

つまり、？？
下記のような構造になるということです。

```
半群 + 単位元e

e <> x = x = x <> e
```
例: Integer同士の足し算を考えたときに、0をどちらかに足し合でも変化がないことが分かると思います。

```
0 + 3 = 3 = 3 + 0
0 + 5 = 5 = 5 + 0
0 + 7 = 7 = 7 + 0
```

## 型クラスMonoidの定義

```
class Monoid a where
  mempty  :: a
  mappend :: a -> a -> a
  mconcat :: [a] -> a
  mconcat = foldr mappend mempty
```

* memptyは、単位元を表しています。
* mappendは、二項演算子を表しています。
* mconcatは、リストに格納されているモノイドを結合する関数です。
* mconcatは、デフォルト実装が定義されている為、インスタンスを利用する場合、memptyとmappendを定義するだけでMonoidになります。


## 型クラスMonoidを使用する

例えば、リスト[x,y,z]にmconcatを適用すると以下のようになります。

```
x `mappend` (y `mappend` (z `mappend` mempty))
```

Monoidクラスの２つのメソッドは、単位元と結合に関する則を満たす必要があります。

```
mempty `mappend` x          = x
x `mappend` mempty          = x
x `mappend` (y `mappend` z) = (x `mappend` y) `mappend` z

```
これらの則を用いると、例えばmconcat[x,y,z]の結果は、下記のように直せます。
→ 理由 : モノイド則によって、結果に影響を与えないことが保証されているためです。

```
x `mappend` y `mappend` z
```
 
## 実際に試してみる

```example.hs
[1,2,3] `mappend` [4,5,6]
```

```
GHCi, version 8.6.5
=> [1,2,3,4,5,6]
```
GASでLINE Notifyする関数メモ


最近はGASがNode.jsのランタイムになったということでほぼ通常のJavaScriptと同様の書き方でいけますね。console.logとか

GASはよく使う訳じゃ無いけど、たまにコピペして使いたいときがあるのでメモっておきます。

## 関数

```js
//LINE NotifyにPOST
function lineNotify(postText){
  try {
    const url  = 'https://notify-api.line.me/api/notify'
    const token = ''; //LINE NotifyのToken
    const params = {
      method: 'post',
      headers: {
        'Authorization': 'Bearer '+ token
      },
      payload: {
        message : postText
      }
    }
   
   const res = UrlFetchApp.fetch(url, params);
   console.log(res);
    
  } catch (error) {
    
    console.log(error);
    
  }
}

```

## 使う時

```js
lineNotify('送信するメッセージ');
```

## おまけ

こんな感じで関数ごとにファイル作っておくと管理しやすいです。

![スクリーンショット 2020-12-10 23.39.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/5239b18b-cf85-47e7-cd00-8ca252fec525.png "スクリーンショット 2020-12-10 23.39.56.png")
NVMe SSDを持つEC2インスタンスで起動時に自動でインスタンスストアのディスクをマウントさせる

# あらすじ

この記事は[AWS Advent Calendar 2020](https://qiita.com/advent-calendar/2020/aws)の10日目の記事です。

c5d系やi3などのインスタンスにはNVMeで接続したSSDのインスタンスストアがつきます。このNVMe SSDは停止に伴いデータがなくなるなど制約はありますが、かなり高いIOPSを安いお値段で実現できます。そのため大量のログなどのIOヘビーな一時テータが必要なワークロードのアプリケーションをコスパよく運用することが可能です。

インスタンスストアはファイルシステムが初期化されていないので、そのままではマウントできません。一応AWSのドキュメントには、ボリュームをフォーマットしてマウントするまでのドキュメントがあります。

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ebs-using-volumes.html

しかし、こんな手順を起動するたびに手作業でちんたら実行するのは不便きわまりないです。
この記事では起動に合わせてインスタンスストアを自動でマウントする方法について紹介します。

なお、OSはAmazonLinux2を前提にしてます。

# ECSホストとして動かす場合

ローカルNVMe SSDをインスタンスが持ってること前提としたECSクラスタを組むケースを想定しています。

当然、その上で動くECSタスクはホストがインスタンスストアをマウントしていることを期待します。そのためホストにはインスタンスストアのファイルシステムの初期化とマウントが終わった後でクラスタに参加してほしいわけです。

これを実現するのは比較的簡単です。たいていの場合ECS用のEC2インスタンスはユーザーデータスクリプトで/etc/ecs/ecs.configにクラスタを書き込むので、その手前でファイルシステムの初期化とマウントを行います。

```shell:user-data.sh
#!/bin/bash
mkfs -t xfs /dev/nvme1n1
mkdir /data
echo "/dev/nvme1n1 /data  xfs  defaults,noatime,discard  1  2" >> /etc/fstab
mount -a
echo ECS_CLUSTER=your_cluster_name >> /etc/ecs/ecs.config
```

ECS_CLUSTERを書き込む前にマウントまで済ますことでディスクがある状態でクラスタに参加してくれます。

インスタンスストアはOSやコンソールによるリブートでは消えないので再起動はできます。しかし、一度停止状態になるとインスタンスストアのデータはファイルシステムの設定ごと消えてしまうので、次回起動時にはインスタンスストアのマウントができない状態になります。そのためインスタンスストアを持つインスタンスを停止する際は使い捨てて、AutoScalingなどで別インスタンスに入れ替える運用にすることをオススメします。


# EC2としてアプリケーションを動かす場合

ECSを使わずに普通のEC2ホストとして利用する場合は少し工夫が必要です。
普通のEC2ホストして使う場合アプリケーションはsystemdで起動することになるのでsystemdでアプリケーションを立ち上げる前にディスクのマウントを完了しておく必要があります。

この場合ユーザーデータスクリプトで初期化するより、ユーザーデータに[cloud-init](https://cloudinit.readthedocs.io/en/latest/#)を渡して初期化した方が起動フェーズの早い段階タイミングでディスクをマウントしてくれます。

```yaml:user-data.yml
#cloud-config

fs_setup:
  - cmd: mkfs -t %(filesystem)s -L %(label)s %(device)s
    filesystem: 'xfs'
    device: '/dev/nvme1n1'
mounts:
  - [ /dev/nvme1n1, /data, xfs, "defaults,noatime,discard", "1", "2" ]
```

そしてアプリケーションを起動するsystemdのユニットファイルにcloud-configの完了の後に起動する依存設定を追加することで、マウントが完了した後にアプリケーションが起動するように制御ができます。

```systemd
[Unit]
After=cloud-config.service

[Service]
...
```


# おわりに

以上簡単ですが、インスタンストアの自動マウントについての紹介でした。
はじめてのAWSその1 サーバ構築のためのVPC作り

AWSでサーバ構築するための覚書です。まずはサーバ設置のためのパブリッククラウドを作ります。

##VPCの設定

AWS Consoleから[VPC]をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/63f4575e-6245-8a4b-0625-1657eac61558.png)

VPCウィザードを起動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/a9d1df8e-6951-771c-8361-285bc21d8692.png)

1個のパブリックサブネットを持つVPCを選んで次に進む
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/e9901def-71e9-f4e8-73a0-6728c5190617.png)

そのままVPCの作成を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/d0b97382-54c2-65d5-7a8f-8109cca61280.png)

VPCの完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/940466/e9924dac-1b5d-09bc-7b44-4272bd0818f4.png)

##ここまででできたこと

* VPC(Virtual Private Cloud) 10.0.0.0/16
* パブリックサブネット 10.0.0.0/24
* ルートテーブル 10.0.0.0/16 local 0.0.0.0/0 →インターネットゲートウェイ
* インターネットゲートウェイ（インターネットへの出口）

#注意点
* リージョンを間違えない
* VPCを削除すると、そこに紐づくサブネットもルートテーブルもすべて消える

##参考文献
* https://qiita.com/shunsuke227ono/items/23dbf4f3bc663a2875f0
* https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/managing-users.html
* https://ja.osdn.net/projects/ttssh2/releases/p7801
Notionこそ、codeのストックにおいて最強！

#はじめに
　プログラミングの学習を始めたときから、コードをどのように保存すればいいか、悩んでいました。よく聞くのは、「VScodeでストック用のファイルを作成して、コメントアウトしておく」というものです。まぁ、出来なくはないが、探しにくいし、結局はエディタなので、拡張性がないし、装飾も出来なくて見返すことに適していないと思っていました。
　そこで、最近使い始めたNotionを紹介します。

##Notionとは
　公式のページでは、
####「The all in one workspace」

と紹介されています。
まさに、その通りだと思います。

[Notion](https://www.notion.so/)←公式ページ

　Web上のメモアプリなので、ネットが繋がっていないと使えませんが、スマホやタブレットでも利用することができます。

　一般的なファイルがNotionでは、pageと言います。フォルダという、まとまりはありません。しかし、pageに階層を設けることで、フォルダと同じような使い方ができます。

##コードのストックに優れている点
- そもそも、コードブロックがある。
- <font color=red>多くの言語がシンタックスハイライトに対応している。</font>
- そのページ自体、マークダウン記法なので、その勉強にもなる。
- <font color=red>どんなに長いコードも、コピーがワンクリック。</font>
- <font color=red>コードブロックの中も、外に書いた文字も検索可能。</font>
- メモ書きがコメントアウトでは無いので、いちいち貼り付けた後に消す手間がなくなる。
- コードブロックごと移動できる。
- レイアウトもできる。

↓こんな感じです。
![](https://i.gyazo.com/3bff24fe4e0ccf5c0f5bebf7eea5ad2e.jpg)


弱点を強いてあげれば、
- そのコードをその場で動かすことが出来ないこと。
- 日本語の説明に対応していないこと。まぁ、極端に難しい英文が出てくるわけでもなく、調べればわかる単語レベルなので、英語アレルギーある人でも使えると思います。

##考えられる使い方
- 言語別にページを作ってよく使うコードをストックしておく。
- 機能毎にページを作ってよく使うコードをストックしておく。
- 作成したアプリケーション毎にページを作ってよく使うコードをストックしておく。
など。

##最後に

　日常生活の全ての記録をこのNotionにしようと、色々と落とし込んで、試行錯誤しているところです。
【Ruby on Rails】deviseの導入から実装するまで


#目標
 deviseを導入し実行できるまで

#開発環境
ruby '2.6.5'
rails '6.0.0'

#実装
devise導入から、実装までの一連の流れ
#deviseをインストール
```:Gemfile
gem 'devise'
```

```:ターミナル 
% bundle install

% rails g devise:install
```
rails g deviseコマンドは、deviseによるユーザー機能の対象を指定することで、モデルとマイグレーションの生成やルーティングの設定などをまとめて処理します。

実行すると、モデルが生成され、routes.rbにはdeviseに関連するパスが追加されます。

#Userモデルを作成
```:ターミナル 
% rails g devise user
```
#マイグレーションファイルを編集
```
class DeviseCreateUsers < ActiveRecord::Migration[6.0]
 def change
   create_table :users do |t|
     ## Database authenticatable
     t.string :email,              null: false, default: ""
     t.string :encrypted_password, null: false, default: ""
     t.string :name,               null: false

     # 省略
     
end
```

nameカラムを追加

```:ターミナル 
% rails db:migrate
```

#viewsを追加

```:ターミナル 
% rails g devise:views
```

deviseに用意されたビューファイルをコピーし、app/viewsの配下に配置してくれるコマンドです。
HTMLを修正できるため、カスタマイズ可能になります。

#viewsを編集

```app/views/devise/sessions/new.html.erb
<div class="contents row">
  <div class="container">
    <h2>Log in</h2>
    <%= form_with model: @user, url: user_session_path, id: 'new_user', class: 'new_user', local: true do |f| %>

      <div class="field">
        <%= f.label :name %><br />
        <%= f.text_field :name%>
      </div>
      <div class="field">
        <%= f.label :email %><br />
        <%= f.email_field :email, autofocus: true %>
      </div>

      <div class="field">
        <%= f.label :password %><br />
        <%= f.password_field :password, autocomplete: "off" %>
      </div>

      <% if devise_mapping.rememberable? %>
        <div class="field">
          <%= f.label :remember_me %><br />
          <%= f.check_box :remember_me %>
        </div>
      <% end -%>

      <div class="actions">
        <%= f.submit "Log in" %>
      </div>
    <% end %>
  </div>
</div>
```
nameカラムの記入欄を追加

#モデルにバリデーションを記入
```app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  before_action :authenticate_user!
  before_action :configure_permitted_parameters, if: :devise_controller?

  private
  def configure_permitted_parameters
    devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
  end
end
```

application_controllerにbefore_actionを使用しているため、全てのアクションが実行される前に、実行されます。

before_action :authenticate_user!により、ログインしていないユーザーをログインページの画面に促すことができます。

configure_permitted_parametersで、configure_permitted_parametersメソッドを呼び出しています。

```:詳細
devise_parameter_sanitizer.permit(:deviseの処理名, keys: [:許可するキー])
```
Deep Health Checkパターンを導入してみた

# 概要

この記事は[DMMグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dmm) 11日目の記事です。

DMM.comでサーバサイドエンジニアをやっている[juve534](https://qiita.com/juve_534)です。
現在は配信基盤のリプレイスプロジェクトにて、スクラムマスター兼デベロッパーとして業務しています。

今回はリリース時に導入した `Deep Health Check` について話していきます。

# Deep Health Checkパターンとは

[CDP:Deep Health Checkパターン - AWS-CloudDesignPattern](http://aws.clouddesignpattern.org/index.php/CDP:Deep_Health_Check%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3)で説明されており、ヘルスチェック用のエンドポイントで、関連するシステム（DBなど）の接続をチェックする仕組みになります。
こうすることで、よりサービスの健康を測れます。

[O'Reilly Japan - 入門 監視](https://www.oreilly.co.jp/books/9784873118642/)では、ヘルスエンドポイントパターンとして記載されており、考え方は同じなのかなと思っています。

# 実装経緯
自分たちのプロジェクトではAmazon ECS上にAPIを配置し、オンプレのDBにアクセスしています。

オンプレのシステムは、専門のインフラチームで保守・運用を行っており、サービスイン前にリリース影響範囲を読み合わせたところ、オンプレのDBへアクセスする部分の監視について話が及びました。
弊社の他サービスで上記の通信経路（DirectConnect）をチェックする仕組みを設けており、弊チームでも導入を提案されました。

そこで、前述した `Deep Health Check` パターンを採用して、実装を行っていきました。

# イメージ図

![イメージ図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39671/8c10f943-4d77-23e6-d308-fba261639e35.png)


イメージ図はこんな感じです。ALBからのヘルスチェック時に、DBにアクセスします。もし繋がらない場合は、CloudWatchのカスタムメトリクスに飛ばします。  
CloudWatchAramで、数秒間に何回値があったら、SNSへ飛ばすようにし、そこからメールとSlack通知を行います。

これで、問題が起きた際にインフラチームと協力して調査できる体制を取れるようにしました。

# 最後に

特に実装してしばらくは出番がなかったのですが、サービスメンテナンスを行った際に、DirectConnect越しにDBに繋がらないことを検知してくれました。
このように、ヘルスチェックを工夫しておくと、問題の検知が素早くできると思いました。

[DMMグループ Advent Calendar 2020](https://qiita.com/advent-calendar/2020/dmm) 11日目の記事でした。
明日の12日目は[daisukeoda](https://qiita.com/daisukeoda)さんです。よろしくお願いします！
Stripe + Herokuで決済サービスを作る時のメモ

## はじめ
Stripeという決済サービスを使って、支払いだけのページを作成しました！
その時のメモを残しておこうと思います。
今回はStripeの登録方法は割愛します!

1. ソースコード取得する
2. herokuを使う

実装環境(html/css/js + node.js)

# 1. ソースコード取得する
下記からソースコードをダウンロードする。
https://stripe.com/docs/checkout/integration-builder

必要でしたら、githubで新しいリポジトリを作ることもありです。
支払い金額が1つだけでしたら、そのまま進めてください！
複数ある場合は、checkout.htmlを編集します
変更前

```
      fetch("/create-session", {
        method: "POST",
        headers: headers,
      })
      
```

変更後

``` 
let headers = new Headers({ "Content-Type": "application/json; charset=utf-8", "money": 1000 });
      fetch("/create-session", {
        method: "POST",
        headers: headers,
      })
      
```
      
にします。

headerにあるので、server.jsの19行目を
> unit_amount: req.headers["money"],
にします。

これで今回は複数対応しました。
他にいいやり方があったら、教えてくださいm(_ _)m



# 2. herokuを使う
herokuのアカウントを作ります。
ここの説明も割愛します。
その後に、server.jsの対応をします。

> 1行目 → Stripeの本番Key
> 6行目 → herokuのURLを設定します。
> 7行目 → const port = process.env.PORT || 4242; 

します!
それに加えて、最後の行を下記のように修正しました。
変更前
```
app.listen(4242, () => console.log('Running on port 4242'));
      
```

変更後
``` 
app.listen(port , ()=>{
  console.log('server listened by port ' + String(port) + ' ...');
});
```

あとは、多分herokuに投稿するだけです！！
https://jp.heroku.com/nodejs

実際公開しているのは、こちらになります〜〜
参考までに
https://castle-pay.herokuapp.com/

ぜひ楽しい課金Webページ作成を〜〜
[Nuxt.js]mac環境でのNuxt.jsの環境構築方法

##はじめに

mac環境でのNuxt.jsの環境構築方法を紹介します。

Nuxt.jsの公式サイトはこちら

https://ja.nuxtjs.org/



こちらの公式インストール手順で環境構築を行いました。

##事前準備
npxかyarnが入っていることを確認する

#####npx公式
https://www.npmjs.com/package/npx

#####Yarn

参考記事：https://qiita.com/noboo/items/d7b540b4bff06d907a6b

```
#インストール
Brew install yarn

#yarnをアップデートする
Brew upgrade yarn

```

##Nuxtのインストール

```
#/create-next-appを使用する方法
① npx create-nuxt-app <project-name>
② Yarn create nuxt-app <project-name>
③ 何個か質問に答える

#インストール完了後
① cd <ディレクトリ>
② npm run dev
③ Localhost:3000 で初期画面表示
```
 

完成！
普段使いしているエディタの遷移と感想（Vim, VScode, intelliJ）

この記事は [BrainPad Advent Calendar 2020](https://qiita.com/advent-calendar/2020/brainpad) 11日目の記事です。

# 前置き

今まで仕事等で使ってきた各エディタの特徴や使い心地についてまとめてみます。基本的にmac OSを前提としています。
なお使用期間としてはVimは6年程度、VS Code(Visual Studio Code)は1年程度、intelliJは数ヶ月程度です。
各エディタに精通しているわけでも無く、そもそも設計方針や使用目的が異なるツールで比較すべきでは無いのかもしれませんが、基本的に開発する中で感じた点について記載してます。

# Vim

[vim 公式](https://www.vim.org/)

Webアプリの開発の勉強を始めた頃、AWSのEC2インスタンス上でファイル操作するのにvimを使ったのがきっかけで、そこから利用するようになりました。独特の操作方法ですが大体[vimtutor](https://vim-jp.org/vimdoc-ja/usr_01.html#01.3)で覚えました。一時期vimrcの設定にはまったり[ブログ](http://woody-kawagoe.hatenadiary.jp/entry/2019/04/28/205737)書いたりしていました。

操作が独特すぎるので使い始めるときのハードルは高いかもしれないですが、他のエディタでも同様の操作ができるので、一度覚えとくと素早くコード編集ができるので役に立ちます。また全ての操作がターミナルで完結するというのも利点です。

なお、よく対比されるエディタとしてemacsが挙げられますが、僕は利用したことないのでここでは特に言及しません。

# VS Code

[VS Code 公式](https://code.visualstudio.com/)

学生の頃はIDEが苦手でvimを使い続けてたのですが、社内でよくVS Codeの話を聞くようになったので試しに使ってみました。
特に設定しなくてもGUIがわかりやすいし感覚的に操作できる、という印象が強いです。
また公開されているプラグインの検索がエディタからできて、そこからすぐインストールできるというのも楽です。
なによりkey bindingの設定でvimと同様の操作ができることがわかるとVS Codeを用いた開発がメインになりました。

学生の頃に行っていた開発は比較的小規模のものだったので、IDEだと余分なものが多いと思って利用を控えていたのですが、
仕事だと複数プロジェクトの開発を行うことがあり、プロジェクト単位で見れるというのがわかりやすいです。
サイドバーからディレクトリ構成が見れるというのは当たり前かもしれませんが、vim生活が長かったので少し感動がありました。
加えて、それまでIDEに感じていた画面の雑多さがあまりなかったというのもとっつきやすいポイントでした。

またメモ帳代わりにも使っています。markdown形式だとカラースキームがつくというのもありますが、
メモ帳用のディレクトリを作成し、その配下でメモを管理すると過去分が見やすいというのがあります。
一時期Typoraのようなmarkdown専用エディタを使っていたときもありましたが、WYSIWIGな操作、例えば箇条書きにするときに自動的に表示が大きく変わる点などが慣れないこと、ファイル移動がしにくい点が不満でVS Codeに切り替えました。

# intelliJ

[intelliJ 公式](https://www.jetbrains.com/ja-jp/idea/?sline=34)

最近携わっている開発プロジェクトがjavaがベースでintelliJ推奨だったので利用しています。
恥ずかしながら正直intelliJにはまだ慣れていなくてVS Codeと併用しています。
ただintelliJの方がテストの実行、タグジャンプがやりやすいと感じます。
これらの機能は他のエディタでもできることですが、特に設定せずとも簡単に利用できる点が良いです。
特にタグジャンプはVS Codeだと辿りきれないことが多々あったりするのですが、intelliJだと辿れたり、
逆に利用されている部分に戻るというのもやりやすいです。

# カスタマイズ性について

上記で紹介したどのエディタにおいてもプリミティブな機能やプラグインは豊富で、できることは非常に多いです。
そのため開発にまつわる全ての機能を1エディタでできるようにする、というのも可能ですが、無理にカスタマイズを極めるのに時間をかける必要は無いと思っていて、既存のツールのUIが十分見やすかったり操作が手慣れてるものがあるのならそれで良いと思います。
むしろツールとして切り離して疎結合なほうが設定不要だしシンプルで使いやすいなと思います。

例えばVS Codeのプラグインを利用することで、CSVファイルの閲覧、dockerのコンテナ状況の確認、git操作、などが可能になったりします。
ただ僕の場合、これらの作業はそれぞれ別のツールから利用しています。
カスタマイズするのが好きだったりそれこそ趣味にしている人のほうがエンジニアらしい気もするし人それぞれだとは思うのですが、
あんまり執着せずにラフな関係でありたいというのが個人的な思想です。

# 別で利用しているツール

+ [iTerm2](https://iterm2.com/)
    + 普通にターミナルとして使ってます。スクリプトの実行、ローカルサーバの起動、git操作等、もろもろ全てここからやってます。
+ [postman](https://www.postman.com/)
    + APIを叩くのに利用しています。繰り返し叩くものとかはここに登録して使いまわしてます。
+ [Docker Desktop](https://www.docker.com/products/docker-desktop)
    + 以前はVS Codeのプラグインからdockerのステータス等見てたのですが、最近UIがわかりやすくなったのでこれで十分かなと思って使うようになりました。
+ [DBeaver](https://dbeaver.io/)
    + DBの確認用です。基本的に立ち上げたままで中身の確認、編集をしてます。

# まとめ

ざっくり、以下のような使い方をしています。

| エディタ | デフォルトの機能の充実度 | 用途 |
|:--|:--|:--|
| Vim | 低 | ssh先や単一ファイルなどの一時的な編集操作 |
| VS Code | 中 | プロダクトコードの編集、コードリーディング、メモ帳 |
| intelliJ | 高 | プロダクトコードの編集、テストの実行 |

なにかしらのエディタが最高、というわけではなくて、現在は並行して利用しています。
これから利用していくなかで使わなくなったり新たなツールを利用したり、やり方は変えるかもしれませんが、
それぞれメリット、デメリットや合う、合わないがあるのでたまに調べてみると面白いかなと思います。
以上です。