OmniAICreator/Qiita-1.07M huggingface dataset:
【BluePrism】コレクションで消費したメモリを解放する

#やりたいこと
大量データをコレクションに格納するとメモリ使用量が跳ね上がってしまう。
コレクションを使い終わったら、メモリを解放して動作に支障が出ないようにしたい。（メモリを圧迫するとOut Of Memoryエラーなど、処理に影響が出るため）

#試すこと
GC.Collect()を使ってメモリ開放がうまくいくか

（参考）
[How do I avoid Out Of Memory issues in the blue prism?](https://rpadevops.com/discussion/16/how-do-i-avoid-out-of-memory-issues-in-the-blue-prism)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/3ff6e3b1-a5a3-8edf-72ef-a1081d99437c.png)

#手順

Excelににカラム数20、30000件のデータを用意する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/9324bd7f-1e43-d324-5718-c5dd7a0a1261.png)

以下のようなフローを用意。
データ取得ブロック内の処理で、Excelを読み込み、コレクションに格納。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/3011dc5f-2404-df74-aa3f-284b1a4c34ce.png)

格納したコレクションデータを削除。
これにより、"Data"コレクションがガベージコレクションの対象としてマークされます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/99e0ded8-f890-aa74-5b28-1f455fcc4ddb.png)

GC.Collect()でメモリ開放。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/8fde0b02-9a18-3143-2828-f5bdd660447c.png)

上記の流れにおいて、メモリ使用量の推移をタスクマネージャーで監視する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/df329256-3368-9fe5-c1bd-3e60030afcf1.png)

#結果
コレクションにデータ格納前
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/f4731665-46a5-e639-9cb9-8d465fe4d336.png)

コレクションにデータ格納後
メモリ使用量が跳ね上がりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/3e784503-4d37-eb44-cf56-30d85ceb321e.png)

コレクションデータを全削除
メモリ使用量はほとんど変わりません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/c19b74b3-36d1-5cb9-59ce-66cb832a3df5.png)

ガベージコレクション実行
データ格納前のメモリ使用量に戻りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/29f587b6-2826-1351-4cf7-1b3e424bb45f.png)

ちなみに、あまりに大量のデータをコレクションに格納しようとすると、OutOfMemoryになってしまいます。
以下の例では10万件のデータを読み込もうとするとエラーになってしまいました。
適切なデータ量で捌いていく実装にしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/186221/b0ee501f-10f2-0472-d1df-a43cea9193cb.png)
コマンドライン（CLI）から Synology DiskStation を再起動する


