OmniAICreator/Qiita-1.07M huggingface dataset:
AWS EC2インスタンスへのSSH接続の仕方

#AWS EC2へのSSH接続の仕方

今更だが、AWSに触ったキッカケはServerlessアプリを作るところからだったのでEC2を使うのが始めてだったりする。備忘録。マイマシンはubuntu18.04です。


###AWSでEC2インスタンスを作成
なんでもいいけど
"Ubuntu Server 16.04 LTS (HVM), SSD Volume Type - ami-bec974d8"で作成した。t2.microというタイプ。ウィザードは全部デフォルト。これだと月に１０ドルくらい。
[AWS 月額料金チートシート](https://qiita.com/jyotti/items/d47b52fa13d12476406f)
最後に.pemファイルをダウンロードすること。キー名というのを設定するがそれがpemファイルの名前になるだけ。


###.pemファイルのアクセス権を変更
.pem ファイルを自分のマシンの適当な場所に移動して（たとえば~/pathフォルダなどを作る）、そこに対するアクセス許可を0777 ではなく 0400にする。

```bash
$ cd ~/
$ mkdir path
$ mv ***.pem path
$ chmod 400 path
```

###sshで接続
以下のコマンド。

```bash
$ sudo ssh -i path/***.pem ubuntu@ec2-11-11-111-111.ap-northeast-1.compute.amazonaws.com
```
#####@の前のデフォルトユーザ名は以下の通り。
![Screenshot from 2019-07-27 18-04-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307441/ce12b3da-f318-f0e4-0e0e-71d17493dffd.png)
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/connection-prereqs.html

以下のようなレスポンスが来て、yesと答えると、

```bash
The authenticity of host 'ec2-111-11-111-1.compute-1.amazonaws.com (10.254.142.33)'
can't be established.
RSA key fingerprint is 1f:51:ae:.
Are you sure you want to continue connecting (yes/no)?
```

こう返ってくる。

```bash
Warning: Permanently added 'ec2-111-11-111-1.compute-1.amazonaws.com' (RSA) 
to the list of known hosts.
```
https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/AccessingInstancesLinux.html

プロンプトはこうなっているはず。繋がった。

```bash
ubuntu@ip-111-11-11-111:~$
```

###rootユーザーになるには？

rootのパスワードは設定されていない。次のコマンドでrootになれる。

```bash
~$ sudo su -
```

作業を終えたらexitコマンド。

<br>

##ファイルをEC2へアップロードする

Googleのdebパッケージをアップロードするには下記のコマンド

```bash
sudo scp -i path/***.pem google-chrome-stable_current_amd64.deb ubuntu@ec2-1-111-11-111.ap-northeast-1.compute.amazonaws.com:/home/ubuntu
```

直接EC2からこれでも良い。

```bash

wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
```
Node.jsでprivateメソッドをテスト方法を検討

#概要

Node.jsに限らず各言語でpriateメソッドをテストする際、程度の差はありますが工夫が必要にあります。
今回はNode.jsでpriateメソッドをテストするまでに時間を要したので、メモとして残しておきます。

#読者対象

- priateメソッドをテストしたいけど、面倒なので放置した方

#不採用になった案

結論は自前でやることになったのですが、パッケージやコードがないかなと思ってググりました。
その中で採用候補になったものをあげておきます。

##requireで細工をする

Nodeでプライベートな(exportsされてない)メソッドのテスト
http://nazomikan.hateblo.jp/entry/2013/04/10/032410
vm.runInThisContext()にする場合の補足
https://stackoverflow.com/questions/20899863/the-module-property-is-undefined-when-using-vm-runinthiscontext

これはrequireを通すとexportされてないものがロードできないため、自前でrequireを用意するやり方です。
似たような感じにして作ってみましたが、私はうまく行きませんでした。
やり方が悪かったのか、記事が古くvm.runInNewContext()の仕様が変わったのかは不明です。
テストコードが比較的スマートなので採用する予定でした。
しかし、一部キャッシュされたモジュールを使いまわす前提の箇所があり、contextが別になるとそこの動作への懸念が出たので不採用になりました。

##rewireを導入

https://www.npmjs.com/package/rewire

rewireパッケージを使うことも検討しました。
普段の書き方と変わるのが少しマイナス。
あまり好まないので、さらに検討を進めて自前になりました。

後で以下を見て、これでも悪くないかなと思ったのは内緒です。
```const test123 = require('./index').__get__('test123');```
https://www.grzegorowski.com/jest-tests-with-rewire-plugin/

#実践

通常と同じ動作をしてほしいし、複雑なことはやりたくない。
とにかくシンプルがいい。ただ、テストの時だけpublicにしたいだけなのに…条件で切り替えればいいだけじゃないか:hugging:
思いついたら後は作るだけ。

```javascript:test.js

const firebaseUtil = require('./firebase/util.js');

test('call private method', () => {
	firebaseUtil.privateMethod();
})

```

firebaseのutilモジュールにあるprivateメソッドをコールするテストを想定します。
privateMethodはexportしていないので、このままでは実行エラーになります。

```javascript:firebase/util.js

const { getPrivateMethodsInTest } = require('../utils/testHelper'); // add code

const publicMethod = () => console.log('this is public');
const privateMethod = () => console.log('this is private');

module.exports = {
    publicMethod,
    ...getPrivateMethodsInTest({ privateMethod }) // add code
};

```

util.jsではpublicMethod()とprivateMethod()があり、publicMethodは通常通りexportしており、privateの方はgetPrivateMethodsInTest()というメソッドを挟んでいます。
getPrivateMethodsInTest()がカギになります。

```javascript:utils/testHelper.js

const getPrivateMethodsInTest = 
    (methods) => process.env.NODE_ENV === 'test' ? methods : {};

module.exports = { getPrivateMethodsInTest };

```
jestの場合、テスト実行時にprocess.env.NODE_ENVに'test'が入るため、それによって渡されたメソッドをそのまま返すか、空のオブジェクトを返すか切り替えているだけのシンプルなものです。
この戻り値を呼び出し元で展開することで、テスト時にはprivateメソッドがexportされ、それ以外の場合にはpublicメソッドのみが展開されるようになります。
この案のメリットはテスト時は通常のpublicメソッドなので、トラブルの心配がないというところです。

シンプルにまとまっていると思いますが、対象となるソースが多くなってくると煩わしく思えるかもしれません。
その場合はrewireの採用を検討したほうがいいかもしれません。
Grad-CAMで、湖畔と谷とマッシュドポテト、構成と質感認識、VGG16の。

#目的
目的が双方向であるが、
VGG16等のDNNの物体認識の状況確認（説明可能性含む？）と、
逆に、その際に登場するGrad-CAMという手段の妥当性の確認のため、いくつかのサンプルを動作させた。
実行コードは、以下のサイトのものを利用。
https://github.com/eclique/keras-gradcam

普通に車や人の検出が上手なことは確認の必要がないので、
以下の２つの視点で確認した。
　(A)認識において、画像の「構成」を意識する必要があるもの。
　(B)認識において、「質感」で判断する必要があるもの（形状が定まらないもの）。

(A)として、「湖畔」と「谷」を認識させた。
(B)として、マッシュドポテト（皿とかが映らない状態のもの、つなり、”フル””マッシュドにて。）

#　結果
**どれも、すばらしかった。**

Model prediction:
        lakeside        (975)   with probability 0.627
        promontory      (976)   with probability 0.048
        valley          (979)   with probability 0.036
        seashore        (978)   with probability 0.036
        volcano         (980)   with probability 0.035
Explanation for 'lakeside'



<img width="112" alt="kohan.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/5a6ae0a6-8618-1154-10f3-1801adf1c3ac.png">


![gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/a6834719-be6e-4b09-f84f-45f2ed8b2271.jpeg)



![guided_gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/99b461dc-69c3-f25a-0f05-ecde748aec16.jpeg)


Model prediction:
        valley          (979)   with probability 0.933
        alp             (970)   with probability 0.023
        cliff           (972)   with probability 0.013
        viaduct         (888)   with probability 0.007
        lakeside        (975)   with probability 0.006
Explanation for 'valley'




<img width="112" alt="tani.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/5183113c-6c08-5fdd-f1a5-0ea34fe44024.png">




![gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/c9c6a15e-2001-514f-e2e2-9f441e277494.jpeg)



![guided_gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/c6f18b26-4773-e1fe-b51f-b27c101449be.jpeg)


Model prediction:
        mashed_potato   (935)   with probability 0.730
        ice_cream       (928)   with probability 0.160
        dough           (961)   with probability 0.065
        cauliflower     (938)   with probability 0.008
        meat_loaf       (962)   with probability 0.006
Explanation for 'mashed_potato'



<img width="112" alt="m_poteto.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/e0320241-0cb3-540c-6b77-b575ce98646e.png">


↓↑　ハケか何かで、ポテトをべたーっとしたところに注目していないあたりは、まだ、甘いと指摘できなくもない（笑）。ただ、ポテトの洞窟のようなところに反応しているのが、凄いと思う。

![gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/0daab3e9-b28a-f594-59d0-36309837d52b.jpeg)



![guided_gradcam.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/69b099d1-3312-b5dc-21f5-37e23fc39c0e.jpeg)


#まとめ

**Grad-CAMが、意外とすばらしい、気がしつつある。**
VGG16もすばらしい。
とり急ぎ。

コメントなどあれば、お願いします。:candy:
もっと、新しい技術も知りたい。


#関連（本人）

[良書「ゼロから作るDeep Learning -- Pythonで学ぶディープラーニングの理論と実装」を読む](https://qiita.com/enoughspacefor/items/d545b23bd64d285647de)
【メモ】cmakeで分からなかったところを書いておくところ

linuxでC/C++のプロジェクトを欠くことが増えてきて必要になってきたのですが，すごい癖があってかなりつまずきまくったのでメモを残して公開しておくことにします．
躓いたら，随時更新していきます．

# 構文について
最初に躓いたのは大文字がある種の定数変数なのかと思ったら，構文の一部だったりすることだった．
pythonだと

```python3
hoge(a,var1=b)
```
の様に書かれる構文が

```
hoge(a VAR1 b)
```
のように書かれることがある．しかも

```python3
hoge(a,var1=[b,c])
```
の意味で

```
hoge(a VAR1 b c)
```
と書かれることがある．

https://qiita.com/medaka5/items/c2aee6c24e6171888838
に書いてある

# 便利な変数たち，
C++のコンパイラオプションは`CMAKE_C_FLAGS` , Cのコンパイラオプションは`CMAKE_CXX_FLAGS`

https://gitlab.kitware.com/cmake/community/wikis/doc/cmake/Useful-Variables


# 変数

```
set(VARNAME hoge)
```

# if 文

```
if ()
hogehoge
elseif ()
hogehoge
else()
hogehoge
endif()
```
()がないとシンタックスエラーなので注意
マクロで変数が定義されているかは `if (DEFINE var)`で確認できる

https://qiita.com/mrk_21/items/49d8802dc63a2791bcc3
 
#マクロ
グローバルに設定するには

```
add_compile_definitions(OPENCV_VERSION=${OpenCV_VERSION})
add_compile_definitions(WITH_OPENCV2)
```
古いCMAKEだと
add_definitionsしか無い
https://cmake.org/cmake/help/latest/command/add_definitions.html

ターゲットごとに追加するには

```
target_compile_definitions(my_target PRIVATE FOO=1 BAR=1)
```

のようにする。

https://stackoverflow.com/questions/9017573/define-preprocessor-macro-through-cmake


#コマンドの実行
cmake実行時にやりたいなら、`execute_process`
makeのときに実行したかったら？`add_custom_command`を使う

https://cmake.org/cmake/help/v3.0/command/add_custom_command.html

https://stackoverflow.com/questions/25687890/running-a-bash-command-via-cmake


# コメントアウト

```
# comment
```

#プリント文

```
message(STATUS "hogehoge")
```
STATUSの部分はWARNINGとかFATAL_ERRORなどにもできる。変数は${}で参照できる。

https://cmake.org/cmake/help/v3.0/command/message.html


# add_subdirectory
パスを追加するみたいな意味合いがあるっぽい？
https://cmake.org/cmake/help/v3.0/command/add_subdirectory.html

#　結局どこで実行ファイルが指定されているのか
`add_executable( {実行ファイルの名前} sourcefile1 sourcefile2 ...)`
のような感じで作られれる．
ライブラリをリンクするときは(gccの`-L`を使いたいときは)
`target_link_libraries({実行ファイルの名前} )`

# find_package
package(例えばOpenCV)が用意してくれる`Find<package_name>.cmake`ファイルを探して実行することで，libとかheaderの場所を`_LIB`,`_INCLUDE`とかの変数に格納する．
自前でやる場合，手っ取り早いのは`find_library`と`include_directories`を

https://cmake.org/cmake/help/v3.0/command/find_package.html
https://qiita.com/osamu0329/items/bd3d1e50edf37c277fa9


# Debug/Releaseビルドを分ける

```
set(CMAKE_C_FLAGS_DEBUG "-g3")
set(CMAKE_C_FLAGS_RELEASE "-O2")
```
のように設定して， `cmake`実行時にコマンドラインで
`cmake -DCMAKE_BUILD_TYPE=Debug`か `cmake -DCMAKE_BUILD_TYPE=Release`の様にすればよい．
なお一つのMakefileにまとめてくれるといった仕様はない模様.

https://stackoverflow.com/questions/10083427/can-cmake-generate-a-single-makefile-that-supports-both-debug-and-release


# build option
[メモ] ラズパイ OpenCV 4.1.1 ビルド時の__atomic_～～エラー対処

OpenCV 4.1.1、いつも通りにビルドしたら、エラーでませんか？

# TL;DR

cmake へのパラメータに、`-DCMAKE_SHARED_LINKER_FLAGS='-latomic'`を追加する。

```bash:例
OPENCV_VERSION=4.1.1
cmake -D CMAKE_BUILD_TYPE=Release \
    -D CMAKE_INSTALL_PREFIX=/usr/local \
    -D OPENCV_EXTRA_MODULES_PATH=${HOME}/opencv_contrib-${OPENCV_VERSION}/modules \
    -D ENABLE_VFPV3=ON \
    -D ENABLE_NEON=ON \
    -D BUILD_TESTS=OFF \
    -D WITH_TBB=OFF \
    -D INSTALL_PYTHON_EXAMPLES=ON \
    -D OPENCV_SKIP_PYTHON_LOADER=ON \
    -D OPENCV_PYTHON2_INSTALL_PATH=/usr/local/lib/python2.7/dist-packages \
    -D OPENCV_PYTHON3_INSTALL_PATH=/usr/local/lib/python3.7/dist-packages \
    -D OPENCV_GENERATE_PKGCONFIG=ON \
    -D BUILD_EXAMPLES=ON \
    -DCMAKE_SHARED_LINKER_FLAGS='-latomic' \
    ..
```

\# 詳細な手順はのちほど。

# 動機

いつも通りにビルドしてみたら、こんなエラーがでた。

```shell-session:エラー
/usr/bin/ld: ../../lib/libopencv_core.so.4.1.1: undefined reference to '__atomic_fetch_add_8'
/usr/bin/ld: ../../lib/libopencv_core.so.4.1.1: undefined reference to '__atomic_fetch_sub_8'
/usr/bin/ld: ../../lib/libopencv_core.so.4.1.1: undefined reference to '__atomic_store_8'
/usr/bin/ld: ../../lib/libopencv_core.so.4.1.1: undefined reference to '__atomic_load_8'
/usr/bin/ld: ../../lib/libopencv_core.so.4.1.1: undefined reference to '__atomic_compare_exchange_8'
collect2: error: ld returned 1 exit status
make[2]: *** [modules/core/CMakeFiles/opencv_perf_core.dir/build.make:541: bin/opencv_perf_core] Error 1
make[1]: *** [CMakeFiles/Makefile2:2597: modules/core/CMakeFiles/opencv_perf_core.dir/all] Error 2
make: *** [Makefile:163: all] Error 2
```

# 関連
- OpenCVのQ&Aフォーラムより: [Make error __atomic_fetch_add_8 on RaspberryPi4](https://answers.opencv.org/question/215735/make-error-__atomic_fetch_add_8-on-raspberrypi4)
# 環境

- 2019-07-10-raspbian-buster (2019-07-27パッケージ更新:apt upgrade)
- Raspberry Pi 4B (4GB) ファン付き

# その他
- OpenCV 3.4.7は、まだ、ためしていない。
Asset Catalogを使って色の管理　Swift

## Asset Catalogを使って色の管理をしてみた

#### 1. 新しくAsset Catalogを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/282e2ccc-a70e-ebfc-7243-4a647e1f8d17.png)

#### 2. 作成したAsset Catalogで`New Color Set`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/47ec2ab5-b90a-7f14-9267-f2e6f4e07393.png)

#### 3. 色の名前、値を設定 (例　名前:`hotpink`、RGB:`#FF69B4`)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/782af489-95c1-7542-fa3f-aa43a83b6b33.png)

### Interface Builderで使用する
- 色を設定するときに`Named Colors`に作成したものが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/470777/90bd78fa-1a3a-afb5-dda2-7bda6a9f41b6.png)

### ソースコードで使用する
- UIColorを拡張する

```swift:UIColor
extension UIColor {
    /// hotpink RGB:#FF69B4
    class var hotpink: UIColor {
        return UIColor(named: "hotpink")
    }
}
```

- 実際に使用する

```swift:ViewController
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.hotpink
    }
}
```

### まとめ
どの画面でも使用する色や各パーツの色をこのように管理することでデザインしやすくなった。
さらにいい方法があったら教えてください。
SVNを職場で使っている人から見たGitの利点


どうも、客先常駐エンジニアのCLBです。
現在こんな環境で仕事をしています。

- 職場：SVN
- 家：Github(Git)

これをやってると、「こんな理由でGitの方がいい！」と感じてきたので書いてみます。

## コミットしてもコンフリクトが起こらない
SVNで同じファイルを2人以上で触っていると、こんなことが起こります。

```
Aさん「作業出来た！コミット！」
SVN「Bさんの作業とコンフリクトしてます。」

Aさん「しゃーない。コンフリクト解消するか。」
SVN「解消を確認しました。コミットします。」

Aさん「作業出来た！コミット！」
SVN「Bさんの作業とコンフリクトしてます。」
Aさん「またかよ・・・」
```

「そうならないようにルールを決めるんだよ！」と言われましたが、
そのルールは大抵の場合、以下のような形になります。

- SVNでロックを掛け、他の人が触れないようにする。その間、他の人の作業は中断される。
- コミットをなるべくしないようにする。ちょっと前のものに戻す事はあきらめる。

Gitの場合、リモートから`クローン`（SVNで言うチェックアウト）すると、
リポジトリが個々のローカル環境に作成されます。
コミットもそのローカルリポジトリに行われるので、この時点ではコンフリクトは起こりません。

「待って、それじゃあローカルからリモートに移すにはどうすればいいんじゃ」

と声が聞こえてきます。Gitではこの操作を`プッシュ`と呼びます。

SVNではコミット＝リモートリポジトリへ反映ですが、
Gitのコミットではリモートリポジトリへは反映されません。
反映は`プッシュ`操作を行う事で初めてリモートリポジトリへ資産が移送される仕組みです。

この時、リモートリポジトリで何らかの変更があった場合はコンフリクトが発生します。
しかしSVNの時と比べ連続してコンフリクトを解消する手間が省け、
しかもコミットを積極的に行う事が出来るようになるのです。
他の人の作業が中断されたりすることもありません。


## 柔軟にコミットを管理することが出来る
前の項目でも述べた通り、コミットもそのローカルリポジトリに行われるので、
コミットを後から修正したり出来ます。
特に強力なのが`squash`機能です。
これは複数のコミットをまとめる事ができる機能で、
これを利用する事によりコミットログを綺麗にする事が出来ます。
`SVN`では"たとえ細かい修正コミットでも無かった事にしてはいけない。"
というスタンスなので、このような事は出来ません。(シュタゲかな？)


## 先進的なツールと連携出来る。
※これは、私が知る範囲での話です。
問題等があれば遠慮無くコメントをお願いいたします。

`Git`の良いところは`Git`だけでは無く、`Github`や`GitLab`と言った先進的なツールと統合出来ることです。
これらのツールで良いところは、

- マージリクエスト時の比較ツールが見やすく、効率よくレビューを行う事が出来る。
- CIツールと連携してマージリクエスト時に自動的にテストを行う事ができ、その結果を上記のツール内で確認する事が出来る。
- xxのソースコードの何行目と言ったステップ単位でコメントを書く事が出来る。

という点があげられます。
特にこれらの機能が1つのツールで行えるため、`SVN`で同様の事を実現しようとすると
ビルド確認は `Jenkins`, タスク管理は `Redmine`などツールが分散しないのが良いと感じました。

## 終わりに
今まで「`Git`の方が良い。」とよく耳にしてましたが、
実際にやってみると「確かになぁ。」と思う部分があります。
これをみて`Git`を使う現場が増えてくれれば良いと思います。
puttyの文字化け問題～解決編～

# はじめに
puttyの文字化けで数時間消費してしまったので、備忘録的に書いておきます。
どなたかの時間短縮になれば幸いです。

# ①その都度解消する
・接続後、タイトルバーを右クリックして、「ChangeSettings...」を選択する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287441/096898b5-1ad0-54a2-d0c5-761e4d5358c5.png)

・Window>Trancelatin>文字コードをUTF-8に変更する

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287441/2db0fc8f-1441-5830-be63-fd844145dcdd.png)

