OmniAICreator/Qiita-1.07M huggingface dataset:
Volatility変動モデルを用いたドル円相場の価格決定

# 目的

ドル円相場の価格予想を行う。
以下の参考記事の再現性の確認

https://www.mlit.go.jp/pri/kouenkai/syousai/pdf/b-150715_1.pdf

# ソロスチャート

ジョージ ソロスの経験則により、為替相場の値動きは両国のマネタリーベース比に相関する。
(日本のマネタリーベース / アメリカのマネタリーベース)を示す。

![soros_chart.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/d3186165-2f7a-a125-0b2b-dacb0875b5c0.png)

# 金利平価説
代表的な為替レート決定モデルとして金利平価説が挙げられる。

(1)カバー付き金利平価説(Covered interest rate parity)

```math
\Delta e_{t+1} = \alpha + \beta・((f_t - \epsilon_t )/ \epsilon_t) + \epsilon_t 
```

(2)カバー無し金利平価説(Uncovered interest rate parity)

```math
\Delta e_{t+1} = \alpha + \beta・(i^*_t - i_t) + \epsilon_t 
```

[1]参照


![interest_rate_parity.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/fcfdfb56-7bfe-7a1f-89e6-a71429ad431a.png)

# 本題(Volatility変動モデル)

TARCH-Mモデル

```math
\Delta e_{t+1} = \alpha + \beta・(i^*_t - i_t) + \gamma・\Delta(MB_t^*/MB_t) + \zeta・log(\sigma^2_t) + \epsilon_t \\
\sigma^2_t = C(1) + C(2)・\epsilon^2_{t-1} + C(3)・\epsilon^2_{t-1}・1_{\epsilon_{t-1} < 0} + C(4)・\sigma^2_{t-1}
```

[1]参照

尚、参考文献より以下の実験値が与えられている

| 係数　　　　       |      係数値　　　　  | 
|:-----------------|------------------:|
| &alpha;　　　　　  |             0.814 |
| &beta;           |            -1.895 |
| &gamma;          |            -0.229 |
| &zeta;           |             3.968 |
| C(1)             |             0.445 | 
| C(2)　　          |            -0.080 | 
| C(3)             |             0.364 |
| C(4)             |             0.568 | 



```python

a = 0.814
b = -1.895
c = -0.229
d = 3.968

c1 = 0.445
c2 = -0.080
c3 = 0.364
c4 = 0.589

b4wnoise = 0.01
b4sigma = 0.01
b4baserastion = 1.0


def nextvalue(usdcall, usdbase, jpycall, jpybase, usdjpy):
    global b4baserastion, b4wnoise

    mean = 0.0
    std = 1.0
    wnoise = random.gauss(mean, std)

    s2 = sigma2()
    delta = (jpybase/usdbase)-b4baserastion
    b4baserastion = (jpybase/usdbase)

    deltaprice = a + b*(jpycall - usdcall) + c*delta + \
        d*(math.log(s2)) + wnoise
    b4wnoise = copy.copy(wnoise)

    return usdjpy + deltaprice


def sigma2():
    global b4sigma, b4wnoise

    if b4wnoise < 0:
        sigma2 = c1 + c2*(b4wnoise ** 2) + c3*(b4wnoise ** 2) + c4*b4sigma
    else:
        sigma2 = c1 + c2*(b4wnoise ** 2) + c4*b4sigma

    b4sigma = copy.copy(sigma2)
    return sigma2


```




![forecat2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/d6fa7c5f-fcf7-998e-9248-6bab0227a138.png)


# 参考記事
[1]

https://www.mlit.go.jp/pri/kouenkai/syousai/pdf/b-150715_1.pdf

[2]

https://www.boj.or.jp/research/brp/ron_2000/ron0003b.htm/

[3]

https://www.boj.or.jp/en/research/wps_rev/wps_2007/data/wp07e22.pdf
フリーランスエンジニアの作り方　その２

https://qiita.com/rikrikrik/items/ab842034b9199e9bbb22

の続き。
頭の中がぐるぐるなので文字に書いて状況を整理する。

結果、フリーランスにこだわる理由ってなんだっけ？
迷宮入りします。

<h1>状況の整理</h1>
<h2>所属会社について</h2>
上長にフリーランスエンジニアとして独立したい旨を報告。
経緯として、給与面に関する不安と、フリーのエンジニアになることで自分の力を試したい旨を説明。
基本的には賛成してくれたが、やめ方、残された人間に対して何も考えられていないと指摘を受ける。

また、フリーランスになることは自分自身にとって有益なことだからチャレンジするのはありだが
それが最善かどうかは考えるべき、例えば会社員でいながら副業的にフリーの仕事をするなど、
とアドバイスをもらう。
※上長もフリーランス経験あり

<h2>現場について</h2>
所属会社との折り合いがつけばフリーランスになったとしても現場は継続してもらえると言ってもらえている。
※採用に関してある程度の力を持つ主任クラスの方に相談しており、確度は高いと考えている。

<h2>自分自身について</h2>
悩んでいることは以下。

1.フリーランスになった後の今の所属会社との関係をどうしたいか
2.以前に仕事が原因で体調（メンタル）を崩したことがあり、いざフリーになった時に１人で対処できるのか
3.フリーランスになることが今の自分にとって最善なのか

<h3>1について</h3>
フリーになる＝今の会社を辞めると思った経緯として
・開発に関わること以外の業務（人員教育や会社制度検討など）に対する負荷が高く、かつそこに対する評価が曖昧、すごくわかりづらく、成果を出しても給与に反映されていないと感じている。
・現場業務以外の自社業務に関して、なんに対しても主体的に一緒に動いてくれる人はいなくて、何をするにしても自分主導で動いていくのが負担だと思っている。（孤独を感じている）
・現場業務内容、貢献度を考えた時に、今の給与に見合っていないと感じている。
・本来自分のやりたいこと、「意欲的な人間とモノづくりに対して熱くなる」ということが、今の会社ではできないと感じている。

が...

まだ会社にも話せていないので、ここはちゃんと話して交渉するべきかな。

また、仮にフリーになったとして、今後仕事を受けるコネクションとしては残しておきたい、と思っている。
（正直色々めんどくさくなってもうどうでもいいやってなってるけど、ここは冷静に...）

<h3>2について</h3>
この記事を書いているのも現在4時半。また不眠の症状が出始めている。
この苦痛を誰にも相談せずに１人で改善・解決していけるのかと不安がある。
根本的に雇われの考え方だなと痛感している。

<h3>3について</h3>
ここまで書いて感じたことは、結局フリーになろうと思ったのも
今の給与よりはなんとなく収入は上がるし、今の会社に居続けるよりはいいだろ、と思ったことがきっかけで、
後付けて色々と理由をつけてきたことにより、本当に思っていることとずれてきているのではと感じた。

そりゃ今よりも楽をして稼ぎたいし、できることなら年収はあげていきたい。
ただ、今の生活の根本を崩してまで不満に思っているわけではないのだろうか。

ひろゆきさんの著書「これからを生きるための無敵の―お金の話」のなかで

ただ稼ぐことが本当に幸せなのか？
自分にとって「いくら」あれば幸せなのか？

的なことが書いてあったが、まさにこれで、
自分にとって明確にどれくらいの収入があったらいいのかのざっくりとした計画もないまま
ただただ収入を上げたいと思っているから考えに収拾が付かなくなっているのかも。

もちろんフリーになっていろんな現場を見て経験を積みたいと言うのもある。本当に。
ただ結局はこれは「２つ目」の理由で、
根本は「もっと稼ぎたい」っていう曖昧な理由なんだったんだと思う。

となると、
会社員として収入を上げるにはどうするべきか？
をもう一度考えてみようと思う。

（え、フリーランスになるんじゃなかったの？？？）
論文まとめ：A Graph Attention Spatio-temporal Convolutional Network for 3D Human Pose Estimation in Video

# はじめに
arXivにある以下の論文
[1] J. Liu, et. al."A Graph Attention Spatio-temporal Convolutional Network for 3D Human Pose Estimation in Video
"
のまとめ

Journal等は不明。

github:
https://github.com/fabro66/GAST-Net-3DPoseEstimation
MIT license, pytorch 1系

# 概要

- ３次元の人の姿勢推定に関するモデルで、sequentialな2Dの骨格を入力として3Dへliftingするもの
- graph convolutionを使うが、隣接関節における対応のみならず、体の対称性に関する対応、及びより広範囲の対応も考慮に入れる
- 特に広範囲の対応はattentionを使う

![GAST_Net_img00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/31352ed0-777c-636f-8946-b295f0b44008.png)

こんな感じで、姿勢によって体の一部が別の一部によって見えなくなる（self-occulution）でも割と正確に推定する

# アーキテクチャ全体
アーキテクチャの全体像は以下

![GAST_Net_img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/ae91b053-908d-beee-07eb-b9dbbc539ac1.png)

１）まず左のようなビデオフレームに対して2D骨格推定モデル（例えばHRNet）で各フレームの2D keypointsを推定する。

２）それをGAST-Netで3D poseにliftingする。

３）3Dのground truthと MSE lossを計算し、学習する

特にGAST-Netは

(a) 時間方向に畳み込む temporal convolution model
(b) 近接する関節ペアに対してgraph convする local attention graph
(c) 離れた関節ペアに対してgraph convする global attention graph

