OmniAICreator/Qiita-1.07M huggingface dataset:
AtCoderのまあまあ便利なPython標準入力フォーマット

まあまあ便利です。

### 基本
```Python:read.py
import sys

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline

```

こいつらで入力すると速い。inputよりもこちらを使う方が実行時間で有利です。
###### readとreadlineの違い
readはEOFまで入力を受け取るのに対して、readlineは各行ごとに入力を受け取ります。AtCoderのコードテストなどではEOFは気にしないでもいいですが、手元実行の場合は入力後Ctrl+Dを押して、入力が終わったこと（EOF）を教えてあげる必要があります。また、EOFの性質上readは一番最後にしか使えません。よって、以下のようなことができません。

```
a = read()      #どこまで見ればいいのか分からない！
b = readline()  
```

##### 入力の加工
また、このコードだと受け取った入力はバイト型で、しかも改行コードを含んでいます。

```
a = readline()  # abc　を入力
b = read()  　　　　　　　# a b
            　　　　　　　# c d を入力

print(a)  # 結果 b'abc\n'
print(b)  # 結果 b'a b\nc d\n'
```

文字列として受け取りたいときはこのままだと扱いにくいので、decodeしてrstripで改行コードを消してあげます。また、readならばdecodeしてsplitすると、文字列リストを作ることができます。これはsplitが標準では`' '`や`'\n'`といった空白文字ごとに文字列を区切ってリストに変換するからです。

```
a = readline().decode().rstrip()  # abcを入力
b = read().decode().split()       # a b
                                  # c d を入力

print(a) # 結果 abc
print(b) # 結果　['a', 'b', 'c', 'd']
```

### 標準入力用関数の作成
上記のコードの下に、listを使うかNumPyのndarrayを使うかに応じて、以下のいずれかを書きます。

```Python:read1.py
#listで受け取る場合

def from_read(dtype=int):
    return [dtype(x) for x in read().decode().split()]

def from_readline(dtype=int):
    return [dtype(x) for x in readline().decode().split()]

def read_matrix(N, M, dtype=int):
    matrix = [None for i in range(N)]
    for i in range(N):
        matrix[i] = from_readline(dtype)
    return matrix
```

```Python:read2.py
#ndarrayで受け取る場合

def from_read(dtype=np.int64):
    return np.fromstring(read().decode(), dtype=dtype, sep=' ')

def from_readline(dtype=np.int64):
    return np.fromstring(readline().decode(), dtype=dtype, sep=' ')

def read_matrix(N, M, dtype=np.int64):
    matrix = np.empty((N, M), dtype=dtype)
    for i in range(N):
        matrix[i] = from_readline(dtype)
    return matrix
```
dtypeはデータの型でint, strなどを意図していますが、本来はNumPyの用語なので注意。list, ndarrayで使い心地が変わらないようにするために引数名を揃えています。（list版read_matrixに使いもしないMを入れているのはそのため）
ただし、ndarray版ではstrは使えません。あくまで数値計算のために使いましょう。

###### 各関数の説明
- from_read - EOFまでlist(ndarray)に要素を格納
- from_readline - 改行までlist(ndarray)に要素を格納
- read_matrix - (N, M)の行列をlist(ndarray)として受け取る

　list（しかりndarray）の入力関数を用意しておくことのメリットはまあまあ大きく、AtCoderにおいてはほとんどの問題で役立ちます。

例えば、数列の受け取りにそのまま使えるのはもちろん、unpackによって要素を個別に代入できます。

###実際の受け取り例

```Python
import sys

read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline

def from_read(dtype=int):
    return [dtype(x) for x in read().decode().split()]

def from_readline(dtype=int):
    return [dtype(x) for x in readline().decode().split()]

def read_matrix(N, M, dtype=int):
    matrix = [None for i in range(N)]
    for i in range(N):
        matrix[i] = from_readline(dtype)
    return matrix

X = int(readline())     # 100
N, M = from_readline()  # 2 3
A = from_readline()     # 3 1 4 1 5
B = from_read(str)      # a b
                        # c d e

print(X)  # 100
print(N)  # 2
print(M)  # 3
print(A)  # [3, 1, 4, 1, 5]
print(B)  # ['a', 'b', 'c', 'd', 'e']
```

使いこなすとまあまあ快適です。
LFIとディレクトリトラバーサルの違い

## 概要
以前、「LFI（ローカルファイルインクルード）」と「ディレクトリトラバーサル」の違いが分からなくなったことがあったので、その時に調べたものを共有したいと思います。
phpのソースコードを実際に見ながら、何が違うのかを見てみましょう。
<font color="Red">本記事は教育目的で書かれています。許可を得ていない対象へのハッキングは犯罪です。</font>

#### 参考

ソースコードは主に以下のサイトから引用しています。

https://medium.com/@Aptive/local-file-inclusion-lfi-web-application-penetration-testing-cc9dc8dd3601

https://www.neuralegion.com/blog/directory-traversal-attack/

## 用語解説

**LFI（ローカルファイルインクルード）**：ローカルファイルインクルードはWebアプリにおける脆弱性で、本来閲覧権限のないサーバー内のファイルを読み込んだり、実行したりすることが可能です。

**ディレクトリトラバーサル**：ディレクトリトラバーサルはWebアプリにおける脆弱性で、本来閲覧権限のないサーバー内のファイルを閲覧することが可能です。

## LFIについて

LFIの脆弱性があるソースコードの例を見てみましょう。

```php
<?php
$file = $_GET['file'];
if(isset($file))
{
include("pages/$file");
}
else
{
include("index.php");
}
?>
```

このコードは、GETリクエストの"file"パラメータにある値（ファイルのパス）を読み込むというシンプルなものです。

一番大事なのは、include()関数です。
この関数は外部ファイル（phpファイル）を読み込み、実行します。
さらに、絶対パスだけではなく相対パスも引数として渡すことが可能です。

つまり上のソースコードの例においては、このようにエクスプロイトすることが出来ます。

```
#通常のリクエスト
http://example.com/script?file=index.php

#LFI用のリクエスト
http://example.com/script?file=../../../../var/www/html/upload/exploit.php

```

include()が相対パスも受け入れ可能なので、"../../../../var/www/html/upload/exploit.php"をきちんを処理してくれます。

ちなみにLFIは、状況によってはRCE（リモートコード実行）が可能になる場合があります。少し今回のスコープから外れるので、詳しくは話しませんが是非調べてみることをお勧めします。

## ディレクトリトラバーサル

ディレクトリトラバーサルの脆弱性があるソースコードの例を見てみましょう。

```php
<?php
$file = $_GET['file'];
file_get_contents('directory/' . $file);
?>
```

このコードも先程と同じように、GETリクエストの"file"パラメータにある値（ファイルのパス）を読み込むというシンプルなものです。

今回一番大事なのは、file_get_contents()関数です。
この関数は、ファイルを文字列として読み込みます。相対パスも引数として渡すことが可能です。

つまり上のソースコードの例においては、このようにエクスプロイトすることが出来ます。

```
#通常のリクエスト
http://example.com/script?file=index.php

#ディレクトリトラバーサル用のリクエスト
http://example.com/script?file=../../../../../../etc/passwd
```

file_get_contents()が相対パスも受け入れ可能なので、"../../../../../../etc/passwd"をきちんを処理してくれます。

気づいた方も多いかもしれませんが、LFIとディレクトリトラバーサルは基本的に同じようにエクスプロイトします。

## ２つの違い

この２つの脆弱性は、ファイルを実行できるのか、それとも文字列として見ることができるだけなのかの違いです。

LFIはファイルを実行できるのに対して、ディレクトリトラバーサルは閲覧のみ可能ということです。端的に言えば、関数の違いということになります。

一般的には、LFIの方が重大な脆弱性であると考えられています。RCEに繋がる可能性がそもそもありますからね。

## 最後に

今回は、LFIとディレクトリトラバーサルの違いを簡単に説明しました。

この記事が皆さんのお役に立てれば嬉しいです。最後まで読んでくださってありがとうございました。

質問がある方は是非コメントしてください😃
IOS Test Flightでアプリが立ち上がらない。

開発環境で、問題なく動いていたアプリ。
これを、AppleStoreConnectに上げて
TestFlightで起動させると、起動した瞬間にアプリがクラッシュする現象が発生しました。

怒

TestFlight
アプリがクラッシュしました。
Xcode3.1

いろいろとやったのですが１日目は解決できず、２日目に解決しました。

原因
there is a bug in the compiler that is producing bad armv7 code, causing this crash. It is addressed in the Xcode 11.5 beta. To avoid this bug, please compile with Xcode 11.3 instead of Xcode 11.4, and disable bitcode so the App Store doesn’t recompile your app with the compiler that has this issue. When Xcode 11.5 is released, please re-enable bitcode.


修正方法
Xcode3.1を使っていたのが原因
Xcode3.2にしたら、問題はなくなりました。
Xcode3.1でBitcodeをOFFにしても、問題ありませんでした。


以上
PowerVC 2.0.2 設定 ~ Viewer ロールのユーザー追加 ~


##### はじめに