# ②設定で解決する
・接続するSessionを選択してLoadを押す
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287441/7eff7cf8-341f-ea7b-80d0-9aeb8276b46c.png)

・①同様、Window>Trancelatin>文字コードをUTF-8に変更する
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287441/2db0fc8f-1441-5830-be63-fd844145dcdd.png)

・SessionでSaveを押す、その後接続
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287441/81176d40-cd4a-e4ae-0c46-d8d272dbc2d2.png)
AWS Cloud9にSymfonyを構築する

テスト環境としてSymfonyが使える環境が欲しいと思い、Cloud9上に構築してみました。
今回構築したときの備忘録です。

同様のことは、EC2でAMIをAmazon Linuxにしても動くと思います。

## PHPのインストール
Cloud9のOSは、2019年7月時点でAmazon Linux2ではなく、以前のAmazon Linuxでした。
なので、`amazon-linux-extras`は使えませんでした。

``` bash
$ cat /etc/system-release
Amazon Linux AMI release 2018.03
```

``` bash
$ sudo yum -y update
$ sudo yum -y install php72 php72-mbstring php72-pdo
$ sudo unlink /usr/bin/php
$ sudo ln -s /etc/alternatives/php7 /usr/bin/php
$ php -v
PHP 7.2.19 (cli) (built: Jun 12 2019 20:55:29) ( NTS )
Copyright (c) 1997-2018 The PHP Group
Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies
```

