OmniAICreator/Qiita-1.07M huggingface dataset:
Boost pythonでndarrayをC++の配列に変換する

（メモ書きです。環境等追記する予定です。）
C++で書いた関数（C++）をPythonから呼ぶため、Boot pythonを使いました。
PythonでOpenCVを使うプログラムとマージしようと思ったのでした。
Boost PythonでOpenCVのcv::Matなどの構造体を扱うのが難しそうなので、
（[こちら](https://qiita.com/peisuke/items/f648375c8fa8f9a08541)を参考にさせていただいたのですが私には無理だった・・）
ひとまずPython側のプログラムでキャプチャした画像をndarrayに保存し、
C++の配列に変換するプログラムを書いてみました。

#参考にしたページは以下です!
http://bluewidz.blogspot.com/2018/05/pythonnumpy.html

###### プログラムは以下です。

```cpp

#include <boost/python/numpy.hpp>
namespace p = boost::python;
namespace np = boost::python::numpy;
                                                                                                                                                                                                         
void plus_scalar(np::ndarray &a, float b)
{
  auto N = a.shape(0);
  auto M = a.shape(1);
  auto *p = reinterpret_cast<float*>(a.get_data());
  float array[(int)N];
  int i;
  for(i=0;i<N*M;i++){
    array[i]=*p;
    p++;
 
  }
  for(i=0;i<N*M;i++){
    printf("print%d,%f\n",i,array[i]);
  }
}
```

#####コンパイル

```
g++ --std=c++14 --shared -fPIC -I$BOOST_PATH/include/ -I/usr/include/python2.7/ test1.cpp -L$BOOST_PATH/lib -lboost_numpy -lboost_python -o test.so
```

#####できた関数を呼び出すPythonのプログラムです

```py
import sys
sys.path.append('.')
import test1
import numpy as np

a = np.array([[1,2,3],[2,3,4]], dtype=np.float32)
print(a)
b = test1.plus_scalar(a, 3.0)
```
【Mac適応道①】Macの便利な初期設定・ショートカット一覧

- 何の前触れもなく、WindowsとMacを扱う日が最近急に訪れる。あまり変わらないだろうと、鼻高々にしていたのが一巻の終わり。
- 環境設定・キーボードの位置・操作感等、あまりの差異ぶりに莫大な作業時間の違いが生じた私が、きちんと適応していくために記録していく記事第一弾。
- 「日々の急速な変化に対応するためには、慣れ親しんだものの執着からの解放が必要」だと、顔も名前も出てこない偉人もどきの発言を思い出し、決して腑に落ちることもなく、ただ「それだけでちやほやされる両刀使い」へなるために精進する。
- 初回は、様々な記事を参考にしながら、便利な初期設定とショートカットキーを書いていくことにしよう。

## 便利な初期設定
### トラックパッド速度最大
→「システム環境設定」から「トラックパッド」から「ポイントとクリック」タブから「軌跡の速さ」を最大にする。

### メニューバーに日付表示
→「システム環境設定」から「日付と時刻」から「時計」タブから「日付を表示」にチェック。

### ファンクションキーを、標準機能にする。
→「システム環境設定」から「キーボード」から「キーボード」タブから「標準のファンクションキーとして使用」にチェック。

### ファイアーウォールの設定。
→「システム環境設定」から「セキュリティとプライバシ」から「ファイアウォール」タブから「ファイアウォールをオンにする。」にチェック。

### Finderのパス表示。
→「Finder」の「表示」メニューから「パスバーを表示」を選択。

### ターミナルのショートカットキー割り当て。  
→キーボードで「command + shift + A」をクリック。
→表示されるアプリケーションフォルダの中から、「Automoter.app」を開く。
→「サービスを選択」
→左画面の検索欄に「アプリ」と入力して、「アプリケーションを起動」を選択
→「サービスは次の項目を受け取ります。」の項目を「入力なし」に変更
→アプリケーションを選択するところで、「その他」から「ユーティリティ」から「terminal.app」を選択。
→選択後、右上の実行ボタンをクリック。
→起動確認後、名前を付けて保存。
→保存後、「システム環境設定」の「キーボード」へ飛ぶ。
→「ショートカットタブ」から「サービス」を選択。
→一番下に先程保存したワーク名があるので、選択してショートカットを追加。
※ショートカット : 「command + option + controll + T」

## ツール導入
### Homebrewの導入  
- 「ターミナル」を開き、下記のコマンドを実行

```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"  
```
→途中で、Return（Enter）キー押下と、パスワード入力が求められる。
※Xcodeが必要になってくるが、自動的にインストールされるので、大丈夫。

### Homebrew Caskの導入
- 「ターミナル」で下記のコマンドを導入

```
brew tap caskroom/cask
```

### Visual Studio Codeの導入
- 「ターミナル」で下記のコマンドを導入

```
brew cask install visual-studio-code
```

### Google Chromeの導入
- 「ターミナル」で下記のコマンドを導入

```
brew cask install google-chrome
```

## ショートカット
|対応キー|機能|
|:---:|:---:|
|command + Q|アプリケーション終了|
|command + W|ウィンドウ終了|
|command + option + W|全ウィンドウ終了|
|command + M|ウィンドウをDocにしまう。|
|command + H|アクティブウィンドウ隠す|
|command + D|ファイル複製|
|command + L|エイリアス(ショートカットフォルダ）作成|
|command + I|ファイル情報見る。|
|control + D|カーソルの右文字削除（Deleteと同様）|
|control + K|カーソルの右文字全て削除|
|control + A|カーソルを行頭に移動。|
|control + E|カーソルを行末に移動。|
|command + Shift + 3|スクリーンショット撮影|
|command + Shift + 4|スクリーンショット撮影(選択範囲)|
|command + delete|ゴミ箱に入れる。|
|command + Shift + delete|ゴミ箱を空にする。|
|command + tab|アプリケーション切り替え|
|command + Shift + H|ホームフォルダを開く。|
|command + Shift + A|アプリケーションフォルダを開く。|
|command + ,|アプリケーションの環境設定を開く。|
|command + ↑|Finderで上の階層に移動する。|
|command + option + P + R|PRAMクリア（必要になったら。）|
|command + Space|検索ツール起動|
|command + option + controll + T|ターミナル起動（※要設定）|



## まとめ
- 今回は、Macの初期設定とショートカット一覧ということで、記憶が定着していない頃に初めてWindowsを使いはじめたころを思い出しながら記事を書く。
- 「やはり新しいものの習得には、時間と労力がそれなりに必要だが、それを超える楽しさと面白さがある」という、歴史的にも最大派閥の大量生産格言を、純粋に染みわたらせている極上の単純人間。
- 今後も、焦らずにきちんと適応させていき、決して訪れることない、華やかな人気生活への夢物語に浸ることにしよう。

## 参考
- https://www.notitle-weblog.com/initial-setting-of-imac  
→初期設定おいて、こちらの記事を参考にいたしました。大変お世話になりました。
- https://matome.naver.jp/odai/2138629469334511401  
→初期設定おいて、こちらの記事も参考にいたしました。大変お世話になりました。
- https://matome.naver.jp/odai/2138612139607002701  
→ショートカットにおいて、こちらの記事を参考にいたしました。大変お世話になりました。
ktlintをAndroid Studio上で自動で実行してフォーマットしてくれるようにする

## モチベーション
ktlintいいのだけど、pushしてからCIが回ってコメントついてから修正するよりも、事前に手元でわかるのであればわかるようにしたい。

とはいえ、毎回手元でktlintを実行するのはちょっとだるいので出来れば自動でいい感じになおして欲しい。
理想はAndroid Studioの方でktlintに沿ってないコードを書いた時に警告が表示されて、option + enterで自動でなおってほしい。しかし、そんなプラグインは現状調べた限りではなさそう。

## やること
File Watchersを導入してktlintコマンドを使って定期的に実行する。

#### 1. ktlintコマンドのインストール

```shell
brew tap shyiko/ktlint && brew install shyiko/ktlint/ktlint
```

#### 2. File Watchersをインストール
pluginの部分で、 `File Watchers` と検索してインストールするだけ



#### 3. File Watchersの設定
以下のように設定する。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/6878/7af90076-983c-1d64-b751-2f18472c7a1e.png)



ポイントはAdvanced Optionsのところのチェックをすべて外すとよいかもしれない。

一番上の `Auto-save edited files to trigger the watcher` の部分にチェックが入っていると、ファイルを編集してauto saveが発動されたタイミングでktlintが実行されてしまう。
これはちょっと修正して考えている間に勝手にファイルがフォーマットされてちょっとうざいのと、ktlintが発動してフォーマット中にファイルを編集すると、メモリ上にあるやつと、フォーマットした結果のファイル、どっちが正しいの？というダイアログが毎回出てきてつらい。


## 弱点
この方法は完璧ではない。

* ktlintが発動して、完了するまでが長い。６秒くらいかかる。一瞬で終わって欲しい。
* 僕はターミナルからgit commitするからいいのだけど、IDEでCommit Changesしてる人は、command + kで出したタイミングでktlintが発動するので、コミットした後にフォーマットされてしまう。ターミナルからでも６秒くらいかかるので、一瞬でgit commitしてしまうと、commit後にフォーマットになってしまう。
* ktlintのコマンドインストールしないといけない。そもそも、Android Studioでいい感じにやってほしい気持ち。

## その他
#### やってもよさそうなこと

https://github.com/shyiko/ktlint#option-1-recommended
こちらにのっている、おすすめの設定の適用をする。

```
ktlint --apply-to-idea-project --android
```


以下のファイルが生成されるため、これをgit管理しとくといいかもしれない。

```
./.idea/codeStyles/codeStyleConfig.xml
./.idea/codeStyles/Project.xml
./.idea/inspectionProfiles/profiles_settings.xml
./.idea/inspectionProfiles/ktlint.xml
./.idea/workspace.xml
```

しかし、codeStyleConfigなどはすでに設定してたりするとバッティングしそう。

#### やってもいいかなと思ったけど、僕はやる気になれなかった事。

```
ktlint --install-git-pre-commit-hook
```


これでpre-commitに追加してくれて、commit前にチェックしてくれる。
しかしながら、これはcommitする時にちょっと処理が遅くなりそうなのと、エラーを出すだけで、自動でformatしてくれなかったのでやめた。
もうちょい様子をみて、やるかどうかは考える。


## 所感
もうちょっといい感じにAndroid Studioが何かしてくれたらいいなぁと思いつつ、自分で出来そうな事を考えてみた。
Androidアプリ開発は基本的にはAndroid Studioを使って開発する人が多いと思うので、それ前提で考えられるのがいいな。もっといい方法をご存知だったらどなたか教えてください。
ktlint、jvmで動いてそうだから実行が遅いのかな？

## 参考資料
* https://qiita.com/na_ga/items/288e34360edb3e05ca44
* https://qiita.com/hkusu/items/f1c55a0e0d03543b24d5
GoogleCloudFunctionsでGoを利用した時の外部依存について

# 外部依存パッケージについて
あまりGoogleCloudFunctionsとは関係ないかもしれませんが、
使う上でどういう挙動になるのかなと思って試してみた。

今まで通りのglideやdepでの管理もできるし、
go1.11のModulesを利用することができる

```
$ cd helloWorld
$ export GO111MODULE=on
$ go mod init helloWorld
```

これを実行すると、ディレクトリ内に `go.mod` というファイルが作成される

## go mod initについて
最初以下で実行したがエラー発生

```
$ go mod init
go: cannot determine module path for source directory xxxxxxxx(outside GOPATH, no import comments)
```

https://github.com/golang/go/issues/27951#issuecomment-438274639
ここのissueにあるようにgitのリポジトリ設定がされていればエラーが出ないんだと思う。

でも動かしてみるだけなのでリポジトリ作成したくなかったので以下で対応

```
# 引数としてモジュール名にあたるものを渡してあげる
$ go mod init helloWold
```

※commandのヘルプ見てみる

```
go mod init --help
usage: go mod init [module]
```

# 試しに外部依存パッケージを利用してみる
今回は `github.com/go-sql-driver/mysql` を依存させてみる
元のソースはコチラで使用したもの

```function.go
package function

import (
	"fmt"
	"net/http"

	_ "github.com/go-sql-driver/mysql"
)

func HelloWorld(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Hello, World!")
}
```

そうしたら依存させたモジュールをダウンロードする

```
$ go mod download
go: finding github.com/go-sql-driver/mysql v1.4.1
go: finding google.golang.org/appengine v1.4.0
go: finding github.com/golang/protobuf v1.2.0
go: finding golang.org/x/text v0.3.0
go: finding golang.org/x/net v0.0.0-20180724234803-3673e40ba225
```

するとディレクトリ内に新たに `go.sum` というファイルができ、go.modの中身が変更される。

```go.mod
module helloWorld

require (
	github.com/go-sql-driver/mysql v1.4.1
	google.golang.org/appengine v1.4.0 // indirect
)
```

さらにGOPATH配下に `mod` というディレクトリが作成され、そこで外部依存のモジュールが管理されることになる。

```
# gvmでgoを管理しているのでpkg指定
$ ls $GOPATH/pkg
mod
```

これで完了。
以前からGoを使ってきた人はvendorディレクトリがないことに気づいたかもしれない。
そうvendorディレクトリがなくなって管理から解放されたのだ。

余談だが、単に `go build` を実行しても同じ挙動になった。


# デプロイしてみる
```
gcloud functions deploy helloWorld --entry-point HelloWorld --runtime go111 --trigger-http
```

デプロイしてCloudFunctionsのコンソールを見てみると

・function.go
・go.mod
・go.sum

がデプロイされる。
さらに、testファイルを置いてみるとそれもデプロイされた。


# vendoringについて
以前のvendoringを利用することもできる
以下のコマンドを実行するとディレクトリ内にvendorディレクトリが作成されビルドに利用される。

```
$ go mod vendor
```

直接buildする際にオプションとしても指定できる

```
$ go build -mod vendor
```

デプロイしてみる

```
gcloud functions deploy helloWorld --entry-point HelloWorld --runtime go111 --trigger-http
```

~~結果、vendorディレクトリはデプロイされなかった。~~
~~go.mod, go.sumがあるとvendorディレクトリは無視されるのかな？~~
~~試しにgo.mod, go.sumを削除してデプロイしてみる。~~

~~やはりvendorディレクトリはデプロイされない。~~
~~GCFにとってvendorディレクトリはデプロイ対象ではないみたい。~~

~~※もしかしてオプションか何かでデプロイできるのかもしれないので~~
~~もしご存知でしたら教えてください。~~

2019/02/12 追記
上記は自分の勘違いでした。

GCFのGUIでソースタブを見るとvendorディレクトリは表示されていなかったのですが、
実際にソースのダウンロードをして解凍して確認してみると、ちゃんとvendorディレクトリが存在していました。


# 今までのvendoringとモジュールについて
この辺が参考になった。

https://github.com/golang/go/wiki/Modules
https://research.swtch.com/vgo-module
https://www.reddit.com/r/golang/comments/9ai79z/correct_usage_of_go_modules_vendor_still_connects/
web開発においてiPad iOS8 Safari でうまく動かなかったこと

##iPad iOS8 Safari
もしかしたらiPad iOS8 Safariという組み合わせだけの問題ではないかも知れません（それぞれ単体でも再現するかも知れません）。中にはSafariだけでなくChromeでも再現するものもありました。

### 1.セレクトリストでvalue値を取得するときにjQueryの`.val()`だと取得できない
#####対応...:writing_hand_tone1:
`on change`イベントで`e.target.value`か`document.getElementById('selectLists').value`で取得できました。


### 2.セレクトリストで動的にリストを変えている場合に何かを選択してしまう（ユーザーが選択するまで何も選択させたくない）
#####対応...:writing_hand_tone1:
[この記事](https://qiita.com/bubbles/items/cdf9e8431f67d01f7cf8)でやっているように動的にセレクトリストの内容を変更している場合に、変更後何かを選択してしまっている状態になってしまうのを回避したかったのです。
`$("#selectLists").prop("selectedIndex", -1);`のようにすると選択を解除できます。
ちなみに試していないですが`-1`でなく`0`でも良いかも知れません。

### 3.styleの`display: flex;`がついていると想定通りの表示にならない
#####対応...:writing_hand_tone1:
`display: block;`とかに変えました。。。
他のブラウザでは中央寄せになっているのにiPadだけでは左寄せになっていたり、そもそもそのスタイルをつけている要素が表示されていなかったりしました。
この問題はweb上にも沢山報告されていました。


##まだあるかも
また他にも見つけたら随時更新します。
そしてここに挙げたものはあくまでも'対応例'としてお考えください。
OpenCVを用いてラベリング

少し前にOpenCVを利用する機会があったので, 今更ながらまとめていこうと思った. 今回はラベリングをする.

# 用意するもの
OpenCV-3.4.3 (Versionは特にこだわる必要はないかも)

今回はUbuntuでプログラムを動かしているが, WindowsでもVisual Studioを使えば動かすことができる. 環境構築については今回は割愛する.

# ラベリングですること
ざっくり説明すると

+ 1  画像をグレースケールで読み込む
+ 2 2値化
+ 3 必要に応じて収縮・膨張
+ 4 ビット反転
+ 5 ラベリング
+ 6 好きな形で出力

こんな感じで今回はコーディングした.

# ソースコード

```cpp:Main.cpp
#include<opencv2/opencv.hpp>

int main() {
	cv::Mat img;
	cv::Mat img_out;
	img = cv::imread("sample.jpeg", 1);
	cv::cvtColor(img, img,cv::COLOR_RGB2GRAY);

	//下2つの処理は必要に応じて適用する
	//入力画像の収縮
	//cv::erode(img_out, img_out, cv::Mat(), cv::Point(-1, -1), 3);
	//入力画像の膨張
	//cv::dilate(img_out, img_out, cv::Mat(), cv::Point(-1, -1), 3);

	//大津の手法を用いているので, 閾値を指定する必要はない
	cv::threshold(img, img_out, 0, 255, cv::THRESH_BINARY|cv::THRESH_OTSU);
	//thresholdかinRangeどちらでもいい
	//cv::inRange(img, 124, 254, img_out);

	cv::bitwise_not(img_out, img_out);
	cv::Mat img_lab;
	//ラベリング
	int nlabel=cv::connectedComponents(img_out,img_lab);
	for (int i = 0; i < nlabel; i++) {
		//ラベルiを取り出す
		cv::compare(img_lab, i, img_out, cv::CMP_EQ);
		//出力画像の保存
		imwrite("out" + std::to_string(i) + ".jpg", img_out);
		cv::imshow("Labelling", img_out);
		cv::waitKey(0);//入力待ち
	}
	return 0;
}

```

入力画像
![sample.jpeg](https://qiita-image-store.s3.amazonaws.com/0/316006/1ee6b41d-7e46-139d-69e7-faf3f40f0535.jpeg)

出力画像
1  
![out_0.jpg](https://qiita-image-store.s3.amazonaws.com/0/316006/cb0adbf8-5026-688b-721a-74ca17f942e7.jpeg)

2
![out_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/316006/b4b003f8-5433-0f40-362b-7dd4f8643d7c.jpeg)

3
![out_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/316006/5662239a-2171-4402-4372-34d7176d180a.jpeg)

4
![out_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/316006/3fcffdd9-91bd-3de4-9b03-dd6e39fa5401.jpeg)

5
![out_4.jpg](https://qiita-image-store.s3.amazonaws.com/0/316006/60d17792-c93d-40cd-8fed-8a3714ee6f49.jpeg)


うまく行きそうな画像を拾って来たので簡単な処理で, そこそこきれいにラベリングできた.
dockerでサクッとWebサーバー(nginx)を立ち上げるワンライナー

## カレントディレクトリのソースをdockerのnginxで動かす

ちょっとした静的サイトの動作確認など意外とよく使うのでメモ

```
$ docker run -d -p 8080:80 --name コンテナ名 -v $PWD:/usr/share/nginx/html nginx
```

↓へアクセス
http://localhost:8080/

とっても簡単ですね。  

## 補足

前提: ↓な感じで配置してあるとする

```
$ tree .
.
└── index.html

0 directories, 1 file
```

1. カレントディレクトリへ移動する。  
1. 上記コマンド実行

### オプションについて
* 8080 => 80 へポートフォワーディングさせていますが8080ポートでなくても構いません。
* コンテナ名のオプションは付けなくても大丈夫です。
* vオプションで$PWD配下をコンテナにマウントしているのでローカルで変更したソースも都度反映されます。
Windows 10 Pro x64 + Excel2016 x86 VBA で Frame + OptionButton を使う

#目的
Frame + OptionButton はペアで使うことが多いのだけど
・OptionButtonクリックイベントで モジュールプライベートの変数にステータスをセット
・CommandButtonクリックイベントでステータスを取得する
だと、前者を選ぶ気がするんだけどな・・
MSのドキュメントで Controls の説明見つからなかったんだけど
どこにあるんだろう？？(あるのかな)
##作成手順
・UserFormを１個追加する
・Frameを１個追加する
・Frameの上にOptionButtonを４個追加する
・CommandButtonを1個追加する
##サンプルコード
```vb

Option Explicit

Private Sub UserForm_Initialize()
    '
    '   初期値の設定
    '
    OptionButton1.Value = True
End Sub

Private Sub OptionButton1_Click()
    Debug.Print "OptionButton1:" & OptionButton1.Value
    Debug.Print "OptionButton2:" & OptionButton2.Value
    Debug.Print "OptionButton3:" & OptionButton3.Value
    Debug.Print "OptionButton4:" & OptionButton4.Value
End Sub

Private Sub OptionButton2_Click()
    Debug.Print "OptionButton1:" & OptionButton1.Value
    Debug.Print "OptionButton2:" & OptionButton2.Value
    Debug.Print "OptionButton3:" & OptionButton3.Value
    Debug.Print "OptionButton4:" & OptionButton4.Value
End Sub

Private Sub OptionButton3_Click()
    Debug.Print "OptionButton1:" & OptionButton1.Value
    Debug.Print "OptionButton2:" & OptionButton2.Value
    Debug.Print "OptionButton3:" & OptionButton3.Value
    Debug.Print "OptionButton4:" & OptionButton4.Value
End Sub

Private Sub OptionButton4_Click()
    Debug.Print "OptionButton1:" & OptionButton1.Value
    Debug.Print "OptionButton2:" & OptionButton2.Value
    Debug.Print "OptionButton3:" & OptionButton3.Value
    Debug.Print "OptionButton4:" & OptionButton4.Value
End Sub

Private Sub CommandButton1_Click()
'
    Dim varCtrl As Variant
'
    For Each varCtrl In Controls
        '
        '   Like "OptionButton[1-4]"
        '       ：OptionButton1～ OptionButton4 に一致
        '
        If varCtrl.Name Like "OptionButton[1-4]" Then
'Debug.Print varCtrl.Name, varCtrl.Value
            '
            '   varCtrl.Name  ：OptionButton1～OptionButton4 に一致
            '   varCtrl.Value ：True/False
            '
            Select Case varCtrl.Name
            Case "OptionButton1"
                    If varCtrl.Value Then
                        Debug.Print "Checked OptionButton1:" & OptionButton1.Value
                    End If
            Case "OptionButton2"
                    If varCtrl.Value Then
                        Debug.Print "Checked OptionButton2:" & OptionButton2.Value
                    End If
            Case "OptionButton3"
                    If varCtrl.Value Then
                        Debug.Print "Checked OptionButton3:" & OptionButton3.Value
                    End If
            Case "OptionButton4"
                    If varCtrl.Value Then
                        Debug.Print "Checked OptionButton4:" & OptionButton4.Value
                    End If
            End Select
        End If
    Next

End Sub
```
ウェブブラウザを簡易テキストエディタとして使う方法

忘れないために備忘録として記す。

この文字列をアドレスバーに入力して開くだけ。

```
data:text/html, <html contenteditable>
```

簡単なメモを取るだけならこれで十分かも。Chromeで動くことは確認した。ほかは知らん。

参照元:
https://coderwall.com/p/lhsrcq/one-line-browser-notepad
UbuntuMATEで端末(ターミナル)を起動せずにCUIに切り替える方法のメモ

僕は**古いPC**にまだまだ頑張ってもらうために**UbuntuMATE**をインストールしました。

**WindowsXP**が搭載されてた**ThinkPad R52**という古いノートパソコンですが、**UbuntuMATE**上で**エディタ**や**ブラウザ**程度なら**実用レベル**で動作しております。

**Windows環境**とは違い**コマンド入力**する場面がよくあり、**UbuntuMATE**には標準で**[MATE端末]**というターミナルアプリがあります。

MATE端末はよく使うのでショートカットキーの**[ctrl]+[alt]+[T]**で起動してますが、**GUI**のMATE端末を起動するのではなく、**CUI**に切り替えるという方法を教えてもらいました。

GUIに戻るには**[alt]+[F7]**か**[ctrl]+[alt]+[F7]**を押します。

切り替えは**[ctrl]+[alt]+[F1]〜[F6]**で6つ同時に起動できます。

GUIのアプリを起動するのと違いサクッと切り替わるので、古いパソコンでも軽快に切り替えできます。
Basic認証を使ってJIRAのissue情報を取得する

## はじめに
弊社ではチャットワークを導入しておりほとんどのやり取りをチャットワークで行なっていたのですが、人が増えるにつれ情報が流れたり錯綜し、混乱する事が多くなってきました。

その解決策としてJiraを導入する事が決定し、APIを利用してChatworkに通知したりその他ほにゃららするツールを作ることになりました。

しかし「PHP Jira API 連携」などと調べてもそれらしき記事が意外にも出てこなく、最初の情報を取得するフローで一番苦労したので記事として残しておきます。

## 目的
JiraのAPIを利用して指定したissueの情報を取得する

## 準備
1. Jiraのアカウントを取得する
2. [API Tokenの発行](https://confluence.atlassian.com/cloud/api-tokens-938839638.html)

## 実装
```PHP:sample.php
<?php
$username = 'Jiraのユーザー名';
$api_token = '取得したAPIトークン';

// 取得したいissueのキー
$issue_key = 'issue_key';

// あなたのJiraのURL
$base_url = 'https://hogehoge.atlassian.net';
$url = $base_url . '/rest/api/2/issue/' . $issue_key;

// 認証
$header = array();
$header[] = "Content-Type: application/json";
$header[] = "Authorization: Basic " . base64_encode($username . ":" . $api_token);

$options = array(
    CURLOPT_URL            => $url,
    CURLOPT_HEADER         => false,
    CURLOPT_HTTPHEADER     => $header,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_SSL_VERIFYHOST => false,
    CURLOPT_SSL_VERIFYPEER => false,
);

// 情報を取得
curl_setopt_array($ch, $options);
$result = curl_exec($ch);
$result = json_decode($result, true);

// 取得した情報をデバッグ
var_dump($result);

```

これで特定のissueの情報は取得できると思います。
この`$result`の中に担当者、報告者、コメントなど全ての情報が入っているので欲しい情報を絞り込んでチャットワークに通知したりできます。

## まとめ
「コメントが追加された時」「チケットが追加された時」などにチャットワークに通知させたい時はJiraでWebhookの設定ができるので、そこから発火させてあげればいいです。

もっと便利な使い方もあると思うので今後はJiraを使いこなして行きたいですね。
[図解]ディープラーニングのパラメーター数ってどうやって数えるんだっけという人へ

# パラメータ数の計算まとめ
<b>NN , CNN , Embedding , SimpleRNN, LSTM, GRU</b>

#CNN, NN(Dense)
```python

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu',
                        input_shape=(150, 150, 3)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(128, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(GlobalAveragePooling2D())
model.add(layers.Dense(32, activation='relu'))
model.add(layers.Dense(1, activation='sigmoid'))
```

＊ MaxPooling2Dは2*2の範囲ごとの最大値を取るだけのためパラメーターなし
＊ GlobalAveragePooling2Dは各チャンネルの平均を取るだけのためパラメーターなし



#Conv2D(１つ目）
<b>3 * 3 * 3 * 32 + 32 = 896</b>

フィルターの縦 * フィルターの横 * 入力のチャンネル数 * 出力のチャンネル数 + バイアス(1チャンネルごとに1つ)

#Conv2D(２つ目）
<b>3 * 3 * 32 * 64 + 64 = 18496 </b>

フィルターの縦 * フィルターの横 * 入力のチャンネル数 * 出力のチャンネル数 + バイアス(1チャンネルごとに1つ)
##図解
![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/94fee695-db09-bed6-22fc-455db7cc3fb6.png)



#Dense
<b>128 * 32 + 32 = 4128</b>

入力ユニット数 * 出力ユニット数 + バイアス（出力1ユニットごとに1つ）
シンプルなニューラルネットワーク,   バイアスを忘れずに
##図解

![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/7d7ab25c-0dd2-de85-880c-9d675f937f15.png)



#Embedding , SimpleRNN, LSTM, GRU
```python
model = Sequential()
model.add(Embedding(4000,32,input_length=20))
model.add(LSTM(64))
#model.add(SimpleRNN(64))
#model.add(GRU(64))
model.add(Dense(3))
model.add(Activation("softmax"))
```

#Embedding
<b>4000 * 32 = 128000</b>

 
・Embedding層は全結合層だが、バイアスはない
・ワンホットベクトルを小さな（密な）ベクトルに変換するための層

##図解

![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/cb90eacc-dead-171e-2430-92ef0e56476e.png)

#SimpleRNN
<b>32 * 64 + 64 * 64 + 64 = 6208</b>

・入力に対しての重み
入力の次元数ｘ隠れ状態の次元数　
→　32*64

・隠れ状態に対しての重み
隠れ状態の次元数 x 隠れ状態の次元数 
→　64*64

・バイアス
隠れ状態の次元数
→　64

##図解


![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/6a99e588-6f42-82d0-b8fb-967332b6318a.png)


#LSTM
<b>32 * 64 * 4 + 64 * 64 * 4 + 64 * 4 = 24832</b>

・入力に対しての重み
入力の次元数 * 隠れ状態の次元数 * 4 　　　(forgetに１つ、inputに2つ、outputに1つ)
→　32 * 64 * 4 

・隠れ状態に対しての重み
　隠れ状態（記憶セル）の次元数 * 隠れ状態の次元数 * 4　　　(forgetに１つ、inputに2つ、outputに1つ)
→　64 * 64 * 4

・バイアス
隠れ状態の次元数 * 4 　　　　　(forgetに１つ、inputに2つ、outputに1つ)
→　64 * 4

##図解
![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/be7cb090-e0ac-af38-4b10-9779ea136303.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/48cfd3fa-225e-1168-8a7c-7e32d6a498b2.png)





#GRU
<b>32*64*3 + 64*64*3 + 64*3 = 18624</b>

・入力に対しての重み
入力の次元数 * 隠れ状態の次元数 * 3 　　　(リセットゲートで1つ、更新ゲートで2つ) 
→　32 * 64 * 3

・隠れ状態に対しての重み　
隠れ状態の次元数 * 隠れ状態の次元数 * 3　　 (リセットゲートで1つ、更新ゲートで2つ) 
→　64 * 64 * 3

・バイアス 
 隠れ状態の次元数 * 3　　 (リセットゲートで1つ、更新ゲートで2つ) 
→　64 * 3


##図解
![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/844e0599-71c7-73b5-784e-244a149d0d18.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/315063/efa3d194-d8d5-10fa-4796-3c860049ea8e.png)
nuxt.jsで:src="require(変数)"で画像パスを指定する時に。。

nuxt.jsでサイトを作る際にちょっと詰まったのでメモ。

# 詰まったところ

nuxt.jsは`assets`に画像ファイルを置くと`src="require('@/assets/hoge.jpg')"`で参照出来るので、
繰り返しの要素で変数に画像パスを格納して、それを使って画像を表示させようとしました。
しかしどんなにパスを確認しても、`Cannot find module '@/assets/hoge.jpg'"と、画像が参照出来ませんでした。

```hoge.vue
<template lang="pug">
  v-container(grid-list-lg fluid pa-0)
    v-layout(row wrap)
      template(v-for="(pr, index) in prContents")
        v-flex(xs12 md4 :key="index")
          v-card
            v-img(:src="require(pr.image)" height="300")
            v-container(fill-height fluid pa-2)
              v-layout(fill-height)
                v-flex(xs12 align-end flexbox)
                  span(class="headline white--text" v-text="pr.title")
</template>

<script>
export default {
  name: 'HomeConcept',
  data () {
    return {
      prContent: [
        {
          title: 'タイトル1',
          contents: 'コンテンツ',
          image: '@/assets/hoge1.jpg'
        },
       {
          title: 'タイトル2',
          contents: 'コンテンツ',
          image: '@/assets/hoge2.jpg'
        },
       {
          title: 'タイトル3',
          contents: 'コンテンツ',
          image: '@/assets/hoge3.jpg'
        },
      ]
    }
  }
}
</script>

<style scoped  lang="stylus">

</style>
```

# 解決策
require内で、パスが単純な文字列として認識されてnuxt.jsの`@`が解決出来ず、参照出来ないため、
`require()`をdataオブジェクトの中で実行するように変更します。

```js
data() {
  return {
    prContents: [
      {
        title: "タイトル1",
        contents: "コンテンツ",
        image: require("@/images/hoge.jpg")
      }
    ]
  }
}
```


修正コード

```vue:hoge.vue
<template lang="pug">
  v-container(grid-list-lg fluid pa-0)
    v-layout(row wrap)
      template(v-for="(pr, index) in prContents")
        v-flex(xs12 md4 :key="index")
          v-card
            v-img(:src="pr.image" height="300")
            v-container(fill-height fluid pa-2)
              v-layout(fill-height)
                v-flex(xs12 align-end flexbox)
                  span(class="headline white--text" v-text="pr.title")
</template>

<script>
export default {
  name: 'HomeConcept',
  data () {
    return {
      prContents: [
        {
          title: 'タイトル1',
          contents: 'コンテンツ',
          image: require('@/assets/hoge1.jpg')
        },
        {
          title: 'タイトル2',
          contents: 'コンテンツ',
          image: require('@/assets/images/3pr-medical.jpg')
        },
        {
          title: 'タイトル3',
          contents: 'コンテンツ',
          image: require('@/assets/images/3pr-compassionate.jpg')
        }
      ]
    }
  }
}
</script>

<style scoped  lang="stylus">

</style>

```
php-master-changes 2019-02-03

今日は opcache の最適化機能内の typo 修正があった！

# 2019-02-03
## TysonAndre: Properly check for array_replace_recursive in sccp.c
- https://github.com/php/php-src/commit/cf56832d000d43623248a081374f2c3a92190c83
- [7.2~]
- ext/opcache で、SCCP 最適化で一部組み込み関数呼び出しをコンパイル時に評価する際、[array_replace_recursive()](http://php.net/manual/ja/function.array-replace-recursive.php) がちゃんと判定されてなかった問題の修正
- [array_merge_recursive()](http://php.net/manual/ja/function.array-merge-recursive.php) を無駄に二回判定してた
oracle12cで作成したユーザーに接続できない時

#概要
PDBで作成しユーザーに接続できない時の対処法を書きます。

下記エラーが出て接続できず、ID,PWがあっているのに接続できないのは何故？という方向けです。
![SmartSelectImage_2019-02-04-07-57-00.png](https://qiita-image-store.s3.amazonaws.com/0/328125/e8ec6251-7b5a-c6e7-49c9-202c351959ad.png)

#原因
PDBに接続するときはリスナー経由でなくてはいけません。

#解決策
tnsnames.oraにpdbの接続識別子と接続記述子を追記することで接続が可能になります。

###① サービス名の確認
まずは下記コマンドにてリスナーのサービス名を確認します
```
lsnrctl status
```

![SmartSelectImage_2019-02-04-07-57-37.png](https://qiita-image-store.s3.amazonaws.com/0/328125/a5a8869e-9c05-dd1e-bec5-a583e7a44ca2.png)


###②tnsnames.oraに追記

```
vi $ORACLE_HOME/network/admin/tnsnames.ora
```
赤〇の部分を各環境に合わせ修正してください。（SERVICE_NAMEは先程確認した名前を記載)

![SmartSelectImage_2019-02-04-08-14-14.png](https://qiita-image-store.s3.amazonaws.com/0/328125/8de561f8-0508-effa-3d5e-0d0ec8d6e165.png)


###③接続確認

```
sqlplus ユーザー名/PW@接続識別子
```

![SmartSelectImage_2019-02-04-07-58-55.png](https://qiita-image-store.s3.amazonaws.com/0/328125/66d06e1f-2f19-1589-9129-0d76e8b99e05.png)


無事、ログインできるようになりました！
mysqldumpコマンド

ちょくちょくしらべるのだるいのでメモる。

mysqldumpのバックアップは、SQLベースのバックアップが可能です。存在するデータをすべてＳＱＬにしてテキスト形式に保存できます。

`$ mysqldump -u root -x --all-databases > dump.sql`

これですべてのデータベースのバックアップが可能です。

特定のデータベースのみのバックアップの場合は、

`$ mysqldump -u root データベース名 > dump.sql`


mysqldumpのすべてのデータベースのバックアップを復元するには、

`$ mysql -u root -p < dump.sql `


のように、mysqlクライアントにファイルの内容をリダイレクトしてあげるだけです。

特定データベースのみの復元は

`$ mysql -u root データベース名 < dump.sql `

のようにします。
質と量　ネット記事の指針。仮説（157）

Qiitaの記事を書いていて、記事の量をたくさん書こうとすると、
記事の質が覿面に落ちてくる。

自動車の安全系の開発において、人材の評価をする際に、
人材評価担当自体の評価をする際に、amazon.co.jpに書籍の感想を
10,000冊記載することにしたときも似た状況があった。

３年で10,000冊書こうという目標をたてた。
結果として４年ちょっとかかった。
途中であまりにも質の低下がひどかった。

当初、３分の１を超えたところ、目標の半分、３分の２を超えたところで、質の向上のための方策をとった。

# 1. 書籍の参考文献をしらみつぶしに読む。
書籍の参考文献をよんでいけば、元の本の内容の理解も深まり、１冊読む度に５冊から１０冊の内容に追記したりできる。

# 2. シリーズ物を読む
自動車技術会、機械学会、鉄鋼など、自分の得意分野ではない自動車関連の講座ものを読んでいく。

# 3. 知り合いの本は読む
知り合いの本は読んでおけば、質問しやすい。技術士の書籍を1000冊読むことを別に目標にした。

# 4. 岩波新書、ブルーバックスを読む
専門書を読むだけでは、最終顧客への説明をする際にどういう論理を展開すればよいか。

# 5.自動車技術など関連雑誌を読む
商業雑誌は岩波新書、ブルーバックスと専門書の間をつなぐ大切な情報源である。

# 6. 週報で１冊づつ紹介のあった本については必ず記載する。

5人から7人ほど常駐していた技術者の週報で１冊本を紹介してもらい、その感想をamazon.co.jpに掲載。
年間2000冊程度になる。自分で選んでいないため、自分の不得意な事項、一見今の事業に関係なさそうな資料を、どう関係付けていくかの役にたった。

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
【今更だけど】Alpha zeroでオセロを実装してみた

# 目標
自分の勝てないレベルを目指す（私自身はオセロが強いわけではない）
# Alpha Zeroとは
2017年にGoogleが人間の知識を全く使わずに、囲碁の世界チャンピオンよりも強い囲碁のプログラムを発表した（[AlphaGo Zero](https://www.nature.com/articles/nature24270)）。その1年後、ほぼ同じアーキテクチャーでチェスや将棋においてもたった1日の学習で世界最強レベルのコンピュータ（もちろん、人間より強い）を超えることができると発表し、大きな話題となった（[Alpha Zero](http://science.sciencemag.org/content/362/6419/1140.full?ijkey=XGd77kI6W4rSc&keytype=ref&siteid=sci)）。

# なぜオセロ?
まず、囲碁や将棋、チェスだと単なるトレースなんで面白くない。また、これらは複雑すぎるのでgoogleほどの計算資源がないと現実的な計算時間で強くするのは難しい（私のPCのスペックで真似すると1年かかっても終わらない）。その点、オセロならみんな知ってるし、適当な複雑さのゲームなので選んだ。

# Alpha Zeroの概要
Alpha Zeroは自己対局を通じて強くなっていく強化学習プログラムである。Alpha Zeroは自己対局→学習→自己対局→学習を繰り返すことで強くなっていく。学習するものは自己対局で実際に現れた、各場面における手の選択（の確率密度分布）とその後の結果である。自己対局の結果を学習するため、自己対局はある程度読んで行わないと意味がない。その「読み」にはMonte Calro Tree Search（MCTS）という手法が使われている。MCTSは学習した手の選択と選択後の状態の手の価値に基づいて読みを行う。また、探索が狭くならないように、訪れていない状態が読まれやすいようにしている。

# 環境
最初はGoogle colabolatoryでやってたが、CPUの並列性能がほしかったので、パソコンを買った。スペックは以下のとおりである。
GPU：GeForce1080X
CPU：Ryzen 7 2700X（8コア16スレッド）

# 実装
ここに書くには長すぎるでコードは割愛する（詳細は[私のgithub](https://github.com/ryuoujisinta/othero)参照）。今回の実装は[Deep reinforcement learning Hands-On](https://www.amazon.co.jp/Deep-Reinforcement-Learning-Hands-Q-networks-ebook/dp/B076H9VQH6)を参考にpythonで行った。ちなみにこの本は深層強化学習全般の実装が解説されており、英語に抵抗がないなら一読の価値はあると思う。この本では、connect-4（4目並べ）をAlphaGo Zeroで実装しているため、それをオセロ用、並列化用に書き換えて学習を行った。なお、この本での実装では

- L2正則化を行っていない
- 選択していない手のMCTSのsub treeを残している

の二点がAlphaGo Zeroの原論文と異なるため、原論文に合わせた修正を行っている。また、AlphaGo Zeroでは学習後、今までの最新モデルと自己対局を行い、一定以上の勝率をあげないとモデルの更新を行わない。しかし、Alpha Zeroでは毎回モデルの更新を行うと書いてあるため、本実装では学習のたびにモデルを更新している。また、Alpha Zeroは将棋やチェスに対応するため、碁にある対称性を利用していないが、オセロは碁と同じように対称性があるため、回転と反転に関しても同様の結果になるとして自己対局の結果に加えている（生成する自己対局数が単純に8倍になる）。では、主な設定を挙げていく。

- 用いるニューラルネットはAlpha Zeroと同じ構造
- 各手のMCTSは800回（Alpha Zeroの論文と同等）
- 自己対局で生成するゲーム数は300ゲーム（15CPU並列で20ゲームずつ、対称性考慮で2400ゲーム、Alpha Zeroでは25000）
- 保存する手の数は150万（1対局約60手として25000ゲーム、Alpha Zeroでは50万ゲーム）
- 1回のトレーニングは64バッチ×32回を1セットとしてそれを500回繰り返す（Alpha Zeroでは1000回繰り返し）
- 学習率は0.01（Alpha Zeroでは0.2から始めて一定回数に達すると1/10にしている）
- 自己対局の始めの20手はランダム性を加える（Alpha Zeroでは30手、オセロが囲碁や将棋、チェスに比べ短手数なため）

また、これに加え、自己対局結果保存の際に割引率0.95を設定している。これは、私自身が対局した時に、初期に意味もなく高い評価値になっている場合があったためである。おそらく十分な自己対局数があれば偏らないと思われるが、Googleのように5000TPUを持っているわけではないので、自己対局数を増やすのは現実的でない。そのため、初期の評価値が偏りすぎないように、割引率を設定した。

# 学習結果
下のグラフにlossを示す。10kあたりからあまり強くなっていないため、ここらへんで学習率を下げるなど、まだまだ改善の余地がありそう。
1日くらい学習したあと（対局→学習を20回程度繰り返したあと、下のグラフの10kあたり）に対戦したら全く歯が立たなかった。MCTSの探索数を少なく（320MCTS）して対戦すると1手先で負けているパターンを読めずに勝てることがあったが、基本は勝てる気がしない。また、探索数を1600MCTSにしてスマホアプリのリバーシLv99とやるとLv32までは勝てた（そのあとはまだ対戦していない）。後手の方が強い気がする。githubにGUIも公開しているので試してみた感想をいただけると嬉しい。なお、GUIはバグが取り切れていないため、たまに止まったりするがご容赦いただきたい。
![total_loss.png](https://qiita-image-store.s3.amazonaws.com/0/294848/e6918cee-c489-76fa-17ff-f6bcec179ae7.png)


# 参考
あまり調べてないですが、[Alpha Go Zeroでの実装](https://qiita.com/mokemokechicken/items/a5803b4280751848e36b)は既出のようです。
ConoHa VPS で Debian 9 をセットアップした　～その2～

「[ConoHa VPS で Debian 9 をセットアップした　～その1～](https://qiita.com/ludwigem/items/f6626603c4fce1bd78ec)」からの続きです。
ここでは、下記を行います。

- sshでrootに接続しする
- 一般ユーザー（newuser）を作成する
- newuserでssh接続できるようにする
- newuser にsudo権限を与える
- rootをsshで接続できないように設定する
- その他

「[ConoHa VPS で Debian 9 をセットアップした　～その3～](https://qiita.com/ludwigem/items/52caf0f9569ba6e2c40a)」に続きます。

# SSHでサーバーにログイン
もう一度、左側の**サーバー**をクリックして、サーバーのネームタグをクリックしてください。
ネットワーク情報のIPアドレスがサーバーの接続先になります。
**サーバーの追加**のときにダウンロードした秘密鍵を設定します。
![IPaddress.png](https://qiita-image-store.s3.amazonaws.com/0/11804/e55681bb-0bcd-17f8-f7fa-9b9786a86d35.png)


私はターミナルソフトはWindowsの[RLogin](http://nanno.dip.jp/softlib/man/rlogin/)を使っています。
SSHターミナルソフトの詳細は割愛します。

# OSをアップデート
最初ですのでOS等を最新にアップデートします。

```
# aptitude update
# aptitude upgrade
```

# いくつかの設定
## テキストエディター nano をインストール
viなどが苦手な方は`nano`はいかがでしょうか。

```
# aptitude install nano
```

##ホストネーム
デフォルトは`123-45-67-89`のようにIPアドレスを基にしたネームです。親しみやすい名前（例として`myserver`）に変更してみましょう。

```text:/etc/hostname
myserver
```


# 一般ユーザー(newuser)を追加する
普段使いの新しいユーザー（例として`newuser`）を追加します。

```
# adduser newuser
```

または

```
# useradd -m newuser
# passwd newuser
```


# newuserにSSHを設定する
さっそく新しく作ったユーザーで作業します。
秘密鍵と公開鍵のペアは用意されていることとします。[^1]
`authorized_keys`ファイルをテキストエディターで開き、公開鍵をコピペし保存します。
ベテランは `$ cat >> authorized_keys` でしょうか。
パーミッションは以下のように設定します。

- ディレクトリー`.ssh`は`755`
- 公開鍵ファイル`authorized_keys`は`600`

**ハマりどころです**。

```
# su newuser
$ cd ~
$ mkdir ~/.ssh
$ chmod 755 ~/.ssh
$ touch ~/.ssh/authorized_keys
$ nano ~/.ssh/authorized_keys
<公開鍵をクリップボードから貼り付けてエディター終了>
$ chmod 600 ~/.ssh/authorized_keys
$ exit
# 
```

[^1]: 不精して鍵ペアをサーバー側で生成して秘密鍵をクライアントにSCPしたりほにゃらら

# 一般ユーザーにSSH接続する
ターミナルソフトのウインドウをもう一つ立ち上げて、`newuser`のSSH設定を行い、接続をテストします。


# newuser にsudo権限を与える
`newuser`が所属しているグループを確認します。

```
# id newuser
uid=1000(newuser) gid=1000(newuser) groups=1000(newuser)
```

ユーザーを`sudo`グループに所属させます。


```
# adduser newuser sudo
# id newuser
uid=1000(newuser) gid=1000(newuser) groups=1000(newuser),27(sudo)
```

`newuser`でログインして`sudo`できることを確認してください。
初回は一般ユーザー`newuser`のパスワードを求められるはずです。

```
$ sudo ls -al
```


# rootをSSHからlogin禁止にする
前述の**[一般ユーザーにSSH接続する](https://qiita.com/ludwigem/items/2011407c86f1be4f6879#%E4%B8%80%E8%88%AC%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%81%ABssh%E6%8E%A5%E7%B6%9A%E3%81%99%E3%82%8B)**が正常に動作することをもう一度確かめてから行ってください。

`newuser`から`sudo`で設定してみます。
`/etc/ssh/sshd_config` を修正します。

```
$ sudo nano /etc/ssh/sshd_config

PermitRootLogin no      # この行を探してコメントアウトし'no'に設定
```

`sshd_conf`の構文チェックします。

```
$ sudo which sshd      # sshdの場所を調べる
/usr/sbin/sshd
$ sudo /usr/sbin/sshd -t
```

`sshd`を再起動します。

```
$ sudo service sshd restart
```

# トラブル等
##sudo: unable to resolve hostが表示されるとき
「[sudo: unable to resolve host が表示されたら](https://qiita.com/ogomr/items/89e19829eb8cc08fcebb)」を参考に`/etc/hosts`を変更します。

```text:/etc/hosts
127.0.0.1       localhost
127.0.1.1       debian
127.0.1.1       myserver
```

#次記事
「[ConoHa VPS で Debian 9 をセットアップした　～その3～](https://qiita.com/ludwigem/items/52caf0f9569ba6e2c40a)」に続きます。
下記のようなセキュリティの設定を行います。

- ファイアーウォール（ufw）のインストールと設定
- SSHポートの変更
ConoHa VPS で Debian 9 をセットアップした　～その1～

# はじめに
この記事は、いきなりクラウドやVPSで実践するのではなく、Raspberry Piで練習してからおこなった方が良いと思います。

#とりあえず
ConoHaのVPSを一通り設定します。
この記事ではVPSを生成（追加）して**「ターミナル」**からrootでログインするところまで行います。
「[ConoHa VPS で Debian 9 をセットアップした記録　～その2～](https://qiita.com/ludwigem/items/2011407c86f1be4f6879)」に続きます。

**[「進化し続けるホスティングサービス ConoHa by GMO」](https://www.conoha.jp/)**

![ConoHa.png](https://qiita-image-store.s3.amazonaws.com/0/11804/b53421f5-854e-4114-e195-1943467c4dfd.png)

- 月額630円の一番リーズナブルなプラン
- Debian 9 stretch
- これをセットアップしてからが本番だ
    - つまりまだ何も出来ない
- その後、H2OをインストールしたりLet's EncryptでSSLしたりします。

# 環境と準備
作業環境と利用したソフトウェアは表のとおりです。

| 項目 | 内容 |
|:---:|:---:|
|OS|Windows 10|
|ブラウザ|Chrome|
|SSH ターミナル| [RLogin](http://nanno.dip.jp/softlib/man/rlogin/)|

#サーバー追加、OSイメージ選択
ConoHaのアカウントを取得し、VPSからサーバーを追加します。
![addServer.png](https://qiita-image-store.s3.amazonaws.com/0/11804/03be10e0-58f4-bd73-68d2-a965ea7e5ca9.png)


- 最小限630円/月のプラン
- OSイメージはDebian 9 stretchを選択
- rootパスワード入力
    - 9文字以上、半角英大文字,小文字,数字,記号を組み合わせる
- ネームタグはお好みの名前で（あとで変更できます）
![selectServerImage.png](https://qiita-image-store.s3.amazonaws.com/0/11804/f6258fc7-6121-6bd7-fd2b-40a5fcb98e63.png)


### オプション設定
- ネームタグ下の「**オプションを見る**」をクリックしてオプション設定を開きます。
- 追加ディスクは使用しない
- 接続許可ポート
    - SSHのみ許可
- SSH Key
    - キーを新規作成
        - 自動生成で良いと思います。一度だけ秘密鍵をダウンロードできます。
            - あらかじめ用意した公開鍵をアップロードできます。Ed25519も可。
    - 生成したパブリックキーを選択します。
- スタートアップスクリプトは使用しない、です。
![Options.png](https://qiita-image-store.s3.amazonaws.com/0/11804/349a1ee9-3dcd-126c-de7d-43a14bd76546.png)


価格を確認して右側の**［追加］**をクリックすると、数分でサーバーが生成されます。
![buy.png](https://qiita-image-store.s3.amazonaws.com/0/11804/25511dff-6e6f-cfdf-7506-7905d22aa917.png)


# サーバーにログイン（ターミナル）
左側の**サーバー**をクリックすると、サーバーリストに生成したサーバーのネームタグが表示されているはずです。
![serverlist.png](https://qiita-image-store.s3.amazonaws.com/0/11804/aab93c8f-aa0a-8496-0177-d04dd1a0ad4d.png)



ネームタグをクリックしてください。
画面が変わって上の方にサーバーに行う操作ボタンが並びます。
試しに**［コンソール］**をクリックしてください。
黒い背景の別ウィンドウが開きます。
![controlepanel.png](https://qiita-image-store.s3.amazonaws.com/0/11804/90a5230b-14c4-e2b6-4f9d-73db97677e56.png)


```
Debian GNU/Linux 9 123-45-67-89 tty1
123-45-67-89 Login: root
Password: <rootのパスワード>

root@123-45-67-89:~#
root@123-45-67-89:~# ls -al
root@123-45-67-89:~# exit

```

ログインできたら成功です。

**※**この**［コンソール］**はもろもろの接続ができなくなったときの命綱になりますので覚えておきましょう。
（TTY接続なので、シリアル接続をWebに中継しているのだと思います）

# 次記事

「[ConoHa VPS で Debian 9 をセットアップした　～その2～](https://qiita.com/ludwigem/items/2011407c86f1be4f6879)」に続きます
ここでは

- sshでrootに接続しする
- 一般ユーザー（newuser）を作成する
- newuserでssh接続できるようにする
- newuser にsudo権限を与える
- rootをsshで接続できないように設定する
- その他

を行います。
public修飾子の必要性の例

基本的にunityの使い方に関する自分のメモを書いていきます

#publicの必要性（スクリプトの場合）
　自分以外のスクリプトが持つメソッドを呼び出したい時には呼び出したいメソッドがpublicで宣言されている必要がある
#publicの必要性（変数の場合）（アウトレット接続）
　public修飾子をつけた変数はインスペクターから見えるようになり代入したいオブジェクトを直接ドラッグ&ドロップで代入できるようになる（例、プレハブ作り）
【今から携わる】レガシーなCSSをやめる理由とその方法

レガシーなCSSを今日から辞めるため、CSSの基本と、今までの書き方がダメな理由を共有いたします。


# CSSの基本
CSSはHTMLの文章の装飾をブラウザに伝える言語です。

# CSSの書き方

## 原文

```
セレクタ { プロパティ： 値；}
```

## 読み下し文

```
どこの？ {なにを？： 〇〇にしなさい；}
```

## 例文

```
h1 {color: red;}
```

h1要素の、文字色を、赤にしなさい


# CSSの４原則（最高のCSSにするため）
・予測しやすい
・再利用しやすい
・保守しやすい
・拡張しやすい

# ３つの設計手法（良いCSSにするため）
・OOCSS：（Object-Oriented CSS）
・BEM（ベム）：「Block・Element・Modifier」
・SMACSS（Scalable and Modular Architecture for CSS ）


上記をふまえて、レガシーなCSSはやめていきましょう！

# やめてほしいCSS

## 要素にスタイルを当てないで

＜例文＞

```css:css
h1 {
    font-size: 24px;
}

.info-section h1 {
    font-size: 24px;
}
```

＜なぜだめか＞
○：予測しやすい
×：再利用しやすい
×：保守しやすい
×：拡張しやすい

大規模サイトになれば、h1のスタイルがひとつなんてことがないからです。
使い回しが全くできなくなります。

タイトルだけでなく、要素に直接スタイルを当てるのはやめましょう！

＜改善案＞

```html:html
<h1 class="ttl">中見出しが入ります。</h1>
```

```css:css
.ttl {
    font-size: 24px;
}

.ttl-border {
    font-size: 24px;
    border: 2px solid #000;
}
```

## 詳細度を上げないで

＜例文＞

```css:css
h1.info-section {
    font-size: 24px;
}

.top-page h1.info-section {
    font-size: 24px;
}
```

＜なぜだめか＞
○：予測しやすい
×：再利用しやすい
×：保守しやすい
×：拡張しやすい

CSSの詳細度が上がると”!important”を付与して上書きするしかありません。
違うタグに同じスタイルを当てることもできなくなります。

>【CSS入門】CSSの上書きルールと詳細度についてまとめてみた！
http://www.yantzn.com/entry/re-css-_study-01

＜改善案＞
基本は

```css:css
　.info-section {・・・
```

のように、

・詳細度をあげない
・要素を記述しない

ようにしましょう。


## ”ページ名”のクラスを”body”タグや”main”タグにつけて書いちゃダメ

＜例文＞

```html:html
<main class="top-page">
    <h1 class="info-section">大見出しが入ります。</h1>
    <p>テキストが入ります。テキストが入ります。</p>
</main>
```

```css:css
.top-page .info-section {
    font-size: 24px;
}
```

＜なぜだめか＞
○：予測しやすい
×：再利用しやすい
×：保守しやすい
×：拡張しやすい

”body”タグや”main”タグに”ページのクラス名”をつけた場合、
・違うページに同じスタイルをあてることができない

上記を無理に行なった結果、

・”body”タグや”main”タグに”ちがうページのクラスが付与されている
・同じようなCSSの記述がいろいろ散らばっている。

ようになるため、やめましょう。


＜改善案＞

```html:html
<main class="top-page">
    <h1 class="ttl">大見出しが入ります。</h1>
    <p>テキストが入ります。テキストが入ります。</p>
</main>
```

```css:css
.ttl {
    font-size: 24px;
}
```

”タイトル”という意味のクラス名に変更する。


## 一つのクラスにあれもこれも詰め込んじゃダメ

＜例文＞

```html:html
<main>
    <h1>大見出しが入ります。</h1>
    <a class="btn" href="#">次へ</a>
</main>
```

```css:css
.btn {
    position: relative;
    padding: 8px 16px 8px 32px;
    max-width: 300px;
    border-radius: 4px;
    background-color: red;
    color: #fff;
    font-size: 16px;
    font-weight: bold;
    text-align: center;
}
```

＜なぜだめか＞
○：予測しやすい
×：再利用しやすい
×：保守しやすい
×：拡張しやすい

サイトには何種類ものボタンが発生するため、ボタンの用途に合わせたCSSを当てるべき


＜改善案＞
スタイルを”見た目：スキン”と”構造：モジュール”に分けて考え、バージョン違いを作ることを前提にする。

```scss:main.scss
.btn {
    position: relative;
    padding: 8px 16px 8px 32px;
    max-width: 300px;
    border-radius: 4px;
    font-size: 16px;
    font-weight: bold;
    text-align: center;
}

.btn-link {
    @extend .btn;
    background-color: yellow;
    color: #fff;
}

.btn-action {
    @extend .btn;
    background-color: green;
    color: #fff;
}

.btn-back {
    @extend .btn;
    background-color: gray;
    color: #fff;
}

.btn-long {
    max-width: 100%;
}
```

# まとめ

＜だめなCSS＞
○：予測しやすい
×：再利用しやすい
×：保守しやすい
×：拡張しやすい

↓↓↓↓

＜最高のCSS＞
○：予測しやすい
○：再利用しやすい
○：保守しやすい
○：拡張しやすい

ダメなCSSは”そのときばったりにつけたクラス名”が100%の原因です。
その見た目と構造の役割を分解して名付けしてあげればいいのです。
UE4 LoadingScreen使用してみる

#ローディングスクリーン
おかずさんのActionRPGをまずはみましょう
https://www.slideshare.net/EpicGamesJapan/ue4action-rpg

試しに使用してみるにはActionRPGのローディングスクリーンモジュールを参考にしていくといいと思います。

##まずはプロジェクト作成
C++のプロジェクトを作成しましょう。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/354342/508eb88f-781f-c208-68be-ae68349700b3.png)
今回はLoadingScreenTestという名前でプロジェクトを作成しました。

ActionRPGソースをベースに作成していくのが簡単です。
ActionRPGより以下のソースを自分のプロジェクトにコピーしましょう
![image2.PNG](https://qiita-image-store.s3.amazonaws.com/0/354342/41882a6f-2fc1-144e-af5b-2826fa064ffb.png)

コピーしてきたファイルを自分のプロジェクトに合う名前に変更してください。
ActionRPGLoadingScreen => Loadingscreenに変更しています。
・LoadingScreen.cpp
・LoadingScreen.h
・LoadingScreen.Build.csの中身も同様に変更していきます。

#モジュールをBuild.csに追加する。
LoadingScreenTest.Target.cs
LoadingScreenTestEditor.Target.csに
```
 ExtraModuleNames.Add("LoadingScreen");		//<< ADD
```
こちらを追加していきます。

```
using UnrealBuildTool;
using System.Collections.Generic;

public class LoadingScreenTestEditorTarget : TargetRules
{
	public LoadingScreenTestEditorTarget(TargetInfo Target) : base(Target)
	{
		Type = TargetType.Editor;
		ExtraModuleNames.Add("LoadingScreenTest");
		ExtraModuleNames.Add("LoadingScreen");		//<< ADD
	}
}
```


LoadingScreenTest.Build.cs内のPublicDependencyModuleNamesにLoadingScreenに追加します。
```
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "HeadMountedDisplay" ,"LoadingScreen" 
```

# C++ソースから使用できるようにします。
 GenerateProjectをしましょう。
![image3.PNG](https://qiita-image-store.s3.amazonaws.com/0/354342/c1e462f2-725c-5805-89f0-091f390d2a8f.png)
LoadingScreenTest.slnを立ち上げます。

LoadingScreenTestGameMode.h/LoadingScreenTestGameMode.cppファイルを開き
BPからLoadingScreenモジュールを呼び出せるように関数を追加します。

#LoadingScreenTestGameMode.h

```
	UFUNCTION(BlueprintCallable)
		static void PlayLoadingScreen(bool bPlayUntilStopped, float PlayTime);

	UFUNCTION(BlueprintCallable)
		static void StopLoadingScreen();
```

#LoadingScreenGameMode.cpp

```
void ALoadingScreenTestGameMode::PlayLoadingScreen(bool bPlayUntilStopped, float PlayTime)
{
	ILoadingScreenModule& LoadingScreenModule = ILoadingScreenModule::Get();
	LoadingScreenModule.StartInGameLoadingScreen(bPlayUntilStopped, PlayTime);
}

void ALoadingScreenTestGameMode::StopLoadingScreen()
{
	ILoadingScreenModule& LoadingScreenModule = ILoadingScreenModule::Get();
	LoadingScreenModule.StopInGameLoadingScreen();
}
```

#Blueprintから呼び出す。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/354342/74ebff1b-99e7-32a0-c7d9-0ec8e0ef07ff.png)

#注意点
PIEではLoadingScreenは確認することはできません。
Standaloneで起動して確認するか、パッケージを作成して確認することになります。

#補足
パーシスタントレベルをOpenLevelで読みかえるだけなら楽なのですが、いろいろ問題もあります。その中でも一番問題になるのがサブレベルの読み込み、ストリーミングボリュームの対応になります。こちらはまた別の記事にて。
[2019年版] Qtでパソコンソフトを作ろう（MinGW使用/VisualStudio不要）【その１：インストール編】

![qt_logo_m.png](https://qiita-image-store.s3.amazonaws.com/0/36751/7d2ed4e8-f5a3-e50e-9948-604e7cf0afc4.png)

**Qt（キュート）は、Windows、Mac、Linux など複数のパソコン向けにソフトを作成できる、クロスプラットフォームな開発システムです。プログラム言語は C++ がメインですが、Qt 独自の API が用意されており、開発しやすくなっています。**

**Qt には<font color="#f00">有償版（Commercial）</font>と、<font color="#00f">無償版（Open Source）</font>があります。また、開発環境も様々ありますが、本ページでは、以下の方針で進めます。**

- 開発PCは Windows 10 Home 64bit
- Qt無償版（Open Source）を使用
- 開発ツールは「Qt Creator」を選択
- コンパイラは MinGW を選択（VisualStudio不要）

なお、本ページの情報は2019年2月時点のものです。

# ![](//goo.gl/78mjX8) インストーラーのダウンロード

１）下記のダウンロードページにアクセスします。
[https://www.qt.io/download-qt-installer](https://www.qt.io/download-qt-installer)

![qt_install_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/36751/26c7f9c7-1591-091c-a371-b050366f7cb6.jpeg)

２）「Download」ボタンを押すと、インストーラーがダウンロードされます。執筆時点のファイル名は `qt-unified-windows-x86-3.0.6-online.exe` です。online と名の付く通り、インストーラー自体は容量が軽く、インストールに必要なファイルをその都度ダウンロードしてくれます。


# ![](//goo.gl/78mjX8) インストール

ダウンロードしたファイルを実行し、ほぼ成り行きで進めていきます。
インストール先のフォルダ名には<font color="#f00">日本語が含まれないよう</font>注意して下さい。（Qtに限らず、開発環境を構築する時はそうしておくのが無難です）
![qt_setup_0.png](https://qiita-image-store.s3.amazonaws.com/0/36751/18d2ca0a-95fb-46ee-42ef-dba92c874659.png)

途中、Qtアカウント情報を入力する画面もありますが「Skip」でOKです。
![qt_setup_1.png](https://qiita-image-store.s3.amazonaws.com/0/36751/473b6c6a-2841-f948-0697-0c713f47cc6d.png)

コンポーネントの選択画面では、以下の３つを選択して下さい。

- Qt
    - Qt 5.12.1
        - MinGW 7.3.0 64-bit
    - Tools
        - Qt Creator 4.8.1 CDB Debugger Support
        - MinGW 7.3.0 64-bit

![qt_stup_2.png](https://qiita-image-store.s3.amazonaws.com/0/36751/f124af5c-44a7-f871-e3c2-de174015c767.png)
![qt_setup_3.png](https://qiita-image-store.s3.amazonaws.com/0/36751/c3aca55d-42bf-9c07-3d02-2bf5c9ad955a.png)

6.5GBほど消費しますので、空き容量には注意して下さい。
![qt_setup_4.png](https://qiita-image-store.s3.amazonaws.com/0/36751/0e631872-fdb4-dd8f-0257-9c0ac6c6bcc4.png)

オンライン・インストーラーなので、ダウンロード＆インストールにはそれなりに時間かかります。気長に待ちましょう。
![qt_setup_5.png](https://qiita-image-store.s3.amazonaws.com/0/36751/051d5f84-5d34-52f2-4c7f-b2b6aaea2787.png)

インストールが完了したら、Qt Creator を起動します。
![qt_setup_6.png](https://qiita-image-store.s3.amazonaws.com/0/36751/66ec9884-67cd-f989-ec4a-299803c17d78.png)

次は[【その２：Hello, World編】](https://qiita.com/yasumodev/items/104446261114e9a7352c)に続きます。

(･o･ゞ いじょー。
【Unity】Bluetooth Low Energy(BLE)でクロスプラットフォームにローカル通信のゲームを作る【そのいち】

# はじめに
Graffity株式会社でARアプリを開発しているむーつんです。
普段はARを使った対戦ゲーム「ペチャバト」のAndroid版の開発を担当しています（春頃リリース予定

[ペチャバト - AR対戦バトル・大乱闘シューティングゲーム ](https://www.youtube.com/watch?v=uTknV2tPwsg)
![graffity-pechabato-2.png](https://qiita-image-store.s3.amazonaws.com/0/243926/864c30a3-673c-58b2-cf16-4487a2ec9e60.png)



ペチャバト(iOS版)では対戦相手の位置情報や攻撃の情報を[MultiPeerConnectivity*1](https://developer.apple.com/documentation/multipeerconnectivity)を利用してローカル通信を行っています。

しかし、Android版を開発するとなるとiOSの機能であるMultiPeerConnectivityは使えませんし、プラットフォームが違っても同じインターフェースで実装できるプロトコルを採用する必要あります。

そこで以下の３つの方法を検討し、最終的にBLEを採用しましたのでその実装内容まで解説できたらと思っています。

- [Photon Cloud*2](https://www.photonengine.com/ja/photon)
- [Google Nearby*3](https://developers.google.com/nearby/)
- [Bluetooth Low Energy(BLE)*4](https://ja.wikipedia.org/wiki/Bluetooth_Low_Energy)


# Photon Cloud
- 言わずもしれたマルチプレイヤープラットフォーム。
- プロトタイピングでもさんざん使ってきたので知見もたくさんあった。
- 何より、下回りの処理をほとんど考えることなくリアルタイム通信ができるので工数が大幅に削減できる

はじめはPhoton Cloudで実装し工数を減らそうと考えていたが、インターネットを使わずにローカル通信がしたい点とすでにリリースされているiOSのプロジェクトとインターフェースを合わせるのが困難そう（iOS開発側の負担が大きかった）なので一旦保留となりました。

※クロスプラットフォームでiOS/Android両方ともUnityで開発する場合良いかもしれません

# Google Nearby
NearbyはGoogleにより公開されている近接通信のためのライブラリでWi-FiやBLE、高周波の音声などを使って端末のIPを特定し、インターネットを介した通信を実現しています。「Nearby Connections」「Nearby Messages」「Fast Pair」の３つの機能があります。

###「Nearby Connections」
- インターネットを使わずに他のデバイスと近接通信ができる
- Androidのみ対応。
- マルチプレイヤーゲーム、リソース配信、チームコラボレーション、コンテンツの共有などの利用を想定されている。

今回はクロスプラットフォームを想定していたのでこれは不適当でした。
（Androidだけの通信でよい場合はUnityのSDKも使いやすいので良いかもしれません）

###「Nearby Messages」
- クロスプラットフォーム
- 近くにある端末間で小さなメッセージを送受信することができる
- インターネット接続が必須。
メンテナンスされていない。。

クロスプラットフォームは対応しているが、いざ実装してみるとBLEなどの近距離通信を使用しているのはIPの共有などだけであとはインターネットを通じて通信しているようでした。
また、メッセージが届くまでのラグがあったためリアルタイム通信が必要なペチャバトには不適当でした。
（Unityのプラグインが存在しなかったので自分でブリッジコードを書かないといけなかったことも要因の一つです）


### 「Fast Pair」
ヘッドホンなどのBluetoothを使いたいハードウェア開発者向けのワンタップペアリングの機能を実装するためのインターフェースを提供

これはあんまり関係ないですね・・・笑

# Bluetooth Low Energy(BLE)

```
Bluetooth の一部で、バージョン 4.0 から追加になった低消費電力の通信モード。（Wikipediaより引用）
```

iOS/Android双方が対応していること、MultipeerConnectivityである程度実績があったことから今回はBLEを採用することになりました。

次回は実際にBLEでクロスプラットフォームにローカル通信ゲームを作る際の実装方法や問題の対処などをまとめたいと思います。


### 関連記事
【Android】BLE通信ざっくりまとめ
https://qiita.com/HideMatsu/items/6a6758eca86500881126
[Ruby] 値の受け渡しは、文字列よりシンボルを使おう

Rubyで値を受け渡す場合、文字列よりシンボルの方が検索が速いらしい。
この検索スピードの違いは、文字列とシンボルでのオブジェクトの扱われ方が関係しているのですが、どういう事なのか調べてみました。

### 文字列とシンボルでのオブジェクトID
同じ名称でも文字列は別オブジェクトで、シンボルは同一オブジェクトとして扱われる特性があります。
試しに下記のようなコードを実行し、オブジェクトIDを調べてみました。

```rb
# 文字列のオブジェクトID
p 'ABC'.object_id
p 'ABC'.object_id

# シンボルのオブジェクトID
p :ABC.object_id
p :ABC.object_id
```

実行結果は、下記になりました。

```rb
70147189139260
70147189139060
1015588
1015588
```

1,2行目の文字列は、別々のIDなのに対し、3,4行目は同一のIDです。
さらに何回か実行してみると・・・

２回目


```rb
70120609515160
70120609514980
1015588
1015588
```

３回目


```rb
70243594897120
70243594896960
1015588
1015588
```

文字列は、実行の度にオブジェクトIDが変わってしまうのに対し、シンボルは、ずっと同一のオブジェクトIDを保持し続けます。
こういった特性から、文字列で検索する時は、
**別オブジェクトだけど、同じ文字列なのか？といった評価の工程の後、検索する**
のに対し、シンボルで検索する時は、
**オブジェクトIDで一発で検索する**
ので速いという事か。

*参考
[Ruby の Hash キーへのアクセスで String と Symbol でどのくらいの差があるのか比較してみた](https://inokara.hateblo.jp/entry/2015/09/29/114619)

###　発展編　実際に使ってみた

第一引数に両替したい円の金額、第二引数に両替したい通貨の定数を入力すると両替後の金額を出すメソッド
「exchange_for_foreign_currency」を作りました。

```rb
class Exchange
  # 為替レート
  EXCHANGE_RATE = { 'doll' => 110, 'euro' => 125 }

  def exchange_for_foreign_currency(yen, monetary_unit)
    ( yen / EXCHANGE_RATE[monetary_unit] )
  end
end

# 実行
p Exchange.new.exchange_for_foreign_currency(1100, 'doll')
```

通貨の定数であるEXCHANGE_RATEのキーは文字列で書かれていますが、両替の値の参照に使うので、このままだと効率が良くありません。
次のようにシンボルで参照するようにしてあげた方が、システム的には効率が良いという事ですね。

```rb
class Exchange
  # 為替レート
  EXCHANGE_RATE = { doll: 110, euro: 125 }

  def exchange_for_foreign_currency(yen, monetary_unit)
    ( yen / EXCHANGE_RATE[monetary_unit] )
  end
end

# 実行
p Exchange.new.exchange_for_foreign_currency(1100, :doll)
```

この辺を気を付けて使おうと思いました。
節分のときに食べる豆の数を正確に計算できるアプリ

# 概要
私も齢30超えた頃から歳の数だけ豆を食べるのがつらくなってきました。

年々増え続ける食べる必要のある豆…


単純に考えると２月１日生まれの人は２月３日には豆をそこまで食べる必要は無いはず…
誕生日に依存して食べる豆の１個以下の部分は上下したりするんじゃないかなぁ


そう思って、単純なアプリを作ってみました。


#完成品
codepenの方に作りました！

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

#懸念点
wikiによると2020年以降の節分は2月3日ではなくなる事があるらしい…
ですので2月3日固定になっている年に指定させていただいております。

時間があれば…個数を豆のイラストにしたいなぁ…