PowerVC 設定操作は一般的にはrootで実行しますが、運用フェーズなどに入った場合にはrootではなく他ユーザーで操作したい要件があることがあります。当記事では、ユーザーにPowerVCの viewer ロールを設定してロールを確認しました。

参照マニュアル：
・オペレーティング・システムのユーザーおよびグループを構成

https://www.ibm.com/docs/ja/powervc/2.0.2?topic=authentication-configuring-operating-system-users-groups

・ロールの管理

https://www.ibm.com/docs/ja/powervc/2.0.2?topic=security-managing-roles

----

##### 環境

PowerVC 2.0.2 (RHEL8.4 ppc64le on PowerSystems)


----

##### ユーザー設定

任意の OS ユーザー"pvc-viewer"を作成し PowerVC 定義グループ "powervc-filter" を追加します。

```
# useradd pvc-viewer
# id pvc-viewer
uid=1009(pvc-viewer) gid=1012(pvc-viewer) groups=1012(pvc-viewer)

# usermod -a -G powervc-filter pvc-viewer

# id pvc-viewer
uid=1009(pvc-viewer) gid=1012(pvc-viewer) groups=1012(pvc-viewer),1001(powervc-filter)


# passwd pvc-viewer
Changing password for user pvc-viewer.
New password:
Retype new password:
passwd: all authentication tokens updated successfully.
```

---

##### ロールの追加

まずは rootでログインして対象ユーザーのロールを設定します。

![スクリーンショット 2021-12-15 14.51.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/0e2e5146-159b-a582-cd1d-dda2ec4a53ca.png)

左レーン - "Global settings" - "Users and groups" を選択します。

![スクリーンショット 2021-12-15 14.52.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/03227f0a-e231-f443-6029-07d37f1ae43a.png)

pvc-viewer が表示されていることを確認します。"Assigned roles" には表示がなくロールが割りあたっていないことがわかります。

"Edit assigned roles" で変更します。

![edit_user1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/bc0cdbd2-9956-7fa8-ac71-47095ac01eb4.png)

"other roles" - "viewer" を選択し、"Save" します。

![図2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/9fe5aaf4-8819-019f-7794-a159916f0026.png)


pvc-viewer の "Assinged roles" に viewer が設定されました。

![edit_user3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/0184e593-e896-17fc-6ae8-f580f8d6932a.png)



----

##### 確認

pvc-viewer でログインします。

![スクリーンショット 2021-12-15 14.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/2a06d89e-69e0-e175-f4a3-789b0d374d79.png)

・ユーザーの確認
pvc-viewer でログインできています。

![スクリーンショット 2021-12-15 14.56.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/1ffb76be-7802-291c-aea0-558f7b46d6f1.png)

・リソース表示の確認
リソースは表示されています。
![スクリーンショット 2021-12-15 14.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/1c712645-1e0d-8f7c-6cc6-301bc297d461.png)


・イメージの確認

イメージのリストは確認できますが、対象を選択しても "Deploy" や "Delete" などの操作ができる表示の出力はありません。

![スクリーンショット 2021-12-15 15.52.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/517421/b4f10e21-9e75-91c3-2685-932bf1e7d262.png)



---

PowerVC の viewer ロールでの設定、表示を確認しました。



以上です。
MySQL インデックス物理構造

![mysqlインデックス_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/493435/2cdd5884-deb9-d90c-a648-94b301c8543f.png)

# はじめに
MySQLでは、インデックスは B+Tree というアルゴリズムで構築されており、これによって効率的な検索が可能になっています。
この記事では、このインデックスの構造を上図をもとに詳述することを目的にします。

# 全体像
MySQLのインデックスはツリー構造で表現され、リーフノード、ノン・リーフノードからなります。

リーフノードには、このインデックスを用いた検索の結果取得したいデータが格納されており、またノン・リーフノードからリンクされています。図では下段が該当します。

これに対してノン・リーフノードにはデータが格納されておらず、リーフノードに中継する役割を果たします。図では上段が該当します。

図には2段しかありませんが、一般には多段構成のツリー上となっており、また、同レイヤーのノード間は互いに対するリンクを持ちます。これによって「隣のノード」へのアクセスを簡易にし、範囲検索の高速化が可能になっています。

インデックスを用いた検索がされる際には、ルートとなる最上段のノードのインデックス値と、検索したいキーとの比較が演算され、そのノードから出ているいずれかの枝が選択されます。そして次に選択されたノードでも同様の演算がなされ、最終的に行データが獲得されます。

#インデックスがもつ情報
ここからは、インデックス構造の詳細を説明します。

## ROW_ID
テーブルの行を示すユニークIDで、データ挿入時に生成され、単調増加していきます。

## TRX_ID
該当行を挿入・更新したトランザクションのIDが格納されます。
分散レベルが Repeatable Read でもファントムリードを防ぐためのしくみ MVCC を実現するため、Undo ログとともに用いられます。

トランザクションが作られるたびに（おそらく）単調増加する値であるため、値の大きいほうが小さいほうより新しいトランザクションであることがわかります。
これがタイムスタンプのような役割をはたすことで、MVCC の実現を可能にします。

## ROLL_PTR
これも **TRX_ID** と同じく MVCC で用いられます。
これには、以下の情報が含まれています。

 - その行が挿入された行かどうか
 - rollback segment（Undoログが格納されるテーブルスペース）の場所
 - 該当するUndoログの、rollback segment 内のオフセット

Undo ログというのは、「更新前データ」を保持するしくみであり、これには rollback segment という専用のテーブルスペースが割り当てられています。

Undo ログは**「どのトランザクション」**が更新したのかという情報を示す **TRX_ID** を、**「更新前はどういうデータだったか」** という情報とともに保持され、Undoログ同士もチェーンのようにリンクされています。

これにより、複数世代の更新前データを保持しています。

そして、十分古くなったUndoログは、ガベージコレクションによって破棄されます。


## KEY
このインデックスが対象としているカラムの名前やカラムタイプ 

## HEAP_NUMBER
該当のインデックス値が存在するヒープ番号

※ インデックスは各ノードが1ページになるため、各ノード16KBとなります。各ノードにはいくつかインデックスが含まれますが、それらの場所を示す番号のようです。1ページでおさまらないときにどうするのかはよくわかりません。

## TYPE
クラスタ化インデックスか、セカンダリインデックスかなど、インデックスの種類を示す模様。

## DELETED
削除処理がおこなわれた際にフラグが立ちます。

更新処理とおなじく、削除処理も処理前のデータを保持するしくみがあります。
削除処理をおこなっても物理削除はされず、インデックス上値は残ります。そして、削除処理をおこなったトランザクションIDを **TRX_ID** に書き込みます。

あるトランザクションがこのインデックス値を読み込もうとしたとき、その値の **DELETED** フラグがたっていて、かつ、自身のほうが新しいトランザクションであった（**TRX_ID**が大きかった）なら、その削除処理はそのトランザクションより過去におこなわれたものであるため、削除されたものとしてあつかいます。

逆に 削除処理をおこなったトランザクションのほうが、このインデックス値を読み込もうとしたトランザクションよりも新しかったのなら、**DELETED** フラグがたっていても、削除されたとはあつかわず、まだ rows 領域に削除されず残されているデータを読み込みます。

これによって、**「他トランザクションによる挿入・削除の影響を受ける」**というファントムが防止できます。

## NEXT
次のインデックス値へのリンクです。


# 参考
https://dev.mysql.com/doc/refman/8.0/ja/innodb-undo-logs.html
https://dev.mysql.com/doc/refman/8.0/ja/optimizing-innodb-transaction-management.html
https://blog.jcole.us/2013/01/10/btree-index-structures-in-innodb/
https://blog.jcole.us/2014/04/16/the-basics-of-the-innodb-undo-logging-and-history-system/
windowsでiverilog その124

#概要　

windowsでiverilogやってみた。
練習問題やってみた。

#練習問題

stackを実装せよ。

#サンプルコード

```

module stack(input clk, input rst, input set, input push, input pop, input [15:0] data, output [15:0] qtop, output [15:0] qnext);
	parameter N = 8;
	integer i;
	reg [15:0] q [0:N - 1];
	assign qtop = q[0];
	assign qnext = q[1];
	always @(posedge clk)
	begin
		if (rst)
			q[0] <= 0;
		else if (set)
			q[0] <= data;
		else if (pop)
			q[0] <= q[1];
	end
	always @(posedge clk)
	begin
		for (i = 1; i < N - 1; i = i + 1)
			if (rst)
				q[i] <= 0;
			else if (push)
				q[i] <= q[i - 1];
			else if (pop)
				q[i] <= q[i + 1];
	end
	always @(posedge clk)
	begin
		if (rst)
			q[N - 1] <= 0;
		else if (push)
			q[N - 1] <= q[N - 2];
	end
endmodule


```

#テストベンチ