などからなる

以下はモデルのアーキテクチャの詳細

![GAST_Net_img02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/755e7255-7c08-27e2-0cbb-ce3463eb6b88.png)

左上は全体像だが、３回のgraph attention block、２回のtemporal conv blockを含む。

graph attention blockは右のように、１） GCN Global attention系統、２）GCN Connection系統、３）GCN Symmetry系統などに分岐するが、最終的にaddされて、１つに統合される。

Temporal conv blockはresicualな形。

以下は各要素の詳細

# Temporal convolutional Network
dilated convで時間方向に畳み込む

# Local Attention Graph
$N$ :関節数
$A \in \mathbb{R}^{N \times N}$ :adjacency matrix or symmetric matrix
$I \in \mathbb{R}^{N \times N}$ :identity matrix
$\tilde{A} = (A + I)$
$W \in \mathbb{R}^{C\_l \times C\_{l+1}}$ :outputのチャンネルへ変換する学習対象の重みmatrix
$X^{(l)}$ :l 層からの出力
$X^{(l+1)}$ :l+1 層からの出力
$M \in \mathbb{R}^{N \times N}$ :学習対象のマスク
として

```math
X^{(l+1)} = \rho (M \odot \tilde{A} ) X^{(l)} W
```

マスクをチャンネルごとにすると

```math
X^{(l+1)} = \|^{C_{l+1}}_{c=1} \rho (M_c \odot \tilde{A} ) X^{(l)} w_c
```

ここで記号 $ || $ はチャンネルのconcat。

A は adjacency matrixの場合（つまり先のFig 3 右図によけるGCN Connection）以下の図の（c）

![GAST_Net_img03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/f49770ab-6f4f-c1a7-c500-290a43e55f95.png)

second orderの隣まで考慮している。

symmetric matrixの場合（つまり先のFig 3 右図によけるGCN Symmetry）は(b)。左右の手における動きの違いになどに注目することを狙ったか？

# Global Attention Graph
global attention graphに関しては以下の演算を行う。

```math
X^{(l+1)} = \|^{C_{K}}_{k=1} (B_k + C_k)  X^{(l)} W_k
```

$B\_k \in \mathbb{R}^{N \times N}$ :適応的globalな隣接行列
$C\_k \in \mathbb{R}^{N \times N}$ :学習対象のglobalな隣接行列
だそうだが、割愛。

# 実験と結果
## Human3.6Mでの定量的評価

![GAST_Net_img06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116706/ea8e88c0-9a4e-2f24-2504-c42ceef1ac67.png)

本モデルはlifting部分なので、Protocol 1 のGTで見ると、31.4と結構良い。
備忘録　2021-04-22

FirebaseUIはv10.0.2でないとエラー発生
Cocoaで最新版のFirebaseUIに更新しようとした結果、詰まった。

![スクリーンショット 2021-04-22 3.02.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295590/4d50ef49-e0f9-2fcd-4665-12414392c889.png)

原因は pod 'FirebaseFirestoreSwift'　

こいつのせいで強制的にFireStore更新ができなくなってたのが原因。

FirebaseFirestoreSwiftを消したら解決した。

なんで入れてたのかよく覚えてない（消してもアプリは動く）ので、今後検証する予定。
[Rails]Reactをインストールする　(RailsでReactを利用する)

##最初に
自分のRailsアプリでReactを使ったのでインストール方法を備忘録として残しておきます。

##手順
```:Gemfile
gem 'react-rails'
```


```
$ bundle install
$ rails webpacker:install:react
$ rails g react:install
```
以上でRailsにReactを実装できます。

##コンポーネントの作成
コンポーネントとはなんぞやという方は以下の記事をお読みください

https://ja.reactjs.org/docs/components-and-props.html

```
$ rails g react:component hoge  ←　作りたいコンポーネントの名前
```
すると
`app/javascript/components`下にhoge.jsが作成されます

そしてhoge.jsを名前変更し`hoge.jsx`に変更します。
するとReact専用のファイルとして利用することができます
MagicLeapnのプロジェクトにMRTKを入れたときに数十のエラーに襲われた話


MagicLeapの公式にてMRTKに対応したとのことなので趣味で開発してるMagicLeapプロジェクトにMRTKを軽い気持ちでぶち込んでみたら数十のエラーに襲われたのでメモ。

↓この公式ページの通りに進めればほぼ大丈夫
https://developer.magicleap.com/en-us/learn/guides/unity-mrtk-project-setup

今回のエラーはもしかしたらワシの環境だけで発生してるのかもしれないけど一応メモ  

一応手順通りにMRTKをインポートしたところまでは問題なかったがその後の Magic [Leap Plugin v1.1 for MRTK 2.6.1 for Unity](https://github.com/magicleap/MRTK-MagicLeap/releases/) をインポートしたら数十のエラーが発生、一応臭いものに蓋ではあるが下の対応をした  
不覚にもスクショとかは一切撮ってなかった...


---

```csarp
Assets\MagicLeap-Tools\Code\Input\Hands\Visualizers\HandAxisVisualizer.cs(57,43): error CS0246: The type or namespace name 'ManagedHand' could not be found (are you missing a using directive or an assembly reference?)
```  

このエラーはManagedHandクラスのnamespaceが MagicLeapToolsからMagicLeap.MRTK.DeviceManagement.Input.Handsへ移動したため以下のエラーが出る、該当スクリプトで↓を追加すれば解消できた。

```csharp 
using MagicLeap.MRTK.DeviceManagement.Input.Hands;
``` 

---

```
Assets\MagicLeap-Tools\Code\Events\EventTemplates.cs(42,53): error CS0246: The type or namespace name 'InteractionPoint' could not be found (are you missing a using directive or an assembly reference?)
```

このエラーも InteractionPoint は MagicLeap.MRTK.DeviceManagement.Input.Hands の名前空間にあるので該当スクリプトにて↓を追加すれば解消。

```csharp
using MagicLeap.MRTK.DeviceManagement.Input.Hands;
``` 

---

```
Assets\MagicLeap-Tools\Code\Networking\Transmission\TransmissionObject.cs(86,29): error CS0103: The name 'TransformUtilities' does not exist in the current context
```

このエラーは TransformUtilities クラスが  MagicLeap.MRTK.DeviceManagement の名前空間にあるので該当スクリプトにて↓を追加すれば解消。

```csharp
using  MagicLeap.MRTK.DeviceManagement;
```

---

```
Assets\MagicLeap-Tools\Code\Input\Hands\Inputs\DirectManipulation.cs(369,33): error CS0103: The name 'MotionUtilities' does not exist in the current context
```

このエラーは該当スクリプトで↓を追加して解消。

```csharp
using MagicLeap.MRTK.DeviceManagement;
```

---

```
Assets\MagicLeap-Tools\Code\Input\Hands\Objects\ManagedHandCollider.cs(82,52): error CS1061: 'InteractionPoint' does not contain a definition for 'DirectManipulations' and no accessible extension method 'DirectManipulations' accepting a first argument of type 'InteractionPoint' could be found (are you missing a using directive or an assembly reference?)
```

こちらのエラーは Grasp の DirectManipulations のプロパティが削除されてるので発生してるっぽかった。
該当コードのコメント //only enable if we aren't directly manipulating anything: よりおそらく何かしらのオブジェクトを把持してないときに有効になる条件だと思われるので以下の様にコードを変更 ( 山勘で書いただけなのでもしかしたら違うかも...

```csharp
if (_managedHand.Gesture.Grasp.DirectManipulations.Count == 0)
// ↑の条件式を↓の形に変更した
if (!_managedHand.Gesture.Grasp.active)
```


とりあえずこれで動くようにはなったけどまだ細かいところをチェックはしてないからそれは後日かなぁ。
アドミニストレーター認定試験に向けた学習 ⇒ アドミニストレーター認定の準備: アプリケーション、活動、モバイル ⇒ セールスアプリケーションとマーケティングアプリケーションの確認

１．Salesforce 認定アドミニストレーター試験のうち、「営業アプリケーションとマーケティングアプリケーション」セクションが占める割合は何パーセントですか?
２．Salesforce 認定アドミニストレーター試験の「営業アプリケーションとマーケティングアプリケーション」セクションで取り上げる主なトピックはどれですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/0c8f28e3-cfc7-fdee-7e21-c3ca4657b3e3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/6e49d36e-0e69-6f0b-70fe-066c71e839c5.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/05ad8c27-c43a-0fe2-dc22-ac8162737104.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/1a322464-06f1-f2ab-3b53-48c61d04154f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/b1995a81-a291-20ae-cd4c-7da3e6c1c2ff.png)
digコマンドをいい感じに使えるようになりたい

digコマンドで諸々することがあって使い方がいまいちだったので調べた。

## digコマンドとは？
DNSサーバに対して問い合わせを行い、その結果を表示してくれる。

### 簡単に使ってみる
google.comのIPアドレスを調べてみる。このようにドメインからIPアドレスを求めることを**正引き**という。


```:コマンド
$ dig google.com
```

```:結果
; <<>> DiG 9.10.6 <<>> google.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 23074
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;google.com.			IN	A

;; ANSWER SECTION:
google.com.		46	IN	A	216.58.196.238

;; Query time: 31 msec
;; SERVER: 192.168.11.1#53(192.168.11.1)
;; WHEN: Thu Apr 22 01:05:38 JST 2021
;; MSG SIZE  rcvd: 55

```