https://qiita.com/kidatti/items/2d6a4a24f89dc71eb66e


## Symfonyのインストール

``` bash
$ wget https://get.symfony.com/cli/installer -O - | bash
$ export PATH="$HOME/.symfony/bin:$PATH" >> .bash_profile
$ sudo mv /home/ec2-user/.symfony/bin/symfony /usr/local/bin/symfony
$ source .bash_profile
$ symfony -v
Symfony CLI version v4.6.2 (c) 2017-2019 Symfony SAS
```
https://symfony.com/download

## Composerのインストール

``` bash
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
$ php -r "if (hash_file('sha384', 'composer-setup.php') === '48e3236262b34d30969dca3c37281b3b4bbe3221bda826ac6a9a62d6444cdb0dcd0615698a5cbe587c3f0fe57a54d8f5') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
$ php composer-setup.php
$ php -r "unlink('composer-setup.php');"
$ sudo mv composer.phar /usr/local/bin/composer
$ composer -v
   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/
Composer version 1.8.6 2019-06-11 15:03:05
```
https://getcomposer.org/download/
http://symdoc.kwalk.jp/doc/book/installation


## Symfonyの起動
Cloud9では外部からアクセスできるポート番号が決まっているため、ポート番号を指定して起動する必要があります。

``` bash
$ symfony new --full my_project
$ cd my_project/
$ php bin/console server:start *:8080
```

メニュー > Preview > Preview Running Applicationを押すと実行ページのプレビューが表示されます。


## Symfonyの停止

``` bash
$ php bin/console server:stop
```


## （補足）アプリの状態をするコマンド
```
$ php bin/console about
```
手動で立ち上げた EC2 に ECS をつなぐ方法


EC2 で ECS を動かす記事をよく見ますが
ECS から設定された EC2 を立ち上げる記事はありますが
自分で立ち上げた EC2 から ECS に連携させる方法の記事が見つからなかったのでメモします
尚、個人的見解ですが、ECS やるなら Fargate 使うほうがおすすめです
EC2 にはパブリック IP が付与されているものとします

## AMIを確認する
AWS で ECS 向けに最適化された AMI が公開されているので使います。
まずは、ECS用に最適化されたAMIの情報を確認します
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/ecs-optimized_AMI.html
英語版のほうが更新が早いので英語版も念の為見ておくと良いです
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-optimized_AMI.html

## ECSを動かせるロールを作成
`AmazonEC2ContainerServiceforEC2Role` ポリシーを付与した EC2 向けのロールを作成します
すでにロールがある場合は、ポリシーをアタッチしてください