```
module test;
	reg clk;
	reg rst;
	reg set,
		push,
		pop;
	reg [15:0] data;
	wire [15:0] qtop,
		qnext;
	stack u(.clk(clk), .rst(rst), .set(set), .push(push), .pop(pop), .data(data), .qtop(qtop), .qnext(qnext));
	initial
	begin
		$display("set, push, pop, data, qtop, qnext");
		$monitor("%d   %d   %d   %d   %d   %d", set, push, pop, data, qtop, qnext);
		clk = 1;
		rst = 0;
		set = 0;
		push = 0;
		pop = 0;
		data = 0;
		#2
			rst = 1;
		#2
			rst = 0;
			set = 1;
			data = 1;
		#2
			set = 0;
			push = 1;
		#2
			push = 0;
		#2
			set = 1;
			data = 2;
		#2
			set = 0;
		#2
			pop = 1;
		#2
			pop = 0;
		#2
			pop = 1;
		#2
			pop = 0;
		#2
			$finish;
	end
	always
		#1
			clk = ~clk;
endmodule

```

#実行結果

```
set, push, pop, data, qtop, qnext
0   0   0       0       x       x
0   0   0       0       0       0
1   0   0       1       1       0
0   1   0       1       1       1
0   0   0       1       1       1
1   0   0       2       2       1
0   0   0       2       2       1
0   0   1       2       1       0
0   0   0       2       1       0
0   0   1       2       0       0
0   0   0       2       0       0

```
以上
【簡単SSH】SSHで初心者が困らないために！

#:point_right:初心者のためのSSH

パソコンからサーバーとかGitに接続するために使うのがSSHです。
詳しくはWikiとかを見ると勉強になります！
ここでは使い方だけに触れます:muscle:

#:point_right:SSHキーを生成する

まずSSHキーを生成するためのコマンドを実行

```
$ ssh-keygen

Generating public/private rsa key pair.
Enter file in which to save the key (/Users/test/id_rsa):
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/test/.ssh/id_rsa.
Your public key has been saved in /Users/test/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:<中略>
The key's randomart image is:
+---[RSA 2048]----+
|.=Ooo oo.        |
<中略>
|E o =...         |
+----[SHA256]-----+

$ 
```

途中で`Enter file in which to save the key (/Users/test/id_rsa):`と聞かれます。
これは「どこにSSHキーを保存しますか？」という意味です。
そのままエンターを押すとかっこの中に書いてある場所に保存されます。

次に`Enter passphrase (empty for no passphrase):`と聞かれます。
これは「SSHキーを見たりするときに使うパスワードを設定してください」という意味です。
通常は設定する必要がありませんので、空白でエンターを押します。
`Enter same passphrase again:`に関しては、その前でパスワードを決めていたらそれを入力してください。

これにてSSHキーが出来ました！

#:point_right:生成したキーの場所と意味

出来たファイルの中身を見ていきましょう！

```
$ cd ./ssh
$ ls -la

total 16
drwxr-xr-x  4 test  2020   128 Dec 15 15:19 .
drwx------  9 test  2020   288 Dec 15 15:19 ..
-rw-------  1 test  2020  1843 Dec 15 15:19 id_rsa
-rw-r--r--  1 test  2020   409 Dec 15 15:19 id_rsa.pub

$ 
```
`~/.ssh`の中には`id_rsa`と`id_rsa.pub`というファイルがあります。

`id_rsa`は秘密鍵と言って、他の人に見せてはいけない鍵です:spy:
この鍵から後程紹介する、公開鍵が作られます。

```
$ cat id_rsa

-----BEGIN OPENSSH PRIVATE KEY-----
<中略>
-----END OPENSSH PRIVATE KEY-----

$ 
```

`id_rsa.pub`は公開鍵です
何かのサービスに接続する際にこの鍵を使います:muscle:

```
$ cat id_rsa.pub 

ssh-rsa 
<中略>

$ 
```

#:point_right:複数のPCでSSHキーを使いまわす

複数のPCでSSHキーを使いまわしたいときに使ってください:grin:

１）普段使用しているPCから秘密鍵を`cat`等で表示させて、コピーします。
２）コピー先のPCで`id_rsa`にコピーした秘密鍵を書き込む
３）コピーした先で`chmod 600 ~/.ssh/id_rsa && ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub`を実行

これで完成です！
普段使っているPCとリモートで使用しているPCで、同じ公開鍵が作れました

#:point_right:まとめ

SSHって便利ですね。
使いまわす方法が`ssh-keygen -y -f ~/.ssh/id_rsa > ~/.ssh/id_rsa.pub`をすればいいよーってよく書かれてます。
自分の環境だと`chmod 600 ~/.ssh/id_rsa`を明示的にしなくちゃいけなかったので困ってました:sob:
という事で備忘録も兼ねてお疲れ様です
読んでくださってありがとうございます:bow_tone2:

追記）絵文字かわいい:anchor:

#:point_right:参考サイト
https://yachibit.hatenablog.jp/entry/2013/04/25/001912

http://blog.digital-bot.com/blog/2013/09/16/ssh-add/

http://tec-shi.com/tips/648/
servicenow デモアカウント　パスワード変更

## ServiceNowで用意されているデモデータのアカウントのパスワードを変更する

- ServiceNowでデモデータのプラグインを入れるとデモアカウントが入る。
- Impersonate Userして成りすましてでもデータのアカウントの動作確認を行えるが、直接ログインしたい場合のパスワード設定について以下に記載する


### 手順
1,Admin権限を持ったユーザでログイン
2,アプリケーションナビゲータに「sys_user.list」を入力し、sys_userテーブルを開く
3,パスワードを設定したいユーザを開き、「Password」にパスワードを入力し、「Update」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2241272/08af021e-2bcb-8550-0b60-1e3f8ce64f13.png)
4,/sp　などへアクセスし、ログイン画面でユーザ名とパスワードを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2241272/fd9e1f62-8a0a-a368-dbd5-8bf68eba52e8.png)

## memo
- Password resetなどではうまくいかなかったので、Listから直接記入したらできました。
- 何かありましたらコメントください。
「インプットできてる気がしない！」時に見直したいこと

# はじめに
「インプットできている気がしない！！！」
ずっとこの状態のままはよくないと思ったので
どうしたらよいかを調べたり考えたりしました。

# 悩み
最近視野が広がることがとても多く、見えるものが多くなり学ぶことが増えていく。
そして何かを学ぶとどんどん見えるものが増えていくという**無限ループ**がある。
いつでも頭が**マニックパニック[^panic]**に。気が付いたら忘れている。。
本当にインプットできているのか？と心配になり。。

**「騒がしい日々に笑えなくなっていった....」[^yoasobi]**

とはなりたくない

# 見直した項目
## タスクリスト、本当に外部記憶化してますか？
パニックにならないためにタスクリストを作っておいてその通りに実行する。
よく見る方法だと思います。僕も作っていました。

**しかしッッ....それを置く場所が良くなかったッ!!!!**

taskListとかいうフォルダの奥底に日付順にたまっています。。。

見るときには日付を見て**いちいち開かない**といけません。
何よりよくなかったのが、**結局自分の頭の中で思い出して**
「あれやんなきゃなー、これやらなきゃなー」とやっていました。

**使い方がヘタクソ！！！！！！**

そこで僕の場合、常に別のディスプレイに表示するようにしました。
**思い出すのではなくディスプレイを見る**ようにしました。

だいぶ改善されたような気がします。（体感）
todoツールを導入してもいいと思います。

とにかく**すぐ見える位置**に置いておくといいと思います。

## アウトプットしてますか？

**グサァ！！！！**

まさに串刺し公の一撃[^yari]ですが、どうか立ち上がってください。


はい、どこでも言われていることです。これは本当にその通りなのです。
アウトプットの効果は絶大です。

**やばい！！整理できる！！抜けている部分がわかる！！！**

習慣化でも、マインドでも**なんでも駆使して**なんとかアウトプットをしよう！！！

記事は書いていますか...(小声)

## 本当にインプットできていないのか？

ここは、マインドの話です。
常に、「俺はだめだ！！！とても弱い。。。」の状態は辛いものです。
それで強くなってしまったお話をどこかで聞いた気がしますが、精神衛生的に私はよくないと思います。
できれば自分が強くなったことを認識して、それをモチベにループさせていきたいですよね？？

私はそうしたい。

だから何か確認する機会を作ってみると良いかもしれません。

- 自分用に確認テストを作ってみる
- 学んだものを使って何かを作る
- 誰かに説明する

ここで書いてあることは大体アウトプットですが、捉え方を変えて見てほしいです。
自分の状態、ステータスを確認する作業だと思ってほしいです。

**失敗でも成功でも、捉え方で経験値は入るのです。レベルは上がるのです。**

それっぽいことを書いてみる...

# 以上
自分に言い聞かせるつもりで書いています。
経験豊富な皆様には役に立たないかもしれません。
同志がいたら参考にしてくれ。少しは変わるはずだ。


[^yari]: ヴラド3世、通称ドラキュラ公または串刺し公。かっこいい。
[^panic]: コスメティックヘアカラー。筆者はいつか使おうと思っている。
[^yoasobi]: 楽曲「夜に駆ける」、歌詞より引用
NVIDIAドライバーが入っているUbuntuでWaylandを使う

# Ubuntu 20.04
NVIDIAのプロプライエタリドライバを使ってるとどうもUbuntu 20.04はWaylandでの起動を無効にするらしい:

* https://askubuntu.com/questions/1240813/wayland-in-ubuntu-20-04-intelgpu
* https://askubuntu.com/questions/1369250/how-do-i-enable-wayland-on-ubuntu-21-10-nvidia

