OmniAICreator/Qiita-1.07M huggingface dataset:
ラズパイ: VLCをコマンドで操作

# 概要

VLCをコマンドで操作


# 環境
- Raspberry Pi 3B / 3B+
- Raspbian: 2019-04-08-raspbian-stretch (デスクトップ環境)



# 手順
0. microSDにOSを焼いて、簡単な設定、パッケージ更新しておく
1. `telnet` コマンドの導入をしておく。<br>`sudo apt update && sudo apt install telnet -y`
1. VLCの設定

    1. VLCを開く
    ![2019-04-12-001015_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/8124fbaa-a04a-d2d7-0c4a-d5b6f8ccaf70.png)

    2. Tools > Preferences
    ![2019-04-12-001045_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/b9bd6537-778f-239d-d6a5-9f49fc48a5ae.png)

    3. 一番下の、Show settingsのところで、Allをクリック
    ![2019-04-12-001057_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/96a28b31-eec4-3de3-63b0-4dc7ae1ec5c7.png)

    4. 左側の項目から、Main interfaces をクリックして、Telnetにチェック
    ![2019-04-12-001219_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/a42dd3ad-c6fd-5eaa-5dc3-e10c2baa7b5f.png)

    5 左側の項目、一個下がって、Luaをクリックして、下のLua TelnetのところのPasswordのところへ入力したら、[Save]をクリック。
    ![2019-04-12-001339_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/d4608a22-5fb3-ee60-8b07-d1a301e2b47c.png)

    6. 一旦、クローズ (右上の × をクリック)
![2019-04-12-001400_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/315c4dcf-5bb0-1b78-24cf-62e1819bb370.png)

2. コマンド操作
    1. VLCとTerminalを開きます。`telnet localhost 4212`と入力して、Enter。パスワードが聞かれるので、先程設定したものを入力(見えない)すると、Welcome, Masterのメッセージが出て、操作ができるようになります。
    ![2019-04-12-001550_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/8166b488-1953-6af5-6ec5-d3466fcb4d6e.png)

    2. `enqueue https://www.youtube.com/watch?v=xxxxx`(YoutubeのURL) で、プレイリストに追加。
    3. `playlist`コマンドで、リスト表示
    4. `play` コマンドで再生開始
![2019-04-12-002002_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/2eb709c4-ea1c-c959-8e9e-8d79c20a50d2.png)

    5. `f on` / `f off` コマンドでフルスクリーン オン・オフ
    6. `pause`で一時停止、`next`でプレイリストの次、`prev`でプレイリストの一つ前、`stop`で完全停止.
    7. `help`でコマンドヘルプ表示
    ![2019-04-12-002031_1280x720_scrot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75594/71baa805-72c9-22c4-d648-e25804284f3a.png)
Amazon EMRでHiveのセットアップ

# TL;DR

* Amazon EMR(Elastic MapReduce)をセットアップし，クエリエンジンHiveを実行して大規模データベース処理を実行します
    * Hiveは，MySQLのようにテーブルデータに対する問い合わせ（クエリ）処理を実行することができます
    * Amazon EMRのセットアップから，データの格納，クエリの実行までの一連の流れを紹介します

# Amazon EMRのセットアップ