## EC2の設定
EC2 の インスタンスの設定画面で
ECS を動かすのに必要なロールを付与

高度な詳細をクリックして開き、
ユーザーデータの部分に以下を追記
HOGE_CLUSTER_NAME を自分の名前クラスター名にする

```bash
#!/bin/bash
echo ECS_CLUSTER=HOGE_CLUSTER_NAME >> /etc/ecs/ecs.config
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/79241/3165ce35-4a0f-b129-8afd-445723ccdf30.png)

あとはよしなににしてどうぞ

参考: https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/launch_container_instance.html
PHPのdate関数にいろんなものを突っ込んでみた


PHPのdate関数にいろんなものを突っ込んだ時のテスト
日付が1日足りない場合の時の挙動なんかおもしろいかも。


```php
echo $birth . '：' . date('Y/m/d H:i:s', strtotime($birth));    //：1970/01/01 09:00:00

```

日付形式に変換できないものは「1970/01/01 09:00:00」になるみたいです。


```php

    $birth = null;
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //：1970/01/01

    $birth = '';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //：1970/01/01

    $birth = 'あああ';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //1999/99/99：1970/01/01

    $birth = '1999/99/99';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //1999/99/99：1970/01/01

    $birth = '1999/00/00';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //1999/00/00：1998/11/30

    $birth = '0000/00/00';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //0000/00/00：-0001/11/30

    $birth = '1999/01/01';
    echo $birth . '：' . date('Y/m/d', strtotime($birth));    //1999/01/01：1999/01/01
    
[/php]


「0000」の場合は日付がずれるみたいです。
PHPのcurlでLocationを辿ろうとしたらエラー


curlのリダイレクトに対応するために、curl_setoptで<br>
CURLOPT_FOLLOWLOCATIONを設定しようとしたらこんなエラーがでました。

```
CURLOPT_FOLLOWLOCATION cannot be activated when safe_mode is enabled or an open_basedir is set in /home/***/***/test.php on line 123
```


原因はPHPが動いているレンタルサーバーがセーフモードで実行していたためでした。
curlでLocationをたどるために以下の方法を使いました。


```php
	$ch = curl_init();
	$limit = 5;
	$url = "http://example.com/has/some/redirect";
	do {
	    curl_setopt($ch, CURLOPT_URL, $url);
	    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
	    $response = curl_exec($ch);
	    $code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
	    $url = curl_getinfo($ch, CURLINFO_REDIRECT_URL);
	} while ($code === 301 || $code === 302 and $limit--);
``
LeetCode / Symmetric Tree

（[ブログ記事](https://mhiro216.hatenablog.com/entry/2019/07/27/171440)からの転載）

[https://leetcode.com/problems/symmetric-tree/]

Given a binary tree, check whether it is a mirror of itself (ie, symmetric around its center).

For example, this binary tree [1,2,2,3,4,4,3] is symmetric:
<img width="103" alt="スクリーンショット 2019-07-27 16.48.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122973/5c67121d-9889-6387-3b7d-17e7416e0956.png">
But the following [1,2,2,null,3,null,3] is not:
<img width="100" alt="スクリーンショット 2019-07-27 16.48.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122973/f34453cf-eb72-16b7-ba02-48662a6e7cea.png">
Note:
Bonus points if you could solve it both recursively and iteratively.

[前回記事のSame Tree](https://mhiro216.hatenablog.com/entry/2019/07/26/165138)に続き、バイナリツリーを扱った問題。
今度はSymmetric、つまり左右対照の図形かどうかを判定します。
ボーナスポイントをくれるとのことですし、recursiveな解法とiterativeな解法の両方を探してみましょう。

#### 解答・解説

##### 解法1
recursiveな解法。

```python
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution:
    def isSymmetric(self, root):
        if not root:
            return True
        else:
            return self.isMirror(root.left, root.right)
    def isMirror(self, left, right):
        if not left and not right:
            return True
        if not left or not right:
            return False
        if left.val == right.val:
            outPair = self.isMirror(left.left, right.right)
            inPiar = self.isMirror(left.right, right.left)
            return outPair and inPiar
        else:
            return False
```
2つ関数を定義していますが、前回のSame Treeと異なりバイナリツリー1つしかないので、もしツリーがない場合Trueを返す処理を挟んでいるだけです。
isMirror関数の処理はSame Treeに似ていますが、
（左側のツリーの左側と右側のツリーの右側）、（右側のツリーの左側と右側のツリーの左側）の各々が同一かどうかを判定するようにします。

##### 解法2
Iterativeな解法。
せっかくなので前回記事でも取り扱った、deque型を使って書いてみます。

```python
from collections import deque
class Solution:
    def isSymmetric(self, root):
        if not root:
            return True

        deq = deque([(root.left, root.right),])
        while deq:
            t1, t2 = deq.popleft()
            if not t1 and not t2:
                continue
            elif (not t1 or not t2) or (t1.val != t2.val):
                return False

            deq.append((t1.left, t2.right))
            deq.append((t1.right, t2.left))

        return True
```

以下にSame Treeの時のコードを再掲します。微妙な差異しかないのが分かるかと思います。

```python
from collections import deque
class Solution:
    def isSameTree(self, p, q):
        def check(p, q):
            if not p and not q:
                return True
            if not q or not p:
                return False
            if p.val != q.val:
                return False
            return True
        
        deq = deque([(p, q),])
        while deq:
            p, q = deq.popleft()
            if not check(p, q):
                return False
            
            if p:
                deq.append((p.left, q.left))
                deq.append((p.right, q.right))
                    
        return True