が、私の環境では以下の手順を踏むと有効化できた。

## gnome-session-waylandのインストール

```
sudo apt install gnome-session-wayland
```

なくてもいいかもしれないらしい

## /etc/gdm3/custom.conf の確認

`WaylandEnable=false` がコメントアウトされていることを確認

## /usr/lib/udev/rules.d/61-gdm.rules の設定
元は以下のようになっていた

```conf 
# disable Wayland on Hi1710 chipsets
ATTR{vendor}=="0x19e5", ATTR{device}=="0x1711", RUN+="/usr/lib/gdm3/gdm-disable-wayland"
# disable Wayland when using the proprietary nvidia driver
DRIVER=="nvidia", RUN+="/usr/lib/gdm3/gdm-disable-wayland"
```

が、全てコメントアウトしておく。

## /etc/default/grub の設定
```
GRUB_CMDLINE_LINUX="nvidia-drm.modeset=1"
```
を足し、`sudo update-grub` をする。再起動。ログイン画面のパスワード入力時に右下に出る歯車でWaylandを選択し、`echo $XDG_SESSION_TYPE` がwaylandになれば成功。

## libnvidia-egl-wayland1 のインストール

```
sudo apt install libnvidia-egl-wayland1
```

をするとハードウェアアクセラレーションが使われるらしいが、差を感じなかった。

# Ubuntu 22.04
状況が変わったような感じがする。少なくとも `/usr/lib/udev/rules.d/61-gdm.rules` の中身がものすごく長くなった。

Ubuntu 22.04では以下のことをするだけでよくなっていた。

## /etc/default/grub の設定
```
GRUB_CMDLINE_LINUX="nvidia-drm.modeset=1"
```
を足し、`sudo update-grub` をする。再起動。ログイン画面のパスワード入力時に右下に出る歯車でWaylandを選択し、`echo $XDG_SESSION_TYPE` がwaylandになれば成功。
create-react-app v5が出たようです