#### 1. DiskStation に SSH 接続してから、`sudo -i` コマンドで root に昇格する
参考資料：[Synology DiskStation で SSH 接続を公開鍵認証方式にする](https://qiita.com/shimizumasaru/items/56474d98e723ea1b5ae3)

#### 2. 再起動、停止のコマンドは4種類
参考資料：[ttyとかptsとかについて確認してみる
](https://qiita.com/toshihirock/items/22de12f99b5c40365369)

```
# その1： まずはこのコマンドを試す。 NAS が再起動しない場合は、”その2”以降に進む
$ reboot

# その2： NAS の電源オン状態から、リセットボタンを押す操作（つまり強制リセット操作）
$ echo C >/dev/ttyS1

# その3： NAS の電源オン状態から、電源オフさせる操作（つまり強制シャットダウン操作）
$ echo 1 >/dev/ttyS1

# その4： NAS の：電源オン状態から、さらに電源オンさせる操作（つまり強制リセット操作）
$ echo 0 >/dev/ttyS1 
```

#### 3. その他の echo コマンド
参考資料：[Echo Commands](https://community.synology.com/enu/forum/17/post/74526)

```
$ echo 0 >/dev/ttyS1 #即時電源オン(強制的)
$ echo 1 >/dev/ttyS1 #即時電源オフ(強制的)
$ echo 2 >/dev/ttyS1 #BEEP音（短）を鳴らす
$ echo 3 >/dev/ttyS1 #BEEP音（長）を鳴らす
$ echo 4 >/dev/ttyS1 #電源のLEDをブルー点灯
$ echo 5 >/dev/ttyS1 #電源のLEDをブルー点滅
$ echo 6 >/dev/ttyS1 #電源のLEDを消灯
$ echo 7 >/dev/ttyS1 #ステータスのLEDを消灯
$ echo 8 >/dev/ttyS1 #ステータスのLEDをグリーン点灯
$ echo 9 >/dev/ttyS1 #ステータスのLEDをグリーン点滅
$ echo A >/dev/ttyS1 #USBCopyのLEDをグリーン点滅
$ echo @ >/dev/ttyS1 #USBCopyのLEDをグリーン点灯
$ echo B >/dev/ttyS1 #USBCopyのLEDを消灯
$ echo C >/dev/ttyS1 #即時リセット(強制的)
$ echo : >/dev/ttyS1 #ステータスのLEDをオレンジ点灯
$ echo ; >/dev/ttyS1 #ステータスのLEDをオレンジ点滅

# TIPS：echoコマンドをエスケープすることで複数コマンドを一気に実行できる
# 例1:ステータスのLEDをグリーン点滅させる
$ echo \9 >/dev/ttyS1
# 例2:ビープ音を鳴らし、複数のLEDライトを点滅させる
$ echo \;\3\A\5 >/dev/ttyS1
# 例3:すべてのLEDを点灯・消灯に戻す
$ echo \8\4\B >/dev/ttyS1
```

####番外編. DiskStation 管理者コマンド
参考資料PDF：[Synology DiskStation Administration CLI Guide](https://global.download.synology.com/download/Document/Software/DeveloperGuide/Firmware/DSM/All/enu/Synology_DiskStation_Administration_CLI_Guide.pdf)
mixhostでのSSHログイン設定

#新しいキーの生成
![ssh1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/2a0687b3-2995-20cb-5cd4-fb4774f01338.png)

#必要項目を入力
パスワードは、SSHログイン時に使うので安全なところに忘れないようにメモ。
![ssh2_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/533ddee4-3ca1-2607-3b5b-d119c37eccb3.png)

#入力完了したら、キーの生成を選択する
![ssh2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/dad4d7e3-7faf-a7fb-2405-aaed0c305c2f.png)


#Authorizeする
![ssh6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/c04171b0-ac05-8544-84c5-5b4cf10cf384.png)

#Authorizeされた画面
![ssh7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/98fa32ef-1144-3b9e-8623-8e9075db4698.png)

#Authorizeされたか確認
![ssh8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593240/e0ce596a-0838-f1a4-54ed-11edf23708da.png)

#実行権限を変更
chmod 6000 ./ssh/(秘密キー)

#秘密キーをダウンロードして、SSHでログインできます。
パスワードは、キー生成時に使ったパスワードを入力
ssh username@hostname -i .ssh/(秘密キー)
Enter passphrase for key '.ssh/(秘密キー)':
Visual Studio で IIS Express を Classic モードに設定する方法

# 設定方法

1. ソリューションエクスプローラーからプロジェクトを選択
2. [F4] を押すか、[View]-[Properties Window] を選択[^1]  
   右クリック → Properties ではないことに注意
3. プロパティウィンドウの Managed Pipeline Mode を Classic に変更

[^1]: Properties ウィンドウを開いている場合は、プロジェクトを選択後、Properties ウィンドウを表示すればよい

# .csproj 内での設定

.csproj 内では

```xml
<IISExpressUseClassicPipelineMode>true</IISExpressUseClassicPipelineMode>
```
で設定されている。

`Integrated (統合)` に戻す場合は `false`。

# 参考

https://stackoverflow.com/questions/5914744/force-iis-express-to-classic-pipeline-mode
IntelliJ + plantUMLを使ってモデル図を管理する

## はじめに
あなたが普段、チームでの開発をしている場合、その実装に当たっては必ずと言っていいほどユースケース図やER図などのモデル図の作成、運用の必要性が生じるのではないでしょうか。
これらは実装の際大変重要なものであるにも関わらず、その運用に関してはどうしてもないがしろにされがちです。
この記事では、plantUMLというDSL(ドメイン特化言語)を使ってこれらのモデル図を作成するメリットや方法についてまとめています。

## plantUMLを使うメリット
### 変更をGitで管理できる
ドメイン図やユースケース図などは実装を進めていくうちに変更されるケースがほとんどです。
IntelliJ等のエディタ上でplantUMLを使ってこれらを作成、運用することにより、変更が保存され、いつでも変更前の状態を確認できるようになります。
### 参照、修正が楽になる
開発のエディタ上で管理できるため、開発の途中でもすぐに参照、修正が可能になります。実装を行う場所と物理的に近い場所にあるため楽ですし、管理がないがしろにされることも少なくなります。
### 無料で何人でも同時に参照できる
LucidChart等のサービスツールを使用すると、無料枠では同時に1つのシートにログインできる人数に制限があり、チーム開発においてはたいへん不便な時があります。plantUMLを使えばいつでもチームのメンバーが各自のPCからいつでも何人同時にでも参照が可能です。

## 準備
### IntelliJ側
1. IntelliJ IDEA -> preference -> pluginsへと進む
2. MarketplaceでplantUMLと検索するといくつか出てくるので、左上のplantUML Integrationをインストールする
![スクリーンショット 2020-03-12 9.40.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547300/50d71ed9-a988-ca9a-1958-928a8229c845.png)

3. IntelliJを再起動する

### Graphviz
シーケンス図以外を作成するには、Graphvizが必要になります。Homebrewからインストールが可能です。また、各OSのインストーラからも可能です。
```
$ brew install graphviz
```
[各OSのインストーラー]　http://www.graphviz.org/Download.php

## 基本的な使い方
### ファイル作成
plantUML Fileを選択し、ファイルを作成
![スクリーンショット 2020-03-12 9.56.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547300/be5086e8-c3a0-0717-581f-19b907bb0f53.png)


### ユースケース図
![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547300/76e31d60-c469-93b7-9479-33cbfb1ed8ca.png)

```
@startuml
:Main Admin: as Admin
(Use the application) as (Use)

User -> (Start)
User --> (Use)

Admin ---> (Use)

note right of Admin : This is an example.

note right of (Use)
A note can also
be on several lines
end note

note "This note is connected\nto several objects." as N2
(Start) .. N2
N2 .. (Use)
@enduml
```
＠startumlと＠endumlの中にコードを書いていきます。
棒人間の図は:Main Admin: as Adminのように::で囲うことでas以下で使用できます。
ユースケースは()で囲います。
矢印は->で水平方向、-->で垂直方向に描画されます。点線は..で、点線の矢印は..>等を使うと描画できます。
また、noteを使うと、吹き出しで注釈を記述できます。また吹き出しの位置もright of XXXやtop of XXXを使って、柔軟に指定が可能です。
### ドメイン図
![dom.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547300/08ba4a8a-1faf-8c9b-71c3-a29463026836.png)



```
@startuml
skinparam nodesep 100 // 水平方向の矢印の長さを調整
object 本社
object 支社
object 社員
object 所属

本社 : 会社名: string
本社 : 本籍地: string
支社 : 支社名: string
支社 : 支社番号: Long
社員 : 名前: string
社員 : 社員番号: Long
社員 : 年齢: Long
所属 : 部署名: string

note top of 支社 : 支社番号は8桁。
note left of 社員 : 年齢は満年齢。
本社 "0..*"-> "1..1" 支社
支社 "0..*" --> "0..*" 社員
社員 "0..*"-> "1..1" 所属

@enduml
```
ドメインはobject XXXで宣言します。
ドメイン名 : key: valueでドメインのもつ値を表現します。
また矢印の左右の""に自由に記載ができ、ドメイン同士の関係を表現できます。
## Tips
slinparamを使って、デザインの変更ができます。
詳細は以下のリンクにあります。
https://plantuml.com/ja/skinparam
## おわりに
plantUMLを利用するとGitでモデル図を管理できたり、複数人で同時に参照ができたりと便利なことがたくさんあります。上記の例以外にもたくさんの使い方があります。plantUMLを駆使して、あなただけのモデル図を作成してみてください。
## 参考
https://plantuml.com/ja/
https://qiita.com/umasoya/items/c1c4e583f393b27ebb7a
備忘録（CSRFについて）


Railsには、悪意のある攻撃に対してセキュリティを高める仕組みが様々用意されています。

CSRFと呼ばれるサイトの成りすましによるクラッキングに対して、どのような対策が取られているか述べてください。



A
　ApplicationControllerにデフォルトで

1
protect_from_forgery with: :exception
という記述がされている。これにより、アプリで作られたフォームに対してトークンが発行され、正しいフォームからの通信なのかを判別することができる。

・protect_from_forgery について述べられている
・トークンの発行によりクラッキングを防いでいることが述べられている
Pythonのいろんなfor文まとめ


## ■基本形
### i=0始まりでn回回す

```input.py
n = 5
for i in range(n):
    print(i)
```
```output.py
0
1
2
3
4
```
### i=xから(y-1)まで
```input.py
x = 1
y = 4 
for i in range(x,y):
    print(i)
```

```output.py
1
2
3
```

## ■文字列
### 一文字ずつ取り出す

```input.py
for char in 'string':
    print(char)
```

```output.py
s
t
r
i
n
g
```


## ■リスト型
### 要素1つずつ取り出す

```input.py
list = ['a','b','c']
for a in list:
    print(a)
```

```output.py
a
b
c
```


## ■辞書型
### 要素1つずつ取り出す
```input.py
dict = {'key1':'val1', 'key2':'val2'}
for k,v in dict.items():
    print(k,v)
```

```output.py
key1 val1
key2 val2
```
### キーだけ取り出す

```input.py
for key in dict:
    print(key)
```

```output.py
key1
key2
```
IPアドレスの調べ方

※この記事は新入社員の問いにあることないことないことないこと話した備忘録です。
## 本日の困りごと
IPアドレスってipconfigで調べられるんじゃないんですか!?
## 経緯
新型コロナの影響でリモート作業推進中。
「家からアクセス許可するのにIPアドレス教えてくんない？」と聞くと
皆こぞって「えぇっと…192.168.…」と答えてくれる。

なるほど。とりあえず皆が「ipconfigコマンドを打つとIPアドレスがわかる！」という所まで知ってることはわかったよ!!!
## 今回の解決方法
手っ取り早くこんな感じのIPアドレス確認サイトで出てきたヤツを教えてほしい。
https://www.cman.jp/network/support/go_access.cgi

IPアドレスには簡単に外向きと内向きのヤツがいる。
世界から見た住所(おうちのルータやWifiに割り振られるアドレス)とおうちの中の部屋(ルータやWifiからそれに繋いでいるコンピュータに割り振られるアドレス)だ。

ipconfigではこの「おうちの中の部屋」を調べることになる。
家からのアクセスをプロジェクトサイトから許可するのに「私の部屋は南側の角の部屋です」って言われても「へぇ。南向きなんだ。いいねぇ！」としか返せない。
勿論、ワンルームな人はipconfigで調べれられることもある。

ipconfigを打って「IPv4アドレス」の所に192.168.…と出てきたら「おや？ローカルIPだな？」と気付いてほしい。
そんなのそこで気付くものじゃないだろとか言ってはいけない。そこで気付いてくれれば全然問題ない。
[Perl][API]Chaplusを使い倒すPerlモジュールを書いた

[Botが雑談に応えられるようにするWEB APIを公開してみた話【個人開発】](https://qiita.com/maKunugi/items/b1afb6441571119729a7)で紹介されている[Chaplus](https://www.chaplus.jp/)を試してみたくてPerlで[APIモジュール](https://github.com/worthmine/API-Chaplus)を書いてみた。CPANリリースはまだ。

# 使い方

```perl

use API::Chaplus;
my $api    = API::Chaplus->new( apikey => 'your_key' );
my $answer = $api->bestResponse( utterance => '調子どう？' );
print $answer;    # お返事が表示される
```

# 使い倒し方

[APIドキュメント](https://k-masashi.github.io/chaplus-api-doc/)を熟読して様々なオブジェクトを盛り込んだ。
Chaplus-APIが用意しているオブジェクトの構造をPerlオブジェクトとして再現したのが[こちら](https://github.com/worthmine/API-Chaplus/blob/master/lib/API/Chaplus/Request.md)。
以下は抜粋。

```perl
use API::Chaplus::Request;
my $pair = API::Chaplus::UtterancePair->new(
    utterance => '肩凝った', 
    response => '適度に運動しないとね',
);

my $addition = API::Chaplus::Request::Addition->new(       
    options        => [qw(疲れた 肩凝った)],
    utterancePairs => $pair,                    # auto optimize to [$pair] by Mouse Coercion
    ngwords        => [ "ため息", "やめてしまえ" ],
);

my $state = API::Chaplus::Request::AgentState->new(
    agentName => 'エージェント',
    tone      => 'kansai',
    age       => '14歳',
);

my $req =  use API::Chaplus::Request->new(
    username   => '太郎',
    utterance  => '調子はどう？',
    agentState => $state,
    addition   => $addition,
);
my $api    = API::Chaplus->new( apikey => 'your_key' );
my $answer = $api->bestResponse($req);
print $answer;    # お返事が表示される
```
リクエストオブジェクトをAPI読み込みメソッドに食わせると、送信するJSONを自動的に生成する。

# 苦労した点

~~公式ドキュメントには特に記載がないのだが、日本語文字列は全てURLエンコードしてから渡す必要がある模様。~~←私の勘違い。してもしなくても正しいリクエスなら通る。
リクエストのJSONを生成する際に、ツリー型構造のPerlオブジェクトを単なる多重ハッシュに変換する処理を行う必要がある。~~ので、思いつきで無茶な魔改造を施し、ソースがえげつないことになっている。~~ソースコードをスッキリさせることに成功した。

# 今後
・テストの項目を増やして細分化したい
・レスポンスの中に、`keyword`などのドキュメントにまだ載っていない項目があるので、いずれフォローしたい。

__プルリクエストは大歓迎です__。

# 感想

- 形態素解析をアウトソースできる上に雑談まで自動で提供するとか神か
- Chaplusの返信してくる内容に感心することがしばしば。
- どうせPerlだからこの記事は伸びないんでしょ？
【新卒研修】教えてくれそうで教えてくれないソフトウェア産業の常識（工数編）

こんにちは、 @illypon です。

教えてくれそうで教えてくれないソフトウェア産業の常識。
今回はプロジェクトの重要な構成要素のひとつである工数の概念についてです。

# 工数って何？
人の実際の稼働を抽象化し、定量的なお金・時間に換算するための仕組みが工数です。

# 工数管理の目的とは？
見積（計画）とそれに対する実績がどうであったかを管理するために工数を使います。
ひとりひとりの社員が自分はどのプロジェクトのどの作業にどれだけの工数を使ったかを申告することにより、
プロジェクトが見積（計画）と比較して順調に進行しているか、プロジェクトの収益性が十分であるかが明確になるわけです。

# 工数は抽象化する仕組みのこと
多くの人がかかわるプロジェクトを管理するうえでは、
ひとりひとりの個性を鑑みてそれぞれを完全に定量化して合算して予算を組むことは困難です。
そのため、実際には一人一人の給料はその能力や実績に応じて異なりますが、
工数管理をする際には便宜上どんな人も同じ価値として扱います。これを単価といいます。

また、現実にはひとりひとりの能力や1か月の労働時間は異なりますが、
工数管理では、1人の人間が1か月に生み出す成果は同じ量として扱います。

これらはあくまで管理をするための工夫です。

# 人月の神話

工数は実際の人の稼働を抽象化する工夫だと言いました。
ここで注意していただきたいのは、抽象化したものは実際の人の稼働には戻らないということです。
「3人で3か月で終わる作業」というように一度抽象化した情報を
「1か月でも9人でやれば終わる作業」という現実に再変換できないということです。

話を極端にしてみれば理解しやすくなります。
たとえば「1人でだと10分で食べ終わる1杯のラーメン」をもし600人で食べれば1秒で完食できますか？
むしろ600人が1杯のラーメンを共有して食べなくてはいけない時点で、1人で食べるよりもはるかに時間がかかりそうですね。
【新卒研修】教えてくれそうで教えてくれないソフトウェア産業の常識（稟議編）

こんにちは、 @illypon です。

教えてくれそうで教えてくれないソフトウェア産業の常識。
今回は会社組織の中で開発をするなら避けては通れない稟議（りんぎ）についてです。

# 稟議って何？

たとえば、適切な目的のために会社のお金を使いたいときであっても、
会社のお金を減らすような重要なことを社員がする場合には会社の承認が必要です。
この「会社から承認をとるためのプロセス」が稟議です。
稟議は稟議書をもって回覧されることが多く、決裁者に承認または否決されます。

エンジニアにとって身近な、稟議が必要となる行為には以下のようなものがあると思います。

* 新しくプロジェクトを立ち上げるとき
* 開発に特別に必要なPCや機材、ツールを買うとき
* 技術本を買ったり勉強会に参加する費用が特別に必要なとき
* 新しく社員を募集して雇うとき
* 協力会社に仕事を発注するとき
* サービスの広告を出すとき
* 新しい事業を立ち上げるとき

# 稟議を通すには

稟議の目的の多くが会社のお金を減らすものである以上、決裁者が納得できる使い道でなければなりません。
稟議を通すのにも技術が必要です。
以下にちょっとしたテクニックを紹介しておきます。

* そもそも期初予算がないと厳しいので、期初予算にふんわりと盛り込んでおく
    * あまり細かい表現にすると予算の転用が難しくなるので、ふんわりとした費目にしておくこと
* 過去に提出された稟議書をチェックして、稟議が通る金額の相場を把握しておく
* 金額によって稟議の決裁者が変わる場合は、その金額を意識して見積を作ることも大切
* 相見積（あいみつ）をとり、2つ以上の見積書を用意する
    * 購入先が自分の中で決まっている場合は、当て馬を用意する
    * 一社からしか購入できないものであれば、その旨を明記する
* 稟議書では目的、費用、効果を明確にする
* 稟議書では投資に対するリターンを定量的に説明する
* 欠員による社員募集などであれば簡潔でよいが、その場合、早めに行動することが重要
    * ずっと行動せずにいると、この部署は人が減っても大丈夫なんだなと思われてしまうため
* 協力会社への業務委託であれば、小さいプロジェクトで実績を作っておくことも重要
Django2.xからDjango3.xでの変更点（かもしれない）の報告：静的ファイルのタグ書き換え・HttpResponseRedirectの指定方法

# 経緯

半年ぶりくらいにDjangoを触ったらバージョンが３になってました。更新速いっ！
で、昔作ったプロジェクトをカスタムしてたらエラーが何個か出たので、変更点っぽいのでDjango扱うかたに有益かもしれないので、共有します。

# 環境など

Django==2.0.4
で作ったプロジェクトをカスタムして、
Django==3.0.4
で構築した時の気づき

Python==3.6.1 (3.7だとエラーが出てしまう。今後要解析。)

# 1 静的ファイル取り扱いタグが昔の奴が使えなくなっていた

```
TemplateSyntaxError at /
'staticfiles' is not a registered tag library. Must be one of:
```

というエラーが出ました。タグを直すだけで直ります！

```
このタグを
{% load staticfiles %} 

↓のように直します
{% load static %}
```

# 2 HttpResponseRedirectの飛ぶ先の指定が変わったかもしれない。

NoReverseMatch　エラー　が出ました。下記のようにAppを指定＋コロンで直りました。（変更点かどうかわかりませんが書いておきます。）

以前動いていたのに、今回エラーで動かなかったもの↓

```
return HttpResponseRedirect(reverse('my_info'))
```

動いたもの↓

```
return HttpResponseRedirect(reverse('user:my_info'))
```
# 参考になった記事

DjangoでNoReverseMatchが発生したときに最初に確認すること
https://qiita.com/Gen6/items/8c5ca882643a4d9aaa01
【新卒研修】教えてくれそうで教えてくれないソフトウェア産業の常識（品質編）

こんにちは、 @illypon です。
[そんなテストで大丈夫か？](https://ja.wikipedia.org/wiki/%E3%82%A8%E3%83%AB%E3%82%B7%E3%83%A3%E3%83%80%E3%82%A4)

さて、教えてくれそうで教えてくれないソフトウェア産業の常識。
今回はモノづくりをする以上は避けては通れないソフトウェアの品質についてです。

# 品質が意味するものは人や状況によって異なるものであって、品質はこれという決まりはない

プロジェクトで最初にやることのひとつは、そのプロジェクトでいう品質とは何なのかを決めることです。
品質と一口に言ってもその概念にはいろいろあり、それらはソフトウェア品質特性として定義されています。

# 知って便利な品質特性

品質特性を使うと、自分たちが品質として呼びたかったものなんなのかが、網羅的にリストアップできます。
副特性は品質特性をさらに細分化したものですが、参考程度に見るだけでも大丈夫です。

[ISO/IEC 9126 ソフトウェアの品質特性モデル](https://ja.wikipedia.org/wiki/ISO/IEC_9126)

# 品質特性と実際の指標との紐づけ

品質特性ごとに実際のプロジェクトの活動で気を付けることをリストアップして明確にします。
プロジェクトを繰り返していくと、だいたいいつも同じようなことに気を付ければいいのだとわかるでしょう。
このときなるべく定性的、もしくは定量的に観測可能な指標を設置することを心がけてください。

# 品質特性にも限界はある

品質特性も万能ではありません。
品質特性は狭義の品質についてしかカバーできておらず、広義の品質の概念が抜けています。

# 会社である以上、広義の品質を意識する必要がある

私たちは信頼している人の口コミを強く信用する傾向にあります。
また、会社ではどうしても限られた予算の中で調達しなくてはならないこともありますし、
どうしてその製品・サービスを買うのかを上手に説明しなくてはならないシーンが多くあります。
その時にいわゆる品質として感じているものは狭義の品質ではなく、
もっと実感を持ちやすく身近なもの、広義の品質であるはずです。

たとえば以下のようなものです。

* 口コミ、レビューの評価
* シェアの高さ
* 会社の信用
* 保守体制の安心感（24時間365日のサポート、継続的にアップデートの提供があるなど）
* 販路の広さ（手にいれやすい）
* ライセンス形態の柔軟さ（小額からスタートできる）
* 発売日の早さ（＝使える時間が長い、オトク）
* 純粋な価格の低さ（やたら安い必要はないが、予算規模に収まらないと検討対象にもならない）
* 製品名・サービス名から受ける印象（生理的に受け入れられない）
* （矛盾のように見えるが）狭義の品質は期待できないがとにかく安い、というのもひとつの広義の品質のよさとなりうる

製品・サービスにいったい何を求められているのか、常に考え続ける必要があるでしょう。

# システムはすべてオーダーメイドなので、プロジェクト間で品質や生産性を定量的に比較できない
ソフトウェア産業の特性として、まったく同じものを二度作ることはないし、まったく同じメンバーで異なるプロジェクトを進めることもないため、プロジェクト間で品質や生産性を定量的に比較することに意味はありません。数字が独り歩きしないようにくれぐれも気を付けることです。

もちろんほかのプロジェクトから学ぶべき点は多くありますので、
よい取り組みや大きな失敗などは参考にしていきましょう。

# 品質はコストより重要ではない  品質第一主義の会社は必ずつぶれる

これは田口博士という人の有名な言葉ですが、会社で働く人にはしっかりと認識していてもらいたいです。
会社にとって一番大事なのはコストです。コストをコントロールしなければ会社はつぶれます。
一方で、品質が期待と乖離しすぎると顧客からの信用を失い、その場合も会社はつぶれます。

期待を裏切らない程度の品質を実現しつつ、コストをコントロールして利益を出す。
これが会社の基本です。

# バグはすべて直さなくてはいけないわけではない

報告されたバグを片っ端からすべて直そうとすれば、おそらくあなたは物事の優先順位を見失って多くの時間を失い、あなたの任されたプロジェクトの作業は停滞するに違いありません。
大事なのは、このプロジェクトはどのような性質を持ったプロジェクトなのか、
そしてどのようなバグであれば直さなくてはならないのかを明確にしておくことです。
自分で判断できないならば、ベテランの人に作業の優先順位をつけてもらいましょう。

一方、バグを放置しすぎると、プロジェクトが進むにつれて直したいけど直せないという事態になることも多いです。
「このサービスでこんな不具合が起きたら大変なことになる」という想像をいつもするようにして、
残したくないようなバグははじめから作らないようにすることが大切です。

# 品質保証とは一定の品質を約束することにすぎない

品質保証という字面だけ見ると、とても品質のいいもののように勘違いをしがちです。
実際には製品・サービスごとに決めた何らかの品質を満たしていることを約束しているにすぎません。

身近な電化製品の例でいうと、保証書に保証期間1年と書かれていることがありますが、
あれは1年間は故障しないことを約束しているだけで、1年を1秒でも過ぎた瞬間に故障することを否定しないという意味です。

必要以上の品質を追求してもコストにしかなりません。
どういう品質のものを作りたいのかというのは、何を作りたいのかと同義です。

# 要求された品質を満たしていなければ、納期には間に合っていない

「品質を下げて納期に間に合わせる」ダメな現場にありがちな話ですが、
ちゃんと炊けてないお米をお客さんに食べさせるような行為です。
それを間に合ったとは言いません。
Kony Internationalization API (i18n)

#目次
1. Kony Internationalization APIの紹介
2. サンプルロジック

##Internationalization APIとは？
・Internationalization APIは、さまざまな地域で複数の言語をサポートできるようにアプリケーションを強化するプロセスです。 Internationalization APIは「i18n」と略されます。 「kony.i18n」は、多言語アプリケーションを開発するための包括的な機能を提供します。

・「i18n」APIについては以下のリンクを参照 
 https://docs.kony.com/konylibrary/visualizer/viz_api_dev_guide/content/internationalization.htm

すべてのi18nキーとそのペア値を含むプロパティファイルを使い、言語対応を行うことができます。そのプロパティファイルはロケール（国や地域の設定）で固有でなればなりません。
プロパティを指定する場合、
(language_Country).propertiesの命名規則に従います。

これから、実装の詳細を説明します。

##サンプルの作成

・多言語プロファイルのサンプルを作成する
[Edit]-> [Internationalization(i18n)]-> [Configure Locales]をクリックし、使用したい言語を選択します 
文字列を挿入する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/d4239a34-48ee-f954-10f4-ec1d305ec709.png)

・多言語プロファイルを作成する
各ローカルのキーと値を入力->完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/5da09170-e85c-3111-3856-4cf700fed81f.png)

・レイアウト
スイッチとリッチテキストでシンプルなフォームを作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/39bc2abe-1afc-5624-9eb8-4897d163c632.png)

ローカライズされた文字列に対応するキーを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/12ff2454-f377-5412-1417-266da9c97f7d.png)

・アクション
スイッチのonSlideアクションを設定し、kony.i18n.setCurrentLocaleAsyncを使用して、指定されたロケールをアプリケーションの現在のロケールとして設定します。

```javascript

define({
    changeLanguage: function () {
        var selectedIndex = this.view.switchChange.selectedIndex;

        if (selectedIndex === 1) {
            this.change("vi_VN");
        } else {
            this.change("en_US");
        }
    },

    onSuccsess: function () {
        var txt = kony.i18n.getLocalizedString("txt");
        this.view.rtxInternational.text = txt;
    },

    change: function () {
        kony.i18n.setCurrentLocalAsync(key, this.onSuccsess)
    }

});
```

・結果
スイッチボタンを押すと、対応するローカライズされた文字列が表示されます
DynamoDBにテーブルを作成しTypeScriptで登録機能を実装する

##概要
AWSのDynamoDBにテーブルを作成し、そのテーブルにvue.js、TypeScriptで作成した画面から入力された値を登録する機能を実装した。
今回この機能を実装するにあたり、[こちら](https://usefuledge.com/pb_00018_dynamodb_cre_ins.html)のサイトを参考にした。

##実装した機能
商品コード、個数、価格を入力することができる画面を作成し、その入力された値が事前にDynamoDBに作っておいたテーブル【PRODUCTS】にそれぞれの値が登録される機能。

##AWSのコンソールからDynamoDBにテーブルとカラムを作成する
1. DynamoDBを開き、「テーブル作成」からテーブル名とプライマリーキーを持つカラムを設定する
2. 「テーブル設定」で作成したいテーブルに合わせた設定する

##Vue.jsでテキストボックスを持つ画面を作成
```vue:add.vue
<template>
  <v-layout justify-center>
    <div>
      <form class="add-item" @submit.prevent="addCode">
        商品コード
        <input type="text" ref="code" />
        商品名
        <input type="text" ref="name" />
        単価
        <input type="text" ref="price" />
        <button>登録</button>
      </form>
    </div>
  </v-layout>
</template>
```
テキストボックスを画面に表示させるだけのものなので、あまりデザインなどは今回気にしていません...

##入力された値をTypeScriptでDynamoDBに登録する
```vue:add.vue
<script lang="ts">
import { Component, Vue, Watch } from "vue-property-decorator";
//プロダクトをインポートする
import { Product } from "@/product.ts";
// AWSを使用できるようにインポートする
import * as AWS from "aws-sdk";

// AWSのユーザー設定(※csvファイルを参照)
AWS.config.update({
  region: "sample",
  accessKeyId: "sample",
  secretAccessKey: "sample"
});

@Component
export default class App extends Vue {
  private addCode() {
    //DynamoDBに商品情報を登録する
    var docClient = new AWS.DynamoDB.DocumentClient();
    let code = this.$refs.code as HTMLInputElement;
    let name = this.$refs.name as HTMLInputElement;
    let price = this.$refs.price as HTMLInputElement;
    let params: any = {
      TableName: "PRODUCT",
      Item: {
        CODE: code.value,
        NAME: name.value,
        PRICE: price.value
      }
    };

    docClient.put(params, (err, data) => {
      if (err) {
        console.log(Unable to add item: ${JSON.stringify(err, undefined, 2)})
      } else {
        console.log(PutItem succeeded: ${JSON.stringify(data, undefined, 2)})
      }
    });
  }
}
</script>
```
※あたり前のことだが、テーブルに設定している型と登録する値の型を合わせなければ登録できないため気を付ける。

###参考にしたサイト
[TypeScript で AWS DynamoDB のテーブル作成からデータ登録までを行う]
(https://usefuledge.com/pb_00018_dynamodb_cre_ins.html)
Appleは個人情報を削除しない

アップルが私のメールアドレス(名前が入っています＝個人情報)を削除してくれない。

<img width="830" alt="スクリーンショット 2020-03-12 10.43.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39852/e8323347-9138-76af-ef25-3c048de5ac1a.png">

<img width="849" alt="スクリーンショット 2020-03-12 10.44.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/39852/449e8aba-b40d-7569-1a7f-6c3f8926d15d.png">
CentOS素人がVagrantディスク拡張でハマったこと

##やったこと

[VagrantのCentOSのディスク容量を増やす手順](https://qiita.com/freeneer/items/ee1ee48cf7895c9f7408)

を参考に進めた

##ハマったこと
>[パーティションタイプの変更](https://qiita.com/freeneer/items/ee1ee48cf7895c9f7408#%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AE%E5%A4%89%E6%9B%B4)

のところで、最後に

``` shell-session
Command (m for help): w
```

これを実行して書き込まないといけないらしい


##ハマったこと2
>[XFSファイルシステムの拡張](https://qiita.com/freeneer/items/ee1ee48cf7895c9f7408#xfs%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%B7%E3%82%B9%E3%83%86%E3%83%A0%E3%81%AE%E6%8B%A1%E5%BC%B5)

xfs_growfs コマンドはCentOS7からだと…

``` shell-session
sudo resize2fs /dev/mapper/centos-root
```

こんなコマンド使うらしい（よくわかってない）


## 参考記事
https://qiita.com/freeneer/items/ee1ee48cf7895c9f7408
Githubでforkした時のGitリモート設定例

# What's this?

「自分のアカウントにforkしてからプルリクエストしてね」って言われた時に実施するGitリモート設定のメモ。

## 前提
フォーク元にはmasterとdevelopブランチが存在し、developにプルリクエストする運用。

# 手順

1. Githubでフォーク元リポジトリから自分のアカウントにforkする
2. ローカル環境にforkしたリポジトリをcloneする
3. gitリモート状態確認

```bash
% git remote -v
origin	git@github.com:自分のアカウント名/リポジトリ名.git (fetch)
origin	git@github.com:自分のアカウント名/リポジトリ名.git (push)
```

4.フォーク元リポジトリをupstreamとしてリモート追加

```bash
% git remote add upstream git@github.com:フォーク元アカウント名/リポジトリ名.git
```

5.gitリモート再確認

```bash
% git remote -v
origin	git@github.com:自分のアカウント名/リポジトリ名.git (fetch)
origin	git@github.com:自分のアカウント名/リポジトリ名.git (push)
upstream	git@github.com:フォーク元アカウント名/リポジトリ名.git (fetch)
upstream	git@github.com:フォーク元アカウント名/リポジトリ名.git (push)
```

6.フォーク元のdevelopブランチ（upstream）を追従させる

```bash
% git fetch upstream
 * [new branch]      develop    -> upstream/develop
 * [new branch]      master     -> upstream/master

% git branch -u upstream/develop develop
Branch 'develop' set up to track remote branch 'develop' from 'upstream'.
```

# 運用
```bash
% git branch
* develop
```
- 最新のdevelopブランチをフォーク元から取り込む

```bash
% git pull
```

- 取り込んだdevelopを元にブランチを作成し実装を開始

```bash
% git checkout -b example_feature
```

- （フォーク元に変更が有れば）随時取り込めば良い

```bash
% git checkout develop
% git pull
% git checkout example_feature
% git merge develop
```

- 実装が完了したらフォーク元のdevelopブランチに向けてプルリクエスト実施
Redmineプラグイン開発の備忘

Redmineのプラグイン開発をしているときに、忘れてしまいそうな事、すぐに忘れてしまうことを備忘として残している、個人的なメモ。
作成したプラグイン
https://github.com/momibun926/redmine_issue_evm

## 日付関連
日付、時間の表示形式はRedmineで使われている形式に合わせる。

* format_date

```
<%= format_date(baseline.minimum_start_date) %>
```

* format_time

```
<%= format_time(baseline.updated_on) %>
```

Ruby Holidays Gemを使って祝日を把握。事前に読み込んでおかないと使えなかった。

``` init.rb
  Holidays.load_all
```


## 検索、活動関連
しばらく実現できなくて悩んだ挙句、なんとか実装できているっぽい。正直ちゃんと理解できていない。

```
  # for activity page.
  acts_as_event title: Proc.new { |o| "タイトルに表示したい文言"},
                description: :description, <-モデルのカラムを指定
                datetime: :updated_on, <-モデルの更新日
                type: Proc.new { |o| "evmbaseline-" + (o.created_on < o.updated_on ? "edit" : "new") },
                url: Proc.new { |o| { controller: "evmbaselines", action: :show, project_id: o.project, id: o.id } } <-モデルのVIEWに飛ばしたいときに指定

  acts_as_activity_provider scope: joins(:project),
                            permission: :view_evmbaselines, <-プラグインのパーミッションを指定
                            type: "evmbaseline",
                            author_key: :author_id

  # for search.
  acts_as_searchable columns: ["#{table_name}.subject", "#{table_name}.description"],　<-検索対象にしたいカラム
                     preload: :project,
                     date_column: :updated_on
```

## チケット関連
直近の進捗率を変更した日付が欲しくてジャーナルを検索して取るようにした。

```
Journal.where(journalized_id: ”知りたいチケットのIDを指定”, journal_details: { prop_key: "done_ratio" }).
        joins(:details).
        maximum(:created_on)
```

子、孫、、プロジェクトすべてのチケットを検索する。

```
@project = Project.find(params[:project_id])
Issue.cross_project_scope(@project, "descendants")
```

上記の検索に対して、条件（Where）を可変にしたいとき、こんな感じのメソッド作って、条件をHashで渡す。条件が指定されていなければ、ALLで検索する。

```
def evm_issues(proj, condition = " 1 = 1 ")
  Issue.cross_project_scope(proj, "descendants").
    where(SQL_COM.to_s).
    where(condition)
end
```

使い方。子孫プロジェクトすべてから指定したTrackerのチケット取得する

```
@project = Project.find(params[:project_id])
condition = { tracker_id: 取得しいTrackerのID }
tracker_issues = evm_issues @project, condition
```
three.js と CANNON.js で ニュートンのゆりかご を作りたい！

## はじめに
最近、Three.jsにハマっていて物理演算が可能な Cannon.js と組み合わせて何か作りたかった(※物理演算に関する知識はありません)。何を作ろうかと悩んだ末にあるものが思いつきました。

それが 「ニュートンのゆりかご」(正式名称初めて知った)

こういうの↓([Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%8B%E3%83%A5%E3%83%BC%E3%83%88%E3%83%B3%E3%81%AE%E3%82%86%E3%82%8A%E3%81%8B%E3%81%94 "ニュートンのゆりかご"))より

![](https://upload.wikimedia.org/wikipedia/commons/d/d3/Newtons_cradle_animation_book_2.gif)

## 初めに結果から

なんか変なのできた。気持ち悪い。

<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="js,result" data-user="RyotaPen" data-slug-hash="xxGPZPj" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Newton's Yurikago">
  <span>See the Pen <a href="https://codepen.io/RyotaPen/pen/xxGPZPj">
  Newton's Yurikago</a> by Ryota (<a href="https://codepen.io/RyotaPen">@RyotaPen</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

ソースは[こちら](https://github.com/TRyota-lab/Newton-s-Yurikago)

## 解説
細かい説明はしませんが、大まかにポイントだけ解説します。

### 紐
鉄球を吊るしている紐をどのように表現するか？ですが、複数の球を作成しそれぞれを繋ぐ方法でやってみました。いわゆるチェーンってやつです。

この関数でチェーンを生成しています。

```javascript
/**
 * チェーンを生成する
 * @param {CANNON.Vec3} origin 基準点(チェーンの始点)
 * @param {number} xAngle X角度(°)
 * @param {number} zGap Z軸ずらし距離(m)
 */
function createChain(origin, xAngle, zGap){}
```

生成するチェーンの球を複数生成し、それぞれを固定します。
固定する場合は、`CANNON.DistanceConstraint`オブジェクトで固定に関する定義を行い、`world.addConstraint`関数で物理演算の世界へ追加します。

```javascript
world.addConstraint(
  new CANNON.DistanceConstraint(
    <オブジェクト1>,<オブジェクト2>,<固定する距離>));
  }
```

なお、`new CANNON.DistanceConstraint`の第3引数(距離)は省略可能です。省略した場合、現在の位置を使用して固定されます。

### 鉄球同士が衝突したときの動き
こんな感じで良いのでしょうか…？
とりあえず、気持ちよく跳ね返ってほしいので反発係数は高めに設定。

```javascript
let contact = new CANNON.ContactMaterial(
  pairs[idx - 1].ironSphere.body.material, //ひとつ目
  pair.ironSphere.body.material, //ふたつ目
  {
    contactEquationRelaxation: 3, // 接触式の緩和性
    friction: 0.1, //摩擦係数
    frictionEquationRelaxation: 3, // 摩擦式の剛性
    restitution: 0.9 // 反発係数
  }
);
world.addContactMaterial(contact);
```

### 一つの鉄球を支えるチェーン同士を固定
これはズルですが、鉄球を支えるチェーン同士がバラバラに動いてしまうので、固定しています。まぁ気休め程度にしか効果がないですが。

```javascript
for (let i = 0; i < chain1.length; i++) {
  // 対向のチェーンと接続
  world.addConstraint(
    new CANNON.DistanceConstraint(chain1[i].body, chain2[i].body));
}
```

## 要改善ポイント？
動きを見ていて、紐(チェーン)が色々な方向へ揺れてしまうことが問題なような気がしてきました。
なので、紐の部分をチェーンではなく、普通に細い棒に変えたらどうなるかはやってみようかなって思っています。
ニュートンのゆりかごの動きをみると紐が曲がることはないので棒でも一緒ですよね。

## 最後に
急募：綺麗に気持ち良くゆりかごする方法
クロスコンパイルでライブラリを使う(libusb)

RaspberryPiで使える某入退室管理システムをPython2のNFCPyからCベースのものに置き換えるためにクロスコンパイル環境をDocker上で用意しようと思いあれ？となりいろいろ調べたのでそのメモです。

# TL;DR
debian系のLinuxで下記のコマンドを実行する

```　sh
# RaspberryPi向けのアーキテクチャもインストール可能にする
dpkg --add-architecture armhf
# クロスコンパイル用のツールをインストールする
apt install -y crossbuild-essential-armhf
# RaspberryPi向けのアーキテクチャのlibusb1.0.0をインストールする
apt install -y libusb-1.0-0-dev:armhf

```

# 解説
クロスコンパイルする際にリンクするライブラリもコンパイルするアーキテクチャに対応したものを用意する必要がありますが、通常aptなどでインストールするとコンパイルをする環境のアーキテクチャ(例えばamd64など)に対応するライブラリがインストールされます。
さてどうすればいいのかと少し悩みましたが、簡単に言えばRaspberryPi向けのアーキテクチャ(armhf)もインストールを可能にすればいいのです。

まず始めにパッケージ管理ツール(dpkg)にarmhfアーキテクチャのパッケージもインストールできるように設定する必要があります。
`dpkg --add-architecture armhf`でarmhfを追加します。

あとは対応したアーキテクチャのパッケージをaptでインストールします。
ここではlibusbをインストールしていますが、対応しているパッケージであれば`apt install -y libusb-1.0-0-dev:armhf`のようにパッケージ名の後ろに`:armhf`などアーキテクチャをつけるとインストールできます。

最後におまけですがクロスコンパイル環境を用意したいので
`apt install -y crossbuild-essential-armhf`などで忘れずにクロスコンパイル用のツールをインストールしてください。

# Dockerfile
冒頭にDocker上でクロスコンパイル環境を用意したいと言った通りDockerfileも用意しています。
Dockerfileの場合は以下の通りです。ちなみに見ると分かりますがgoでのコンパイルにも対応しています。

``` Dockerfile
FROM golang:1.13.6-stretch

RUN dpkg --add-architecture armhf
RUN apt update && apt install -y crossbuild-essential-armhf libusb-1.0-0-dev:armhf

ENV CC arm-linux-gnueabihf-gcc
ENV CXX arm-linux-gnueabihf-g++

ENV CGO_ENABLED 1
ENV GOOS linux
ENV GOARCH arm
```

# あとがき
クロスコンパイルでlibusbなどのライブラリを使う方法がなかなかわからず苦戦したのでまとめてみました。
これで同じように悩む人が減ることを願っています。
もし間違いなどがあればご指摘いただければ幸いです。

# Reference
https://qiita.com/myahal@github/items/fc332e53713df244518f
Fargate+Selenium+ChromDriverでスクレイピング時に"tab crush"が頻発した

#はじめに
Fargateにchromedriverを格納したコンテナをデプロイし、スクレイピングを実行する環境を構築しました。タスクを実行すると"tab crush"が発生し、コンテナが停止してしまいました。少しつまづいたので、備忘録を兼ねて解決策を投稿します。

#環境
以下の環境で実行しました。
![my-first-document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/560888/a842207f-1bf2-dc02-6120-f69336a32772.png)

・APP container
　使用したDockerImage：python:3.7-slim
　メモリ：1GB
　タスクCPU：0.25V

・selenium container
　使用したDockerImage：selenium/standalone-chrome
　メモリ：1GB
　タスクCPU：0.25V

#状況
・Fragateでタスクを実行するとタスクは正常に起動しスクレイピングが実行される。
・数分後にタスクの状況を確認すると"tab crush"が発生し、タスクがSTOPしている。
・"tab crush"は毎回発生するが、停止位置がまばら。

#デバッグ
Cloud Watchのメトリクスを確認するとSeleniumコンテナのメモリ使用率が99%に張り付いていることが発覚。Seleniumコンテナのメモリを8GBにしました。するとスクレイピングを完走してくれるようになりました。
[latex]IEEEtranでalgorithmパッケージの使い方

# はじめに

IEEEにlatexで論文投稿する場合、IEEEtran.clsというクラスファイルを使います。
このクラスファイルのHOWTOには、アルゴリズムのfloating environmentとしてalgorithm.sty, algorithm2e.styを使うな、と書かれています。
では、どうすればいいのか、というとfigure environmentを使え、ということらしいです。

algorithm.styの使い方はググればいっぱい出てきますが、algorithm.styのfloating environmentを使わずにfigure environmentを使ってアルゴリズムを載せるコードがあまり見当たらないので、例を載せておきます。

方法としてはfigureの中にalgorithm環境を埋め込めばOKです。

### 参考
https://tex.stackexchange.com/questions/147598/
https://tex.stackexchange.com/questions/82271/

# 例

algorithmic.styとalgorithmicx.styはどちらを使っても良い。
以下の例はalgorithmicx.sty用

```latex
\usepackage{algorithm}
\usepackage{algorithmicx}
\usepackage{algpseudocode}

% 中略

\begin{figure}[!t]
  \begin{algorithm}[H]
    \caption{Caption}
    \label{alg1}
    \begin{algorithmic}
      \Require args $x_i$
      \Ensure total $s$
      \State $s \leftarrow 0$
      \For{$i=1,\cdots,n$}
        \State $s \leftarrow s + x_i$
      \EndFor
      \State \Return $s$
    \end{algorithmic}
  \end{algorithm}
\end{figure}
```

![alg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156722/c353845e-2d36-4787-65f3-b0acaca23eec.png)
[android] ターミナルからAVDを起動する

# はじめに
VScodeでReactNative開発するのにターミナルからAVDを起動できるようにすると便利なので、環境変数にAndroidのパスを通します。

# 開発環境
Linux

# やり方

```
# ------------------------------------------------------------------
# Android
# ------------------------------------------------------------------
export ANDROID_HOME="$HOME/Android"
export ANDROID_SDK_ROOT="$ANDROID_HOME/Sdk"
export PATH="$ANDROID_SDK_ROOT/tools/bin:$PATH"
export PATH="$ANDROID_SDK_ROOT/emulator:$PATH"

```

# 確認

```terminal

❯ emulator -list-avds                              2020/03/12 10:23:44

Lolipop
Nexus_6_API_28


❯ emulator -avd Lolipop                            2020/03/12 10:25:06

 - Start Android Studio
 - Select menu "Tools > Android > SDK Manager"
 - Click "SDK Tools" tab
 - Check "Android Emulator" checkbox
 - Click "OK"
```

# まとめ
AVDがターミナルから起動・停止できるようになりました。
Dockerでメールフォーム開発用コンテナを3分クッキング

## TL;DR

コードだけ読んでいただければよろしいかと。

## 前置き

実はメールフォーム設置だけの案件を意外と多く請けます。なお現在のところPHP率100%です。

今まではローカルの環境構築に `php -S` でローカルサーバー建てて [mailcatcher](https://mailcatcher.me/) に投げてテストしていて、正直これで十分だと思っていますしこれからもこれで行く気がします。軽いし。

しかしながらメイン業務であるフロントエンド開発では、基本としてDocker環境を活用した作業になることが多く、ローカル環境はこれからはDockerだな！というわけでミニマムなメールフォーム開発用コンテナを試し書きしてみたところです。

前置きおわり。

## やってみた

### ディレクトリ構成

```
/
├ php/
│ ├ php.ini
│ └ Dockerfile
├ html/
└ docker-compose.yml
```

想定するディレクトリ構成はこんな感じにしました。登場人物も少ないので割と自由に置いて良いと思います。

### docker-compose.yml

```yml:docker-compose.yml
version: "2"
services:
  mailhog:
    image: mailhog/mailhog
    ports:
      - 1025:1025
      - 8025:8025
  php:
    image: php:7.4-apache
    build: ./php
    volumes:
      - ./php/php.ini:/usr/local/etc/php/php.ini
      - ./html:/var/www/html
    ports:
      - 8080:80
```

mailcatcher の代わりに [MailHog](https://github.com/mailhog/MailHog) を使います。

mailhog のポートは `1025` がSMTPで、`8025` がWebメーラー閲覧用です。 `http://localhost:8025` にアクセスすると mailcatcher の様にローカルのWebメーラーが見られます。その辺り詳しくは [MailHogのREADME](https://github.com/mailhog/MailHog) で。


### php の Dockerfile

```dockerfile:php/Dockerfile
FROM php:7.4-apache

RUN curl -sSL https://github.com/mailhog/mhsendmail/releases/download/v0.2.0/mhsendmail_linux_amd64 -o mhsendmail \
    && chmod +x mhsendmail \
    && mv mhsendmail /usr/local/bin/mhsendmail
```

`docker-compose.yml` の `services.php.build` で設定されているビルド用のDockerfileの内容です。

`php` から `mailhog` 宛にメールを送信するためにはその間を繋ぐ何かがなければいけません。そこで `mailhog` から提供されている [mhsendmail](https://github.com/mailhog/mhsendmail) というツールに `sendmail` に成り代わってもらい、間をつないでもらいます。上で行っているのは、その `mhsendmail` の導入です。

### php.ini

```ini:php/php.ini
[Mail]
sendmail_path = "/usr/local/bin/mhsendmail --smtp-addr=mailhog:1025"
```

`docker-compose.yml` の `services.php.volumes` に記述した `php.ini` の中身です。上で導入した `mhsendmail` でメールを投げる設定を追記します。

この他にも `php.ini` でphpの設定をいじりたいケースも出てくると思うので、このように `php.ini` を `volumes` で外から編集できるようにしておくのは良いと思います。

### ビルドして起動してテスト

```bash
$ docker-compose up --build
```

`html/index.php` などをこさえて送信テストをしてみましょう。 `http://localhost:8080` でアクセスできるはずです。

```php:php/index.php
<?php

var_dump(
  mail(
    'to@example.com',
    'TEST MAIL',
    'This is test mail',
    'From: from@example.com'
  )
);
```

`http://localhost:8025` のWebメーラーで受信が確認できればOKです。


## おしまい

これだけの事でDockerを使うのは正直リソースの無駄だと思うので、ミニマムな案件は `php -S` と `mailcatcher` で十分でしょう。だって軽いんだもの。

もっと大きな開発案件でメール送信をローカルで試験したい時には `mailhog` の箇所だけ役立つかもしれません。
いつも忘れる.bash_profile

## はじめに
新しい環境だといつも忘れるプロンプトの設定。。
箇条書きでメモです。

以下の記事を参考にさせていただきました、この場を借りてお礼申し上げます。捗るぜ！

[.bash_profileと.bashrcについて](https://qiita.com/shyamahira/items/260862743e4c9794b5d2)
[本当に正しい .bashrc と .bash_profile の使ひ分け](https://qiita.com/magicant/items/d3bb7ea1192e63fba850)
[.bash_profile ? .bashrc ? いろいろあるけどこいつらなにもの？](https://qiita.com/hirokishirai/items/5a529c8395c4b336bf31)

## 結論
Homeディレクトリに`.bash_profile`をviとかtouchで作成。
`export PS1="[\u@\h]$ "`を追記して、source .bash_profileで再読み込みしてあげる。

## 追記
zshになったので手順が変わりました。

`/etc`に`zshrc`ファイルが存在し、デフォルトのプロンプトはここで定義しています。
以下はzshrc抜粋。書き換えちゃった後ですが。。

```
# Default prompt
PS1="%n$ "
```

記法はbashとちょっと違いますが、そんなに乖離がある訳でもないので大丈夫だと思います。
ここをいじくってターミナルを再起動すれば反映されます。たぶん`source ./zshrc`とかでも大丈夫です。

また、bash同様ファイル毎の違いがありますね。
全ユーザーに反映されるとか、ログインユーザーのみとか、シェルプロンプト起動時のみとか。

ちょっとだけ調べたので以下にリンクを貼っておきます！

https://leico.github.io/TechnicalNote/Mac/catalina-zsh

https://www.webdesignleaves.com/pr/plugins/mac_terminal_basics_05.html


## おわりに
ユーザ名@ホスト名にしつつ、装飾で大かっこと権限の後に半角スペースを入れています。
3ブロック目にカレントディレクトリを追加しようかと思ったのですが、
別にいらない気がするので今回はやめておきました。

簡単ですが以上です。
【ClozeTS】TypeScript穴埋めクイズ#3 (Type assertions)

[ClozeTS]とは、TypeScriptの穴埋めクイズです。コードの一部が「穴」になっていて、その部分に適切なコードを当てはめて解く形式のクイズです。

[ClozeTS]: https://qiita.com/suin/items/3090ce2d1b1407577006

## 問題

このTypeScriptコードの中の`__MISSING_CODE__`を適切なコードに置き換えて、コードを完成してください。

```typescript
let someValue: any = "this is a string";
let stringLength: number = (someValue as __MISSING_CODE__).length;
```

→**[TypeScript Playgroundでコードを書く](http://www.typescriptlang.org/play/?esModuleInterop=false&declaration=false&module=1&ssl=2&ssc=42&pln=2&pc=58#code/DYUwLgBAzg9gtiAagQ2AVxALgsgdgTwgF4IAiMACwEsoIadowAnK3Ac1IG4AoUSKZqzYAZEO0rZcaOACMQTYhAAUsBCnQgctAPraAsgEkAykYMA5AOLaAwgHkAIgFFdASgB0ocRU5A)**←

__ルール__

* コメントで`Error`と書かれた行は、**コンパイルエラーになる**ようにする。
* それ以外の行は、コンパイルエラーにならないようにする。
* 型に`any`は使ってはならない。(any縛り)
* `__MISSING_CODE__`の部分以外は変更してはならない。
* コードを書く際にはTypeScript Playgroundをお使いください。(バージョンやコンパイル設定統一のため)

__ヒント__

* [基本の型 | TypeScript 日本語ハンドブック | js STUDIO](http://js.studio-kingdom.com/typescript/handbook/basic_types#type_assertions)

__解けたら__

* 回答はコメント欄に投稿する。(任意)
* 自分と同じ回答がある場合、投稿の代わりに「いいね」する。(任意)
* 気に入った回答には「いいね」する。(任意)
* 技巧輝く回答には、ちょっとした解説を添える。(任意)
* →[Q.なぜコメントしたり、いいねするといいの？](https://qiita.com/suin/items/3090ce2d1b1407577006#2-%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E6%AC%84%E3%81%A7%E5%9B%9E%E7%AD%94%E3%82%92%E5%85%B1%E6%9C%89%E3%81%99%E3%82%8B)

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">【ClozeTS】TypeScript穴埋めクイズ#3 (Type assertions) <a href="https://t.co/VsPSEOejZB">https://t.co/VsPSEOejZB</a><br><br>このクイズの難しさはどのくらいでしたか？</p>&mdash; suin (@suin) <a href="https://twitter.com/suin/status/1237898673020784640?ref_src=twsrc%5Etfw">March 12, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【回答編】Keras（TensorFlowバックエンド）でのマルチコア・マルチプロセッサ並列化、GPU並列化はどんな実装になっているのだろう？

どうも ryo_grid です。
回答編としているものの、クエスチョンに関する記事は自分のブログに書いていたので、ちょっとアレですが、その点はご容赦下さい（Qiitaで共有しても意味のない内容は自分のブログに書くようにしている、という事情です）。
　
というわけで、自身のブログで恐縮ですが、以下の記事への一部回答ともなっている記事を、
[【Need Help!】Keras（TensorFlowバックエンド）でのマルチコア・マルチプロセッサ並列化、GPU並列化はどんな実装になっているのだろう？ - Ryoの開発日記 Neo!](https://ryogrid.hatenablog.com/entry/2020/03/04/081144)

先日Qiitaに書きました。
[Kerasのfit_generatorのプロセス並列化の実装を読んでみた（おまけ: GPUはじめ並列化実装のもろもろの話） - Qiita](https://qiita.com/ryo_grid/items/0db4958192f3cc3765a5)
　
加えて、上のQiita記事では継続調査となっていた、マルチコア（マルチプロセッサでも同様だと思いますが）での並列化については、自分でTFのコードを読むまでもなく以下の記事が回答で良さそうです（上のブログ記事を書いた時点で、インターネッツを漁った時にはヒットしなかったんだよなあ・・・）。
[マルチスレッドに関するTensorFlowの内部構造について - Qiita](https://qiita.com/hisak/items/68c3bc8b3eeaa3257aaf)
　
上のスレッド並列実装に関する記事は2016年のものなので、TF1.x時代だと思われますが、該当するコードは現在のTFのgithubリポジトリのmaster（のHEAD）にもありました。
tf.compat.v1.xxxx という形で1.x系のコードが動かせるように残してあるコードも2.x系にはあって、そこに残っているコード、という可能性もゼロではありませんが（2.x系に取り込まれたKerasのfitやpredictが該当コードの呼び出しをしているかまではコードを追っていません）、当時のバージョンでもfit_generator（上にリンクした私が書いたQiita記事等ご参照）などはあったはずで、それと同様のマスタ・ワーカ型というのも検討されたでしょうし、現時点での最新あたりのTFで利用できる tf.distribute.Strategy モジュールに含まれるStrategy が採用している設計での並列化というのも検討されたであろうと思います。で、その上で、スレッド並列で動作する行列演算ライブラリを叩くという実装が選択されたはずで、それが、4年経ったとはいえ、変わっているとは考えにくいと個人的には思います（細かい実装は変わっているかもしれないですが、大枠の設計は変わっていないはず）。
　
以上！
Atom用plantuml-previewプラグインの設定を改善する

# 忙しい人向け

* HomebrewでPlantUMLをアップグレードするたびにplantuml-previewプラグインの設定を変えなくてはならず、煩わしい
* jarファイルのパスを `/usr/local/opt/plantuml/libexec/plantuml.jar` と指定すればよい

# 詳細

Atom向けプラグインの[PlantUML Preview](https://atom.io/packages/plantuml-preview)では、ユーザーがPlantUMLのjarファイルを別途用意する必要があります。 `brew install plantuml` でインストールしたものを使うには、 `/usr/local/Cellar/plantuml/1.2020.2/libexec/plantuml.jar` （ `1.2020.2` はバージョン番号）をプラグインの設定画面で指定すればOKです。

<img width="576" alt="A11BAA08-98EF-4878-9E5F-BE9863EBB63A.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528506/7c0a43ad-a238-fc7a-9b3b-b693806e5339.png">

というのがよくある使い方解説なのですが、これだと `brew upgrade plantuml` でバージョンアップするたびにjarファイルのパスが変わってしまい、その都度プラグインの設定も変更しなくてはなりません。

PlantUMLのインストール済みファイルは、実は `/usr/local/opt/plantuml` からシンボリックリンクされており、こちらから辿れば固定のパスで参照できます。

```shell-session
$ brew --prefix plantuml
/usr/local/opt/plantuml

$ ls -l /usr/local/opt/plantuml
lrwxr-xr-x  1 user1  users  27  3  5 11:01 /usr/local/opt/plantuml -> ../Cellar/plantuml/1.2020.2

$ ls -l /usr/local/opt/plantuml/libexec/
total 16344
-rw-r--r--  1 user1  users  8366053  3  1 20:09 plantuml.jar
```

# 結論

`/usr/local/opt/plantuml/libexec/plantuml.jar` を指定すればよい

# おわりに

この記事を書いている途中で見つけたのですが、[Markdown Preview Enhanced](https://atom.io/packages/markdown-preview-enhanced)というプラグインのことを知りました。こちらもPlantUMLのプレビューに対応しており、jarファイルを内包しているのでわざわざパスを設定せずに使えるようです。
[aws,rails,css]awsにデプロイした時にcssが反映されないエラーの解決例

#1.エラーの原因は？
ec2上の`etc/nginx/conf.d/rails.conf`の記述内容の参照先の誤りにより、

`/var/www/アプリ名/public/asset`とすべきところを
`/var/www/アプリ名/current/public/asset`としていたためでした

#2.解決方法

下記コマンドで設定箇所に飛びます

```
[ec2-user@ip-111-11-11-11 ~]$ cd /etc/nginx/conf.d
[ec2-user@ip-111-11-11-11 conf.d]$ sudo vim rails.conf
　　　　　　　　　　　　　　　　　　　　#↑書き込みを行うのでsudoをつけてください（権限ありで開くコマンド）
```

下記のように内容を編集してください

```
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/freemarket_sample_62d/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name 3.115.38.38;

  # ↓このpathを誤まってcurrent/publicの中を参照するようにしていました。下記が正解です。
  root /var/www/freemarket_sample_62d/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
# 筆者は↑にもcurrent指定してしまっていたためこのように修正しました。
  }

  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
```

簡素ですがこれで筆者はエラー解決をすることができました


#3.なぜわざわざ記事にしたか
cssが反映されないで検索すると、コンパイルか、config/deploy/production.rbに関する記事しかヒットせずこの間違いにたどり着くまでにとても苦労したため、後の方々に少しでも早く解決していただければと思い作成しました。

筆者は"rails scss"で繰り返し検索をかけ、アセットパイプラインなる用語を見つけ、それを調べて初めて解決の糸口となった下記の記事に辿りつきました。（"scss rails 反映されない"の検索ではヒットしませんでした）
https://qiita.com/metheglin/items/c5c756246b7afbd34ae2

なので今後学習される方がこのエラーの解決方法の検索で苦しまないように、"エラー"や"反映されない"の検索でこの記事をに辿りつき、その後上記の記事にたどり着いてもらえればいいなと思っております。

コンパイルはしたし、コンパイルの保存先も間違ってなくエラーが見つけられないで苦しんでいる方はおそらくこれが原因なので、上記の記事を一読していただければ良いのではないかなと思います。

純粋にローカルでエラーがあるかもという方は下記のrailsガイドをご参照ください
https://railsguides.jp/asset_pipeline.html

#4.後日談（記事より２週間後の話）
何故か再度この修正が仇となってエラーが起き、下記のように修正し、unicorn.rbの`app_path = File.expand_path('../../../', __FILE__)`を`app_path ="/var/www/freemarket_sample_62d"`としたらまた直りました。参考までに。

```
upstream app_server {
  # sharedの中を参照するよう変更
  server unix:/var/www/freemarket_sample_62d/shared/tmp/sockets/unicorn.sock;
}

server {
  listen 80;
  server_name 3.115.38.38;

  # currentの中を参照するよう変更
  root /var/www/freemarket_sample_62d/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
    root /var/www/freemarket_sample_62d/current/public;
  }


  try_files $uri/index.html $uri @unicorn;

  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;

    proxy_redirect off;
    proxy_pass http://app_server;
  }

  error_page 500 502 503 504 /500.html;
}

```
Javascriptのobjectに入ってるfunctionの中のthisのスコープがアロー関数と普通の関数で違うっぽい

Javascriptでご飯を食べてる人にとっては、今更な話題かもしれませんが、、、

Objectに追加した関数内の"this"のスコープが、普通の関数とアロー関数で違ってくるのに気付きました。

```javascript
const methods = {
  test_function: function () {
    console.log(this);
  },
  test_arrow: () => {
    console.log(this);
  }
}
```

chromeのコンソールで試した画像がこちら

<img width="525" alt="Screenshot 2020-03-11 at 23.39.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145550/d708497b-dd67-5b26-15ad-7d7ecc179f0d.png">

コンソールではアロー関数だとWindowがスコープになってるみたいです。

最近覚えてカッコつけてアロー関数を使い始めたんです。``() => {}``みたいなアロー関数。見た目がなんとなく格好良い。でも``function() {}``みたいなコテコテの普通の関数とは少し挙動が違うみたい。

今日Vueをいじっていたら、スコープの挙動がどうやら違うらしい事に気付きました。そこでこのポストの件にぶち当たりました。Vue内だと、普通の関数だと上のスクショの様にobjectが平積み（って言って良いのかな？）だけど、アローだと"a"の入れ子になっちゃう。

そのまま見過ごして不可解なバグになるところだったので、おかげさまで運が良い一日を過ごせました。なんかよくわからないけど色々ありがとう。
Swaggerのコンポーネントを正しく使ってきれいに書く

apiの仕様書として、swaggerを使っていますが行数が増えてきたので、コンポーネントを使って短く書く方法を調べました。

# Swaggerのコンポーネントとは
> Often, multiple API operations have some common parameters or return the same response structure. To avoid code duplication, you can place the common definitions in the global components section and reference them using $ref.

https://swagger.io/docs/specification/components/

同じ記述を減らすためにswaggerがapiに必要なものを提供してくれています。

```
components:
  # Reusable schemas (data models)
  schemas:
    ...
  # Reusable path, query, header and cookie parameters
  parameters:
    ...
  # Security scheme definitions (see Authentication)
  securitySchemes:
    ...
  # Reusable request bodies
  requestBodies:
    ...
  # Reusable responses, such as 401 Unauthorized or 400 Bad Request
  responses:
    ...
  # Reusable response headers
  headers:
    ...
  # Reusable examples
  examples:
    ...
  # Reusable links
  links:
    ...
  # Reusable callbacks
  callbacks:
    ...
```

# コンポーネントの使い方サンプル
実際にどうやって使うか書いてみました。
## parameters

```
paths:
  /article/{articleId}:
    patch:
      summary: edit article
      parameters:
        - $ref: '#/components/parameters/userId'
        - $ref: '#/components/parameters/articleId'

components:
  parameters:
    userId:
      name: X-User-ID
      in: header
      description: user id
      required: true
      schema:
        type: integer
    articleId:
      name: articleId
      in: path
      description: article id
      required: true
      schema:
        type: integer
```
## requestBodies
作成や更新で必要になるrequest bodyもコンポーネントを組み合わせることで短く出来ます。
https://swagger.io/docs/specification/describing-request-body/

```
paths:
  /article/{articleId}:
    patch:
      requestBody:
        $ref: '#/components/schemas/article'
components:
  requestBodies:
    article:
      description: A JSON object containing article information
      required: true
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/article' # contentもコンポーネントを使うことで簡潔になる
  schemas:
    article:
      type: object
      required:
        - title
        - sentence
      properties:
        title:
          type: string
        sentence:
          type: string
```
## responses
エラー処理などの共通のレスポンスに対して短く出来ます。
https://swagger.io/docs/specification/describing-responses/

```
paths:
  /article/{articleId}:
    patch:
      responses:
        '200':
          $ref: '#/components/responses/success'
        '404':
          $ref: '#/components/responses/notFound'
components:
  responses:
    success:
      description: Success
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Success'
    notFound:
      description: Not found
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/notFoundError'
```

# まとめ
もともとコンポーネントをschemasくらいしか使っていなかったために共通の処理をまとめたところ、2000行以上のswaggerファイルで400行程短く出来ました。
まだリファクタの途中なので、今後さらに共通化を進めて綺麗にできそうです。
swaggerを書こうとしている方の参考になれば嬉しいです。