`;; ANSWER SECTION:`と書いている部分で、`216.58.196.238`と書いていることがわかる。これが`google.com`のIPアドレス。

今回のようにDNSサーバーからの返答は`ANSWER SECTION`に記述してある。


### とりあえず正引きのみしたいとき(余計な情報はいらないとき)
`+short`オプションを利用する。

```:コマンド
dig +short google.com
```

```:結果
172.217.31.142
```

こんか感じでシンプルにIPアドレスのみ表示される。


### 利用するDNSサーバーを指定したいとき

問い合わせるDNSサーバーを指定することもできる。
`@8.8.8.8`のように@をつけてDNSサーバーのIPアドレスを指定する。
ちなみに、`8.8.8.8`はgoogleのGoogle Public DNS。

余談だが、Public DNSは他にも以下のようなものがある。

* Cloudflare社とAPNICが運営する1.1.1.1
* IBM社などが共同運営するQuad9による9.9.9.9

```:コマンド
dig @8.8.8.8 google.com
```

### ドメインに関連する様々なレコードの情報が知りたいとき

`ANY`オプションを利用する。

```:コマンド
dig google.com ANY
```

結果の`ANSWER SECTION`のみ抽出して表示する。

```:結果
;; ANSWER SECTION:
google.com.		263	IN	A	172.217.26.14
google.com.		263	IN	AAAA	2404:6800:4004:809::200e
google.com.		21563	IN	NS	ns2.google.com.
google.com.		3563	IN	TXT	"google-site-verification=wD8N7i1JTNTkezJ49swvWW48f8_9xveREV4oB-0Hf5o"
google.com.		3563	IN	TXT	"apple-domain-verification=30afIBcvSuDV2PLX"
google.com.		563	IN	MX	30 alt2.aspmx.l.google.com.
google.com.		3563	IN	TXT	"facebook-domain-verification=22rm551cu4k0ab0bxsw536tlds4h95"
google.com.		21563	IN	CAA	0 issue "pki.goog"
google.com.		23	IN	SOA	ns1.google.com. dns-admin.google.com. 369489900 900 900 1800 60
google.com.		21563	IN	NS	ns1.google.com.
google.com.		563	IN	MX	10 aspmx.l.google.com.
google.com.		3563	IN	TXT	"docusign=1b0a6754-49b1-4db5-8540-d2c12664b289"
google.com.		3563	IN	TXT	"google-site-verification=TV9-DBe4R80X4v0M4U_bd_J9cpOJM0nikft0jAgjmsQ"
google.com.		3563	IN	TXT	"docusign=05958488-4752-4ef2-95eb-aa7ba8a3bd0e"
google.com.		21563	IN	NS	ns3.google.com.
google.com.		563	IN	MX	20 alt1.aspmx.l.google.com.
google.com.		563	IN	MX	50 alt4.aspmx.l.google.com.
google.com.		563	IN	MX	40 alt3.aspmx.l.google.com.
google.com.		3563	IN	TXT	"globalsign-smime-dv=CDYX+XFHUw2wml6/Gb8+59BsH31KzUr6c1l2BPvqKX8="
google.com.		21563	IN	NS	ns4.google.com.
google.com.		3563	IN	TXT	"v=spf1 include:_spf.google.com ~all"
```

### どのDNSサーバーが応答してくれたか知りたいとき
`+identify`オプションを利用する

今回は例として、`+short`オプションと併用する

```
dig google.com +short +identify
```

```
172.217.31.142 from server 192.168.11.1 in 39 ms.
```

`192.168.11.1`から応答が返ってきたことがわかる

### 権威サーバーに問い合わせてみたいとき
`+norecurse`オプションを利用する。

```
dig google.com +norecurse
```

##　まとめ
好きなコマンドは`dig`です。って言えるようになりたい。
Chromaticで簡単にStorybookをもっと活用する


# Chromaticとは

https://www.chromatic.com/

Storybookのドキュメント公開、UIテスト、UIレビューの仕組みを提供してくれるサービス


---

# Chromaticの機能紹介
## Storybookドキュメントの公開

ビルドされたStorybookはGitのコミット単位で記録されます。
つまりStorybookのバージョン管理が行なえます。

---

## UIテスト（ビジュアルテスト）
ChromaticはStory毎にスナップショットを撮影し、自動で前のスナップショットとの差分をチェックします。
もし差分があればそれについてレビューを行い、変更が正しいことを確認します。

---

# Chromaticの導入