[reddit](https://www.reddit.com/r/reactjs/comments/rghdli/create_react_app_v5_has_been_released/)を見ていたら、create-react-appのv5が出たというスレッドを見つけました。

https://github.com/facebook/create-react-app/releases/tag/v5.0.0

ざっとリリースノートを流し読むと:

- webpack 5にアップデート
- Jest 27にアップデート
- ESLint 8にアップデート
- PostCSS 8にアップデート
- Fast Refresh周りの改善
- Tailwindのサポート
- package manager判定の改善
- dependenciesのピン留め廃止
- Node 10 and 12の非サポート

最後のNodeのサポートバージョンの変更がBreaking Changesになっています。

その他もろもろ改善している感じですかね。あまりトピックとして書くものが見つからない。

codesandboxでも動くか試してみましょう。

[https://react.new](https://react.new) を開きます。

今だとまだreact-scriptsは4.0.0なのでドロップダウンで5.0.0にします。"Update to latest"のボタンでもできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63327/49901c3f-0aa3-f313-8722-8ea04182f92c.png)

試しに、[valtio](https://github.com/pmndrs/valtio)でカウンターを作ってみました。

https://codesandbox.io/s/holy-rain-dfubb?file=/src/App.js

コードはこちら:

```jsx
import { proxy, useSnapshot } from "valtio";

const state = proxy({ count: 0 });
setInterval(() => {
  ++state.count;
}, 500);

const App = () => {
  const snap = useSnapshot(state);
  return <div>count: {snap.count}</div>;
};

export default App;
```

以上、もし参考になれば。
大きな開発こそ小さくリリースしよう

この記事は [Ateam Lifestyle Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ateam-lifestyle) 19日目の記事です。

## はじめに
現在、株式会社エイチームライフスタイル
D2C事業部にてデザイナーをしております@Shion84です。

2021年はいろんな開発にチャレンジさせていただきました。
その中でも規模の大きい開発の担当をさせていただいた際には、
とても多くの失敗と学びがありました。

簡単にご説明しますと

- やらなければいけない実装
- 今後を考えるとやっておいたほうが良い実装

をまとめて実行しようとしてしまった結果
レビューイ/レビューアー双方の疲弊や、大幅なリリースの遅れを生んでしまいました。
自身を含め、同じ失敗を誰も繰り返さないために
「開発時に気をつけたいこと」のお話を記事にさせていただきたいと思います。
どなたかの参考になれば嬉しく思います。

## この記事で伝えたいこと
#### 大きな開発は、小さなリリースの連続に変換すべし
- 巨大なプルリク1つではなく、細かいプルリクを多くレビュー依頼しよう
    - 実装したらリリース or developブランチにさっさとmerge

#### 絶対にissue単位で実装をすべし
- 差分が小さいからといって、別のissueを同じプルリクに乗せるのはダメ
    - 本筋とは別の実装を加えると、影響範囲が広がる

## なぜ伝えたいのか？
#### 事業のスピードが上がる
- 小さく区切ることで差分が少なくなる
    - diffが少ないほど見る範囲や責務が明確になるのでレビューアーが見やすくなる
        - 負荷ががさがるので高速にリリースできる

#### 安全性の確保    
- 「本当に必要な機能」に予定通り時間をかけることができる
    - 時間をかけることが正義ではないが、影響範囲や検証を十分にできる
        - 結果的にお客様に迷惑がかからない


## 体験談
ここから話すことが、私が実際に実装をしていたときの話です。
(少しフェイクを入れて、抽象的にしています)

以前から積み上がっていた過去の負債をリファクタリングをしたいと思っているときに
Aというサイト全体に関わるissueを依頼されました。

長くスケジュールのある実装をするなら、できる範囲で不要なコードを消していこうと同じプルリク内であれこれ実装をし始めました。

気づいたときにはdiffは凄まじい数になり、影響範囲も膨大に
コミットも汚くなってしまっていました...
レビューを依頼した際のレビューアーの全てを悟った菩薩のような顔が忘れられません。

そしてスピード感は落ち、抜け漏れも生まれ、ジリ貧になってしまいました。

これではいかん...


## 大きな開発こそ小さくリリースしよう
一気にやろうとすると自分もメンバーも疲弊してしまい
事業のスピードは落ち、最悪の場合 お客様にも迷惑をかけてしまうかもしれません。
改めて、開発をする際は

- 必要なものに絞る
- 要件定義
- タスクの細分化
- マイルストーンを引く
- 丁寧にコミットしながら実装

これを着実にすることが大切なことなのだと思います。
「やったほうがいいこと」を本当にやるのかは慎重に判断をしましょう！

## まとめ
「大きなことをするためには、小さく始めよう」
というテーマでお話させていただきました。
余談としては、おそらくこれは開発に限った話ではなく
すべての業務や、人間関係、更には人生にも言えることだと思います。
この記事を読んでくださった方の今後のためになったら幸いです。


明日12月20日（月）は @ponco さんの記事です。
お楽しみに！
matplotlibでx軸の範囲調整をx_limを使い試みたが、x_limの引数がX軸リストのindexとして取得されてしまう

もの凄い初歩的な部分で時間を食ったので自分への戒めとしてここに記そうと思う。
まず以下のような散布図を描いた。

```python
import matplotlib.pyplot as plt

X = ["10","20","30"]
Y = ["0.001", "0.01", "0.1"]

fig, ax = plt.subplots(figsize=(6, 5))
ax.scatter(X,Y)

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790888/642d8e7a-0491-8e6a-911a-3648c14c8303.png)

ここで、X軸の範囲を0~にしたく思い、`Axes.set_xlim`を使い軸の範囲調整を試みた。

```python
import matplotlib.pyplot as plt

X = ["10","20","30"]
Y = ["0.001", "0.01", "0.1"]

fig, ax = plt.subplots(figsize=(6, 5))
ax.scatter(X,Y)
ax.set_xlim(left=0)

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790888/1d646d2c-8007-48fa-afd1-239365894f55.png)
左端をX=0にしたかったのだが、X=10が来てしまっている。この```left=0```がリストのインデックスを拾ってしまっているようだ。
早速だが原因はデータリストの要素が文字列だったためである。
CSVからデータを取り込んでパパっと処理しようって意気込みだったからか全く気づけなかった、、、
つまりこれで解決

```python
import matplotlib.pyplot as plt

X = ["10","20","30"]
Y = ["0.001", "0.01", "0.1"]

X2 = [int(x) for x in X]
Y2 = [float(y) for y in Y]

fig, ax = plt.subplots(figsize=(6, 5))
ax.scatter(X2,Y2)
ax.set_xlim(left=0)

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790888/7575f9bd-8e84-1056-2ee7-7a0c49042d47.png)
Vagrant Centos7インストール

#ディレクトリ作成
```
$ mkdir centos7
$ cd centos7
$ vagrant init
```

#Vagrant file 編集

```
vagrantfileのプロパティを開きセキュリティタブのusersを編集してフルコントロールに変更してから下記記述

 ...
Vagrant.configure("2") do |config|
　...
  config.vm.box = "centos/7"
　config.vm.network "private_network", ip: "192.168.33.10"
  ...
$ vagrant up
$ vagrant ssh
```

#vimインストール

```
$ sudo yum -y install vim-enhanced
```

#python3.5インストール

```
sudo yum -y install wget

sudo wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz

sudo tar zxvf Python-3.6.3.tgz

cd Python-3.6.3

sudo ./configure --prefix=/usr/local/python363 --with-ensurepip

sudo make test

sudo make

sudo make install

ls /usr/local/python363/
bin  include  lib  share
ls /usr/local/python363/bin
2to3  2to3-3.6  easy_install-3.6  idle3  idle3.6  pip3  pip3.6  pydoc3  pydoc3.6  python3  python3.6  python3.6-config  python3.6m  python3.6m-config  python3-config  pyvenv  pyvenv-3.6


/usr/local/python363/bin/python3 -V
Python 3.6.3

sudo rm -r Python-3.6.3.tgz
sudo rm -r Python-3.6.3
```
UNVTについて

### ごあいさつ
こんにちは. 青山学院大学4年 平澤彰悟と申します。
現在、[The United Nations Vector Tile Toolkit （UNVT）](https://unvt.github.io/)を対象に研究しています.

この記事では、UNVTって何？というところから、自身の詳しい研究内容についてご紹介していきます.

## The United Nations Vector Tile Toolkit とは？

ベクトルタイルの生成・スタイル・最適化・ホスティングをオープンソースのツールを用いて行う [UN Open GIS Initiative](http://unopengis.org/unopengis/about/about01_01.php) のプロジェクトの1つです.

ベクトルタイルの生成には[Tippecanoe](https://github.com/mapbox/tippecanoe).　スタイルには[Hocon](https://github.com/lightbend/config/blob/master/HOCON.md), [Maputnik](https://maputnik.github.io/), [Charites](https://github.com/unvt/charites). ホスティングにはGitHub Pagesもしくは,Raspberry Pi. 最適化処理には[VT-optimizer](https://github.com/ibesora/vt-optimizer)が用いられています.

誰もが簡単にベクトルタイルを生成,スタイル,ホスティング,最適化が行えるようにするツールキットがUNVTです.

![FOSS4G SotM Oceania 2021_ShogoHIRASAWA.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/7ac1f7e1-f63a-ab99-9eaf-8a79e7ef6d85.jpeg)

UNVTは国連平和維持活動や人道支援を後方支援する国連グローバルサービスセンターでの配備が進められています[詳しくはこちら](https://maps.gsi.go.jp/pn/meeting_partners/data/20211208/1_kikakuchosa.pdf?fbclid=IwAR19mz13uMGyOH2w5XnDcCRw-0KCpoQ_TfkW6PJ131SsTgw9KK7XFk7g0Y0)

## 研究内容

私はUNVTを災害直後の環境で利用するためのを研究をしています。

![FOSS4G SotM Oceania 2021_ShogoHIRASAWA (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/467847/649b3107-9197-0fdd-435a-c7d67228b80d.jpeg)

私が所属する古橋研究室では,災害が起きた際にドローンを飛ばし空撮をおこない,その状況を行政の方々に伝える活動を行っています.

ここで課題なのは,行政の方にどうやって情報を渡し,どうやって見てもらうか。ここが非常に大事になってきます。

行政の方すべての人が地理空間情報に精通しているわけではありません.
専門的な知識が必要になるハード,ソフトウェアでしかお渡しできない状態だとせっかく作ったデータも無駄になってしまいます.

ここで、UNVTが役に立つと私は考えます.
作ったデータをRaspberry Pi（UNVT Portable）に取り込ませ、そこでホスティングをさせ、ブラウザで見てもらう.

Raspberry Piは比較的安価で誰もが手軽に用意することができます。また、行政の方が持っているPCとRaspberry Piの通信さへすることができれば、オフライン環境下でもホスティングされたデータを見ることができます.

災害直後に電波が入らないということは珍しいことではありません。災害環境でもデータのやり取りができる仕組みをUNVTで構築することが重要になってきます.

## 最後に
青山学院大学 古橋研究室ではMapbox,国連といった様々な組織と共同してUNVTコミュニティを育んでいます。
以下にUNVTのGitHubリポジトリと古橋研究室のUNVTプロジェクトのリポジトリを添付しておくので興味のある方はぜひご覧になってください

[UNVT](https://github.com/un-vector-tile-toolkit)
[古橋研究室 UNVTプロジェクト](https://github.com/unvt/hackathonmeetup202112)
Dockerコマンド

#イメージの確認

```
$ docker images
```

#コンテナ確認

```
$ docker ps -a
```

#コンテナの起動

```
$ docker start【コンテナID】
```

#コンテナの停止

```
$ docker stop【コンテナID】
```

#コンテナの削除

```
$ docker rm【コンテナID】
```
#イメージの削除

```
$ docker rmi 【IMAGE ID】
```

#すべてのコンテナを停止する

```
$ docker stop $(docker ps -q)
```

#すべてのコンテナを削除する

```
$ docker ps -aq | xargs docker rm
```

#すべてのイメージを削除する

```
$ docker images -aq | xargs docker rmi
```
Go1.18からジェネリクスが導入されるらしいので、試してみた

**ジェネリクス**とは、データの型を束縛せず、型そのものをパラメータ化して扱う技術です。
利点としては、型を抽象化して利便性を上げつつ、静的型付け言語の安全性を保つことのできることが挙げられます。

### ジェネリクスを導入する前は
同一の処理をする関数であっても、型が違うだけでそれぞれ実装しないといけませんでした。
例えば、`int`と`float64`で和を求めるシンプルな実装をするとしましょう。
和を求める処理自体は同じなのに、型が違うだけの理由で似たような関数を二つ用意することになります。
https://go.dev/play/p/9uIhwWrlJK1

```go
func main() {
	sumInt := sumInt(1, 2)
	fmt.Println(sumInt, " is ", reflect.TypeOf(sumInt))

	sumFloat64 := sumFloat64(1.0, 2.0)
	fmt.Println(sumFloat64, " is ", reflect.TypeOf(sumFloat64))
}

func sumInt(a, b int) int {
	return a + b
}

func sumFloat64(a, b float64) float64 {
	return a + b
}

```

### ジェネリクスを導入後は
型そのものをパラメータ化して扱うことができるので、一つの関数で済むようになります。
例えば、　ジェネリクスを使って上記の処理を実装すると、こうなります。
https://go.dev/play/p/uaMTQ1QV9lO?v=gotip

```go

func main() {
	s1 := sum(1, 2)
	fmt.Println(s1, " is ", reflect.TypeOf(s1))

	s2 := sum(1.0, 2.0)
	fmt.Println(s2, " is ", reflect.TypeOf(s2))
}

func sum[T int | float64](a, b T) T {
	return a + b
}
```

### ジェネリクスを試すには
[The Go Playground](https://go.dev/play/)で試すことができます。
デフォルト状態では、「Go release」が使用されます。
ジェネリクスは、「Go dev branch」を選ぶことで、開発ブランチで試すことができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/272102/23239b0a-558d-f33c-a648-0ac588989a1b.png)
Oracleで「ORA-01033 Oracleの初期化またはシャットダウン中です」と出たときの対応

個人的メモです。
原因1と2を書いていますが、他にもora-01033を起こす原因はあるかもしれません。
間違いがあればご指摘いただけると嬉しいです。

## 原因1. DBがマウントされていない
DB起動時のマウントに失敗している。
### 対応
sqlplusにてsysdba権限ユーザで接続しマウントして開始する。

以下でログイン(ユーザ名は環境に応じて)

```
sqlplus sys as sysdba
```

以下でマウントと開始

```
ALTER DATABASE MOUNT;
ALTER DATABASE OPEN;
```

参考
https://cosol.jp/knowledge/knowledge_post/ot0007_ora01033/


マウントされていないだけならこれで解決します。

ファイルが破損している場合[ALTER DATABASE MOUNT]で、すでにマウントされていますと言われ、[ALTER DATABASE OPEN]で以下のようなエラーが発生します。
破損しているファイルによってORAコードは異なる？

```
ORA-00742:
ログの読取りでスレッドx、順序xxxx、ブロックxxxxに書込みの欠落が検出されました
ORA-00312: オンライン・ログx スレッドx: 'C:\xxxx\REDO01.LOG'
```


## 原因2. REDOログの破損
起動時、REDOログの不整合が見つかったため、DBを開始できない。
### 対応
以下URLを参考にRMANを使ってリカバリーする。
https://atmarkit.itmedia.co.jp/ait/articles/1111/11/news138.html
https://atmarkit.itmedia.co.jp/ait/articles/1109/22/news118.html

REDOログはグループ別に管理されており、それぞれグループに1つ以上のメンバーが属しています。
1つのグループにログを書き込んでいき、ファイルサイズが上限に達すると、書込み先を別グループにします。
ローテーションで回していき、最後のグループのあとは初めのグループに戻り古いログに上書きする仕組みです。

同じグループに属するメンバーには同じログを書き込みます。これによって、あるメンバーが破損しても同じグループで無事なメンバーがいれば、完全リカバリができます。それができない場合（全メンバー破損、グループにメンバーが1つしかないなど）、不完全リカバリします。
JAVA Springメソッド

備忘録として残します。
人に説明したりするのが僕にとって良いアウトプットになっているのでもし間違っていましたらご指摘宜しくお願い致します。

今後も追加予定です。

##equalsメソッド

equalsメソッドとは、文字列の比較を行うことができる命令文です。

比較といえば基本データ型である整数の比較があります。

基本データ型の整数比較とは異なり、equalsを使用する際は、参照データ型の文字列比較になる点が異なります。

eaualsメソッドでは、一致するときにtrueを返し、一致しない場合にはfalseを返します。


##アプリケーションプロパティズのcontext-pathについて。

```
server.servlet.context-path=/spring_training
```

HTML内でパスを通すときに以下のように

```
/spring_training/lesson01_08/login
```
spring_trainingのルート設定をしているということになるので、フォルダの前に明記する必要がある。

##コントローラーの命名

コントローラーには拡張子前にControllerと名付ける必要がある。
コントローラーとして認識されない。



##フィルタクラス

「フィルタ（フィルタクラス）」とは、各コントローラの実行前に共通して実行したい処理（共通処理）をまとめたクラスのことです。
コントローラを実行する前に、以下のような共通処理を実行したい場合があります。

❑ アクセス中のユーザのログイン情報がセッション中に存在するか確認する（ログインチェック）
❑ ログイン中のユーザの権限で対象のコントローラにアクセス可能か確認する（権限チェック）


このような処理を各コントローラ内に記述すると、冗長的なコードが増えてしまい、改修時の修正箇所が多くなるなどのデメリットがあります。そのため、このような処理はフィルタとして作成することが一
般的です。

```filter.java
package jp.co.sss.shop.filter;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import org.springframework.stereotype.Component;
@Component
public class Message01Filter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException {
System. out .println("Done Message01Filter");
chain.doFilter(request, response);
}
}