```
ROCm PyTorch のビルドにチャレンジしてから 1 年が経ちました(2019 年 7 月 27 日) (2019 年 9 月 24 日追記)

ROCm pytorch をコンパイルする試み(2018 年 7 月 27 日時点 実行時 seg fault)
https://qiita.com/syoyo/items/ecb0ee0797d1d192666f

から 1 年が経ちましたので振り返ってみます.

# 2019 年 9 月 24 日追記

ROCm PyTorch ビルド済み Docker イメージがありました.

https://hub.docker.com/r/rocm/pytorch/tags

rocm2.7_ubuntu18.04_py3.6_pytorch など, `_pytorch` のプレフィックスがついているタグになります.
`_pytorch` prefix タグなしは, PyTorch ビルド用の環境(e.g. hip コンパイラなど)のみを提供している Docker イメージです.
 
image が 3.5 GB もあるので, wheel パッケージを配布してほしいところです.
(野良ビルド wheel を作って配布してもよいのですが, オフィシャルから出るのが理想)
 
# 2019 年 7 月時点の状況

ROCm, MIOpen など各種ライブラリの整備が整備され, PyTorch も 1.1 となり, ビルドも整備され, やっと基礎的なものが動くくらいにはなりました.

現状では ROCm TensorFlow のように prebuilt バイナリはありません. 

Pytorch-ROCm DockerでPytorch-ROCmをビルドしてみる(ROCm2.4編）
https://qiita.com/T_keigo_wwk/items/1a525768ad7585bda34f

などを参考に自前ビルドが必要です.

## ビルド所感

HIP でのコンパイルが激重で, 時間がかかります.
Ryzen5 1600 + 24GB + MAX_JOBS 4 で 108 分, Threadripper 1900X + 64GB mem + MAX_JOBS 8 で 58 分でした.
hipcc がメモリを使うので, MAX_JOBS で並列ビルド数あげるばあいはそれなりにメモリが必要です(1 job あたり 6~8 GB 必要そう).

はやく pip などでのコンパイル済みパッケージ配布を整備して欲しいですね.
(もしくは Jenkins での build artifact をダウンロードできるようにしてほしい)

コンパイルが遅いと, 学習時にエラーがおきたりおかしかったときのデバッグもやりずらくなります.

## 動作所感

MNIST, CIFAR10, VGG など古典的で convolution や画像処理系は学習/推論は問題なく動作すると思われますが, 新し目のモデルや, LSTM, GRU などの RNN 系, **音声系は全滅(うごかない, 計算がおかしい, 動作しても CPU/GPU と比べて 5 ~ 100 倍くらい遅い)**でした.

たとえば, deepspeech などいくつか音声認識, tacotron など音声合成系の学習をためしましたが, 1080 Ti ~ 2080 Ti などと比べて 4~6 倍くらいは遅く, また複数 GPU にするとさらに遅くなりまともに使えるものではありませんでした(高性能 CPU で学習したほうが速い). さらにわるいことにはときどき NaN が出たりします.
(正確になにが原因か突き止めるのは面倒で時間もかかるのでやってませんが, 概ね MIOpen や ROCfft など周辺ライブラリに問題がありそうです)

## 今後の所感

まず, Polaris などの GPU(gfx8xx) は今後の ROCm では基本活発な開発は中止(no active development)になります.

機械学習を始めたい優秀な小学一年生さまに,

冬到来! RX470 8GB マイニングエディションと ROCm TensorFlow で, GPU 機械学習をはじめよう(CIFAR10 7,600 examples/sec @ 88W)
https://qiita.com/syoyo/items/c6bc6dd4efbc10049640

というのをやりずらくなります. :cry:

RX5700 などの NAVI 世代(RDNA)は, 主にゲーム向けというのもあり, まだ ROCm 対応していません(ROCm 以前に, コンパイラ周りの整備も必要になり, 開発環境が対応する時間はかかりそう)

したがって現状しばらくは Radeon VII, VEGA56/64 に限定されます. しかし Radeon VII は製造中止になったらしいというニュースも出てきています(VEGA56/64 はすでに終わっているかしらん).

その上で, ROCm(+ PyTorch/TensorFlow, MIOpen) が今後開発が続きメンテされるか... という不安もあります(MIOpen 含め, 一部のソフトウェアスタックは Roadrunner 向けにサポートが続きそうではありますが).

そんな不安を抱えつつ, ベンダー以外のユーザが ROCm PyTorch ビルドを直したりバグの原因を突き止めるには多大な労力と時間が必要になるため, ROCm PyTorch は参考程度にして, 自作 DNN フレームワークを作ったほうが早そうな感がしています.
(もしくは PlaidML で OpenCL ベースで DNN できる環境を整える)

自作の場合は, Vulkan + Compute Shader(次点で Fragment Shader) というのがよいかもと感じています(少なくともゲーム向けにドライバ周りの開発は十分行われるはずなので. Linux でも AMDGPU-Pro 19.30 ドライバですと Navi で Vulkan 対応は済んでいる模様ですので, headless 環境で multi GPU で動かせるものと思います).

Vulkan だと Windows でも動くという利点があります(ROCm は Windows 未対応)

Vulkan での欠点は, 基本高級言語が HLSL/GLSL に限られる,  RCCL が使えない(GPU 間 collective 通信ができない. multi GPU は Vulkan でも対応しているので, もしかしたら拡張でなにかあるかも?)でしょうか.

Vulkan 向けの高級言語については, 限定的ではありますが, OpenCL カーネルを Vulkan(SPIR-V) に変換するツールも出てきています.

https://github.com/google/clspv
PHPでRSSを作成


rdf拡張子のRSSを表示させる場合は以下の行が書かれた「.htaccess」を作成して、表示させたいrdfのディレクトリに置いてください。<br>
「.htaccess」を作成させる場合はサーバーにアップしてからリネームすると「.」がついたファイルを作成できます。

.htaccess

```
AddType application/xml .rdf
```

SimpleXMLElementを使う事で、簡単にRSSを作成できます。
今回は作成したRSSをすぐに表示させていますが、一度ファイルとして保存したものを表示する方法でもいいと思います。
表示されない場合はhtmlspecialchars()で文字をエスケープしてから表示してみてください。
myblog.rdfを保存する場合は、サーバーの公開ディレクトリ直下にrssフォルダを作成してください。

rss.php

```php
<?php

    try{
    
        $RSS = <<<EOT
<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0">
        <channel>
            <language>ja</language>
        </channel>
    </rss>
EOT;

        $rssFileName = 'myblog.rdf';
        
        $XML = new SimpleXMLElement($RSS);
        $XML->channel->addChild('title', "ブログタイトル！");
        $XML->channel->addChild('link', 'http://' . $_SERVER['HTTP_HOST'] . '/rss/' . $rssFileName);
        $XML->channel->addChild('description', "ブログの更新情報です");
        
        $item = $XML->channel->addChild('item');
        $item->addChild('title', "記事タイトル");
        $item->addChild('link', 'http://' . $_SERVER['HTTP_HOST'] . "/page/mypage.html");
        $item->addChild('category', "カテゴリ");
        $item->addChild('description', "記事についての説明");
        $item->addChild('content', "記事の中身");
        $item->addChild('date', date('Y-m-d H:i:s'));
        
        
        header('Content-Type: text/xml');
        ob_end_clean();
        echo $XML->asXML();
        
        $file = fopen($_SERVER['DOCUMENT_ROOT'] . '/rss/' . $rssFileName, "w");
        fwrite($file, $XML->asXML());
        fclose($file);
    
    }catch ( Exception $e ) {
        // var_dump($e->getMessage());
    }
    
    
?>

```

ポイントとしてはob_end_cleanを使用することで、作成したRSSを直接表示させることが出来ます。
JFreeChart-レーダーチャート/SpiderWebChart/UIで特定データを強調する


目次 ⇒ [JFreeChartサンプル](https://qiita.com/artery/items/3e9c63e5c14a9e965c97)

```java

package jp.avaj.lib.chart;

import org.jfree.chart.ChartFrame;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.SpiderWebPlot;
import org.jfree.data.category.CategoryDataset;
import org.jfree.data.category.DefaultCategoryDataset;

import jp.avaj.lib.algo.ArMatrix;

/**
■ JFreeChart-レーダーチャート/SpiderWebChart/UIで特定データを強調する.

・ArcSpiderwebChartEmphasizeWinを起動すると、データの選択画面が表示される.
 */
public class Chart06_03 {
  // 目次-レーダーチャート(SpiderWebChart)
  A_Chart06 a_Chart06;
  // 目次-Artery-JFreeChart用のライブラリ
  A_Chart00 a_LibChartSampeContents;

  /** 成績のレーダーチャートを作成する */
  public static void main(String[] args) {
    // レーダーチャート(SpiderWebChart)にはCategoryDatasetを使用する
	// CategoryDatasetの作成方法は、以下を参照
    Chart01_CategoryDataset_2 categoryDataSetSample;
    // ここではArMatrixからCategoryDatasetを作成する
    DefaultCategoryDataset dataset;
    {
      ArMatrix<String,String,Integer> mat = new ArMatrix();
      // Aの成績⇒理系が得意
      mat.put("A","英語",70);
      mat.put("A","数学",90);
      mat.put("A","国語",55);
      mat.put("A","理科",95);
      mat.put("A","社会",45);
      // Bの成績⇒文系が得意
      mat.put("B","英語",100);
      mat.put("B","数学",60);
      mat.put("B","国語",80);
      mat.put("B","理科",55);
      mat.put("B","社会",70);
      // Cの成績
      mat.put("C","英語",70);
      mat.put("C","数学",70);
      mat.put("C","国語",70);
      mat.put("C","理科",70);
      mat.put("C","社会",70);
      //
      dataset = ArcDefaultCategoryDataset.create(mat,null,null);
    }
    // SpiderWebPlotはRendererやRendererは指定する必要がない
    SpiderWebPlot plot = new SpiderWebPlot((CategoryDataset)dataset);
    JFreeChart jfreeChart = new JFreeChart("成績レーダーチャート",(Plot)plot);
    // チャートを表示する
    ChartFrame cFrame = new ChartFrame("RadarChartFrame",(JFreeChart)jfreeChart);
    cFrame.pack();
    cFrame.setVisible(true);
    //
    // UI画面を表示する
    ArcSpiderwebChartEmphasizeWin win = new ArcSpiderwebChartEmphasizeWin(cFrame,plot,dataset);
  }
}