* [Amazon EMR](https://aws.amazon.com/emr/)から「コンソールにログイン」し，EMRサービスを選択する
* [クラスターを作成]をクリック
* 下記画像の通り設定（いじる部分はほとんどない）して「開始」ボタンをクリック
    * クラスター名を適当に設定
    * SSHログインするためのEC2キーペアの設定
    * <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309617/8e5098fc-8e72-4e00-d4d5-362aeb841162.jpeg">
* クラスターが「実行中」になるまでしばらく(10分程度)要する
    * 「実行中」になったら，SSHでログインできる
    * 画像の[マスターパブリックDNS]に記載のホスト名にSSHする
* **注意：** セキュリティグループ設定で，22/TCPを開けておく必要があるかもしれない
    * <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309617/bd641a12-a2ef-e376-2a75-8bd95a7f7432.jpeg">

# 実行

* hadoopユーザと，設定したEC2秘密鍵を使用してSSHログイン

```shell
$ ssh -i ~/.ssh/keykey.pem hadoop@ec2-XXXX.ap-northeast-1.compute.amazonaws.com

Warning: Permanently added 'ec2-XXXX.ap-northeast-1.compute.amazonaws.com,' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
7 package(s) needed for security, out of 12 available
Run "sudo yum update" to apply all updates.

EEEEEEEEEEEEEEEEEEEE MMMMMMMM           MMMMMMMM RRRRRRRRRRRRRRR
E::::::::::::::::::E M:::::::M         M:::::::M R::::::::::::::R
EE:::::EEEEEEEEE:::E M::::::::M       M::::::::M R:::::RRRRRR:::::R
  E::::E       EEEEE M:::::::::M     M:::::::::M RR::::R      R::::R
  E::::E             M::::::M:::M   M:::M::::::M   R:::R      R::::R
  E:::::EEEEEEEEEE   M:::::M M:::M M:::M M:::::M   R:::RRRRRR:::::R
  E::::::::::::::E   M:::::M  M:::M:::M  M:::::M   R:::::::::::RR
  E:::::EEEEEEEEEE   M:::::M   M:::::M   M:::::M   R:::RRRRRR::::R
  E::::E             M:::::M    M:::M    M:::::M   R:::R      R::::R
  E::::E       EEEEE M:::::M     MMM     M:::::M   R:::R      R::::R
EE:::::EEEEEEEE::::E M:::::M             M:::::M   R:::R      R::::R
E::::::::::::::::::E M:::::M             M:::::M RR::::R      R::::R
EEEEEEEEEEEEEEEEEEEE MMMMMMM             MMMMMMM RRRRRRR      RRRRRR

[hadoop@ip-AAA-BBB-CCC-DDD ~]$ hive # hiveコマンドでHiveサーバに接続
Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
hive> show databases; # SQLライクなHive HPL/SQLでクエリ発行できる
OK
default
Time taken: 0.626 seconds, Fetched: 1 row(s)
```

* ```hive``` コマンドでHiveサーバに接続できる
    * その後は，SQLライクなHive用クエリ言語 [Hive HPL/SQL](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=59690156)でクエリを実行することができます

# 参考

* [Hive HPL/SQL](https://cwiki.apache.org/confluence/pages/viewpage.action?pageId=59690156)
* [Amazon EMR](https://aws.amazon.com/emr/)
ローカルからContainerRegistry(GCR)にDockerイメージをpushする

#やることになった経緯
werckerのdocker-pushでDockerイメージをContainer Registry(GCR)に登録する
https://qiita.com/issei_0403/items/d2197a7756cbd1de5b49

これがなかなか動かず、とりあえずローカルからContainerRegistryに登録してみよう、ということでやってみました。


#####何はともあれビルド。

```sh
$docker build -t 【image name】 .
```

#####ローカルのイメージがgcrのリポジトリ名に紐付けられます。タグ名も指定可能です。

```sh
$docker tag 【image name】 【GCR repository name】
```

#####紐付いたリポジトリ名に向けてpushします

```sh
$docker push 【GCR repository name】
```

#参考
https://cloud.google.com/container-registry/docs/pushing-and-pulling?hl=ja


#####注意点
これ↓

```sh
$gcloud auth configure-docker
```

を実行すると、それ以降に定義追加したdocker-compose.ymlがエラーになります。。
docker-composeも利用するなら、もとのconfigファイル
~/.docker/config.json
を保管しておいたほうがいいかもしれないです。
Firebase device registration token に関してちょっと詳しくなるやつ

## なにこれ
Android開発してる僕がFCMのdevice registration token(以下デバイストークン)がGCMのそれのように一定期間でコロコロ変わると壮大な勘違いをしていたので少し詳しくなるようにまとめる

## device registration tokenについてちょっと詳しくなる

for Android
https://firebase.google.com/docs/cloud-messaging/android/client?hl=en

for iOS 
https://firebase.google.com/docs/cloud-messaging/ios/client?hl=en

後述の**Instance ID**から生成されるPUSH通知で利用されるトークン情報
**再生成はされるものの** GCMのdevice tokenのように一定期間で変更されるわけではなく、以下のようなタイミングで更新される

* アプリによってインスタンス ID が削除される場合
* アプリが新しいデバイスで復元される場合
* ユーザーがアプリをアンインストール / 再インストールする場合
* ユーザーがアプリのデータを消去する場合


## Instance IDについてちょっと詳しくなる
https://developers.google.com/instance-id/

> Instance ID provides a unique ID per instance of your apps. You can implement Instance ID for Android and iOS apps as well as Chrome apps/extensions.

Android・iOS・Chrome apps/extensions などでそれぞれ各端末に対して発行される **ユニークキー**
Crashlytics for Firebase や Analytics for Firebase などでユーザー(=端末)を紐付ける為に利用されるキーで
各プラットフォームライブラリやREST APIで削除・再生成することが可能で、削除するとそのInstance IDに紐づくユーザーデータが各Firebase Productsから削除される
werckerのdocker-pushでDockerイメージをContainer Registry(GCR)に登録する

#やりたいこと
1.Javaのソースコードをbitbucketにpush
2.werckerでビルド
3.ビルドされたjarをDockerイメージに配置
4. 3.のイメージを、GCE上で動かす (※別記事を書く予定です。本記事では触れません。)


#wercker.yml
プロジェクト直下に配置します。
internal/docker-pushについて定義を書いていきます。
前段のpipelineでbuildを行うことで、必要なjarファイルが/pipeline/output配下にコピーされています。
docker-pushでは、/pipeline/output配下のファイルたちが
Dockerイメージ内の/pipeline/sourceにコピーされるので、
キックしたいjarファイルのファイルパスは下記のようになっています。


```wercker.yml
my-wercker-process:
  box: gcr.io/google-appengine/openjdk
  steps:
    - internal/docker-push:
      # 固定文字列
      username: _json_key
      #GCPのサービスアカウント発行時にダウンロードできるjson
      password: $GCR_JSON_KEY_FILE
      repository: gcr.io/$PROJECT_ID/$MY_IMAGE
      registry: https://gcr.io/v2
      ports: 8080
      # 環境変数
      env: "hoge=value1 fuga=value2"
      # jar実行
      entrypoint: java -Djava.security.egd=file:/dev/./urandom -jar /pipeline/source/app.jar
```

#wercker上の設定
下記画面で設定したkey-valueが、wercker.ymlの$に格納されます。
※keyは適当です

![スクリーンショット 2019-04-09 17.15.22.png](https://qiita-image-store.s3.amazonaws.com/0/262530/f080b726-72c3-9557-1719-7ce091ef5571.png)



#つまずきポイント(1): internal/docker-pushを使う場合、internal/docker-build内でDockerfileを用いたdocker buildはできない
steps:
    - internal/docker-push:
の前段で
    - internal/docker-build:
      dockerfile: Dockerfile
みたいなことをしていたのですが、Dockerfileに書いた内容がイメージに反映されませんでした。

そのかわりにdocker-push内にイメージ作成の定義を書けます。
https://devcenter.wercker.com/administration/containers/building-an-image/


#つまずきポイント(2): docker-pushしたらGCPに拒否られた
GCRのサービス アカウントのIAMの設定で、
【ストレージ管理者】
を追加してあげてください。

![スクリーンショット 2019-04-09 17.10.46.png](https://qiita-image-store.s3.amazonaws.com/0/262530/f2b98eaf-4344-8e51-adfb-0a2be9a1588d.png)

#結果
ContainerRegistryのイメージ一覧に、
```repository: gcr.io/$PROJECT_ID/$MY_IMAGE```
で登録した$MY_IMAGEの名前でイメージが登録されていれば成功です。
![スクリーンショット 2019-04-15 10.25.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262530/44b868ce-21cf-2630-4d0b-8dd79781bb38.png)


#参考URL
#####docker-push
https://devcenter.wercker.com/administration/containers/pushing-images/
https://devcenter.wercker.com/development/steps/internal-steps/#internal-docker-push

#####Container Registry概要
https://cloud.google.com/container-registry/docs/overview?hl=ja
activerecord-import がやっぱり神だった話

## 概要 & お願い
今回 gem activerecord-import  を使って感動した話を書き綴る。
導入部分は `bundle insatll` するだけなので省略する。
ご存知の方はスルー&間違っていたら指摘お願いします:relaxed:

## activerecord-import ってなに
ActiveRecordを使用してデータを一括挿入するためのライブラリ。
each でぐるぐる回して１件ずつレコード追加更新は負荷がかかるため、バルクインサート/バルクアップデート を使おう。

## ここがナイス:thumbsup:
- N + 1 対策してくれる
- 以下リンクの通り、`on_duplicate_key_update：` を設定することにより、新規追加か更新かのロジックを意識せずに実装ができる
    - https://github.com/zdennis/activerecord-import/#duplicate-key-update
 
## 勘違いしていたこと
- 以下 `target_users` を作成際に、新規作成と更新でロジックを変えないといけないのかと思っていた（わかりにくいが before 参照のこと）
 

#### before（動作は未検証 :relaxed:）
```ruby:hoge.rb
target_users = []
# 一括で登録したいユーザー情報
user_lists = [{key: 'hoge', name: 'ほげ'}, {key: 'fuga', name: 'ふが'}, {key: 'piyo', name: 'ぴよ'}]
users = User.all

# 新規作成
if users.blank?
    user_lists.each do |user_list|
        target_users << User.new(
            key: user_list['key'],
            name: user_list['name']
        )
    end
# 更新の場合は
else
    user_lists.each do |user_list|
        users.each do |user|
            next unless user.key == user_list.key
            user.name = user_list.name
            target_users << user
        end
    end
end
User.import target_users, on_duplicate_key_update:[:name]
```
あ”あ”あ”あ”あ”あ”あ”あ”あ”長い長い長い :japanese_goblin:


### after 
```ruby:hoge.rb
target_users = []
user_lists = [{key: 'hoge', name: 'ほげ'}, {key: 'fuga', name: 'ふが'}, {key: 'piyo', name: 'ぴよ'}]

user_lists.each do |user_list|
    target_users << User.new(
        key: user_list['key'],
        name: user_list['name']
    )
end
User.import target_users, on_duplicate_key_update:[:name]
```
実はこれだけで新規追加も更新もよしなにしてくれた :sob: 
きもいきもいと思っていたコードが全部なくなってくれて感動した :sob: 

**！ `on_duplicate_key_update:` は、MySQL、PostgreSQL（9.5以降）、SQLite（3.24.0以降）で設定がサポートされているが、PostgreSQL は微妙に書き方が違うので注意が必要。**

## 最後に
Rails6でinsert_all、insert_all!、upsert_all追加されたから、activerecord-import は使われなくなってしまうのかな... :relaxed:
雑だけどおわり。
[mac] vscodeをterminalから起動したい

windowsのshellで`code .`みたいに出来るのにmacで出来なかったのでメモ

## やりたいこと

windowsのこれ↓

```
> code .
```

## やり方

1. vscodeを開く
2. commant + p
3. `> shell` と入力
4. `Shell Command: Install 'code' command in PATH` を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52392/febf0e4b-4523-cbce-c753-c340af6cd233.png)

## やってみた

```
$ code .
```

出来た！一安心。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/52392/c606079e-0d8a-43a4-5351-87ab64f16950.png)
さくらのレンタルサーバ スタンダードへのcomposerとLaravelのインストールメモ

# 環境
さくらのレンタルサーバ スタンダード。
PHPのバージョンとインストール時にエラーになる。
php.cgiで任意のディレクトリのみPHPのバージョンを変更しても不可なので注意。


# composerのインストール
参考
https://metrograph.jp/sakura-composer-install/

## sshで接続

```sh
% ssh アカウント名@初期ドメイン
```

## インストール
`/home/アカウント名` へのインストールを想定。
完了すると composer.phar が作られる。

```sh
% curl -sS https://getcomposer.org/installer | php

All settings correct for using Composer
Downloading...
Composer (version 1.8.5) successfully installed to: /home/アカウント名/composer.phar
Use it: php composer.phar
```

バージョンの確認。

```sh
% php composer.phar -V

Composer version 1.8.5 2019-04-09 17:46:47
```


# Laravelのインストール

参考
https://laraweb.net/environment/674/

## インストール
任意のディレクトリ（ `/home/アカウント名/www/test.アカウント名.com` ）で以下を実行。
sampleproject部分は任意に指定できるっぽい。

```sh
% php ../../composer.phar create-project "laravel/laravel=5.8.*" sampleproject
```

## ファイルの移動

`/home/アカウント名/www/test.アカウント名.com/sampleproject（プロジェクト名）/public`
の中身を
`/home/アカウント名/www/test.アカウント名.com/`
へ移動させてindex.php内のパスを変更するらしいが、今回はテストなので移動させずにこのまま。
Go言語でMySQLを使ってみる

以前Webアプリケーション開発の学習の一環としてデータベースの基礎的なところの勉強をしたので投稿する。

##使うもの
後述するコードでは使用しないが、データベースに接続する際に必要なものをgo getしておく。

```
go get github.com/go-sql-driver/mysql
```


##扱うデータ
今回扱うデータは下記図の通り

```
DB:App
|---Table:userData
    |---id
    |---pass
```

idとpassはともにtext型とします。

##コード
データベースを操作する機能をいくつか実装した

```go
const (
	ID = "id"
	PASS = "pass"
	TABLE = "userData"
)


//ユーザーデータ
type User struct{
	Id string `json:"id"`
	Password string `json:"pass"`
}

//ユーザーの追加
func InsertUser(db *sql.DB, user User)error{
	_, err:=db.Exec(fmt.Sprintf("INSERT INTO %s VALUES(?, ?)", TABLE), user.Id,user.Password)
	if err!=nil{
		return err
	}
	return nil
}

//データをすべて取り出す
func SelectAll(db *sql.DB, user *User) error{
	results, err := db.Query(fmt.Sprintf("SELECT * FROM %s", TABLE))
	for results.Next() {
		err = results.Scan(&user.Id, &user.Password)
		if err != nil{
			return err
		}
		fmt.Println(user.Id, user.Password)
	}
	return nil
}

//特定のユーザーの検索
func SelectUser(db *sql.DB, name , pass string)(bool, error){
	row := db.QueryRow(
		fmt.Sprintf(
			"SELECT * FROM %s WHERE %s = ? AND %s = ?",
			TABLE,
			ID,
			PASS,
		),
		name,
		pass,
	)
	var retId, retPassword string
	if err := row.Scan(&retId, &retPassword); err != nil{
		return false, err
	}
	return true, nil
}

//パスワードの更新
func UpdatePass(db *sql.DB, name ,newpass string) error{
	_, err :=  db.Exec(
		fmt.Sprintf(
			"UPDATE %s SET %s = ? WHERE %s = ?",
			TABLE, PASS, ID),
			newpass,
			name,
		)
	if err != nil{
			return err
	}
	return nil
}

//IDの更新
func UpdateId(db *sql.DB, pass ,newname string) error{
	_, err :=  db.Exec(
		fmt.Sprintf(
			"UPDATE %s SET %s = ? WHERE %s = ?",
			TABLE, ID, PASS),
		newname,
		pass,
	)
	if err != nil{
		return err
	}
	return nil
}


//ID, パスワードともに更新
func UpdateUser(db *sql.DB, name ,pass string, newUser User) error{
	_, err :=  db.Exec(
		fmt.Sprintf(
			"UPDATE %s SET %s = ? ,%s = ?WHERE %s = ? AND %s = ?",
			TABLE, ID, PASS,ID, PASS),
		newUser.Id,
		newUser.Password,
		name,
		pass,
	)
	if err != nil{
		return err
	}
	return nil
}


//ユーザーの削除
func DeleteUser(name, pass string, db *sql.DB) error{
	_, err :=  db.Exec(
		fmt.Sprintf(
			"DELETE FROM %s WHERE %s = ? AND %s = ?",
			TABLE, ID, PASS),
		name,
		pass,
	)
	if err != nil{
		return err
	}
	return nil
}

```

このコードではまずデータベースに接続し、sql.DB型のポインタをうけとり、引数に入れる必要がある。

##おわりに
今回は簡単な機能だけ追加したが、今後Webアプリ等で実装する際はパスワードの暗号化など、セキュリティ面を考慮した設計にする必要がある。

##Githubにソースコードを置きました。
https://github.com/Reinker/mySQL/blob/master/db.go
wordpressでプラグイン使わずにカスタムフィールドも検索結果に含めたい。

wordpressではカスタムフィールドの検索はデフォルトではできない。
プラグインで実現する方法もあるようだけど、今回は `function.php`で実現する方法。

まず全体のコードは以下の通り。後で処理ごとに解説します。
やっていることとしては、投稿の本文エリア（the_content）にカスタムフィールドの値を突っ込んで検索の対象に含めています。

なので前提として、**本文エリア（the_content）を既に使っている場合は今回の方法は使えません。**


```function.php

function set_contents($post_id) {
  if ( ! wp_is_post_revision( $post_id ) && get_post_type($post_id) === 'faq' ) { //適用する投稿タイプ指定。

    // この関数をフックから外し、無限ループを防ぐ。
    remove_action( 'wp_insert_post', 'set_contents' );

    // カスタムフィールドを取得
    $faq_txt = get_post_meta($post_id, 'faq_txt' , true);
    $faq_txt2 = get_post_meta($post_id, 'faq_txt2' , true);

    //タクソノミーを取得
    $faq_cat = get_the_terms( $post_id, 'faq_cat' );
    if ( $faq_cat && ! is_wp_error( $faq_cat ) ) {
      $faq_cat_names = array();
      foreach ( $faq_cat as $term ) {
        $faq_cat_names[] = $term->name;
      }
      $faq_cat = join(',', $faq_cat_names );
    }

    // 更新データを格納
    $update_post = array(
      'ID' => $post_id,
      'post_type' => 'faq',
      'post_content' => $faq_txt .',' . $faq_txt2 .',' . $faq_cat,
    );

    // 更新
    wp_update_post( $update_post );


    // この関数を改めてフックする。
    add_action( 'wp_insert_post', 'set_contents' );
  }
}

add_action( 'wp_insert_post', 'set_contents', 10, 1 );
```

**カスタム投稿タイプ名**
- faq

**カスタムフィールド名**
- faq_txt
- faq_txt2

**カスタムタクソノミー名**
- faq_cat



# コード解説

## 適用する投稿タイプを指定

```function.php
  if ( ! wp_is_post_revision( $post_id ) && get_post_type($post_id) === 'faq' ) { //適用する投稿タイプ指定。
```

`wp_is_post_revision`は最新版を反映するための処理。

`get_post_type($post_id) === 'faq'`はこの処理を適用する投稿タイプを指定しています。
**これを指定しないと、いろんなところで処理が走って大変なことになるので超重要です。**
通常の投稿の場合は `faq` を `post`とすればOKです。
対象とする投稿タイプが複数の場合は条件を追加してください。

## カスタムフィールドを取得

```function.php
    $faq_txt = get_post_meta($post_id, 'faq_txt' , true);
    $faq_txt2 = get_post_meta($post_id, 'faq_txt2' , true);
```

カスタムフィールドを取得しています。

## タクソノミーを取得

```function.php
    $faq_cat = get_the_terms( $post_id, 'faq_cat' );
    if ( $faq_cat && ! is_wp_error( $faq_cat ) ) {
      $faq_cat_names = array();
      foreach ( $faq_cat as $term ) {
        $faq_cat_names[] = $term->name;
      }
      $faq_cat = join(',', $faq_cat_names );
    }
```
タクソノミー も検索に入れたい場合はこの処理を入れます。
いらなければ削除してOK。

## 更新データを格納

```function.php
    $update_post = array(
      'ID' => $post_id,
      'post_type' => 'faq',
      'post_content' => $faq_txt .',' . $faq_txt2 .',' . $faq_cat,
    );
```
`post_content`に取得したカスタムフィールドやタクソノミー を入れています。
カンマ区切りなのは、意図しない文字の連結を防ぐためです。
例えば、「岡山」と検索した時に「福岡山形」とあったら引っかかってしまいます。カンマで区切って「福岡,山形」とすることで防止できます。

##コード設置後
各投稿ごとに一度更新して本文エリアに格納する処理を走らせる必要があります。
更新ボタンを押して本文エリアにデータが反映されているか確認してください。
本番環境でのみ画像が表示されない

開発環境では画像は表示されるが、本番環境では画像表示されないことで
めっちゃハマったので備忘録。


##problem:smiling_imp:
開発環境では画像は表示されるが、本番環境では画像表示されない

#####エラー文
```rb
Failed to load resource: the server responded with a status of 404 (Not Found)
```

#####HTML
```rb
.imageslider.banner__slider
%div= image_tag 'banner-nasukashi’
%div= image_tag 'banner-new-life'
%div
```
#####Image
```rb
assets/images直下
```
##Cause:thinking:
開発環境と本番環境ではイメージへのパスが異なるため！

本番環境ではassets内のSCCファイルやJsファイルが最小化され、Public下で管理されます。
（アセットパイプラインというフレームワークが使われています）

当初の記述ではassetsのimageを読んでいるので、見つからないよ、とエラーになったようです。

##Solution:innocent:
#####①プリコンパイルでPublic内にAssetsファイルを作成
```rb
[ユーザー名|アプリ名]$ rake assets:precompile
```
deployで自動で作られると思ってたのですが違うかも。。。？


#####②HTMLのパスを再指定
```rb
.imageslider.banner__slider
%div= image_tag asset_path('banner-natsukashi')
%div= image_tag asset_path('banner-new-life')
```
assets_pathを記述することで、開発環境ならasset/imageから、本番環境ならpublic/assets/imageから引っ張ってくることができます。（便利！）
#####③デプロイ
→無事表示されました！

####他の方法
●imagesをそもそもpublicに作っておく
public/images以下に設置した画像はコンパイルされないため、本番環境にデプロイしてもパスが変わらない様子。

```rb
mv assets/images public/images
```
（assets/image内のファイルをpublic/imageに動かすコマンドです）

#Reference
他にもやり方はいっぱいあるようです。
https://qiita.com/wadako111/items/03bc00d914e62243a511
この記事の①を実践しました。
GoでFirebase CloudFirestore接続、値取得まで

# Firebase共通鍵の入手

Firebaseコンソールへログイン
「設定」→「プロジェクトの設定」で設定画面を表示
「サービスアカウント」タブを押し、Firebase Admin SDKを表示する

Admin SDK 構成スニペットでGoを選択
【新しい秘密鍵の生成】ボタンから秘密鍵(json)をダウンロード

# クライント接続
```golang
package main

import (
	"fmt"

	"golang.org/x/net/context"

	firebase "firebase.google.com/go"
	"google.golang.org/api/option"
)

func main() {
    opt := option.WithCredentialsFile("key.json")
    ctx := context.Background()
    app, err := firebase.NewApp(ctx, nil, opt)
    if err != nil {
        fmt.Errorf("error initializing app: %v", err)
    }
    client, err := app.Firestore(ctx)
    if err != nil {
        fmt.Errorf("error initializing client: %v", err)
    }
    defer client.Close()
    fmt.Println("Connection done")
}
```
# 値の取得
```golang
package main

import (
	"fmt"

	"golang.org/x/net/context"

	firebase "firebase.google.com/go"
	"google.golang.org/api/option"
)

func main() {
    // クライアント接続
    opt := option.WithCredentialsFile("key.json")
    ctx := context.Background()
    app, err := firebase.NewApp(ctx, nil, opt)
    if err != nil {
        fmt.Errorf("error initializing app: %v", err)
    }
    client, err := app.Firestore(ctx)
    if err != nil {
        fmt.Errorf("error initializing client: %v", err)
    }
    defer client.Close()
    fmt.Println("Connection done")

    // 値の取得
    collection := client.Collection("コレクションID")
    doc := collection.Doc("ドキュメントID")
    field, err := doc.Get(ctx)
    if err != nil {
        fmt.Errorf("error get data: %v", err)
    }
    data := field.Data()
    for key, value := range data {
        fmt.Printf("key: %v, value: %v\n", key, value)
    }
}
```
[UE4]マルチユーザー編集 を速攻で使う

#はじめに
ver 4.22 でマルチユーザー編集機能が追加されました。

英語だと MultiUserEditing です。
まだ翻訳されてませんがドキュメントもありますね。あんまり読んでません。
https://docs.unrealengine.com/en-us/Editor/MultiUser

これによって複数人が同時にレベル編集作業が行えるようになり、
変更状態が即座に同期されます。

実際さわってみるとマルチプレイゲームみたいで楽しいです。

#書いてること
最短操作でマルチユーザー編集機能を使う。

英語だとめんどくせぇなぁとか、
ドキュメントって細かく書かれすぎてわかりづれぇなぁって人用です。

#できること
みんなで一つのレベルをリアルタイムで編集できます。
![MultiUserEditingScale.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/0c1f89ca-b4fc-0214-8f24-e0eecc3e293f.gif)
自分が選択しているのは階段ですが、他のユーザーが置いたものや変更したものが適応されています。
少しわかりづらいかも…。

#準備
UE4 4.22が入ってローカルエリアでつながったパソコンを2つ。
「マルチユーザー」編集機能なので、もう1人遊んでくれる人がいると捗ります。

#手順
両PCで必要な項目、別々に必要な項目がありますので以下の（）で分類しておきます。
（どちらも）（親）（子）

##1.プロジェクト作る（どちらも）
2PCで「同じテンプレート」で「同じ名前のプロジェクト」を作成します。
ディレクトリはお好きに。
![MultiUserEditing00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/a98c52c7-1394-d081-b94c-79fc01bea3d6.png)
（普通ならバージョン管理から落とすはずなので、同期しているはず）

##2.MultiUserEditing プラグインを有効に（どちらも）
したあと再起動。
![MultiUserEditing01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/7f07fcaf-b636-ef6f-8c73-e2454761fe44.png)

##3.サーバーを立てます（親）
「Go Live」というボタンが表示されたはずなので、そこのプルダウンから選びます。
コマンドプロンプト的なやつが立ち上がればOKです。
![MultiUserEditing02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/050def7b-2077-8eeb-9284-dd845bbd0f2c.png)

##4.セッションを作ります（親）
「Go Live」ボタンをクリック
![MultiUserEditing03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/43d07e81-e82e-460f-0a6a-ca501b201743.png)

Multi-User Browserが立ち上がるので、自分のPC名のサーバーを選んで、「Create Session」
![MultiUserEditing04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/eded8b10-cc2c-72dd-7cb9-96a4e7826d6f.png)


てきとーに名前を入れて「作成する」
![MultiUserEditing05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/fcd19606-6977-15d1-84d7-b59442302982.png)

##5.セッションに参加します（子）
子供は参加するだけです。
「Go Live」ボタンをクリック
![MultiUserEditing03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/43d07e81-e82e-460f-0a6a-ca501b201743.png)

Multi-User Browserから親のサーバーを選んで、立っているセッションへJoin
![MultiUserEditing06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/0494a194-863b-8370-c371-03a43d682547.png)

接続されたらOKです。
僕が詰まったのは、同じプロジェクト名にしているかどうかぐらいでした。

#あそぶ
まずこんな感じで他のユーザーがビューポートに表示されます。
![MultiUserEditing07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/56feb54e-a97c-8e76-fbec-e2a3fb17b91b.png)

リアルタイムで見てる位置、方向が見えます。この時点で結構楽しい。
![MultiUserEditingMove.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/ca248b82-3522-d597-ad71-85eac7a23c33.gif)

新しくオブジェクトを置いたり、移動したりスケールしたりが反映されます。
![MultiUserEditingPop.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/3cfd49c8-7eb3-3c92-7583-abe7653ef30b.gif)![MultiUserEditingScale.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154327/0c1f89ca-b4fc-0214-8f24-e0eecc3e293f.gif)

#どう使うと効率いいわけ？
わかんねっす…
すごい人がすごいこと考えてくれるはずっす…
LSM9DS1で加速度の値をシリアルにプリントする

SWITCH SCIENCE社のマイコン**ESPr Developer 32**に9自由度の慣性計測装置（IMU）の**LSM9DS1**を接続し、Arduino IDEを用いて**3軸加速度をシリアルに出力**する方法です。

**まずは、[Arduino公式サイト](https://www.arduino.cc/)からArduino IDEを手順に沿ってインストールします。**
1. "Download"へ移動
2. 各種PCに合わせたインストーラをダウンロード
3. インストーラを実行
4. 設定はデフォルトから特に変更する必要なし
5. デスクトップにArduinoのアイコンができれば完了

**続いて、ESP32のボードを使うための設定をします。**
1. "File" → "Preference"を開く
2. 下方の"Additional Boards Manager URLs"に、"https://dl.espressif.com/dl/package_esp32_index.json" をコピペする
3. "OK" をクリックして"Preference"を閉じる
4. "Tools" → "Board" → "Board Manager"を開く
5. "esp32 by Espressif Systems" を探す（検索できます）
6. カーソルを当てると右下に"Install" と出るので、クリック
7. インストールが終わったら"close"
8. "Tools" → "Board"でスクロールすると"ESP32 Dev Module"があるので選択
------これで環境設定は終了です。------

**最後に、ボードをPCと接続！**
"Tools" → "Port"で繋いだポート番号を選択（コードを抜いたときは表示されていなくて接続したら表示される番号です）

以下はシリアルに**加速度を出力するためのコード**になります。

```accelerater.ino
#include <SparkFunLSM9DS1.h>

#define LSM9DS1_M 0x1E
#define LSM9DS1_AG 0x6B

LSM9DS1 imu;

float x,y,z;
uint16_t connectionState = 0;

void setup()
{
  Serial.begin(115200);

  imu.settings.device.commInterface = IMU_MODE_I2C;
  imu.settings.device.mAddress = LSM9DS1_M;
  imu.settings.device.agAddress = LSM9DS1_AG;
  if (connectionState == 0)
  {
    connectionState = imu.begin();
    while (connectionState == 0)
    {
      Serial.println("Failed to communicate with LSM9DS1.");
      Serial.println("Double-check wiring.");
      Serial.println("Default settings in this sketch will "
                     "work for an out of the box LSM9DS1 "
                     "Breakout, but may need to be modified "
                     "if the board jumpers are.");
      Serial.print("Connection Status: ");
      Serial.println(imu.begin());
      delay(1000);
      connectionState = imu.begin();
      Serial.println("------------------------------------------------------\n");
    }if(connectionState!=1){
      Serial.print("connectionState: ");
      Serial.println(connectionState);
    }
  }
}


void loop()
{
  imu.readAccel();
  x=imu.calcAccel(imu.ax)*10;
  y=imu.calcAccel(imu.ay)*10;
  z=imu.calcAccel(imu.az)*10;
  Serial.print("x=");
  Serial.print(x);
  Serial.print(", y=");
  Serial.print(y);
  Serial.print(", z=");
  Serial.println(z);
}
```

↓このアイコンを押してボードに書き込みましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390958/c039a1de-3459-d86f-fcd7-1a7cce105af9.png)
書き込みが完了したら、ウィンドウ右上の虫眼鏡をクリックするとシリアルウィンドウが開きます。
シリアルウィンドウ右下の転送レートを115200bpsに変更すると、出力された値が見られます。

**以上です！
初投稿読んでいただきありがとうございました！
続きはこちら↓
「[スイッチを押しているとき、加速度の値をBluetoothで送信する](https://qiita.com/Shun141/items/6f75ab644482902b746e)」**
matplotlib よく使うグラフまとめ（折れ線、積み上げ面グラフ）

##はじめに

matplotlibでよく利用するグラフのまとめ
-　折れ線グラフ
-　積み上げ面グラフ

参考：https://python-graph-gallery.com/

（詳細は追記予定）

##実行環境
Jupyter notebook 4.4.0
Python 3.6.6
matplotlib 2.0.2

##準備

####matplitlib インポート

```python
import matplotlib.pyplot as plt
```

####データ

よくデータ分析の時に利用するような縦持ちのデータ

```python

df_prop.head()
---
	topic	year	prop
0	1	1998	0.051152
1	2	1998	0.132362
2	3	1998	0.048417
3	4	1998	0.044677
4	5	1998	0.044055

```

####色の設定

20色あって良い色なのでこちらを利用

```python

color_list = list(plt.get_cmap("tab20").colors)
```

####ｘ軸（年度）データの表示感覚

2年間隔で表示させたいので、以下のリストを作成

```python
year = df_prop['year'].unique()
range_year = np.arange(min(year), max(year)+1, 2).tolist()
print(range_year)
---
[1998, 2000, 2002, 2004, 2006, 2008, 2010, 2012, 2014, 2016]
```
##折れ線グラフ
####複数データ 同一プロット

```python
plt.figure(figsize=(8, 6))
for topic in df_prop['topic'].unique():
    phi_plot = df_prop[df_prop['topic']==topic]
    plt.plot(phi_plot['year'].astype(np.int64), phi_plot['prop'], marker="o", label=topic, color=color_list[topic-1])
    plt.xticks(range_year)
plt.legend(loc = 'upper right', bbox_to_anchor = (0.15, 0, 1, 1),title="Topic#")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113406/5800ef43-47c1-974a-c97d-8f998bb073cb.png)

####複数データ 複数サブプロット

ｘ軸の値が入りきらなかったので、レンジを変更

```python
range_year2 = np.arange(min(year), max(year)+1, 3).tolist()
print(range_year2)
---
[1998, 2001, 2004, 2007, 2010, 2013, 2016]
```


```python
plt.figure(figsize=(20, 15))
plt.rcParams["font.size"] = 12
plt.subplots_adjust(wspace=0.05, hspace=0.2)

for topic in df_prop['topic'].unique():
    plt.subplot(5,5, topic)
    # plot every group
    for topic2 in df_prop['topic'].unique():
            phi_plot = df_prop[df_prop['topic']==topic2]
            plt.plot(phi_plot['year'].astype(np.int64), phi_plot['prop'],  marker='', color='grey', linewidth=0.5, alpha=0.3)
    # plot color line
    phi_plot = df_prop[df_prop['topic']==topic]
    plt.plot(phi_plot['year'].astype(np.int64), phi_plot['prop'], marker="o", linewidth=1, label=topic, color=color_list[topic-1])
    
    # Same limits for everybody!
    plt.xticks(range_year2)
    plt.ylim(0, 0.15)
 
    # Not ticks everywhere
    if topic in range(16) :
        plt.tick_params(labelbottom='off')
    if topic not in np.arange(1, 21, 5).tolist() :
        plt.tick_params(labelleft='off')
        
    plt.title('Topic#' + str(topic), loc='left', fontsize=12)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113406/46f4d8a7-a1bb-ed7a-6514-3989ffb783dd.png)


##積み上げ面グラフ

```python

plt.figure(figsize=(8, 6))
area_plot_data = []
topic_list = df_prop['topic'].unique().tolist()
for topic in topic_list:
    area_plot_data.append(df_prop[df_prop['topic']==topic]['prop'].tolist())
plt.stackplot(phi_plot['year'].astype(np.int64), area_plot_data, labels=topic_list, colors=color_list)
plt.xticks(range_year)
plt.legend(loc = 'upper right', bbox_to_anchor = (0.15, 0, 1, 1),title="Topic#")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113406/9ca53f26-592c-e67c-562f-8013747800e5.png)
Netlify CMS + GitLabでEditorial Workflowが使えなかった件


VuePress + GitLabで作ってるサイトにNetlify CMSを適用させようとしたところ

<img src="https://i.gyazo.com/b71e8f365cab0a89901fcd39c67c4b19.png" width="500px">

とエラーが出ました。

[ドキュメント](https://www.netlifycms.org/docs/configuration-options/#publish-mode
)によれば、

> Editorial workflow works with GitHub repositories only. Support for other Git hosts is [coming soon](https://github.com/netlify/netlify-cms/issues/568).

と書いてますね。おとなしくGitHub使えばいいのだろうけど、GitHubだと無料プライベートリポジトリの人数3人までとか制限があるし、うーんって感じです。

## `publish_mode`をコメントアウト

これで上手くいきました。

<img src="https://i.gyazo.com/a1dc360b119a0e2608e486533ee3cf3b.png" width="500px">

## 動いた

動いたけど、ドラフト系が全くないのでちょっと使いにくいかも。。。

<img src="https://i.gyazo.com/13cf86da1fa041605c8bb642ea566329.png" width="500px">

VuePress + Netlify CMSだからなのかな？ HugoだとHugo側でドラフトの仕組みもあるので表示が違う可能性もあるかも?

対応はカミングスーンって言ってるけど、会話のスタートが2017年とかなのでとりあえずはおとなしくGitHubにしておいた方がいいかもしれないなぁなど思いました。
日付データのフォーマットにはISO8601を使う

## TL;DR

- APIなどで日付データをやり取りする必要がある場合にはISO8601形式を使うのがオススメです
- PHPでは[Datetime::ATOM](https://www.php.net/manual/ja/class.datetime.php)で利用できます


## ISO8601とは

ISO8601は日付・時刻に関する国際規格です [wikipedia](https://ja.wikipedia.org/wiki/ISO_8601) /  [ISO](https://www.iso.org/standard/40874.html)

## ISO8601を使ったほうがいい理由

- 国際規格なので、プログラミング言語間での扱いの差がなく標準的に利用できる
    - 例えばJSでは以下のようにDateのコンストラクタにISO8601でフォーマットされた文字列を投げればそれだけでパースを完了してくれます

 ```js
new Date('2004-04-01T00:00:01+09:00')
> Thu Apr 01 2004 00:00:01 GMT+0900 (日本標準時)
```

- (YYYY-MM-DD)や日付+年+日のような形式でデータを渡す場合に比べて、独自でparse/formatする必要がない(=バグが少ない)
    - 桁数の違いをミスったり、JS/JavaでsetMonth/getMonthの数字が1少ないのを忘れててミスったり・・・みたいなことが起きません

```js
// バグりやすいのでこういうフィールドの扱い方をしないほうがいい
{
  hogeYear: "2014",
  hogeMonth: "05",
  hogeDay: "06"
}
```

- フォーマットの中にタイムゾーンが含まれている


## tips

ISO8601では YYYYMMDDThhmmssだけじゃなくもうちょっと情報が扱えます
例えば以下のようなことができます

- 年の中の週を取得する
- 年の中の通算日を取得する

### JSでのサンプル

JSでISO8601を出力するには[toISOString](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)を使えばいいですが、書式指定とか細かい融通が効かないので以下のサンプルでは[date-fns](https://date-fns.org/)というライブラリを使ってます

```js
dateFns.format(new Date(), '今日はYYYY年の第W週目で年度内ではDDD日目です')
"今日は2019年の第15週目で年度内では102日目です"
```
EDITOR=vim rails credentials:editを実行すると「ActiveSupport::MessageEncryptor::InvalidMessage」と言われる


「[AWS S3を使って画像アップロードできるようにする](https://qiita.com/hmmrjn/items/479c9e9ce82771f1b6d7)」の記事を読みつつ進めていたところ、以下のコマンドを実行するところでエラーが出ました。

```
EDITOR=vim rails credentials:edit
```

```
ActiveSupport::MessageEncryptor::InvalidMessage
```

全く身に覚えがなくエラーが意味するところも不明だったので、ググりまくって解決しました。

### 結論：原因は「credentials.yml.enc」がすでに存在していたから

多分以前にも上記のコマンドを実行したことがあって、それによって`credentials.yml.enc`がすでに存在しているためエラーが出た感じでした。

### 解決策：`credentials.yml.enc`を削除

credentials.yml.encを削除して、`EDITOR=vim rails credentials:edit`を実行してあげれば、ちゃんと編集できます。

### Railsの秘匿情報管理の仕組み

`rails credentials:edit`がやることは、以下のことらしいんです。

- ①暗号化済のファイルを複合
- ②指定のエディタで編集
- ③再度暗号化して`config/credentials.yml.enc`に保存

勉強になりました。

### 参考リンク

- [Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)
- [Rails 5.2 で ActiveSupport::MessageEncryptor::InvalidMessage](https://qiita.com/scivola/items/cc06ddbfd94d3118f693)
- [Heroku上でRailsデプロイ時にmaster.keyのApplicationError
](https://qiita.com/lemtosh469/items/92da68b74f7e29ade1a2#_reference-38c08c38dcee17570042)
【Laravel】Excelファイルをアップロードして読み込んで使う（DBを使わない方法）

##環境
[laradock](https://github.com/Laradock/laradock)
(PHP - 7.2)
(Laravel - 5.7)
※動作確認はローカルで行ってます。

##追加プラグイン

[PhpSpreadsheet](https://github.com/PHPOffice/PhpSpreadsheet)

##事前準備
####PhpSpreadsheetの追加
dockerで構築しているので、まずはworkspaceにログインします。

```
cd <自分のpath>/laradock
docker-compose exec --user=laradock workspace bash
```

composerでPhpSpreadsheetを追加します

```
composer require phpoffice/phpspreadsheet
```

##ファイルアップロード

ファイルアップロード時のバリデーションとエラーハンドリングは割愛します。

####アップロード画面
```html:resources/views/upload.blade.php
<!doctype html>
<form method="POST" action="/upload/" enctype="multipart/form-data">
   {{ csrf_field() }}
  <input type="file" id="file" name="file" class="form-control">
  <div class="">
      <button type="submit">アップロード</button>
  </div>
</form>
```

####UploadController
```php:app/Http/Controllers/UploadController.php

<?php

namespace App\Http\Controllers;
use Illuminate\Http\Request;

class UploadController extends Controller
{
    public function index()
    {
        return view('upload');
    }

    public function store(Request $request)
    {
        //デフォルトでは/storage/app/に保存される
        $request->file('file')->storeAs('', 'upload_file.xlsx');
    }
}
```
####ルーティング

```php:routes/web.php
Route::resource('/upload', 'UploadController');
```

####アップロードを実行
アップロード画面のフォームでファイルを選択し、アップロードボタンを押します。

####ファイルの確認
workspaceに接続

```
cd <自分のpath>/laradock
docker-compose exec --user=laradock workspace bash
```

storage/app/を確認

```
cd /storage/app
ll
```

##ファイルの読み込み

###ReadController.php

```php:app/Http/Controllers/ReadController.php
<?php
namespace App\Http\Controllers;

class ImportController
{
    public function read()
    {
        $reader = new \PhpOffice\PhpSpreadsheet\Reader\Xlsx();
        $spreadsheet = $reader->load("/var/www/storage/app/upload_file.xlsx");
        //0番目のsheetを読み込む
        $sheet = $spreadsheet->getSheet(0);
        //読み込んだsheetを配列にする
        $sheetData = $sheet->toArray();
        //3行3列目のcellを読み込む
        $celldata = $sheetData[2][2];
        //sheet名を取得する
        $sheetName = $sheet->getTitle();
        //*使いたいデータをreturnしよう
    }
}
```

##おまけ
.bladeファイルへの反映はこちらも参照してみてください。
[【Laravel】Controllerで返したphpの配列をJavaScriptの配列に変換する](https://qiita.com/azumagoro/items/51a884eb9840b08a29ee)


##トラブルシューティング
・ファイルサイズが大きい場合
```/etc/php.ini```を書き換える必要があります。

```php.ini
post_max_size = 8M
upload_max_filesize = 8M
```

・ControllerがClass not foundになる
Controllerのファイル名とClass名が一致しないと駄目なようです。
それらが一致していてもこのエラーが出る場合は、
workspaceで```composer dump-autoload```を実行すると直ることがあるようです。


##備考
DBアップロードされたファイルの情報をDBに追加するのであれば、
[Laravel Excel](https://laravel-excel.com/)
を使うのが良さそうです。

PhpSpreadsheetの前にLaravel Excelを触ってみましたが、データをDBに追加するのが大前提になっている作りでした。

##参考文献
https://reffect.co.jp/laravel/how_to_upload_file_in_laravel
[Ruby] 配列を特定の条件で区切る

# 例

```rb
list = %w[1 茉里 2 乃莉 なずな 3 ゆの 宮子]
#=> ["1", "茉里", "2", "乃莉", "なずな", "3", "ゆの", "宮子"]
```

という配列がある。これを

```rb
[['1', '茉里'], ['2', '乃莉', 'なずな'], ['3', 'ゆの', '宮子']]
```

という様に区切りたい。

配列を区切るといえば思い浮かぶのは [Enumerable#each_slice](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_slice.html) だが、このメソッドは固定の長さに区切るので、今回のように区切った後の配列の長さがまちまちなケースでは使えない。

# 方法

[Enumerable#slice_when](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/slice_when.html) を使う。

```rb
# 次の要素が整数の文字列の場合は、その手前で区切る。
list.slice_when { |_a, b| b.match?(/\d+/) }.to_a
#=> [["1", "茉里"], ["2", "乃莉", "なずな"], ["3", "ゆの", "宮子"]]
```

なお、亜種として [Enumerable#chunk_while](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/chunk_while.html) というメソッドも存在する。slice_when は区切る条件を指定し、chunk_while は同じグループにする条件を指定するイメージだ。
MacのOpenCVからUSBカメラを製品名で区別

# 経緯
PythonのOpenCVを利用して複数台のカメラが乗っている場合、利用したいカメラを指定したかった。
OpenCVのVideoCaptureはindexの数値を指定するしか方法がない。そのindexが
USBの付ける位置によって毎回変わってしまうという糞仕様だった。せめて名前か何かユニークなもので判別して自動で利用するカメラを選びたかった人生。

# 手法
`system_profiler` でWebカメラの情報を取って、部分一致した文字列で雑に使用するカメラを指定出来るようにした。

```python
import sys
import subprocess

def get_camera_name(camera_name):
    # カメラリストの取得
    cmd = 'system_profiler SPCameraDataType | grep "^    [^ ]" | sed "s/    //" | sed "s/://" '
    res = subprocess.run(cmd, stdout=subprocess.PIPE, shell=True)
    # 出力結果の加工
    ret = res.stdout.decode('utf-8')
    camera_list = list(filter(lambda a: a != "", ret.split('\n')))
    print(camera_list)
    
    # 指定カメラの取得
    for index, row in enumerate(camera_list):
        if row.find(camera_name) != -1: 
          return index
                
    raise Exception('指定カメラなし')
```

```python
>>> get_camera_name('HD')
['FaceTime HD Camera', 'USB_Camera']
0
>>> get_camera_name('USB')
['FaceTime HD Camera', 'USB_Camera']
1
```

# 参考
https://stackoverflow.com/questions/4316690/list-video-devices-via-terminal/20102084#20102084
Bitbucket Pipelines + Rails + MySQL でRspec を実行

## Bitbucket Pipelines とは
[公式](https://ja.confluence.atlassian.com/bitbucket/get-started-with-bitbucket-pipelines-792298921.html)の通り、Atlassian製のCIツール。
他にまとめられている方がいるのでこの辺りの詳細はぶん投げ:relaxed:

## やりたいこと
開発環境をRuby -> Ruby on Docker へ移したため、Pipelines の設定もそれに追従させたい。

## 対応したこと
今回は環境変数を `.env` で管理しているため、テスト環境で使用する `.env.test` ファイルを用意。

```ruby:.env.test
RDS_USERNAME=root
RDS_PASSWORD=password
RDS_HOSTNAME=127.0.0.1
```
ひとまず以下成功した設定 :tada: 

```ruby:bitbucket-pipelines.yml
pipelines:
  branches:
    development:
      - step:
          image: ruby:2.4.4
          caches:
            - bundler
          script:
            - apt-get update && apt-get install -y nodejs
            - bundle install
            - cp .env.test.env
            - bundle exec rails db:setup RAILS_ENV=test
            - bundle exec rake db:migrate RAILS_ENV=test
            - bundle exec rspec
          services:
            - db
definitions:
  caches:
    bundler: ./vendor
  services:
    db:
      image: mysql:5.7
      environment:
        MYSQL_ROOT_PASSWORD: password
```
Ruby のupgrade は明日から本気出す。
##### 上の設定で大事なこと①
 `definitions: services: db: environment:` 以下に `MYSQL_DATABASE:` を設定しない。
これを設定して実行すると、MySQLがdb を作成し `rails db:setup` で文字コードが合わず？エラーが発生する :sob: 

:writing_hand: 以下発生したエラー
```ActiveRecord::StatementInvalid: Mysql2::Error: Incorrect string value: '\xE3\x81\xBF\xE3\x81\x9A...' for column 'hoge_hoge' at row 1: INSERT INTO `hoges` (`hoge_id`, `hoge_name`, `hoge_name_kana`) VALUES ('1', '???', '????')
```

##### 上の設定で大事なこと②
Bitbucket Pipelines でデータベースを使用する場合、ポートマッピングやホストの設定は不要。
[公式](https://ja.confluence.atlassian.com/bitbucket/use-services-and-databases-in-bitbucket-pipelines-874786688.html)曰く、 localhost で動くお:relaxed:とのこと。

>パイプラインの実行時、bitbucket-pipeline.yml のステップで参照されているサービスが、パイプライン ステップ内で実行されるようにスケジューリングされます。これらのサービスは、ビルド コンテナとネットワーク アダプタを共有するほか、localhost でオープンなポートを共有します。ポート マッピングやホスト名は不要です。たとえば、Postgres を使用している場合、localhost のポート 5432 に接続するだけでテストを行えます。

知らずにホストをdocker-compose.yml のホスト名と合わせて `db` 等にすると、以下のエラーが発生し延々としらばっくれられて心の傷を負うことになるので注意。
`Mysql2::Error: Unknown MySQL server host 'db' (-2)`


##### 上の設定で大事なこと③
`.env.test` の `RDS_HOSTNAME` は 127.0.0.1 に設定する。
[公式](https://confluence.atlassian.com/bitbucket/test-with-databases-in-bitbucket-pipelines-856697462.html)の説明をみると、Unixソケットを介して接続することがあるため、localhostの使用は避けてとのこと。

>##### Connecting to MySQL
If you use the example above, MySQL (version 5.7) will be available on:

>Host name: 127.0.0.1 (avoid using localhost, as some clients will attempt to connect via a local "Unix socket", which will not work in Pipelines)
Port: 3306
Default database: pipelines
User: test_user, password: test_user_password. (The root user of MySQL will not be accessible.)
You will need to populate the pipelines database with your tables and schema. If you need to configure the underlying database engine further, refer to the official Docker Hub image for details.

いやlocalhost で動くって言ってたじゃん！と思うが、localhost のまま実行をすると `Mysql2::Error: Unknown MySQL server host 'localhost' (-2)` とキレられて辛酸を嘗めることになるので注意。

## 最後に
意外と Bitbucket Pipelines ＋ Rspec の記事少なかった（ような気がした）ので、誰かの救いになれば良いな...... :pray:
最新の記法でコーディングしたJSのコードを古いブラウザでも動作するコードにコンバートする。

会社でとても便利だなーというツールを教えていただいたので備忘録として残します。

#■はじめに
JSのコードがあるブラウザではこけた。
こんな経験あるWebエンジニアはいるのでしょうか？
Chromeでは動くけどIEだと動かない。
よくあります。ええ。


原因の大半が記法が最新のECMAScriptで定めたものであったためとか。
IE9は2019/04/12の現時点ではWindowsserver上でのサポートはギリギリ継続中のため、要件にあった場合は無視できません。
特に、日本の企業はIEが大好きですからね。（皮肉）


#■どうやってコンバートするの？
下記にアクセスして、コードを張るだけ。
https://babeljs.io/repl

▼左が元コード：右がコンバート後のコード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213462/e86a45e0-56e0-14fc-d7e3-557d3aba4a70.png)


#■さいごに
Chromiumエンジンを使っているWebブラウザであれば、最新のESの記法ができるとは思いますが、IEでの動作をケアしないといけない場合は、重宝しそうです。
vuex-persistedstateの値が復帰しない！？

# VuexのStateを永続化したい時は
vuexのstateの値を永続化したい。そこで使っていたのが、[vuex-persistedstate](https://github.com/robinvdvleuten/vuex-persistedstate)。

LocalStorageにstateの値を保持してくれる奴。使い方などは他の記事様などで詳しく書かれていると思うので、割愛させていただく。

# 問題
問題は、実際にリロードした時。stateに値があるかどうかで初期処理をしたい時に、stateの値を見ると…… `undefind`だった。
**ん？ これっていつvuexに反映されてるの？**

# 答え
`mounted()`が実行された後。
え、`mounted()`って表示コンポーネントが揃った後に実行されるんじゃないの？ `mounted()`が実行された後に戻ってくるということは、stateの値で判断して初期処理を変えたい時なんかはちょっと不便。

## 対処方法
```javascript
mounted(){
  setTimeout(() => { // 反映されるのを待ってから実行
    // 初期処理
  }, 0)
}
```

# まとめ
っていうだけの記事でした。
MongoDBのaggregateで統計値を出そう

# まずソート
```json
 { "$sort": [{"name": "targetValue", "direction": 1}] },
```

# 次にgroupして標準偏差、平均値、中央値を求める
```json
{"$group": {
  "_id": "$service",
  "avg": {"$avg": "$targetValue"},
  "targetValues": {"$push": "$targetValue"},
  "stdDev": {"$stdDevPop": "$targetValue"},
  "stdSamp": {"$stdDevSamp": "$targetValue"}
}},
```

# 第一四分位、第三四分位も求める
```json
{"$project": {
    "_id": 1,
    "avg": 1,
    "stdDev": 1,
    "stdSamp": 1,
    "median": {
      "$arrayElemAt": ["$targetValues", {"$toInt": {
        "$divide": [{"$size": "$targetValues"}, 2]
      }}]
    },
    "1stQuarter": {
      "$arrayElemAt": ["$targetValues", {"$toInt": {
        "$divide": [{"$size": "$targetValues"}, 4]
      }}]
    },
    "3rdQuarter": {
      "$arrayElemAt": ["$targetValues",{"$toInt": {
        "$multiply": [{"$divide": [{"$size": "$targetValues"}, 4]}, 3]
      }}]
    }
  }
}
```

# 一つにして
```json
[
{ "$sort": [{"name": "targetValue", "direction": 1}] },
{"$group": {
  "_id": "$service",
  "avg": {"$avg": "$targetValue"},
  "targetValues": {"$push": "$targetValue"},
  "stdDev": {"$stdDevPop": "$targetValue"},
  "stdSamp": {"$stdDevSamp": "$targetValue"}
}},
{"$project": {
    "_id": 1,
    "avg": 1,
    "stdDev": 1,
    "stdSamp": 1,
    "median": {
      "$arrayElemAt": ["$targetValues", {"$toInt": {
        "$divide": [{"$size": "$targetValues"}, 2]
      }}]
    },
    "1stQuarter": {
      "$arrayElemAt": ["$targetValues", {"$toInt": {
        "$divide": [{"$size": "$targetValues"}, 4]
      }}]
    },
    "3rdQuarter": {
      "$arrayElemAt": ["$targetValues",{"$toInt": {
        "$multiply": [{"$divide": [{"$size": "$targetValues"}, 4]}, 3]
      }}]
    }
  }
}
]
```

# 注意点
mongoのバージョンはv4以上じゃないと`$toInt`が使えないです。
nuxt.jsでi18nするまで

なんだかまとまっている情報がどこにあるんだかわからんなぁ・・・と少々路頭に迷ったのでまとめておく。

## やりたいこと

- nuxt.jsのi18nをしたい
- 定義ファイルはyamlで書きたい

## やり方にたどり着くまで

- [ここ](https://ja.nuxtjs.org/examples/i18n/) みても「はぁ？そんだけ？」となるが、実は下の方にリンクがある
- [結局ここ](https://github.com/nuxt-community/nuxt-i18n/) 経由で、 [さらにこちら](https://github.com/nuxt-community/nuxt-i18n/blob/master/docs/vue-i18n-loader.md) にたどり着き解をゲット


## 結局実施した変更

### nuxt.config.jsに以下を追記

#### modulesセクション

```javascript
 modules: [
    // Doc: https://axios.nuxtjs.org/usage
    '@nuxtjs/axios',
    // Doc:https://github.com/nuxt-community/modules/tree/master/packages/bulma
    '@nuxtjs/bulma',
    '@nuxtjs/pwa',
    // 以下追記
    [
      'nuxt-i18n',
      {
        locales: [{ code: 'ja', iso: 'ja_JP' }, { code: 'en', iso: 'en-US' }],
        defaultLocale: 'ja',
        vueI18n: {
          fallbackLocale: 'ja',
        },
        vueI18nLoader: true,
      },
    ],
  ],
```

#### buildセクション

```javascript
  build: {
    postcss: {
      preset: {
        features: {
          customProperties: false,
        },
      },
    },
    /*
     ** You can extend webpack config here
     */
    extend(config, ctx) {
      // この部分を追記
      config.module.rules.push({
        resourceQuery: /blockType=i18n/,
        type: 'javascript/auto',
        loader: ['@kazupon/vue-i18n-loader', 'yaml-loader'],
      })
      ...
    },
  },
```

### 変換用のファイルを設置

自分の場合は、 ``@/locales/ja.yaml`` , ``@/locales/en.yaml`` を置いてそこに以下を追記

#### ja.yaml

```yaml
ja:
  hello: 'こんにちは世界'
```

#### en.yaml

```yaml
en:
  hello: 'Hello World'
```

### ファイル内でyamlをインポートしつつにmsgid相当を記載

とりあえず普通にsrcしたけど、多分layoutに書くとか、moduleでimportするとかでも行ける模様。

ちなみに `@` は忘れがちですが `srcDir` へのエイリアスですね。

```html
<i18n src="@/locales/ja.yaml"></i18n>
<i18n src="@/locales/en.yaml"></i18n>

<template>
  <section class="section">
    {{ $t('hello') }} <-- こんにちは世界
  </section>
</template>
```

ちなみにこのtemplateではbulmaを使ってますが、まぁそこはあまり大事ではないので大丈夫かなと。

以上。
VS CodeのPHP Intelliphenseがとても心地よくコードを補完してくれる件

[こちらの記事](https://qiita.com/motuo/items/5c9b24606ef75535f882)でもおススメしている`PHP Intelliphense`[参考サイト](https://marketplace.visualstudio.com/itemdetails?itemName=bmewburn.vscode-intelephense-client)ですが、いつの間にか、更に使い勝手がよくなっていました。
折角なので、その素晴らしい動きをご紹介。

## vendor配下も楽々補完
冒頭の記事でも紹介しましたが、vendor配下のClassも楽々補完。
![samlple1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154110/59e3ecb5-f64f-a7fe-7209-0061c4918f98.gif)

## もちろん、Docment commentも綺麗に出してくれる。
![sample2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154110/4f2c8fba-7e2f-9ebb-5585-8c4c81772b93.png)

## 誤った引数を渡したり、返り値の型を誤ると警告してくれる。
PHPと言えども、型はきちんと定義したいですよね。そんなときの強い味方。
![samlple3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154110/0783ec0d-90ab-2905-562a-927410353865.gif)

[PHP Intellisense](https://marketplace.visualstudio.com/itemdetails?itemName=felixfbecker.php-intellisense)、最近は使っていませんがどうなんだろう。。。