```

##@Component アノテーション
フィルタを Spring の DI コンテナに登録するために、クラスブロックに@Component アノテーションを
付与します。
##Filter インターフェース
クラスをフィルタとして機能させるためには、Filter インターフェースを実装（implements）する必要
があります。


##Filter#doFilter()メソッド
doFilter()メソッドは、Filter インターフェースからオーバーライドしたメソッドです。このメソッドは
フィルタが呼ばれた際に実行されます。
doFilter()メソッドの引数を下表に記載します。


###doFilter()メソッドの引数


| 型 | 役割 |
|:-----------|------------:|
| ServletRequest      | リクエスト情報を管理する。      |
|ServletResponse    | レスポンス情報を管理する。      |
| FilterChain       | 他のフィルタを探して実行する。        |


##ServletException クラス
ServletException クラスは、Spring のベースとなる技術 Servlet に関するエラーをあらわす例外クラスです。
IOException クラスと一緒に Filter#doFilter()メソッドから送出するように定義されているため、
これらの例外クラスに対して、送出、または例外処理を行うように記述する必要があります。
##FilterChain#doFilter()メソッド
フィルタ中の doFilter()メソッド内では、引数 chain から同名のメソッドが呼び出されています。

このdoFilter()メソッドは FilterChain インターフェースで定義されているものであり、Filter#doFilter()メソッドとは別機能です。

このメソッドは他に実行可能なフィルタが存在するかを探索します。

そして、存在する場合は、対象のフィルタ中の doFilter()メソッドが呼び出されて実行されます。
また、他に実行可能なフィルタが存在しない場合は、元々リクエスト対象だったプログラムの処理が実行されます。
FilterChain#doFilter()メソッドにより、複数のフィルタの実行、およびリクエスト対象のプログラムの実行ができる。
【ABC231】D問題を解説 DFSを使った解法 (C++) 

##初めに
皆さんこんにちは！
競プロの理解を深めるために解説記事を書いていこうと思います．また，私自身の考えを__アウトプット__ するためでもあります．

気に入っていただけたら__LGTM__して頂けるとうれしいです！
何かあれば__コメント__や[Twitter](https://twitter.com/python05238919)からお願いいたします!

#["D - Neighbors"](https://atcoder.jp/contests/abc231/tasks/abc231_d)
問題は上の見出しから参照をお願いします．
###条件
・$ 2 \leq N \leq 10^5$
・$ 0 \leq M \leq 10^5$
・$ 1 \leq A_i < B_i \leq N $
・$ (A_i, B_i)$は相異
###考察
横一列に並べるので**一人に対して二人**まで隣り合うことができると考えられます．一人に対して三人以上条件がある場合は横一列に並べることができません．
　また条件に沿って人を並べたときに**円のようにループ**なったら横一列には並べることはできません．例えば以下のようになったときはループになっています．
![無題の図形描画 (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1836240/9114d91f-d9d2-bd9b-c108-3547a5096b7d.jpeg)
この場合**2**, **3**, **4**で**ループ状態**になるので横一列にはできません．

これらのことに気を付けて実装していきます．
##実装
人の数$N$をグラフの葉とみなして無向グラフとして考え，**DFS(深さ優先探索)**を使ってループになっていないか見ていきます．
####DFS
 深さ優先探索をする際にループかどうかを確認するため，すでに探索済みの数を数え，**二人とも探索済みの場合はループである**とわかります．
　上の図で確認すると1→2→3→4で探索したときに4の時に2, 3はすでに探索済みであるのでループだとわかります．

##コード
正解コードは以下のようになります．

```C++:d.cpp
#include <bits/stdc++.h>
using namespace std;
vector<bool> seen;
bool ok;
void dfs(const vector<vector<int>> &G, int v){ //DFSで解く
    seen[v] = true;
    int cnt = 0;
    for(auto nv : G[v]){
        if(seen[nv]){ // 探索済みの人数を数える
            cnt++;
            continue;
        }
        dfs(G, nv);
    }
    
    //探索済みの人数が2人以上の時false
    if(cnt > 1) ok = false; 
    return;
}