主に[こちら](https://www.chromatic.com/docs/setup)の資料を参考に（ほぼそのままですが）まとめました

### 1. chromaticにプロジェクトを連携

とりあえずログイン。利用したいプロジェクトがあるアカウントでログインしてください。
![スクリーンショット 2021-03-22 021525 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/6c160d48-cc65-0a08-5b3b-aaedf22ee744.png)

プロジェクトを選択すると以下のような画面が表示されます。

![スクリーンショット 2021-03-22 020141.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/c623f7f8-37ea-88d1-8c5c-e00ddebe44b7.png)

プロジェクトトークンは後で使うのでメモっておきましょう

### 2. プロジェクトにchromaticをインストール
次のコマンドでchromaticをインストールします。

```bash
npm install --save-dev chromatic
```

### 3. chromaticへのデプロイコマンドを実行
chromaticの画面に表示されていたトークンでchromaticコマンドを実行します。
このコマンドはstorybookのビルドからchromaticへのデプロイ、UIテストまでを行ってくれます。

```bash
npx chromatic --project-token=xxxxxxxxx
```

![スクリーンショット 2021-03-22 021035.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/80a0c32a-e604-06e1-0f5d-b26a57bd0528.png)

途中`chromatic` scriptを追加するかの質問が出ます。
これは`"chromatic": "npx chromatic --project-token xxxxx"`のようなscriptがpackage.jsonに生成されます。
特に必要性を感じないならトークンはクレデンシャル情報なので入れないほうが良いでしょう。


chromaticのプロジェクトページを確認するとビルドされた結果が表示されます。（以下は初回デプロイ後の表示です）
![スクリーンショット 2021-03-22 021414 - コピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/9df3e996-6996-6149-09c0-1a00d416a74d.png)



#### chromaticコマンドに失敗？
chromaticコマンドは初期設定ではUIテストを自動で実行し、差分があるとエラーを返します。（多分CI用）
デプロイ自体は成功しているので、chromaticのWeb画面を開いてUI差分を確認しましょう。

![スクリーンショット 2021-03-22 221946.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531073/94a547e6-f2ce-fef5-28ee-9b2f4b30159d.png)


### 4. CIの設定（GitLab）
以下は`.gitlab-ci.yml`に記述する最小限のジョブです。
ただし`project-token`はクレデンシャルなので環境変数で指定するほうが良いでしょう。

```yaml:.gitlab-ci.yml
chromatic_publish:
  image: node:14
  script:
    - npm install
    - npx chromatic --project-token=$CHROMATIC_TOKEN --exit-zero-on-changes
```

`--exit-zero-on-changes`は「chromaticコマンドに失敗？」で紹介した差分による失敗を無効にします。

GitLab以外のCIについてはこちらを参照
https://www.chromatic.com/docs/gitlab
【メモ】Git GitHubでバージョン管理する流れ

# GitHubのリモートリポジトリ新規作成時

1. ***GitHub***でリポジトリを新規作成しておく。
2. ***gitbash***でGitHubと連携させる。  
`remote add origin リモートリポジトリURL`  
(作成したときに出てきたコマンドをコピペでOK。)
3. ***gitbash***でブランチを作っておく。  
`git branch ブランチ名`


# リモートリポジトリにpushするまで
1.  ***gitbash***でブランチを切り替えておく  
`git switch ブランチ名`
1.  ***gitbash***でステージングエリアに追加  
`git add .`  
1.  ***gitbash***でコミット  
`git commit`
1. リモートリポジトリへプッシュする  
`git push origin ブランチ名`

# プルリクエスト
1. ***GitHub***でpullRequestする。
1. レビューを後***GitHub***でmergeする。
1. ブランチをmasterに切り替えた後***gitbash***でmergeした内容をmasterに取り込む  
`git pull` or `git fetch origin master` ＆ `git merge origin/master`
1. ブランチが不要になったので破棄する  
`git branch -d 不要なブランチ名`

# 使いそうなコマンド

####今の状況を確認したい
- `git status` 状態を見る
- `ls -a` 中身をみる
- `git cat` コードを見る

####差分が見たい
- `git diff` ステージとの差　
- `git diff --staged` ステージとローカルリポジトリの差　

####変更履歴を見たい
- `git log --oneline`　一行で簡潔に
- `git log -p index.html`　特定の履歴だけ
- `git log -n 4`　最近の〇個だけ表示
- GitHubでBlameを見る

####戻したい・消したい
- `git rm ファイル名` リモートもgitからも消える
- `git rm -r ディレクトリ名` リモートもgitからも消える
- `git rm --cached ファイル名` リモートは残しgitからは消える
- `git checkout` ファイルの変更を戻す

####バージョン管理したくない
- gitignoreファイルを作成し管理内容を記述する

####なかったことにしたい
- `gitcheckout  --ディレクトリ名` ディレクトリの変更をなかったことに
- `git reset HEAD ディレクトリ名` ステージした変更(add)をなかったことに  
(ディレクトリは関係ない)
- `git commit --amend` commitの修正(※push前)。  
 （変更したい内容をaddしてからamendする）


####リモートリポジトリのURLを変更したい
- `git remote set-url origin [変更先のURL]`

####コミットしたくないけど保存したい・一時避難
- `git stash` 一時避難する
- `git stash list` 避難したものを見る
- `git stash apply` 復元する
- `git stash drop` 避難した作業を削除する
AWS Chatbot が Amazon EventBridge に対応したので Amazon RDS イベントを通知させてみる


# はじめに

『[こちらの記事](https://qiita.com/takiguchi-yu/items/2b2af40f7ef498a7f4e3)』の延長で、 Amazon RDS のイベント(起動や停止など)を `EventBridge` + `Chatbot` 経由 で Slack 通知するようにしました。

![chatboteventbridge.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/725c7c0a-f624-bf00-2e59-c2780ef9d334.png)

今までは、Chatbot が EventBridge に対応してなかったみたいですね。

https://aws.amazon.com/jp/about-aws/whats-new/2021/04/aws-chatbot-now-expands-coverage-of-aws-services-monitored-through-amazon-eventbridge/

# やること

- SNS トピックの作成
- Chatbot の作成
- EventBridge ルールの作成

# SNS トピックの作成

まずは `SNS トピック` を作成します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/1dc65cd1-e007-2df0-1c78-0826b1c29013.jpeg" width="600px">

# Chatbot の作成

続いて `Chatbot` に先ほど作成した `SNS トピック` を設定します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/f179ce7a-5436-b5ba-af28-db327b4b6a4e.jpeg" width="600px">

`Chatbot` を設定すると自動で `SNS サブスクリプション` が作成されます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/2d13555a-aecf-a916-7983-bed1180c5674.jpeg" width="600px">

# EventBridge ルールの作成

今回は `RDS` のイベントを通知したいので、RDS をぽちぽちと選択します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/e3cec81f-aeaa-113b-e4bf-4e956af2451f.jpeg" width="600px">

# 通知デモ

試しに RDS のインスタンスを落としてみます。うまく通知がきましたね。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59081/5309ef72-a519-e216-ebda-5e86377022d5.jpeg" width="600px">

# さいごに

これからは `AWS Chatbot`を使えば、アプリケーションのオートスケーリングや CI/CD ワークフローの監視など、運用アクティビティをより効果的に管理できそうですね！
Javaで画面キャプチャを取得する

######以下のサイトを参考にさせていただきました。
http://ogawa.s18.xrea.com/tdiary/20120805p01.html


実装したもの
-

######１.画面キャプチャを取得するクラス

ディレクトリを引数としてキャプチャを出力するクラスを以下のように作成します。

```ruby:ScreenCapture.java
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;

import javax.imageio.ImageIO;

import application.utility.FileUtil;

public class ScreenCapture {
    
    public static void execute(String dirPath) {
        
        File dir = new File(dirPath);
        if(!dir.exists()) {
            dir.mkdir();
        }
        File file = FileUtil.createUniqueFile(dir, "capture.png");
        
        try {
            Robot robot = new Robot();
            Rectangle screenSize = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize());
            BufferedImage screenShot = robot.createScreenCapture(screenSize);
            ImageIO.write(screenShot, "png", file);
        } catch (Exception e) {
            System.out.println("キャプチャの取得に失敗しました。" + e.getMessage());
        }
        System.out.println("画面キャプチャを取得しました。" + "\r\n" + file.getPath());
    }
}
```

######２.出力ファイルに対してユニークな連番を付与するクラス
出力ファイル名に対して重複しない連番を付与する関数を用意します。


```ruby:FileUtil.java
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

public class FileUtil {
    public static File createUniqueFile(File directory, String fileName) {
        String name;
        String extention;
        if (fileName.contains(".")) {
            name = fileName.split("\\.")[0];
            extention = "." + fileName.split("\\.")[1];
        } else {
            name = fileName;
            extention = "";
        }
        int counter = 0;
        do {
            String uniqueName = String.format("%s%03d%s", name, ++counter, extention);
            File f = new File(directory, uniqueName);
            if (!f.exists()) {
                return f;
            }
        } while (true);
    }
}
```

######３.起動クラス
画面キャプチャを実行するための起動クラスを作成します。

```ruby:ScreenCaptureSample.java
public class ScreenCaptureSample {
    
    public static void main(String[] args) {
        
        ScreenCapture.execute("C:\\capture");
    }
}
```


実行結果
-
以下のように連番で画面キャプチャが出力されるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1333971/163207ce-3c0f-8119-4114-62df4107570b.png)



次回
-
今回作成したものを効率的に使用可能とするため、ツール化します。
https://qiita.com/mamamap/items/b3b8d5914b8fc4879d12

実施内容は以下です。
１.タスクトレイに常駐するツールを作成します。
２.タスクトレイに常駐するツール画面キャプチャの機能を追加します。（今回の作成したものを追加）
High and Low ゲームを作ってみた

#はいあんどろー
簡単な、High and Low ゲームです。
自分のカードの数字が相手のカードと比較して「大きい」か「小さい」かを選択して、
あたりの場合に点数が加算されます。
あたり、はずれ、どちらかが5回に達した時点でゲームは終了します。
普通に作るだけでは面白くないので、おこさまを対象にイメージしました。

###なぜ作ったか
まずはKotlinがどれだけ記述が異なっているのかの練習として選びました。
お手本通りに作ってはいますが、それだけではゲームとして不十分だったので
独自に変更したものです。

![handlsample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1351586/ed737c84-df84-6cf5-aebe-0b9694016bb6.png)

![handlsample2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1351586/26b31fda-1d5b-6224-96a5-57c79d2f3863.png)

トランプ画像は可愛さという面からいらすとやさんからお借りしています。



###作ってみた感想
自身がJavaもさることながらVB.netのお仕事を多く関わってきたからか、
Kotlinはとっつきやすいと感じました。
カッコやセミコロンがいらない場合があるからです。（いるところは、いる。）
あと、変数や関数の書き方がシンプルでよかったです。

感覚が掴めたところで、次はスマホ独自の機能を利用するアプリを挑戦してみます。



コードなんかはまた機会があれば載せてみようと思います。
文字列

```py
print('Hello')
print("Hello")
print("I don't know")
print('I don￿\'t know')
print('say "I don\'t know"')
print("say \"I don't know\"")

print('Hello\nHow are you?')
print(r'c:\name\name') #c:\name\name 改行されない

#前後に改行が入ります。
print('#######')
print("""
line1
line2
line3
""")
print('#######')

#改行させたくない場合
print('#######')
print("""\
line1
line2
line3\
""")
print('#######')

print('Hi.' * 3 + 'Mike.') #Hi.Hi.Hi.Mike.

#文字列が長い場合の書き方
s = ('aaaaaaaaaaaaaaaaaa'
     'bbbbbbbbbbbbbbbbbb')
print(s)

#下記のようにも書けます。
s = 'aaaaaaaaaaaaaaaaaaa' \
    'bbbbbbbbbbbbbbbbbbb'

print(s)
```
出力結果：

```
Hello
I don't know
I don￿'t know
say "I don't know"
say "I don't know"
Hello
How are you?
c:\name\name
#######

line1
line2
line3

#######
#######
line1
line2
line3
#######
Hi.Hi.Hi.Mike.
aaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb
aaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbb
```
AWS CLI の設定


やったこと

#AWS CLIのインストール（公式）

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-install.html

CLI１とCLI２があって一部互換性がないらしい。自分の環境はCLI1
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cliv2-migration.html

随分前の設定が残っていたので自分の環境の設定を追加

```
.aws/config
.aws/credentials
```

S3 を見てみる。あっさり

```
~ $ aws s3 ls
2021-04-20 23:39:46 gogo-for-upload
~ $ aws s3 ls s3://gogo-for-upload
2021-04-21 00:34:05      56130 android-chrome-260.png
~ $
```

#AWS CLIにaliasの設定
便利そうだったので設定

https://dev.classmethod.jp/articles/aws-cli-alias/

早速これをやってみる。適当なインスタンスにタグを設定して表示させてみる

https://dev.classmethod.jp/articles/awscli-describe-nametags-alias/

```
~ $ aws nametag
Enter the value:"*"
--------------
|DescribeTags|
+------------+
~ $
```

あれ？
何もでない。

普通にインスタンスの情報を表示してみる。これはできた
( インスタンスに Name タグを設定しないで実行していたので表示されなかったという落ち

```
~ $ aws ec2 describe-instances --instance-ids i-xxxxxxxxxx --output table
------------------------------------------------------------------------------------------
|                                    DescribeInstances                                   |
+----------------------------------------------------------------------------------------+
||                                     Reservations                                     ||
```

また今度
Colab環境にファイルをアップロード＆ダウンロード

![SS 192.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/565043/a41cd967-f549-8677-1efa-2e99bf69518d.png) 　Colab上でgit cloneした.pyファイルをローカルで編集する時とか
##やること

Colablatoryにファイルをアップロード、ダウンロードします。

##環境

- [Colaboratory環境](https://colab.research.google.com/notebooks/intro.ipynb)
- ブラウザはChrome推奨

##ローカルにダウンロードする場合

```python:python
from google.colab import files
files.download('ファイル名。必要に応じてパスも。')
```

とします。

##ローカルからアップロードする場合

```python:python
from google.colab import files
files.upload()
```
を実行したあと、現れるボタンを押してファイルを選択すればOKです。

##google driveを使う場合

グーグルドライブをマウントすれば、ドラッグ＆ドロップでも作業ができます。
[説明はこちら](https://qiita.com/Ninagawa_Izumi/items/5b0a2facd6927498c9ba)
Open Exchange Rates APIから為替の値を取得する [Python]

# PythonでOpen Exchange Rates APIから為替の値を取得する
Open Exchange RatesのAPIからPythonを使って為替の値を取得します。フリープランは1月につき1000リクエストまでということですが、自分の場合は十分すぎるくらいに感じます。

Open Exchange Ratesの登録に関してはこちらの記事を参考にさせていただきました。
<a href=https://qiita.com/ryoju/items/19c5c39bebcabb5fbb34>Pythonでopen exchange ratesから為替レートを取得する</a>

2015年の記事ですが、UIがほぼ変わっていないので記事通りに登録できました。

## APIの使用までの流れ
Open Exchange Rates APIに関しての概要がこちら
<a href=https://docs.openexchangerates.org/docs/>API Introduction・Open Exchange Rates</a>

ベースURLである`https://openexchangerates.org/api/`にいろいろpathを足して欲しいデータを絞り込んでいくようです。
<ol>
<li>最初の選択肢は`latest.json(最新の値)`、`currencies.json(わからない)`、`historical/2013-02-16.json(過去のデータ、日付を指定する)`の3種類です。
currencies.jsonに関してはよくわからなかったのですが、今回の目的は最新のデータですのでlatest.jsonをベースURLに追加します。

`https://openexchangerates.org/api/latest.json`
</li>
<li>次に自分のAPP IDをつけ足します。
`https://openexchangerates.org/api/latest.json?app_id=自分のID`
これでどうやら米ドルをベースとしたリクエストが可能になるようです。さらに `&base=通貨`をつけ足すことで別の通貨をベースにもできるようですが、とりあえず米ドルでやってみます。
</li>
</ol>
## プログラムを作成
HTTPリクエストを行うためのrequest、json形式のデータを扱うのでjsonモジュールをそれぞれインポートします。
また、とりあえずおおよその形式を把握するためにpprintで全体を表示してみます。

```python
import requests
import json
import pprint

response = requests.get('https://openexchangerates.org/api/latest.json?app_id=自分のID')
pprint.pprint(response.json())
```
かなり簡単な形式ですがこんな感じでとりあえず実行してみます。
-実行結果-
![スクリーンショット (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1362813/11f079bd-205c-b97c-70a8-7a66ad20628f.png)
一応取得はできているようです。次回以降もう少し細かく通貨ペアの指定などしてけたらと思います。

初めての投稿で拙い部分も多いですが、ここまで読んでくださりありがとうございました。
【Android】RecyclerViewの移動アニメーションをオフにする方法

RecyclerViewにはデフォルトでアニメーションが設定されており、アイテムの順番が変わった時などに移動アニメーションが行われるかと思います。

アニメーションがあると切り替わりが視覚的にわかるので便利である一方、アニメーションをなくしたいなと思う場面もあるかと思います。

そこで今回は、RecyclerViewの移動アニメーションをオフにする方法を2つほどご紹介したいと思います。

※ 移動アニメーションは↓の並び替え時のアニメーションを指しています。
![1619012378.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/fcfabae1-13a6-92b6-a2f6-a93be2d9b65a.gif)

# ①. `itemAnimator` に `null` をセットする方法
一番手っ取り早い方法です。
そもそもRecyclerViewにはデフォルトで `itemAnimator` に [DefaultItemAnimator](https://developer.android.com/reference/androidx/recyclerview/widget/DefaultItemAnimator?hl=ja) というのがセットされており、それがアニメーションを提供しています。
なので `itemAnimator` に `null` をセットし `DefaultItemAnimator` を使わないようにすることでアニメーションをオフにする形です。

```kotlin
val recyclerView = ...
recyclerView.itemAnimator = null // nullをセット
```

このようにすると、アイテムの順番が変わった際にアニメーションが走らず、パッと切り替わるようになります。
![1619011994.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/087ff377-bdf9-2b0e-0e2f-d22fcac157ae.gif)

# ②. `DefaultItemAnimator` を使いつつ、移動アニメーションだけオフにする方法
①の方法が手っ取り早く楽なのですが、 `DefaultItemAnimator` には移動アニメーション以外にも、アイテムを表示する際のアルファのアニメーションもあったりするので、全部をオフにするとアイテム表示時にやや唐突な印象を与えてしまうかもしれません。

そこで、`DefaultItemAnimator` は使いつつ、移動アニメーションだけをオフにしてみます。

`DefaultItemAnimator` の無名クラスを `itemAnimator` にセットし、 `animateMove` というのをオーバーライドしてあげます。

```kotlin
val recyclerView = ...
recyclerView.itemAnimator = object : DefaultItemAnimator() {
    override fun animateMove(holder: RecyclerView.ViewHolder?, fromX: Int, fromY: Int, toX: Int, toY: Int): Boolean {
        dispatchMoveFinished(holder) // これは呼んだほうがいいらしい
        return false // falseで返すことで後続の処理を呼ばないように指定
    }
}
```

このようにすると、移動アニメーションに関しては①と変わらずですが、RecyclerViewにアイテムが最初に表示される時にアルファのアニメーションが走るようになります。（gifが若干わかりにくいですが…）

|①の時|②の時|
|:------------:|:------------:|
|![after.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/18f84b2c-95fe-cf69-c4d8-44c2be8efabe.gif)|![before.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/995/50bdbc5d-b793-704e-bd2c-be9e2c251e97.gif)|

---
以上、RecyclerViewの移動アニメーションをオフにする方法を2つご紹介しました。
他のやり方・もっといいやり方などご存じの方がいらっしゃいましたら、コメントなどいただけると嬉しいです。
LeetCode日本語修行8日目- [91- デコード方法]

###Decode Ways
#####参考：https://leetcode.com/problems/decode-ways/
###問題の内容:
A-Zの文字を含むメッセージは、以下のマッピングを使って数字にエンコードできます。

```
'A' -> "1"
'B' -> "2"
...
'Z' -> "26"
```
暗号化されたメッセージを解読するためには、すべての数字をグループ化し、上記のマッピングの逆を使って文字にマッピングする必要があります（複数の方法がある場合もあります）。例えば、"11106 "は次のようにマッピングできます。

グループ化（1 1 10 6）した "AAJF"
グルーピング（11 10 6）を使用した "KJF"
ただし、グルーピング(1 11 06)は、"06 "が "F "にマッピングされないため無効である。"6 "は "06 "とは異なるからだ。

###例:
例1:
Input: s = "12"
Output: 2

例2:
Input: s = "226"
Output: 3

例3:
Input: s = "0"
Output: 0
###ヒント:
1 <= s.length <= 100
s contains only digits and may contain leading zero(s).

---
DPを使う。
s.charAt(i)の時
その前の文字の暗号化した後の数字は一桁又は二桁
即ち　f(i-1) || f(i-2)
それを判断して、処理します。


```Kotlin
class Solution {
    fun numDecodings(s: String): Int {
        var m = s.length
        var array = IntArray(m+1)
        
        array[0] = 1

        for(i in 1 until array.size){
            if(s[i-1] != '0'){
                array[i] += array[i-1]
            }

            if(i>1 && s[i-2] != '0' && (s[i-2]-'0')*10 + (s[i-1]-'0') <= 26){
                 array[i] += array[i-2]
            }
        }
        return array[m]
    }
}
```
画像のセグメンテーション[Graph Based Image Segmentation]

### はじめに
ばら積みされたタオルから3Dカメラを使用した把持位置認識の際に```Graph Based Segmentation```のアルゴリズムが使用されていました。

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC6387280/

今回はその```Graph Based Segmentation```について知識を深めるために、画像に対してそのアルゴリズムを使用したものを試してみました。

### 準備

1.まずソースコードを以下のサイトからダウンロードします。

http://cs.brown.edu/people/pfelzens/segment/

2.入力画像の取得

入力する画像を決めるのですが、入力する画像はppm形式でなくてはいけません。
jpgなどを使用したい場合は次のようなサイトでppm形式に変換します。

https://convertio.co/ja/jpg-ppm/

今回自分が使用したのは次のようなペンギンの写真です。
![Screenshot from 2021-04-22 00-09-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/774b33f5-a7c4-6518-c4bc-ee260ded8e33.png)


### 使ってみる
それでは使ってみます。

1.ビルド

```
cd segment
make
```

2.実行

READMEに記載があるのですが実行する際に引数を入れる必要がありその順番は次のようになります。

```
segment sigma k min input output
```

それぞれのパラメータの意味は以下の通りです。

```
sigma:セグメンテーションをする前の平滑化に使用
k:しきい値関数の値
min:最小の領域サイズ
input:入力画像
output:出力画像
```

それでは実行してみます。

```
./segment 0.5 500 50 pengin.ppm pengin2.ppm
```

生成された画像は次のようになりました。

![Screenshot from 2021-04-22 00-09-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/791f8e45-c669-269f-2c40-4b399c611a6a.png)


次に、しきい値の値を500から200に下げて実行してみます。

```
./segment 0.5 500 50 pengin.ppm pengin2.ppm
```

より細かい領域に分割されました。
![Screenshot from 2021-04-22 00-08-58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/537df2e1-1c26-db0e-57ae-de9584e1d62e.png)

そして次にmin(最小コンポーネントサイズ)を50から20に減らしてみます。

```
./segment 0.5 500 50 pengin.ppm pengin2.ppm
```
結果はこのようになり、更に細かい領域が出現しました。
![Screenshot from 2021-04-22 00-13-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589906/41362c10-231f-62cf-c76e-95685b3919f3.png)

### さいごに

```Graph Based Image Segmentation```というアルゴリズムを使用した画像のセグメンテーションを行いました。
今後は3Dカメラから取得した点群に対してもこのアルゴリズムを適用できるよう,今回使用したソフトウェアの内部のグラフセグメンテーション部分についての知識を深めていきたいです。

### 参考

- パラメーターについて
https://qiita.com/shngt/items/e654fb221b5058519526

- python実装
https://github.com/sirius-mhlee/graph-based-image-segmentation
[HTML]メタタグの書き方

#メタタグとは
記事のコンテンツ情報を検索エンジンに伝える役目をしています。
SEO対策のうちの１つで、設定することでサイト名やタイトル名などや、OGP設定、Google検索に載せたくないページを設定することができます。

#メタタグの書き方
metaタグは、HTMLコードのheadタグ内に記述します。

##titleタグ
サイトのタイトルを設定します。

```
<title>タイトル名</title>
```

##descriptionタグ
ページの概要文にはどんな内容の記事コンテンツであるかを１２０字程度でまとめます。


```
<meta content="ページの概要文">
```

##OGPタグ
OGPとは`Open Graph Protocol`の略です。
FacebookやTwitterなどのSNSで共有された際に、ページのイメージ画像やタイトル、概要文、URLなどを正しく表示させるために設定します。

```
<meta property="og:title" content="ページのタイトル">
<meta property="og:description" content="ページの概要文">
<meta property="og:type" content="ページの種類">
<meta property="og:url" content="ページのURL">
<meta property="og:image" content="サムネイル画像のURL">
<meta property="og:site_name" content="サイト名">
<meta property="og:locale" content="ja_JP">
```
踏み台に本番サーバへポートフォワーディングさせてHTTP通信する

久々の投稿。

踏み台を経由して本番サーバにSSHして作業することは多いのですが
たまに本番サーバに入っているzabbixなどのWEBのコンソール画面を開きたくなります。
踏み台でポートフォワーディングすればよいのですが、sshのオプションをよく忘れるのでメモしておきます。

```bash

ssh -g -N -L [踏み台の空いてるポート]:[接続先IP]:[接続先ポート番号] hoge(sshconfigの名前)
```


なお、踏み台で使っていないポート番号はXXXXにポート番号を入力して何も表示されなければ開いてるポートとなる。

```bash

netstat -an | grep XXXX
または
ss -ant | grep XXXX
```
The DevOps HANDBOOKを読んでみた

##前置き
本記事はインフラエンジニアをやっている視点から`The DevOps HANDBOOK`を読んだので書評となります。
今後のインフラエンジニアもこういった知識が必要となると思いインフラエンジニアの方にも本書を勧めたい（DevOpsに関わらなくてもちょっとした運用改善活動等のヒントも記載されているため）と思い書評を書いてみました。
※アプリケーション開発の経験はほぼないため、インフラエンジニア視点で記事を書いているので、そこはご了承頂ければと思います。

## DevOpsHandBookを読もうと思った理由
　インフラエンジニアをやりながらAnsible等のツールを利用して、基盤のオーケストレーションを実施した経験から、こういった今更ながらにDevOpsの成り立ちや、考え方を整理したかったため。

## こんな人に読んでほしい
・DevOpsについてしりたい！というエンジニア
・これからアジャイル開発を行おうかなと思っているエンジニア
・現場である程度実務経験があるエンジニア
・Infrastructure As Codeを実践しているエンジニア
・現場のエンジニアから管理職、組織のTOPの考え方も入っているため、役職等関係なくDevOps文化を学びたい人

## 構成  
　DevOpsを実践してシステム開発における悪循環を断ち切り、顧客への素早いサービス価値の提供するための一つの方法論が記載されています。

#####1.DevOpsを支える原則について
　本書全体の概要が記載されていて、作業の単位を小さく、作業のキューを個人が溜め込まないや組織一丸（開発から運用まで）となったシステム開発。開発結果からのフィードバックによる改善、継続的な学習・改善活動の実施。如何に顧客へのサービス価値の提供を早くするかといった内容で、ここを読むだけでも改めて考えさせられるものがある。　

#####2.DevOpsを始めるために
　DevOpsにおいて組織内の文化の形成（チームビルディング）。アーキテクチャのあり方（システムを疎結合に作る）について記載されている。
　ここでの考え方や手法は、今後チームリーダーとなったときに役に立つなと思う。

#####3.実際にどのようにフローを改善するのか
　実際にシステムを構築していく中で、素早いサービス提供を実現するために、継続的インテグレーションを実践や信頼性工場のためのテスト、マイクロサービスアーキテクチャについて触れられていて、インフラエンジニアの目線から見ても、システム構築時に役に立つことが書かれている。
　
#####4.フィードバック文化
　特に目新しかったのがA/Bテストを業務フローに盛り込むことで
　ユーザフィードバックをより早くシステムに組み込んで、より良いシステムをリリースしようという内容が記載されていて
　そんな考え方はなかったと驚いた。

#####5.継続的学習文化について
　組織内で学習のための土壌作りについて記載されている。
　システムエラーから学ぶことや、組織内で教え合う文化について触れられており
　組織の学習レベルのベースアップのためのことが書かれている。

#####6.セキュリティ・コンプライアンス
　デプロイラインにセキュリティテスト、コードに対しての整合性・セキュリティ、承認プロセスといったシステムを運用していく上では欠かせない、セキュリティ・コンプライアンスを守るための手法が書かれている。
　　

　全体的に、過去にあった実例等を用いて説明されていてわかりやすい印象です。
割と細かく章立てされていて内容が章ごとにコンパクトにまとまっており、文章全体で冗長な部分がなく読みやすい文章でした。
※本書は、著者が海外の方のため日本語訳されています。
　原文を読んだわけではないのではっきりとは言えませんが、訳もそこまで違和感のあるものではなく読みやすかったです。

## まとめ・感想
　イントロダクションとして過去から現在におけるアプリケーション開発の中で
DevOpsがどのように出てきたのかというところから始まり、過去と現在での一つの機能をリリースするスピードの違い（過去は数ヶ月～数年、現在では分単位）
そしてその違いはどこから生まれてきて、そういった素早い機能のリリースはどのようにすれば生まれてくるのか、といったメソッドが記載されている書籍です。

　個人的には`9章.デプロイパイプラインの構築`～`第11章.継続的インテグレーションの実現と実践`は、インフラエンジニアとして携わっていた部分でもありました。
　環境をオンデマンドですぐに構築する仕組みから始まり、機能のデプロイ、そしてテストといった機能をある程度沿った形で実装した経験していました。その時の思考や手法を本書と比較しながら読み、あそこはダメここは良かったと改めて自分の中で振り返りができました。

　また、ある程度実務を経験してきた方だと、本書内の過去事例（問題プロジェクトがDevOpsを導入してどのように改善されたか）が、エンジニアからするとあるあるなネタのため、あ～似たようなことあったな・・・と
自分の過去事例と比較しながら、どのような改善が行われたか、また自分だったらどうしたかを比較しながら読めるので、頭に入りやすいと思います。
そういった意味では、本書はある程度現場で経験を積んだ人のほうが、理解しやすいかもしれないなと印象を受けました。
GANについての整理①

##概要
__敵対的生成ネットワーク(GAN:Generatice Adversarial Networks)__　名前だけでも不思議とかっこよさを感じてしまうのは僕だけでしょうか。
このGANは一体どういったものなのか、僕はすぐさまGANについて調べはじめました。

今回はこのGANについて調べたり、勉強してきたのでそれをまとめる記事になります。
別の記事でGANを用いてmnistデータセットから手書き文字を生成するコードを書いているのでぜひ読んでください。


##GANについて
GANでできることといえば、とてつもなく__リアルな画像を生成__することがあげられます。
これは本当にリアルで、本物と見分けがつきません、、、
そしてもう１つ優れた能力として、__画像から新たな画像を生成__できることです。
有名なのが馬の画像からしまうまの画像を生成する例です。（以下に画像あり）
他にもゴッホの書いた絵画像を学習させ、普通の絵画像からゴッホ本人が書いたような絵の生成する例もあります。

こんなことができるなんて凄すぎますよね。。。。。
<img width=100% src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQTmQX5o88XuRbnuI5Oy87elHSPfFdRpJJP2Ur0mKgXU7anMWq8lgOgX1Zno8uPV6SZ7Rs&usqp=CAU'>

では、この凄まじい能力のあるGANはどのような仕組みになっているのでしょうか。
難しい式を使わず説明していきます


###GANの仕組み
GANは日本語訳すると__敵対的生成ネットーワーク__と言います。この敵対的という言葉がまさにGANの仕組みを象徴している言葉になります。
GANは大きく分けて2つのネットワークで構成されています。
それは__識別器と生成器__です。
この２つの仕組みを理解できるとGANの仕組みをおおよそ理解できます。
GANによる画像生成の仕組みを簡単述べると、__識別器を騙せるほど本物そっくりに生成器が画像を生成する__です
例えばゴッホがかいたようなリアルな絵画を生成するとします。
生成器ではゴッホの絵画のような偽の画像を生成します。
識別器では生成器が生成した画像と本物の画像を見比べてどちらが本物なのか区別します。
そして生成器は、識別器が分類した結果のフィードバックを受け取り、より本物に近い画像を作れるように学習します
これを繰り返し行うことで識別器が本物か偽物か正しく判断できないような画像を生成器が生成できるようになります。
この識別器と生成器の関係性が敵対しているから敵対的生成ネットワークというのです。

__生成器__
＜出力＞
できるだけ本物に見える偽のサンプル
＜目標＞
識別器が本物と判断する偽のデータを生成すること

__識別器__
＜出力＞
入力サンプルが本物である推定確率
＜目標＞
生成器からくる偽のデータと、訓練データからくる本物のデータを見分けること

<img width=100% src='https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRnuMkULlpsFianLeK7HGQMwq-gT_XhSiv0EQ&usqp=CAU'>
重複ファイルを1つだけ残して削除するコマンド

### 以下の1行を整理したいディレクトリで実行
```bash
md5sum * | awk '!colname[$1]++{print}' | awk '{print "-not -name " $2}' | paste -sd " " | xargs -i sh -c 'find -type f {}' | xargs rm
```
ハッシュ値が同じなら同一とみなしています(普通は衝突しないので問題ないと思いますが、念のためバックアップはとってください)
ファイル名が違っても中身は一緒ってファイルを見つけて消したい時にお使いください。
### 参考にさせていただいた記事
http://akiniwa.hatenablog.jp/entry/2014/04/04/203256
https://qiita.com/soymsk/items/7c1621ffca4d0f7ad678
https://qiita.com/piroor/items/55ff672cb9f8e375e659
出品詳細削除機能実装



```ruby
<%= link_to 'リンクに表示する文字', 'リンク先のURL', method: :'HTTPメソッド名' %>
<%= link_to '削除', "/tweets/#{tweet.id}", method: :delete %>
```


一覧
-

|メソッド|役割|
|--|--|
|GET|データを取得する
|POST|データを送信し、保存する
|DELETE|データを削除する
|PATCH|データを置き換える
研究室でDockerを使うメリット

# はじめに
私は現在、大学院の修士２年生の学生です。4月になり新しく研究室に入ってくる人がいるタイミングで、研究室内でこれまでの古い研究環境から、Dockerを使った新しい環境にしようという動きが出てきました。今まさに色々調べている段階なのですが、どういう構成で環境を構築することになったのか、また研究室でDockerを使用するとどのようないいことがあるのか、ということをお話ししていこうと思います。

## 研究環境の全体像
![overall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306038/62a6e243-2e6a-ad6e-d9f0-72d5d141a105.png)
この全体像は新入生向けに作ったもので、Windowsを使っていたり、Jupyterを使っていたりするのですが、参考になるかもしれないので一応載せておきます。

## 研究室でDockerを使用する主なメリット
- 環境構築が楽
今までは環境構築が大変でした(Python入れて、Tensorflow入れて、さらにGPUを使うのであればさらに色々しないと動かないみたいな🤮)
それをDockerを使えば，コマンド一つでこれら全ての設定を良い感じに行なってくれます。

- 実行環境を簡単に共有できる
例えば、先輩のソースコードをGitHubなどからとってきて実行したいみたいな場面は研究室ではそこそこあると思います。これまでは、Pythonやライブラリのバージョンまではすぐに再現することができませんでした。そのため、バージョンなどに起因するエラーが発生して詰まるといった問題が発生したりしていました。これもDockerを使えば，環境を文書化して共有することができ，簡単に全く同じ環境を再現することができます。

- GPUを搭載したパソコンを複数人で使う場合に、CUDAのバージョンなどを合わせなくて良い
私の研究室では、GPUを搭載しているパソコンは複数人で使うことが多いのですが、その際に誰かが１年前に入れたCUDAのバージョンに皆が合わせないといけないみたいな状態が生まれていました。このような問題もDockerを使えば、ドライバをダウンロードすればそれぞれの人が、好きなバージョンのCUDAを使用することができ、平和になるのではないかと考えています。

## 技術のざっくりとした説明
- WSL2(Windows Subsystem for Linux)
Windows上で、Linuxを利用することができるものです。純粋なLinuxカーネルを仮想マシン上で動作させています。DockerをWindowsで使う場合、WSL2を使用しなくても使うことはできますが、将来的にGPUを積んだ計算用のパソコンを使用する際には、Linuxを使うことになるので、どうせなら最初から同じ環境でやった方がいいということで使っています。

- Docker
何番煎じかという感じですが、コンテナ型の仮想化サービスを提供しています。以下の図がDockerの構成を表している．それぞれの用語の説明をすると，
![docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306038/8d59775f-f8a6-8a83-0a69-b39147c61fe2.png)
    - Dockerホスト  
    Dockerが動作している仮想マシン(今回の場合はWSL2にあたる?)
    - Dockerサーバー  
    コンテナとDockerイメージを管理するサーバ
    - Dockerクライアント  
    利用者がDockerを使用するために操作するコマンドやツール群
    - Dockerイメージ  
    コンテナを立ち上げるために必要なミドルウェアなどの設定やコマンドが、ひとまとめになったテンプレート(Ubuntu, Python, Tensorflow…)
    - コンテナ  
    Dockerイメージをもとに作られた仮想環境のこと．これが，Pythonなどを実行する環境になる．
    - Dockerレジストリ(DockerHub等)  
    Dockerのイメージが公開されているサイト．フリーのソフトウェアのイメージをはじめ、個人で作成したイメージも公開されている．Dockerコマンドなどから簡単にダウンロードすることができる．

- Jupyter
新入生向けの環境を考えているので今回はなるべく、環境構築の複雑さを省くためにブラウザから操作できるJupyterを使用してもらうことを考えています。
Automation AnywhereとUiPathを戦わせる

#はじめに

RPAは一般的に複数Botの同時実行ができません。
ロボットAが動いているときは、ロボットBは待たされますね。
でも違うRPA製品のBotであれば同時に実行することができます。
というわけで、Automation Anywhere(Automation360)とUiPathで同じロジックを組んで戦わせてみました。

#戦いの舞台
単純な陣取り合戦です。10×10のマスからランダムに選んで埋めていきます。
プログラムは.NetのWindows Form。各マスはTextBoxです。
![game01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/632535/bdddb8eb-023d-820d-0035-57a478e73808.png)
#Botのロジック
- 乱数で10×10からマスを１つ選びデータを読み出す。
- データが入ってなければ自分の数字(UiPathは1、Automation360は2)  をうちこむ。

これだけです。
※UI要素の操作は、UiPathでは変数による動的セレクタ、AAではレコーダー⇒キャプチャしたあとプロパティ変数化、でやってます。

#結果（水色がUiPath、赤がAA）
https://www.youtube.com/watch?v=vLVreciI6DM


#さいごに
実行速度でUiPathの圧勝でした。
どうもUI要素の操作がAutomation360は少し遅いみたいです。
でもAutomation360の方が楽に作れた印象。
非プログラマにはAutomation360の方が扱いやすいかもしれません。

まぁ、C#アプリ含め2，3時間で作った適当な物なのでお遊びとみてください。
本当はコアウォーズみたいな事をやりたかったんですけどね。
データ品質 ⇒ データ品質の向上

１．会社の Salesforce システム管理者が、データ管理計画を策定するように依頼されました。この計画に組み込むべきデータ標準は何ですか?
２．営業担当チームは、テリトリーを計画するために、すべての取引先の正確な取引先責任者情報を必要としています。営業担当チームがその情報を確実に得られるようにするため、Salesforce システム管理者はどのようにすればよいですか?
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634241/723aab98-cc15-f627-1e55-723b6628bdff.png)
Macbookのファンがうるさい原因の対策方法（CPU使用率確認）

最近、macOSでファンが煩くなり負荷が上がるケースが増えてきました。その時にターミナルを起動してCPU使用率をみるのですが、LinuxだとデフォルトがCPU使用率なのでソートする必要がないケースが多いですが、macOSだとCPU使用率順ではないのでソート（並び替え）が必要です





topコマンドを使用時に、CPU使用率に並び替えて起動するようにします。
その際に使用するオプション付きのtopコマンドは「top -o cpu」と入力すればOKです






先程は、起動時にオプションを付けて起動してCPU使用率順に並び替えましが、起動後にCPU使用率順にソートするには、「o」→「cpu」と入力すればCPU使用率順にソートできます

１．ターミナルを起動します

２．topコマンドを入力します

３．top が起動したら「o」と入力します。「primary key [-pid]:」と表示されます

４．「cpu」と入力して「Enter」を押すと、CPU使用率に並び替えができます

５．使用率が高いアプリケーションやソフトウェアを停止させる。
数値

```py
import math

print(7 // 2) #商3
print(7 % 2) #余り1

pie = 3.1415
print(round(pie,2)) #3.14

print(math.sqrt(25)) #5.0
print(math.log2(10)) #3.321928094887362

print(help(math)) #関数やライブラリのドキュメント見れます。
```
AzureLogicAppsを使って、HTTPリクエストからのメール送信をやってみた

メール送信の機能をささっと作りたかったので、AzureLogicAppsを使って作ってみました。

#AzureLogicAppsの大きな流れ
とてもシンプル！！！

1. HTTPトリガー
1. メール送信（今回は、Gmail）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/b27b9c82-b8c3-66e2-e564-103e858e8ac9.png)

#HTTPリクエストでのパラメーター渡し
「宛先・件名・本文」を変更しながら使いたいので、パラメーターで渡せるようにします。
詳しくは以下の公式ドキュメントを参考にして欲しいのですが、要するに、URLに埋め込んで渡します。
この記事の参考URLを例にすると、「postalCode=123456」が渡したいパラメーターになるので、今回の場合は、「to=xxx@xx.xx.xx&title=aaaaa&message=bbbbb]のように置き換えて考えます。
・to：宛先
・title：件名
・message：本文

>1 つ目の位置: https://prod-07.westus.logic.azure.com:433/workflows/{logic-app-resource-ID}/triggers/manual/paths/invoke?postalCode=123456&api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig={shared-access-signature}

実際のHTTPトリガーのURLは、LogicAppsデザイナーから取得しておいてください。
また、メソッドはGETを使用します。

詳しくは、以下の公式ドキュメントを参考にして下さい。

https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-http-endpoint#accept-values-through-get-parameters

#AzureLogicApps側でのパラメーターの受信
上記のURLから渡されるパラメーターを抜き出し、「メール送信」の部分で使います。
パラメーター値を取得するには、triggerOutputs() 式を使います。

「宛先・件名・本文」は以下のように取得できます。to/title/messageは適宜読み替えてもらっても大丈夫です。
>triggerOutputs()['queries']['to']
triggerOutputs()['queries']['title']
triggerOutputs()['queries']['message']

LogicAppsデザイナー上では、こんな感じで入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/9880ea86-3f08-8d13-3c22-1a9218d13d47.png)

「宛先・件名・本文」を全て入れるとこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/c9cd6b3f-4e02-0fa5-abe3-6f21ffd0c8c3.png)

詳しくは、以下の公式ドキュメントを参考にして下さい。

https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-http-endpoint#accept-values-through-get-parameters


#最後
これで、HTTPリクエストを使って手軽にメールが送信できるようになりました。
「宛先・件名・本文」もある程度はカスタマイズできるので使い勝手も良いと思います。
あとは、これだけ用意しておけば、AzureFunctionsを起点にメール送信したり、M5Stackなどにも手軽にメール送信機能を追加したり、いろいろ使える気がします。
laravel chartjs 線グラフにしたいときデータがテーブルのうちの一つしかもらえない？

chartjsで、データをもとにグラフを作成したかったのだが、、、

```
<td>{{$body->date}}</td>
<td>{{$body->evaluation}}</td>
    <td>{{$body->memo}}</td>
    <?php $Yaxis1s[] = array() ?>
    <?php $Xaxis1s[] = array() ?>
    <?php $Yaxis1s[] = $body->date; ?>
    <?php $Xaxis1s[] = $body->evaluation; ?>
    <td>
var Xaxis1s = <?php echo json_encode($Xaxis1s) ?>;

        var Yaxis1s = <?php echo json_encode($Yaxis1s) ?>;
```

で、送られたデータはテーブルの最後の一行だけ。

試行錯誤（〇〇時間）の結果

```
<?php $Yaxis1s[] = array() ?>
    <?php $Xaxis1s[] = array() ?>
```
これがいらないらしい

削除して完成
【メモ】Pandas 特定の条件の行を抽出する

## はじめに

表形式のデータをきれいにする時に特定の条件の行を抽出したくなる時などがあると思います。

今回はそんな時に使えそうなpandasのquery()関数を紹介します。

## 書式
書式はシンプルでquery()の引数に条件式を書いてあげるだけです。

df.query(条件)

## 実際のコード

```python:tohoku.py
import pandas as pd
import numpy as np
a_values = [1,2,3,4,5,6]
b_values = ["Aomori","Akita","Iwate","Miyagi","Yamagata","Fukushima"]
c_values = [129,96,122,230,108,184]
my_dict = {"番号":a_values, "県名":b_values, "人口":c_values}

df = pd.DataFrame.from_dict(my_dict)
df
```

```python:tohoku.py
#人口が100万人より多い県を抽出する
print(df.query('人口 > 100'))
```

```python:tohoku.py
#人口100万人未満の県を抽出する
print(df.query('人口 > 100'))
```

[Google Colaboratory](https://colab.research.google.com/drive/1tYFJ2aPS8oms0crI_1jGmPyFAIKPe9x2?usp=sharing)はこちらから
[PHP]Windowsで静的解析ツールPhanを動かす

Windowsで静的解析ツールPhanを使ってみたので、手順の覚え書き。

## 環境

* OS: Windows 10
* PHP: 7.4.11<br>
→ PHP7.2以上である必要あり
* Phan 4.0.4
→ 今回インストールされたバージョン

## 手順

ほとんど公式GitHubの

* [Getting Started・phan/phan Wiki | GitHub](https://github.com/phan/phan/wiki/Getting-Started)
* [Tutorial for Analyzing a Large Sloppy Code Base・phan/phan Wiki | GitHub](https://github.com/phan/phan/wiki/Tutorial-for-Analyzing-a-Large-Sloppy-Code-Base)

辺りに従った内容となります。

### 1. composerのインストール

phanのインストール方法はいくつかありますが、今回はcomposerを用いました。

未導入の場合は、
[Download Composer | getcomposer.org](https://getcomposer.org/download/)
のComposer-Setup.exe のリンクをクリックして、インストーラをダウンロード。
その後、ウィザードの内容に従ってインストール。

### 2. php-astのダウンロードと設定

(1) まず、PHPのバージョンを確認します。

```
> php -v
```

[ast 1.0.10 for Windows | pecl.php.net](https://pecl.php.net/package/ast/1.0.10/windows)より、対応バージョンのzipファイルをダウンロード。

Non Thread Safe（NTS）とThread Safe（TS）がありますが、間違った方を選ぶと実行時にエラーになるので、環境にあった方を選択。
自分の場合は、Thread Safe（TS）が正解でした。

(2) 続いて、ダウンロードしたzipファイルを展開し、php_ast.dllをextension_dirに移動させます（他のファイルは配置しなくて大丈夫）。
extension_dirの確認コマンドは以下の通り。

```
> php -i | findstr /I extension_dir
```

(3) php.iniに、php-astに関する記述を追記します。
どこにあるか確認したい場合は、ルートフォルダに移動して、dirコマンドで検索。
/sをつけることで、サブディレクトリ込で探してくれます。

```
> cd /
> dir /s php.ini
```

php.iniに追記する内容は以下の通り。

```config:php.ini
extension=php_ast.dll
```

### 3. phanのインストールと設定

(1) 任意の場所で、以下のコマンドを実行してphanをインストールします。
専用のフォルダで行うのがよいでしょう。

```
> composer require --dev "phan/phan:4.x"
```

(2) 設定ファイルを作成します。
(1) のコマンドを実行したフォルダで以下のコマンドを実行。
--init-levelは、1から5の任意の数字を設定してください。
解析レベルは、1が最も厳密で、5が最少となります。

```
> vendor\bin\phan --init --init-level=5
```

今回は最低限でよいので、5をチョイス。

完了すると、同フォルダ配下に、

`.phan\config.php`

という設定ファイルができあがっています。

(3) 解析対象の設定
(2) で作成された.phan\config.phpを開き、directory_listで検索、その中に解析対象を記入しましょう。
依存関係のあるフォルダ or ファイルも記入します。


解析対象がC:\php\srcで、C:\php\lib配下のファイルに依存している場合は以下の通り。

```
    'directory_list' => [
         'C:\php\src',
         'C:\php\lib',
         'vendor',
    ],
```

(4) 解析対象外の設定

解析結果出力対象以外は、exclude_analysis_directory_listに記載しておくことで、除外できます。

今回は、C:\php\srcのみ解析したいので以下の通り記述。

```
    'exclude_analysis_directory_list' => [
         'C:\php\lib',
         'vendor',
    ],
```


### 4. 解析の実行

解析を実行します。
analyze.txtファイルに解析結果を出力する場合は以下の通り。

```
> phan -p -o analyze.txt
```

※コマンド実行でファイルも作成されるので、あらかじめ作っておく必要はありません。

以上！

## 終わりに

プログラムの整合性チェックや、バージョンアップなどに重宝しそう♪

## 参考

* [phan/phan | GitHub](https://github.com/phan/phan)
* [ファイルの一覧表示(DIR) | Let's プログラミング](https://www.javadrive.jp/command/file/index1.html)