```

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278568/9a616993-5f38-c387-b502-fd322547a51e.png)
emacsにneotreeを導入してみた

emacsにneotreeを導入してみたので紹介します。
![NeoTree](https://live.staticflickr.com/65535/48385436792_f843793b6e_b.jpg) 

## 設定
```emacs-lisp
(use-package neotree
  :init
  (setq-default neo-keymap-style 'concise)
  :config
  (setq neo-smart-open t)
  (setq neo-create-file-auto-open t)
  (setq neo-theme (if (display-graphic-p) 'icons 'arrow))
  (bind-key [f8] 'neotree-toggle)
  (bind-key "RET" 'neotree-enter-hide neotree-mode-map)
  (bind-key "a" 'neotree-hidden-file-toggle neotree-mode-map)
  (bind-key "<left>" 'neotree-select-up-node neotree-mode-map)
  (bind-key "<right>" 'neotree-change-root neotree-mode-map))


;; Change neotree's font size
;; Tips from https://github.com/jaypei/emacs-neotree/issues/218
(defun neotree-text-scale ()
  "Text scale for neotree."
  (interactive)
  (text-scale-adjust 0)
  (text-scale-decrease 1)
  (message nil))
(add-hook 'neo-after-create-hook
	  (lambda (_)
	    (call-interactively 'neotree-text-scale)))

;; neotree enter hide
;; Tips from https://github.com/jaypei/emacs-neotree/issues/77
(defun neo-open-file-hide (full-path &optional arg)
  "Open file and hiding neotree.
The description of FULL-PATH & ARG is in `neotree-enter'."
  (neo-global--select-mru-window arg)
  (find-file full-path)
  (neotree-hide))

(defun neotree-enter-hide (&optional arg)
  "Neo-open-file-hide if file, Neo-open-dir if dir.
The description of ARG is in `neo-buffer--execute'."
  (interactive "P")
  (neo-buffer--execute arg 'neo-open-file-hide 'neo-open-dir))
```

## アイコン対応にする
all-the-iconsをパッケージインストールして、`(setq neo-theme (if (display-graphic-p) 'icons 'arrow))` を設定するだけで簡単に実現できました。

## 文字サイズを変更する
Githubのissuesボードの設定をそのままパクりました。
`(text-scale-decrease 1)` の数字を大きくするとより縮小サイズになります。

## キーカスタマイズ
neotreeのデフォルトキーマップは、`C-c`をprefixとしていますが、`(setq-default neo-keymap-style 'concise)`を設定すると一部の機能がワンキー操作できるようになります。

|key-bind|コマンド            |
|:------:|:------------------| 
|C       |neotree-change-root|
|c       |neotree-create-node|
|+       |neotree-create-node|
|d       |neotree-delete-node|
|r       |neotree-rename-node|
|e       |neotree-enter|

私の場合、[diredの設定](https://github.com/minorugh/emacs.d/blob/master/inits/30_dired.el) と操作性を統一するために以下のキーバインドも追加設定しています。

* a：隠しファイルの表示/非表示をトグル
* left：一つ上のデレクトリへ移動
* right：カーソル位置のデレクトリをルートとして再表示

## ファイルを開くときはツリーを隠す
neotreeはSPCキーを押すことでカーソル上のファイルが別バッファーにプレビュー表示されます。また、RETキー押しすると表示された別バッファーがアクティブになり編集可能になります。

それぞれ使い分けて便利ですが、RET押しの場合には自動的にツリーが隠れてくれる方が私は好きなので、カスタマイズしてみました。と言ってもこれもパクリです。デレクトリ上でRETするとツリーを展開し、ファイル上でRETしたときだけツリーを隠す…という動作です。
Fluxに学ぶVuex

### 最初に

この記事は自分なりに**Vuex**を噛み砕こうと初心者がまとめたものです。
この解釈違うだろ等あるかもしれませんので、そのときはご指摘いただけると嬉しいです！
なお、今回はソースについては触れず、概念についての解釈をまとめています。


### この記事を書くことになった背景

現場でまず**Vue.js**の新規開発、続いて**knockout.js**の(以下ko.js)保守開発に関わる機会がありました。
どっちにも触れた上での最初の感想、「えっko.js分かりにくいがすぎる！データの流れがよ、よめない。」という感じでした(笑)
ko.jsは一瞬流行ったフレームワークだそうで・・・不人気！？
それがまた大規模で複雑なシステムだったので、余計でした。
**Vuex**の状態管理の恩恵を実感することができました。
実感しているうちに、自分で調べたことを含め、まとめておこうと思います。


### 目次
１.Fluxについて（概念）
２.Vuexについて（概念）


#### １.Fluxについて
**Vuex**は[**Flux**](https://github.com/facebook/flux/tree/master/examples/flux-concepts)というアーキテクトの概念から影響を大きく受けています。
**Flux**とは、一言で言うと、状態管理のための**一方向のデータフローのアーキテクチャー**です。
なんじゃそりゃ・・・
**Flux**を勉強するのに
[漫画で説明する Flux](https://medium.com/samyamashita/%E6%BC%AB%E7%94%BB%E3%81%A7%E8%AA%AC%E6%98%8E%E3%81%99%E3%82%8B-flux-1a219e50232b)が絵で説明されていてわかりやすかったです。

**Flux**が生まれた背景として・・・

[![Image from Gyazo](https://i.gyazo.com/d486e831568ed5e14ef370746c9f7148.png)](https://gyazo.com/d486e831568ed5e14ef370746c9f7148)

・**「[漫画で説明する Flux](https://medium.com/samyamashita/%E6%BC%AB%E7%94%BB%E3%81%A7%E8%AA%AC%E6%98%8E%E3%81%99%E3%82%8B-flux-1a219e50232b)」から引用**
>データを持ち、データを描画するために View 層にデータを渡す Model があります。
ユーザーの操作は View を介して起こっているので、View は時々ユーザーの入力に基づいて Model を更新する必要がありました。
加えて、ときにこれらのユーザーの操作は他の変更の連鎖を誘発します。

非同期に自由にいろんな場所でデータの変更が行われることでデータの流れが追いにくくなり、デバックがしづらくなりました。

この問題に対して解決策として考え出されたのが**Flux**です！！
**一方向のデータフローのアークテクチャー**を設計することで、データの変更を追いやすくしたのです！

[![Image from Gyazo](https://i.gyazo.com/a550500a97199251bd60dae7500e5b4e.png)](https://gyazo.com/a550500a97199251bd60dae7500e5b4e)

ReactJSの状態管理フレームワークReduxもこのFluxから影響を受けています。

#### ２.Vuexについて
まずVueの一つの特徴である**単一ファイルコンポーネント**の話から始めます。
**単一ファイルコンポーネント**にはHTML、JS、CSSをまとめることができ、画面ごとにファイルを管理できて大変便利です。
さらにHTMLの各要素（例えばBUTTONなど）を再利用可能なUIコンポーネントとして作成することもできます。
そして、画面ごとの**単一ファイルコンポーネント**を作成して、そのコンポーネント内にUIコンポーネントを配置していきます。
そのような構成になり、コンポーネント間でデータを共有することが必要になり、コンポーネント間でのデータの受け渡しをするようになりました。
ですが、そこには問題がありました・・・

・[公式サイト](https://vuex.vuejs.org/ja/)からの引用

>しかし、単純さは、共通の状態を共有する複数のコンポーネントを持ったときに、すぐに破綻します:
複数のビューが同じ状態に依存することがあります。
異なるビューからのアクションで、同じ状態を変更する必要があります。
一つ目は、プロパティ (props) として深く入れ子になったコンポーネントに渡すのは面倒で、兄弟コンポーネントでは単純に機能しません。
二つ目は、親子のインスタンスを直接参照したり、イベントを介して複数の状態のコピーを変更、同期することを試みるソリューションに頼っていることがよくあります。これらのパターンは、いずれも脆く、すぐにメンテナンスが困難なコードに繋がります。

**Vuex**の**storeパターン**はこの問題を解決します。
コンポーネントから共有している状態（データ）を抽出し、それをグローバルに管理するというものです。
これにより、コンポーネント間でデータを依存していたのが、どのコンポーネントも自立して管理された状態にアクセスできるようになりました。

さらに、**状態管理に関わる概念を定義、分離し、特定のルールを敷く**ことで、**コードの構造と保守性**を向上させることができます。

[![Image from Gyazo](https://i.gyazo.com/84bbb9ba1f66e9cc5c68915a3548ffd2.png)](https://gyazo.com/84bbb9ba1f66e9cc5c68915a3548ffd2)


### 終わりに
ko.jsのソースを見たとき、いつ、どこでデータが変更されたかデータを追うのに苦労しました。
それにより、どこまでソースに手を加える必要があるか予測しづらかった。

**Flux**に基づいた**vuex**を使って状態管理することで、
・ViewとModelの双方向のデータの変更を**mutation**が取り持ち、**state**を管理することでデータを変更する流れを単一方向にした
→**データの流れが追いやすくなった**
・データの変更の流れを「state」、「mutations」、「actions」、「getters」の４つの役割に分け、明確にした
→**ソースの箇所を特定しやすい**
→**何をテストすればよいか明確になる**



コードの保守性がぐんとあがりそうですね！！

今はここまで。このFluxについては、まだまだ知見を深めていきたいです。
UILabelのAttributedが反映されない Swift

## 問題
StoryBoardやxibなどでUILabelに対してAttributedを設定した状態で

```swift:Swift
label.text = "新しい文字" 
```
のように設定すると行間のスペースなど、Attributedで設定したものが反映されなくなってしまう。


## 解決策
UILabelを拡張してみる

```swift
extension UILabel {
    func setAttributedTextString(string: String) {
        self.attributedText = NSAttributedString(string: string,
                                                 attributes: self.attributedText?.attributes(at: 0, effectiveRange: nil))
    }
}
```

実際に作成した`setAttributedTextString`を呼び出す。

```swift
label.setAttributedTextString(string: "新しい文字列")
```

これで変更前のattributedを保持したまま文字列のみ変更することができる。
【Rails】CSVダウンロード後の画面のリロード

あるデータの一覧のCSVダウンロードした後に画面の情報が変わっていることを確認させる必要があったときの開発メモ。

# controllerからだとリダイレクトは出来ない。
自分の考えとしてはcontroller内のアクションにダウンロードした後にリダイレクトをさせれば良いと考え以下のように記載。

```ruby
def download
    respond_to do |format|
      format.csv do
        send_data render_to_string, filename: "#{__method__}_#{Time.zone.now.strftime('%Y%m%d')}.csv", type: :csv
      end
    end
    redirect_to hoge_url
end
```
ただこれだとDouble renderとなり起こられてしまう。
# 解決 jsでリダイレクトさせる
slim

``` slim
.text-right
  = link_to 'CSV', download_path(format: :csv),
    class: 'btn btn-link', id:'download-csv', target: '_blank'
```

js

``` js
  $('#download-csv').click -> location.reload()
```

参考: http://tshidax.hatenablog.com/entry/2017/09/11/120000
Node.jsでCSVからPHPに雑に変換してみる

WordPressのリプレイスもどき案件で大量(1,000件以上)のリダイレクトをすることになりそうなので、後の自分のダメージを減らすべく、準備がてらなるべく楽にリダイレクト出来る方法を考えました。  
表題の通り **雑に** 書いています。取り敢えず目的を果たす為だけにつくりました。

## 達成したいこと
* 大量のリダイレクトの処理の手間を減らしたい。
  * ~~目視で1件ずつは勘弁…~~
* 本番・開発・ローカルでファイルを共有出来る状態にしておきたい。
  * サーバーの仕様に影響される `.htaccess` は本番・開発・ローカルで共有したくない。(共有出来ない可能性がある。)
* 自分以外の人もリダイレクト元とリダイレクト先の情報が一度に確認出来る状態にしておきたい。
  * プラグインを利用した場合、管理画面から1件ずつ確認するのが面倒臭そう。間違いに気付きにくい。
  * GoogleDriveなどで表にしておいて、必要な情報のみ抜き出して編集・閲覧出来る状態にしておけば、間違いに気付きやすくなる。
  
  
## 考えた方法
リダイレクト元とリダイレクト先のURLを記載したCSVファイルを作り、リダイレクト用のPHPに変換し、`header('Location:...')` を利用してリダイレクト。  
今回はリダイレクトの条件の部分の変換を行いました。( `header('Location...` を書いてある別ファイルにincludeする前提)
  
## プラグインを使用しなかった理由
* プラグインによっては更新が止まっているものがある(アップデート後に不具合を起こす可能性がある)。
* リダイレクトの設定が `.htaccess` に吐き出されるプラグインは避けたい。
  * 本番・開発・ローカルで `.htaccess` を使い回すことは避けたい。


## 前提条件
* `Node.js` をインストール済みであること

## 使うもの
* [csv](https://www.npmjs.com/package/csv)

## 準備

パッケージをインストール

```
yarn add csv -D
```

若しくは

```
npm i csv -D
```

## csvファイルと変換先の空のファイルを用意
### csv

* `title`：ページのタイトル
* `old`：リダイレクト元のドメインより後のURL
* `new`：リダイレクト先のドメインより後のURL

``` csv:CSVのデータ
title,old,new
Contact,contact,sample-page
りだいれくとのてすと。さんぷるページに移動,19,sample-page
りだいれくとてすと２。プライバシーポリシーにいどう,21,privacy-policy
```

### 空のファイル

中身は書かずに `hoge.php` で保存

## スクリプトを書く

`convert-csv.js` で保存

``` javascript:変換用スクリプト
/**
 * csvからリダイレクト用のPHPに変換するスクリプト
 */
const fs = require('fs');
const csv = require('csv');


/**
 * データをパースする
 */
const parser = csv.parse( { columns: true }, ( error, data ) => {

  if ( error ) {
    console.error(error);
    return;
  }

  /**
   * データからリダイレクト元とリダイレクト先のURLのみ取り出した配列を作成
   */
  const redirectUrlArray = data.map((obj) => {
    const oldUrl = obj['old'];
    const newUrl = obj['new'];
    return { oldUrl, newUrl };
  });

  /**
   * リダイレクト元とリダイレクト先の配列を元にPHPのswitch文の中身を作成
   */
  const arrayText = redirectUrlArray.map((obj) => {
    return `    case home_url('/').'${obj['oldUrl']}/':\n      $redirectUrl = home_url('/').'${obj['newUrl']}/';\n      break;\n`;
  });


  /**
   * テキストに変換
   */
  const outText = arrayText.join(',').replace(/,/g, '');
  
  /**
   * PHPファイルの中身
   */
  const outputData = `<?php\n  switch ($url) {\n${outText}\n  }\n?>`;

  /**
   * ファイルに書き出し
   */
  fs.writeFile(__dirname + 'hoge.phpのファイルパス', outputData, (error) => {
      
    if ( error ) {
      console.error(error);
      return;
    }
    console.log(outputData);
    console.log('変換完了');
  
  });

});


/**
 * ファイルの読み込み
 */
fs.createReadStream(__dirname + 'CSVデータのファイルパス').pipe(parser);
```

## 実行

`convert-csv.js` を保存したディレクトリで以下を実行

```
node convert-csv.js
```

### 実行結果

``` php
<?php
  switch ($url) {
    case home_url('/').'contact/':
      $redirectUrl = home_url('/').'sample-page/';
      break;
    case home_url('/').'19/':
      $redirectUrl = home_url('/').'sample-page/';
      break;
    case home_url('/').'21/':
      $redirectUrl = home_url('/').'privacy-policy/';
      break;

  }
?>
```

最後の `break;` の後に改行が入りますが動作に影響は無いので無視で・・・
Python3のrange関数の使い方

##はじめに

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている坂口です。
今週はPython3を使ってHackerrankの問題に取り組んだりしていたのですが、なかなかに難しくて早くも挫折しかけています…。
ということで（？）、今週はPython3のrange関数の使い方を自分メモとして書いていきます。

##range関数とは
range関数は連続した数字のオブジェクトを作る機能を持った関数です。
Python以外の言語にも存在する概念ですが、for文をよく使うPythonとは特に相性がいいようです。
rangeは和訳すると"範囲"という意味であり、rangeの基本的な使い方は数字の範囲を指定することになります。

##range(stop)
range(stop)のように、引数に整数を1つ設定すると、0 ≦ i < stopまでの連番の数列を作ることができます。
引数stopの値は結果には含まれないので、注意が必要です。
例えば、

```Python:
In: print(list(range(3)))

Out: [0, 1, 2]
```
となります。

##range(start, stop)
range(start, stop)のように、引数に整数を2つ設定すると、start ≦ i < stopの連番の数列を作ることができます。
引数startの値は結果に含まれるのに対して、引数stopの値は含まれないので注意が必要です。
例えば、

```Python:
In: print(list(range(3, 6)))

Out: [3, 4, 5]
```
となります。

##range(start, stop, step)
range(start, stop, step)のように、引数に整数を3つ設定すると、start ≦ i < stopの範囲でstepずつ増加する等差数列を作ることができます。
例えば、

```Python:
In: print(list(range(3, 12, 2)))

Out: [3, 5, 7, 9, 11]
```
となりますし、stepに負の整数を入れれば、

```Python:
In: print(list(range(12, 9, -1)))

Out: [12, 11, 10]
```
のように降順の数列を作ることもできます。

##for文との組み合わせ
for文を使うと、ループ処理をしながらrange関数を出力することができます。
例えば、

```Python:
In: for i in range(5)
    print(i)

Out: 0
     1
     2
     3
     4
```
という具合になります。pythonで多用されるrange関数の使い方です。

##まとめ
ここまでrange関数のことを説明してきて今さら？って感じではあるのですが、pythonにはrange関数を使わなくても数列を作れる、スライスという便利な機能もあるらしい…。
初心者には違いがまだよくわかっていないのですが、仕組みとしては似ているようです。どちらも使えるようになったら便利かも。
また、当方プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし誤りがあれば修正するのでどんどん指摘してください。よろしくお願いいたします。

##参考URL

Pythonのrange関数の使い方
https://note.nkmk.me/python-range-usage/
Pythonプログラミング史上最低の関数を作っ勃った

はい乙pyです。

Python史上最低の
関数ができてしまいました。

ほんとクソの役にも勃たないものです。

動画はこちら
https://youtu.be/ebjPs_Bqs-E

matplotlib を使って可視化するだけですが

元となる形を作るための式が

y = np.abs(t*np.sin(x)) + ((5*np.e)**(-x**k)) * s * np.cos(x)

です。

これを元に
xの値を使ってyを作っていきます。

コードはこちら

```
import numpy as np
import matplotlib.pyplot as plt
from ipywidgets import interact, FloatSlider, IntSlider
%matplotlib inline

s = FloatSlider(min=0.8 , max=10,step=0.1,value=2.1)
t = FloatSlider(min=0.1 , max=2,step=0.1,value=0.2)
k = IntSlider(min=2,max=20,step=2,value=4)
@interact(s=s,t=t,k=k)
def plot(s,t,k):
    plt.figure(figsize=(10,9))
    x = np.arange(-3,3,0.01)
    y = np.abs(t*np.sin(x)) + ((5*np.e)**(-x**k)) * s * np.cos(x)
    plt.ylim(0,10)
    plt.xlim(-5,5)
    plt.plot(x,y)
    plt.show()
```


実行していただくと
アレが出ますんで・・・

ちょっと画像の方は割愛させていただきますねーー

一応使い方として
![スクリーンショット 2019-07-27 16.05.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379626/6bfc7119-6779-ccfa-3bc5-c841dcf38955.png)

S：サオ
T：タマ
K：カリ

となっているので
察してくださいませ。

それぞれスライダーを変化させると
伸び縮みします。

最初は
短かっ！！！！

と思うでしょうが
育ててあげてください・・・

その暖かな心で

今回はここまでです。

それでは。
即席のinput要素が欲しいときはquicksettingsが便利そう

ブラウザ用JSライブラリやアプリの簡単なAPI動作確認などでinput要素が欲しいときがあります。
例えば以下のようなクラスがあったとして、add/subメソッドがちゃんと動いているのかを、実際に色々値を入れて確認したいとき、input type="number"要素を用意したりします。

```js
class CounterApp {
  constructor(root) {
    this._count = 0;
    this.viewElement = document.createElement('div');
    root.appendChild(this.viewElement);
    this.viewElement.innerText = this._count;
  }

  add(v) {
    this._count += v;
    this.viewElement.innerText = this._count;
  }

  sub(v) {
    this._count -= v;
    this.viewElement.innerText = this._count;
  }
}

const app = new CounterApp(document.querySelector("#app"));
const input = document.createElement('input');
input.type = "number";
input.onchange = function(e) {
  const num = Number(e.target.value);
  app.add(num);
}
document.body.appendChild(input);

```

ただ、そのためだけに冗長なhtmlやらjsやらを正直書きたくはないので、ライブラリに頼りたいところです。
この手のライブラリは[dat.gui](https://github.com/dataarts/dat.gui)しか知らなかったのですが、こちらはオブジェクトのpublicなプロパティを指定する必要があり、また値を直接変えたいわけではなので、用途としてはちょっと違うなと思いました。

もっと簡単で用途に合ったライブラリは無いものかとネットの海をさまよっていたら、[quicksettings](https://github.com/bit101/quicksettings)というライブラリがsweeeetな感じだったので紹介します。
![demo](https://raw.githubusercontent.com/bit101/quicksettings/master/images/master_demo.png)
[デモページ](http://bit101.github.io/quicksettings/demos/master_demo.html)を見れば何となく分かると思いますが、簡単なコードでパネルコンポーネントの生成し、そこに色々なinput要素などを追加できます。


## 使い方
githubのREADMEを見れば大体わかりますが、ポイントだけ書いてみます。
以下に示すコードではライブラリはすでに読み込んでる前提となります。
scriptタグでもrequireでも読み込めます。

```html
<script src="https://cdn.jsdelivr.net/npm/quicksettings@latest/quicksettings.min.js"></script>
```

### インスタンス生成
create関数でインスタンスを生成・取得します。

```js
// settings = QuickSettings.create(x, y, panelTitle, parent);
const settings = QuickSettings.create(0, 0, "タイトル", document.getElementById('qs-parent'));
```

引数で初期位置x、y、パネルのタイトル、親要素を指定できます。
引数はすべて省略可能。その場合、左上にパネルが表示されますが、邪魔になりそうならx、yを指定します。

個人的には以下のように指定して右上に配置するのがおすすめです。

```js
const settings = QuickSettings.create(window.innerWidth-200);
```

※パネル幅がデフォルトの200pxの場合。パネルサイズをsettings.setSize等で変える場合は適宜調整します。
なお、パネルはドラッグ操作で移動させることもできます。

:grimacing:（ここはdat.guiを見習ってデフォルト右上配置にしてほしい…）

### パネルに要素を追加
要素はsettings.addXxxみたいな関数で追加します。
それぞれ引数が違い、ラベル名や初期値、限界値などを指定できます。
またすべてのメソッドで値変更やインタラクション時のcallbackを指定できます。

```js
const cat = new Cat();
const settings = QuickSettings.create();

// input:text
settings.addText("名前", (v)=> {
  // コールバックで変更値vが取得可能
  cat.setName(v);
});
// チェックボックス
settings.addBoolean("寝", cat.isSleep, (v)=> {
  cat.setSleep(v);
});
// ボタン
settings.addButton("鳴く", ()=> {
  cat.meow();
});

```

何を追加できるか、引数はどうなっているのかは[公式のリスト](https://github.com/bit101/quicksettings#adding-controls)を参照して下さい。

他にも指定オブジェクトとバインディングしたり、localStorageに設定値を保存できたりするそうですが、使ったことが無いので保留。
古典SFチックなデザインと相まって、割と気に行ってます。
VRMMOゲーム開発:要点


## VRMMOゲームが作りたい！

私はVRMMOゲームを制作しています。
現在は仕様を練っている所です。

今回の記事が、私と同様VRMMOゲームを作ろうとする人の役に立つ事を願います。

## 制作環境

まず、ゲーム制作環境ですが、Unityにて開発、steamへアップロードを想定しています。
これは、OpenVR SDKやsteamVR pluginを初めとした外部技術導入の容易さからです。


以下に私の使用する外部技術を挙げます。

OpenVR SDK：UnityゲームをVR対応にする為に用います。情報が少ないです。

steamVR Plugin：ゲームをVR対応にする為に用います。こちらはカメラや各種コントローラ入力を扱います。

steamworks SDK,API：課金やアップロードなどを扱います。クライアント・自分のサーバ・steam WEB APIサーバでやり取りします。

随時記事を更新作成します。

## ログイン


次に、ログイン機能についてです。

ログインにおいてはクライアント、サーバ間のやり取りが必要となります。
参考までに、

クライアントから、IDとパスワード、アバター情報をサーバに送信します。

VRM-FBX-JSONは相互変換可能です。アバター情報をJSON形式化します。

1. クライアント：Unity及びPHPを用いてテキストデータ及びJSON形式データをHTTPにて送信

2. サーバ：nginxにてテキストデータを取得、PHPを介してテキストデータをMySQLへ格納
2.1 PHPにてアバターデータを取得、PHPを介してJSON形式データをMySQLへ格納

3.サーバ内でデータを照合します。ハッシュ化された値が正しいか確認。暗号化はダメです。復号されてしまうので。

4.データが正しい場合、PHPを介してサーバからクライアントへ照合完了を伝え、ログイン完了となります。

情報照合方法は改めて検討します。

また、細かな手続きについては都度記事を更新作成します。

## アバター生成

JsonUtilityを用いて、MySQLから取り出したJSONをアバターに復元します。

## 90fpsの維持

1.クライアントは、Unity,C++を用いて、常時アバターの位置情報とアクション内容情報をJSON形式でUDPにてサーバに送信します。

同時に、サーバから情報を受け取った場合、空間情報を全て更新します。

2.サーバは、クライアントから受け取ったJSON情報を元に、各々、位置、アクション情報を更新します。

その後、更新したJSON情報をサーバ間で同期します。

最後に、同期された情報をクライアントへUDPにてJSON情報を送信します。

3.クライアントは受け取ったJSONデータを元に空間を再構成します。

これを1秒間に180回行います。UDP通信なので半分の通信は失敗する想定です。

細かな手続きは随時記事を作成更新します。

実験してみないと分からない事が多いです。

## 最後に

VRMMOゲームのシステムについて考えてみました。

一緒に作りたいという方は連絡下さい。作りましょう。

ご意見のある方がいらっしゃいましたら、アドバイスを下さい。

分からない事が多い為、情報提供頂けると助かります。

よろしくお願いします。