int main(){
    //入力
    int N, M;
    cin >> N >> M;
    vector<vector<int>> G(N);
    for(int i = 0; i < M; i++){
        int a, b;
        cin >> a >> b;
        a--; b--;
        G[a].push_back(b);
        G[b].push_back(a);
    }
    
    
    ok = true;
    seen.assign(N, false); //seenの初期化
    for(int i = 0; i < N; i++){
        if(G[i].size() > 2){ // i番目の条件が3人以上のときfalse
            ok = false;
            break;
        }
        if(seen[i]) continue;
        dfs(G, i);
    }

    if(ok) cout << "Yes" << endl;
    else cout << "No" << endl;
}
```
TeraTermのフォントにHackGenを設定する

TeraTerm のフォントに白源/HackGen (https://github.com/yuru7/HackGen) を設定する。
なぜか、 [ Setup ] - [ Font... ] のプルダウンリストに出てこないので、`TERATERM.INI` を直接編集する。
`VTFont` を検索して `HackGenNerd Console` と書き換える。

```
;	Font
;VTFont=Myrica M,0,-16,128
VTFont=HackGenNerd Console,0,-16,128
```
バチバチ静電気をおさえるには？

#はじめに

こんにちは。

先日、1時間のうちに10回以上バチバチした学生です。

静電気はなぜ起きるのか、起こさないようにするにはどうしたらよいのか。
友達や先生と話した内容と、調べた知識をここにまとめたいと思います。

#静電気が起こる仕組み
そもそも静電気とはどうやって起こるのでしょうか。
（知ってるわ！って方はとばしてください）

まず、すべての「もの」はプラスとマイナスの電気を持っています。（もちろん人間も）
何もしていなければプラスとマイナスが均等の状態、すなわち中性を保っています。中性の状態であれば触れても「バチッ」とはなりません。

静電気はその「もの」のプラスとマイナスのバランスが崩れることで発生します。「もの」と「もの」が接触しているとき、それは起こります。「もの」によってマイナスの電気を引き付ける力が違うため、力の強いほうがマイナスを奪い（マイナスが強くなる）、弱いほうがマイナスを奪うのです（プラスが強くなる）。そこでバランスが崩れ、静電気が生まれてしまいます。

静電気の発生の仕方は３つあります。（どれも似たようなタイミングですが、、、）


「接触帯電」
１つ目は、二つの異なる「もの」が接触したときです。
強い刺激がなくても、触れているだけで微量ながら発生しています。

「剥離帯電」
２つ目は、二つの異なる「もの」が離れるときです。
小さなテープやシールをはがしたりする際にも発生します。
強くくっついているもの（離しにくいもの）のほうが多く帯電します。さらに剥がすスピードを速くすると、さらに多く帯電します。

「摩擦帯電」
３つ目は、二つの異なる「もの」がこすれあうときに発生します。
お察しの方もいると思いますが、生活の中で感じやすいのは、服を脱ぐときです。

この３つによって静電気が生まれます。

人間が静電気を感じるのは、人の体にたまった静電気をほかの「もの」に一気に放出するときです。

#静電気対策
対策は意外と簡単（？）で「静電気をためない」、「こまめに逃がす」です。
（知ってるわ！って方はとばしてください）

身に着けているものの組み合わせ次第で、静電気の起きやすさは変わります。
ナイロンやウールはプラスに、ポリエステルやアクリルはマイナスに帯電しやすい素材です。綿や絹は帯電しにくいです。

例えば、ナイロンとポリエステルが素材のそれぞれの服を重ね着すると、静電気がたまるのは当然です。
ポリエステルではなくウールにすると、静電気は起きにくくなります。静電気が起こりやすい組み合わせでも、あいだに帯電しにくい素材をはさめば、静電気を防ぐことができます。

靴も静電気にかかわっています。靴と靴下での帯電はもちろんですが、
靴底がゴムなどの場合、たまった電気が地面に逃げず、たまり続けます。
たまりにたまって放電すると、まぁ痛いです。
静電気防止のシューズでなくても、底が革だったりすると電気を逃がしてくれます。

また、「静電気体質」という言葉もありますが、その原因は生活習慣の乱れだそうで、、、
体の酸化や皮膚の乾燥などで、静電気は起きやすくなるようです。

乾燥つながりで、静電気は空気中の水分に少しずつ逃げていくので、肌の乾燥にも、静電気対策にも、加湿は有効です。

静電気を逃がすのは、静電気除去キーホルダーなどが売っているのでおススメです。
別に買うほどでもない、けど「バチッ」は嫌だという方は、電気を通しやすいものを触る前に、通しにくいドアの面や建物の壁を触りましょう。気を付けてほしいのは、「バチッ」とならないために、「電気を通しにくいもの」を触るのですから一瞬だと静電気はなくなりません。電気が抜けていくのはゆっくりなので、一瞬だと効果がないということです。

#おわりに
静電気について、周りの方と話したり、ざっと調べたことをまとめてみました。
「静電気イヤァァァ」という方もいれば「別に気にせん」という人もいるかと思います。
私はすごく気になった日があったので、そういう日がまた来た時に意識してみようと思います。
（試着をするたびにバチバチしている私から静電気の痛みが消える日が来るとは思えませんが、、、）

ちなみになんですが静電気は数万ボルトまで行くらしいです。
もう少しでピ〇チュウですね。

本当にざっくりとした記事かと思いますので、間違いや改善点、「こういうのもいいと思います」的な意見があればコメントへよろしくお願いします。では。
Javaを使用してHTMLをPDFに変換する方法

今回の記事でJavaを使用してHTMLをPDFに変換する方法を紹介します。変換することには、以下の2点に注意する必要があります。

##変換プラグインを使用します
対応するプラグインは、さまざまなシステムに応じてダウンロードできます。ダウンロード先：[windows-x86.zip](https://www.e-iceblue.com/downloads/plugins/java/plugins-windows-x86.zip)、[windows-x64.zip](https://www.e-iceblue.com/downloads/plugins/java/plugins-windows-x64.zip)、[macosx_x64.zip](https://www.e-iceblue.com/downloads/plugins/java/plugins-macosx-x64.zip)、および[linux_x64.zip](https://www.e-iceblue.com/downloads/plugins/java/plugins-linux-x64.zip)。ダウンロードした後、プラグインパッケージをローカルで指定されたフォルダパスに解凍します。
##PDFライブラリーSpire.PDF for Javaバージョン：4.12.1以降のバージョンを使用します
jarをインポートするには2つの方法があります。
1. jarパッケージを手動で**[ダウンロードし](https://www.e-iceblue.com/Download/pdf-for-java.html)**解凍して、libフォルダー内のjarファイルをJavaプログラムにインポートします。
2. Mavenプロジェクトプログラムを作成し、pom.xmlファイルでMavenリポジトリパスを構成し、Spire.PDF for JavaのMaven依存関係を指定してから、jarをインポートします。
最終的なjarファイルのインポート結果は次のとおりです。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/3e5a1cbf-29b1-899c-fed6-a89445dc677e.png)
##Java変換コード一覧
```
port com.spire.pdf.graphics.PdfMargins;
import com.spire.pdf.htmlconverter.qt.HtmlConverter;
import com.spire.pdf.htmlconverter.qt.Size;

public class HtmlToPDF {
    public static void main(String[] args) {
        //変換したいHTMLを定義する
        String url = "https://www.google.com/";

        //変換された結果ドキュメント（結果ドキュメントはJavaプロジェクトプログラムファイルに保存されます）
        String fileName = "HtmlToPDF.pdf";

        //解凍されたプラグインのローカルアドレス
        // （プラグインパッケージはJavaプロジェクトフォルダーに配置されます。他のローカルパスをカスタマイズすることもできます）
        String pluginPath = "F:\\plugins-windows-x64";
        HtmlConverter.setPluginPath(pluginPath);

        //メソッドを呼び出してPDFに変換し、PDFサイズを設定する
        HtmlConverter.convert(url, fileName, true, 1000, new Size(700f, 800f), new PdfMargins(0));
    }
```
HtmlをPDFに変換すると、元のhtml形式、ハイパーリンクなどが保留され、次のようになります。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/e047ff08-2cce-0aa0-f203-71d81e684093.png)

今回の記事は以上でした、最後まで読んでいただきありがとうございます。
新卒の新卒による新卒のための振り返り

# はじめに
こちらは、[エーピーコミュニケーションズ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/ap-com)　の15日目の記事です。

新卒１年目のぴかつと申します。
近々、2022年度内定者の方々とお話しする機会があるので、何かしらアドバイスできることはないか？と思い、自分なりに今年一年を振り返ってみました。
こちらはその備忘録となります。

※"新卒のための"と謳いいつつ、実際は来年４月に入社を控えた内定者の方々向けの内容を大いに含みます。

# 入社前にしてよかったこと
### 早めの配属対策
配属希望を選ぶ際には、誰でも自社のプロジェクトについて調査されると思います。
ただ、自分は入社前から、会社HP,転職サイトを通して情報収集しており、内定式を迎える時点で、配属希望を固めておりました。
その後、内定式,入社式,面談でのアピールや、関連分野の資格取得を進めることで、無事念願のプロジェクトにアサインされ、社会人生活を好調なスタートで切ることができました。

最初の配属先で全てが決まるわけでもなく、努力次第で希望が必ず通るわけでもないのも理解しています。
とはいえ、今後のキャリアのためにも、仕事を楽しむためにも、できる限り先手先手で配属に向けた準備をすることをお勧めします。

### 自分主体で何か作ってみること
学生時代の自分は、座して本を読む学習スタイルで、実機操作はハンズオンで軽く触る程度でした。
内定式を終えて一息ついた頃にふと目の前に現れたのが、"何らかのシステムを作って提出しろ"という曖昧な卒業課題でした。
なんの縛りもない中で、インフラの構成を考えていく内に、妙に楽しくなってきて、夢中でドキュメント読み漁りながら、休憩時間を返上してGCPと格闘していたのをを覚えています。
誰かが用意してくれたレールに沿って作るのではなくて、自分で設計から取り掛かり、興味の赴くままに試行錯誤しながら作り上げていく最中が、今までのどの座学よりも、"技術が身についている"ように感じました。

### 英語学習
あちらこちらで言われている気がしますが、英語が苦手な方ほど本当に実施した方がいいと思います。
英語文章の理解という点では、大抵の場合は、DeepL先生が解決してくれますが、、、Udemy等の動画講座の受講可否、アクロニム（頭字語）の暗記速度にかなり影響があると思っています。
入社以降の学習速度にある程度差が出ると個人的に思っているので、英単語レベルでも勉強することをお勧めします。

# 入社前にしておけばよかったこと
### 技術面以外でのスキルアップ
入社前までの自分は、「エンジニア = 高い技術力は求められるが、ビジネススキルはあればなお良し程度」というイメージを抱いていました。
けれどいざ配属されると、①調査内容のドキュメントまとめ、②会議のファシリテーション、③お客様用のパワポ資料作成等々、技術そのものとは関係ないタスクがたくさん舞い込んできました。
"技術さえ弄っていればいい"と思っていた自分にとっては、割と衝撃的でした。
特に文章作成については、自分は大学のレポートさえまともに書けないほど、文章を考えるのが大の苦手なので、苦戦を強いられました。（今現在も絶賛奮闘中）

エンジニアといえども、オフィススキル,ビジネススキルは当たり前のように要求されるので、不慣れな方は対策しておくことをお勧めします。

# 入社後～現在までにしてよかったこと
### 苦手なことへのチャレンジ
自分は、学生時代の頃から登壇活動に憧れていましたが、人前で話すのが苦手なためずっと先送りにしてました。
配属されて月日が経ったある日、登壇活動奨励の流れがチーム内で生まれ、それに乗っかる形でついに登壇デビューを果たしました。
発表中は緊張でいっぱいでしたが、終わってみると、あっけらかんとしていて、今まで必死に避けてきたのが嘘のようでした。

新しい生活の幕開けなので、苦手なことを克服するには絶好のタイミングだと思います。
今まで避け続けてきた苦手なことに今一度向き合ってみるのはいかがでしょうか。

# 入社後～現在までにしておけばよかったこと
### プロジェクトに対して当事者意識をもつ
これは、仕事をさぼっていた、とかそういうお話ではなくて、
自身が所属する組織のことを自分事として考えることができているか？というお話です。
実際、自分のタスクに関しては自分事として取り組むことはできていました。
ただ、プロジェクトの未来、課題に関する議論に遭遇すると、正直全く意見が思いつかず、普段プロジェクトのことを全然意識してないのが浮き彫りになっていました。
来年からは、プロジェクトの課題に自分事として関わり、より自律的に動くことで、
組織のパフォーマンスに寄与しつつ、自身の成長にも繋げていきたいと思います。
Terraform EC2インスタンス作成

#IAMユーザー作成
作成時にAWS Access Key IDとAWS Secret Access KeyのCSV保存しとく

#AWS CLI インストール

```
$ mkdir aws && cd aws
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
```

~/.aws/credentials にAWSの認証情報保存

```
$ aws configure
AWS Access Key ID :IAMユーザー作成時ーのもの
AWS Secret Access Key :IAMユーザ作成時ーのもの
Default region name :us-west-2(オレゴン)
Default output format :text
```

#.tf ファイルを作成

```
$ vi variables.tf
provider "aws" {
  version = "~> 2.0"
  region  = "us-west-2"
}
```

#EC2 のスペック定義

```
$ vi ec2.tf
```

Amazon Linux 2 AMI (HVM), SSD Volume Type (64 ビット x86)
のamiのIDをhttps://aws.amazon.com/jp/amazon-linux-2/release-notes/ からとってくる
わかんなかったらインスタンス作成するときに対象のID書いてあるからそこからとってくる
Nameはcount(台数)によってかわるようにするけどとりあえず1台

```
resource "aws_instance" "sandbox" {
  count         = 1
  ami           = "ami-0e8c04af2729ff1bb"
  instance_type = "t2.micro"

  tags = {
    Name = "${format("sandbox-%02d", count.index + 1)}"
  }
}
```

#variable.tf と ec2.tf が置かれているディレクトリ内で以下を実行
初期化

```
$ terraform init
```

定義内容チェック

```
$ terraform plan
```

出力結果

```
+ aws_instance.sandbox.0
    ami:                          "ami-0e8c04af2729ff1bb"
〜
    tags.Name:                    "sandbox-01"
Plan: 1 to add, 0 to change, 0 to destroy.
```

#定義を適用してインスタンス作成

```
$ terraform apply
Enter a value: と出力されるからyesと入力
Enter a value:yes
Apply complete! Resources: 2 added, 0 changed, 0 destroyed.
```

作成したオブジェクトの内容出力

```
$ terraform show
```

AWSコンソールを確認すると作成されている

#リソース全削除

```
$ terraform destroy
Enter a value: yes
```

AWSコンソールで削除されていることを確認
【Vue.Router】ナビゲーションガード

# ナビゲーションガード
* クリック後にコンポーネントが切り替わる間に処理を実行できる機能。
* ライフサイクルフックのようなイメージ

## 3つの書き方
### グローバルコンポーネントビフォーガード

* 全てのルートに適用される。
* 認証系の手続きで使う事がある。
* routerのインスタンスに直挿


```router/index.js
const router = new VueRouter({ ... })

router.beforeEach((to, from, next) => {
  // ...
})
```

### ルート単位ガード

* 直接ルート設定オブジェクトの `beforeEnter` ガードを定義することができます。

```js
const router = new VueRouter({
  routes: [
    {
      path: '/foo',
      component: Foo,
      beforeEnter: (to, from, next) => {
        // ...
      }
    }
  ]
})
```

### コンポーネント内ガード

* ルートコンポーネント(ルータ設定に渡されるもの)の内側でルートナビゲーションガードを直接定義する

* beforeRouteEnter
* beforeRouteUpdate (2.2 で追加)
* beforeRouteLeave

```js
const Foo = {
  template: `...`,
  beforeRouteEnter(to, from, next) {
    // このコンポーネントを描画するルートが確立する前に呼ばれます。
    // `this` でのこのコンポーネントへのアクセスはできません。
    // なぜならばこのガードが呼び出される時にまだ作られていないからです!
  },
  beforeRouteUpdate(to, from, next) {
    // このコンポーネントを描画するルートが変更されたときに呼び出されますが、
    // このコンポーネントは新しいルートで再利用されます。
    // たとえば、動的な引数 `/foo/:id` を持つルートの場合、`/foo/1` と `/foo/2` の間を移動すると、
    // 同じ `Foo` コンポーネントインスタンスが再利用され、そのときにこのフックが呼び出されます。
    // `this` でコンポーネントインスタンスにアクセスできます。
  },
  beforeRouteLeave(to, from, next) {
    //ページ遷移するときなど
  }
}
```

#### beroreTouteLeaveを使用したcase

* ページを離れる時に「本当にこのページを離れますか？」という確認をユーザーに即すときなどに使う。

```some.vue
/*
.
省略
*/
<script>
export default {
  name:'About',
  beforeRouteLeave(to, form, next){
    const checkLeave = window.confirm('本当にこのページを離れますか？')
    if(checkLeave){
      next()
    }else {
      next(false)
    }
  }
</script>
```

![ezgif.com-gif-maker (5).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/acdd9f46-b120-f7cc-2a82-1beacf9f6c57.gif)




# to, from, nextとは

* to :Routeオブジェクト
    * 新しい遷移先のオブジェクトを返す。
* from: Routeオブジェクト
    * 遷移前のオブジェクトを返す。
* next: Function
    * ナビゲーションガードの最後にnext()関数を呼び出す。
    * next()関数を呼ばないと、コンポーネント間のパイプラインが終了できない。
    * 結果として描画されないようになる。
* next()の引数
    * next()
        * 処理のパイプラインが完了し次のフックに移動する。
    * next(false)
        * 現在のナビゲーションを終了させ、ブラウザのurlが変化した場合はfromルートに戻る。
    * next('/') or next({path: '/'})
        * 現在のナビゲーションが終了。
        * 任意のロケーションをnextに以下のようにセットできる。
            * replace: true
            * name: 'home'
            * router-link
            * toプロパティ
            * router.pushで使用される任意のオプション
    * next(error)
        * ナビゲーションは中止
        * 引数に渡されたものがErrorインスタンスの場合`error.onError()`を介して登録されたコールバック関数が渡される。
* next()関数は一度だけ呼ばれるようにする。
    * 2回呼ばれる場合はerrorになる。
    * 2回呼ばれるようなコードの書き方

``` js
// 2回呼ばれる悪いケース
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  // ユーザーが認証されていない場合、 `next` は2回呼ばれる
  next()
})
```

```js
// 修正したコード
router.beforeEach((to, from, next) => {
  if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' })
  else next()
})
```

##  まとめ

![スクリーンショット 2021-12-16 20.20.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378066/8e519708-42dd-70b7-0af6-b17edc12435a.png)
Github Actions に AWS ECR + AWS ECS を用いた自動デプロイを実装する

# Github Actions に AWS ECR + AWS ECS を用いた自動デプロイを実装する

## 経緯

- Github で管理しているコードを、AWS EC2 で動作するアプリとして載せることになった
- k8s ほどではないけど、オートスケーリング + Docker が欲しく、マルチクラウド対応も特に考えてないため ECS を選択
- 管理はある程度自動化したいので Github Actions で CI/CD を組むことになった

## 記載すること

- Github Actions の yml を記載
- ECR、ECSの設定は済んでいるものとして、設定方法などはこの記事で記載しない

## 内容

### 全体図

このような流れを想定

![img001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2199780/b457c97c-cc65-da1f-c74d-bc60c201f6b8.png)


### Github Actions 

詳細については後述

```yaml
name: develop-cicd

on:
  push:
    branches: [develop]

jobs:
  build-register:
    if: github.ref == 'refs/heads/develop'
    runs-on: ubuntu-latest
    steps:

      - uses: actions/checkout@v2

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
          aws-region: ap-northeast-1
      
      # AWS ECR への Docker ログイン
      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1
      
      # Build 及び Push
      - name: Build Docker And Push ECR
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: xxx-yyy-zzz-repository  # Pushしたいリポジトリを指定
          IMAGE_TAG: develop # タグ名
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG

      # ログアウト
      - name: Logout of Amazon ECR
        if: always()
        run: docker logout ${{ steps.login-ecr.outputs.registry }}

  # ジョブを分けなくても動く
  deploy:
    needs: build-register
    runs-on: ubuntu-latest
    steps:
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
          aws-region: ap-northeast-1

      - name: Deploy
        env:
          ECS_CLUSTER_ARN: arn:aws:ecs:ap-northeast-1:0123456789:cluster/my-cluster-name # ECS のクラスター名
          ECS_SERVICE_NAME: my-service-name # ECS のサービス名
        run: |
          aws ecs update-service --cluster $ECS_CLUSTER_ARN --service $ECS_SERVICE_NAME --force-new-deployment
```

### Github Actions の詳細

AWS ECR への ログインはこのようにする。前のステップで Credentials 認証を設定するのと併せて必須。

```yaml
- name: Login to Amazon ECR
  id: login-ecr
  uses: aws-actions/amazon-ecr-login@v1
```

プッシュした Docker イメージを置き換えただけではサービスは反応してくれないので、強制デプロイを aws-cli で行う。

```
aws ecs update-service --cluster $ECS_CLUSTER_ARN --service $ECS_SERVICE_NAME --force-new-deployment
```