OmniAICreator/Qiita-1.07M huggingface dataset:
SQLのCASE式を使って集計する場合のテクニック

## ポイント

- CASE式は、単純にラベルを読み替えているだけではない
- 既存のコード体系を新しい体系に変換して集計することができる
    - 例えば、以下のような都道府県テーブルと、市区町村テーブルがあるが
        - 地方区分、つまり東北地方や東海地方ごとの（人口などの）件数を出したい場合
        - リージョンズ（regions）というモデルを新設するのは手間
            - 集計だけが目的ならその選択肢はない

https://www.apprendrelejaponais.net/japan-cities-postal-sql-data

## 都道府県や市区町村ごとではなく地方ごとに集計したい場合

| 地方 | 件数 |
|--------|-------------|
| 中国     |        10 |
| 中部     |        11 |
| 九州     |         20 |
| 北海道    |         60 |
| 四国     |         92 |
| 東北     |         176 |
| 近畿     |        1700 |
| 関東     |        2001 |

こんなとき case式が役に立ちます

## 実例

```sql
SELECT
	CASE p.name
		WHEN '北海道' THEN '北海道'
		WHEN '青森県' THEN '東北'
		WHEN '岩手県' THEN '東北'
		WHEN '宮城県' THEN '東北'
		WHEN '秋田県' THEN '東北'
		WHEN '山形県' THEN '東北'
		WHEN '福島県' THEN '東北'
		WHEN '東京都' THEN '関東'
		WHEN '茨城県' THEN '関東'
		WHEN '栃木県' THEN '関東'
		WHEN '群馬県' THEN '関東'
		WHEN '埼玉県' THEN '関東'
		WHEN '千葉県' THEN '関東'
		WHEN '神奈川県' THEN '関東'
		WHEN '新潟県' THEN '中部'
		WHEN '富山県' THEN '中部'
		WHEN '石川県' THEN '中部'
		WHEN '福井県' THEN '中部'
		WHEN '山梨県' THEN '中部'
		WHEN '長野県' THEN '中部'
		WHEN '岐阜県' THEN '中部'
		WHEN '静岡県' THEN '中部'
		WHEN '愛知県' THEN '中部'
		WHEN '京都府' THEN '近畿'
		WHEN '大阪府' THEN '近畿'
		WHEN '三重県' THEN '近畿'
		WHEN '兵庫県' THEN '近畿'
		WHEN '滋賀県' THEN '近畿'
		WHEN '奈良県' THEN '近畿'
		WHEN '和歌山県' THEN '近畿'
		WHEN '鳥取県' THEN '中国'
		WHEN '島根県' THEN '中国'
		WHEN '岡山県' THEN '中国'
		WHEN '広島県' THEN '中国'
		WHEN '山口県' THEN '中国'
		WHEN '徳島県' THEN '四国'
		WHEN '香川県' THEN '四国'
		WHEN '愛媛県' THEN '四国'
		WHEN '高知県' THEN '四国'
		WHEN '福岡県' THEN '九州'
		WHEN '佐賀県' THEN '九州'
		WHEN '長崎県' THEN '九州'
		WHEN '大分県' THEN '九州'
		WHEN '熊本県' THEN '九州'
		WHEN '宮崎県' THEN '九州'
		WHEN '鹿児島県' THEN '九州'
		WHEN '沖縄県' THEN '九州'
		ELSE NULL -- ELSE は必ず書く
	END AS region, -- END 忘れずに
	count(s.id)
FROM prefectures AS p

-- 色んなテーブルを紐づけていく
LEFT JOIN cities AS c ON c.prefecture_id = p.id
LEFT JOIN shops AS s ON s.city_id = c.id

-- グループ化
GROUP BY region -- AS つけておくと ２箇所に同じ case文を書く手間がない
```

## 注意点

- 分岐が返すデータ型は統一する
    - エラーにならないので自分で気を付ける
- `END`の書き忘れをしないように。しても構文エラーになる。
- `ELSE`は必ず書く
    - 書かなくてもエラーにはならない、なぜなら暗黙的に `ELSE NULL` 扱いになるから
    - 「エラーにはならないけど結果が違う」原因を探すのに時間かかる可能性があるから
        - 明示的にNULLを返すようにした方が気づきやすい

## 参照

https://www.amazon.co.jp/dp/4798157821/

1-7p

## アウトプット100本ノック実施中

https://qiita.com/ryosuketter/items/713474dbd009870e4103
[JSTQB AL TM]　5. テストプロセスの改善　を視覚的にまとめてみた

# はじめに
2021年8月のJSTQB　Advanced Level Test Manager(TM)の試験を受験予定のMa5am1nです。
[シラバス](http://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TM_Version2012.J04.pdf)[^1]を読んでいるのですが、どうも文字が多くて頭に入りにくいので、図など視覚的に入ってきやすそうな形式でまとめてみます。

[^1]: 2012年度版 Advanced Level シラバス　日本語版　-テストマネージャ
**※あくまで私個人の解釈で作成したものです。内容が100%シラバスの通りであることは保証できませんので、ご了承ください。**
**※スライドの青文字、青線になっている箇所は、シラバスに記載されていない、私独自の解釈で記載した内容です。**

このページでは、5. テストプロセスの改善について扱います。

※2021/8/1　5.5にTPI Nextの「16のキーエリア」を追加

# 5. テストプロセスの改善
## 5.1 イントロダクション
![JSTQB AL TM (42).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/66b984c7-5b1d-c040-308d-e279a696861e.png)

## 5.2 テスト改善プロセス
![JSTQB AL TM (43).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/6c381524-8633-1066-7c69-594994242ac1.png)

### 5.2.1 プロセス改善の紹介
![JSTQB AL TM (44).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/7b19d228-6f79-3290-7fb5-2aa7e2ec86b8.png)

### 5.2.2 プロセス改善のタイプ
![JSTQB AL TM (45).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/2ef206f7-4111-9892-0e5a-e856bbb9f5ca.png)


## 5.3 テストプロセスの改善
![JSTQB AL TM (46).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/7195f760-e9bd-3bb3-560c-344aacfaecc1.png)


## 5.4 TMMi によるテストプロセスの改善
![JSTQB AL TM (47).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/12ffe009-295f-88eb-65f2-07309e27f593.png)


## 5.5 TPI Next によるテストプロセスの改善
![JSTQB AL TM (48).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/95c781e9-5f44-9cd1-fd38-d770152da4e0.png)
![JSTQB AL TM （後半） (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/1a5ddd6a-5924-9e48-f407-be4f02a1cbb3.png)


## 5.6 CTP によるテストプロセスの改善
![JSTQB AL TM (49).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/521225ab-cb52-5d92-f93d-1559f14ea8cb.png)

## 5.7 STEP によるテストプロセスの改善
STEP＝Systematic Test and Evaluation Process
![JSTQB AL TM (50).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/d00107a8-0a7b-0c14-8562-7c45abb8653a.png)
Oracle Cloud のディスクサイズを拡張する

Oracle Cloud の Always Free Resources では最大200GBのディスクが使用できる。

[Always Free Resources](https://docs.oracle.com/en-us/iaas/Content/FreeTier/freetier_topic-Always_Free_Resources.htm)

ディスクサイズは「カスタム・ブート・ボリューム・サイズを指定します」から指定するが、
値に関係なく50GBで認識するので、拡張が必要となる。

# 拡張方法

ルートディレクトリ（`/`）が`/dev/sda3`にマウントされている場合

```shell
growpart /dev/sda 3
pvresize /dev/sda3
```

拡張できるサイズを確認する。

```
$ pvscan
  PV /dev/sda3   VG ocivolume       lvm2 [<98.90 GiB / <53.43 GiB free]
  Total: 1 [<98.90 GiB] / in use: 1 [<98.90 GiB] / in no VG: 0 [0   ]
```

`pvscan`の`free`で表示された値を指定する。

```shell
lvresize -r -L +53G /dev/mapper/ocivolume-root
```

# 参考

 - [ブロック・ボリュームのパーティションの拡張](https://docs.oracle.com/ja-jp/iaas/Content/Block/Tasks/extendingblockpartition.htm#Extending_the_Partition_for_a_Block_Volume)
 - [ボリュームサイズ変更後の Linux ファイルシステムの拡張 - Amazon Elastic Compute Cloud](https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/recognize-expanded-volume-linux.html)
セキュリティ情報のリンクまとめ

セキュリティ情報に関するリンクについてまとめます。

##■セキュリティ情報
https://www.ipa.go.jp/security/

https://www.jpcert.or.jp/

https://www.jc3.or.jp/

https://www.nisc.go.jp/

##■セキュリティ脅威
https://jvndb.jvn.jp/apis/myjvn/mjcheck3.html

https://www.lac.co.jp/solution_product/jlist.html

##■セキュリティ監査・評価
https://www.sysaudit.gr.jp/

https://www.jasa.jp/audit/

https://www.ismap.go.jp/csm

##■セキュリティソフトウェア
http://www.sourcenext.com/product/security/zero-virus-security/?i=rd

https://www.mcafee.com/ja-jp/index.html

https://www.trendmicro.com/ja_jp/business.html

https://www.nortonstore.jp/
データサイエンティスト求人の歓迎スキルを調べてみた

##はじめに
データサイエンスに興味があり、Rを勉強しています。
が、実際のところ、PythonやSQLの求人をよく見るけど、
Rはどのくらい需要があるのだろう？と不安になり（？）

「現場では、データサイエンティストはどのようなスキルを求められているか？」
が気になり、現在の求人を調べてみました。

##調査方法
せっかくなので、Rを用いて
求人サイト掲載中のデータサイエンティスト・データアナリスト求人から、
必須スキル・歓迎スキルを、形態素解析することに。

##データ対象
+ [転職サイトGreen](https://www.green-japan.com/)　76求人（2021年3月2日時点）をお借りしました
+ 応募資格内の、必須スキル・歓迎スキルのテキストを手動抽出
+ 画像解析・システム構築に関する求人は除く

###分析データ
length= 1121文字

##分析の流れ
+ 形態素解析　RMeCab
+ 名詞の洗い出し
+ ワードクラウド可視化

##環境
R version 3.6.1 
Windows10
テキストソフト：windowsのメモ帳
##出力結果
####▼頻度3以上の名詞を可視化
![頻度3以上の名詞を可視化](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510346/a45a653b-15bb-9f93-f6d6-548b6a50c4be.jpeg "図１")
####▼頻度3以上の名詞からスキル要素をピックアップ
![wordcloud_PROGRAM_Freq3.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510346/90f361d5-d9af-11ed-bc3c-6bb578142a09.jpeg "図２")


####▼スキル要素上位15　（表１）
これは手作成

| No | Term | Freq |
|:-----------|------------:|:------------:|
| 1       | Python       | 71         |
| 2     | SQL      | 62       |
| 3       | R        | 49         |
| 4         | BI         | 29           |
| 5       | Web       | 22       |
| 6    | Tableau    | 19      |
|7|AI	|16|
|8|AWS	|15|
|9|GCP	|11|
|10|Google	|10|
|11|BigQuery	|9|
|11|SPSS	|9|
|12|DB	|8|
|12|Kaggle	|8|
|13|Azure	|7|
|14|Analytics	|6|
|14|Hadoop	|6|
|14|SAS	|6|
|15|Excel	|5|
|15|IT	|5|
|15|TensorFlow	|5|




##コード
```R 
library(RMeCab)
library(stringr)
library(dplyr)

#手動抽出したファイルを読み込み、形態素解析
Skill <- RMeCabFreq("skill.txt")


Skill$Term	<-
str_replace_all(Skill$Term, "【.*?】", "")	%>%	# 【】で括られた見出しを削除
str_replace_all(., "［.*?］", "") %>%	# ［］で括られた見出しを削除
str_replace_all(., "《.*?》", "") %>%	# 《》で括られた見出しを削除
str_replace_all(., "<.*?>", "") %>%	# <>で括られた見出しを削除
str_replace_all(., "≪.*?≫", "")%>%	# ≪≫で括られた見出しを削除
str_replace_all(., "[0-9]", "")%>% 	#単独の数字
str_replace_all(., "\n", "")%>%	#改行
str_replace_all(., "[:punct:]", "")	#句読点

write.csv(Skill, "Skill_01.csv")	#念のためreplaceしたテキストを保存

#名詞の洗い出し
Skill_r1 <- filter(Skill,Info1 == "名詞") %>%
  filter(., Info2 == "一般" |  Info2 == "固有名詞") %>%
  select(., -c(Info1, Info2))

================================================
#頻度3以上の名詞を可視化 （図１）

library(ggplot2)
library(wordcloud)

wordcloud(Skill_r1$Term, Skill_r1$Freq, 
scale =c(7, 1),  min.freq = 3, random.order = FALSE,
   random.color = TRUE, colors = brewer.pal(8, "Dark2"))


==================================
#さらにスキル要素の名詞をピックアップする

#書き出した"Skill_01.csv"ファイルを手作業で編集する
#編集したファイル名　「Skill_03.csv」
Skill_r2 <- read.csv("Skill_03.csv",header=T,row.names=1)


#頻度3以上、スキル要素の名詞を可視化（図２）
wordcloud(Skill_r2$Term, Skill_r2$Freq, 
scale =c(7, 1),  min.freq = 3, random.order = FALSE,
   random.color = TRUE, colors = brewer.pal(8, "Dark2"))

```
##補足
「スキル要素」は手作業で、スキルや機能などのワードをピックアップ
（ただちに求人の歓迎スキルと関連のないワードも含んでいます）

##おわりに
頻度結果をみると、やはり、
Python
そして
SQL
が上位に。
Rも上位で安心（？）
意外だったのは
Tableau
やはりツールを用いるのかな

###改善点
・抽出データ、またスキル関係の名詞は手作業
・ピックアップしたスキル関係の名詞も曖昧
・前処理ももっとかっこよく（？）

改善点をふまえて、また出直します！
[シリーズ] docker-composeを活用して即座にGitLabを立てて使ってみる

# はじめに

docker-compose を活用して GitLab を立て上げて、GitLab を使ってみたときの記録です.

|コンテンツ|
|:--|
|[[01] docker-composeを活用して即座にGitLabを立てて使ってみる ... GitLab立ち上げまで](https://qiita.com/robozushi10/items/6ea798fd8f9863ef5439)|
|[[02] docker-composeを活用して即座にGitLabを立てて使ってみる ... git clone 〜 push をする](https://qiita.com/robozushi10/items/1b820fb0b7f30799462f)|
|[[03] docker-composeを活用して即座にGitLabを立てて使ってみる ... Git LFS を使う](https://qiita.com/robozushi10/items/ba55385356707404172e)|
|[[04] docker-composeを活用して即座にGitLabを立てて使ってみる ... PlantUML を使う](https://qiita.com/robozushi10/items/253750ac16e9712dab8c)|
[シリーズ] docker-composeを活用して即座にJenkinsを立てて使ってみる [JNLP通信]

# はじめに

docker-compose を活用して Jenkins を立て上げて、Jenkins を使ってみたときの記録です.
Master - Slave 間の通信は JNLP です.

|コンテンツ|
|:--|
|[[01] docker-composeを活用して即座にJenkinsを立てて使ってみる ... 1マスタ、1スレーブ構成](https://qiita.com/robozushi10/items/5d98d0fce0ab22e4850c)|
|[[02] docker-composeを活用して即座にJenkinsを立てて使ってみる ... 1マスタ、3スレーブ](https://qiita.com/robozushi10/items/f6ff1aade15ab2bd06a1)|
|[[03] docker-composeを活用して即座にJenkinsを立てて使ってみる ... WindowsPC を Slave として登録する](https://qiita.com/robozushi10/items/328635e79fd0a6ae7b47)|
Laravelアプリをロリポップへ設置した

laravel6のwebアプリをロリポップ スタンダードプランで動かしたときに結構時間かかったのでメモを残す。

##作業環境
Win10 home
Laravel 6.20
PHP 7.4
MariaDB 10.6

##SSHでロリポップへ接続
ロリポップの管理画面からSSHでの接続情報を入手して入力する。
（Git Bashを使用したが、PowerShellなどでも同じだと思う）

:::note info
ssh (アカウント)@(サーバー) -p(接続ポート)
:::

```:入力例
ssh abcde-123456789@abc.lolipop.jp -p1234
```

次にパスワードを聞かれる。
自動生成された30文字くらいの文字列なので間違えないよう慎重に入力する。
（パスワードは入力しても何も表示されないので何文字入力したかもわからない）
正しいパスワードを入力すると下記のように表示される。

:::note info
[(アカウント)@(サーバー番号) ~]$
:::

```:表示例
[abcde-123456789@abc123 ~]$
```

##PHPのパスを通す
この時点ではパスが通っておらず`php -v`を実行してもPHPのヴァージョンを確認できない。

```bash:PHPのパスを通す
$ export PATH="$PATH:/usr/local/php/7.4/bin"
```

上記を実行することで`php -v`が通るようになる。
ただ、このままでは毎回パスを通さないといけなくて面倒なので、.bash_profileファイルを作成する。

```bash:.bash_profileを作成しviで開く
$ vi ~/.bash_profile
```

viコマンドで.bash_profileを開いたら、「i」キーを押して「挿入」モードにする。

```bash:.bash_profileへ下記を記入
PATH="$PATH:/usr/local/php/7.4/bin"
```

上記を入力して「esc」キーを押して`:wq`で保存する。
これで今後もパスが通った状態となる。

##Composerをインストールする
下記コマンドを実行してwebディレクトリへ移動。

```bash:webディレクトリへ移動
$ cd web
```

ここに下記を実行してcomposerをインストールする。

```bash:composerをインストール
$ /usr/local/php/7.4/bin/php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"
```

インストールしたら一応`composer -v`を実行してcomposerがインストールされているか確認する。

##FTP接続してファイルを転送する
今回設置するWebアプリはGitHubなどに上げていないのでFTPで転送する。

Windows10のエクスプローラーを起動して、アドレスバーにロリポップのFTPサーバーアドレスを入力。
（パスワードなどのFTPサーバー情報は、ロリポップの管理画面から`ユーザー設定 → アカウント情報`で入手する。FTPサーバーアドレスは`WebDAV`の欄に記載されている）
WebDAVのアカウントとパスワードを入力して接続する。
任意のディレクトリを作成しそこへ必要なファイルを転送。
`.git`、`node_modules`、`vendor`の3ディレクトリ以外は全ファイルを転送した。
今回は`.env`ファイルも転送したが、データベースの接続情報は開発環境のままなので、エディタでロリポップのデータベース用に内容修正。

##composer updateを実行
SSH接続しているGitBashに戻り、`composer update`を実行したがエラーで停止してしまった。

```bash:composerUpdateを実行
$ composer update
```

下記のようなエラーが出た。

```bash:エラー内容
Loading composer repositories with package information
Warning from https://repo.packagist.org: Support for Composer 1 is deprecated and some packages will not be available. You should upgrade to Composer 2. See https://blog.packagist.com/deprecating-composer-1-support/
Updating dependencies (including require-dev)

mmap() failed: [12] Cannot allocate memory

mmap() failed: [12] Cannot allocate memory
PHP Fatal error:  Out of memory (allocated 679682048) (tried to allocate 8592000 bytes) in phar:///usr/local/bin/composer/src/Composer/Util/RemoteFilesystem.php on line 462

Fatal error: Out of memory (allocated 679682048) (tried to allocate 8592000 bytes) in phar:///usr/local/bin/composer/src/Composer/Util/RemoteFilesystem.php on line 462
```

メモリが足らんということらしいので、エラー内容から検索して下記を実行。

```bash:composerUpdateでメモリ不足を解消したコマンド
$ php -d memory_limit=-1 ../composer.phar install
```

上記コマンドを実行すると、composer updateが再開し無事終了。
ログイン画面を表示することができた。

##参考サイト
今回はいろいろ調べ回りましたが、主に下記2サイト様を参考にさせていただきました。
非常に助かりました。ありがとうございました。

https://zenn.dev/bardothodol/articles/2ef4048fefb0ee

https://uiuifree.com/blog/develop/php-composer-install-memory-limit/
BitbucketでCI/CDを設定する

## 概要
Bitbucket pipelineを使ってCI/CDを設定します。
今回はReactのアプリケーションの場合、どのように設定するかをご紹介します。
設定方法が分かれば、他の言語を使ったアプリケーションでも応用が効きます。

# bitbucket pipelinesを有効にする。
Repository settingsからpipelinesのSettingsを選択して、有効にします。
![スクリーンショット 2021-07-25 15.40.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243749/6fdeba5b-17e0-a6d2-0500-09379716c3bc.png)


# bitbucket-pipelines.ymlを設定する
設定したいリポジトリのホームディレクトリにbitbucket-pipelines.ymlを設定します。
以下は、最低限の設定を記載しました。必要に応じて追加してください。

```home/bitbucket-pipelines.yml
pipelines:
  default:
    - step:
        caches:
          - node
          - pip
        script:
          - npm install
          - npm test
  branches:
    develop:
      - step:
          script:
            - apt-get update
            - ssh ec2-user@0.0.0.0 /var/www/home/scripts/devCdScript.sh
    staging:
      - step:
          script:
            - apt-get update
            - ssh ec2-user@0.0.0.0 /var/www/home/scripts/stgCdScript.sh
    master:
      - step:
          script:
            - apt-get update
            - ssh ec2-user@0.0.0.0 /var/www/home/scripts/prodCdScript.sh

```

一つ一つ解説して行きます。
どのブランチにマージしたかに関わらず、defaultの部分は、scriptが毎回実行されます。
なので、この部分にはテストコードなど品質を担保するためのscriptを追加すると良いです。
JavaScriptのflowなどを入れても良いと思います。
一方で、branches以下はブランチ名によって、実行されるscriptが異なります。
例えば、developブランチにプルリクエストをマージする場合、defaultとdevelopのscriptが実行されます。

ssh ec2-user@以降のIPアドレスは適宜変更してください。
homeとなっている部分もディレクトリ名を適宜変更してください。

.shファイルは各環境毎に一つずつ用意します。
デプロイ時に実行したいスクリプトをここに書きます。

```home/scripts/devCdScript.sh
#!/bin/bash

cd /var/www/home

git pull;

if [ $? -eq 0 ]; then
  echo 'git pull success.'
else
  echo 'git pull failure.'
  exit 1;
fi

npm install;
npm run build;
```

# SSH keyの設定
Repository settingsからSSH keysを選択し、SSH keyの設定ができます。
Generate keysを選択すると公開鍵と秘密鍵を作成できます。
![スクリーンショット 2021-07-25 15.49.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243749/7362c970-d91c-da40-ffa1-87c52e5ba6ff.png)

作成した公開鍵をサーバーに設定します。
EC2の場合、以下のファイルにコピーした公開鍵を貼り付けます。
/home/ec2-user/.ssh/authorized_keys

Repository settings → SSH keysからKnown hostsを設定します。
設定したいサーバーのIPアドレスを入力して、Fetchを選択。

ここまで設定したら、プルリクエストを対象のブランチにマージした際にpipelineが動くと思います。
なお、pipeline実行時にpermission errorでfailedになった場合は、devCdScript.shなどのスクリプトファイルの権限を変更してみて下さい。

・参考
https://ja.confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html
Rails API時のルーティング[メモ]

RailsでAPIサーバを立てるとき、ルーティングとコントローラーの紐付けに悩むことがあったので備忘録

ルーティングについては以下のサイトが参考になりました。
https://techracho.bpsinc.jp/baba/2020_11_20/15619

このようなルーティング時、
URIはどのようになるか
コントローラはどうなるか

```
Rails.application.routes.draw do
  get 'transfer/index'
  namespace 'api' do
    namespace :v1 do
      mount_devise_token_auth_for 'User', at: 'auth'
    end
    namespace 'users' do
      resources :tickets, only: [:index] do
        member do
          resources :transfer, only: [:index]
        end
      end
    end
end
  # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html
end
```

namespaceがある時のURIは以下のようになりました
[:id]の部分はmemberによって作成されています。不要であればcollectionを使用します。

```
/api/users/tickets/:id/transfer(.:format)	
```


コントローラーは以下でした。

```
api/users/transfer#index
```

コントローラーのフォルダは以下に作成します。

```
app/controllers/api/users/transfer_controller.rb
```

transfer_controller.rbファイルの中身は以下です。
Api::Users::をつけています。

```
class Api::Users::TransferController < ApplicationController
  def index
    render json: {test: 'test'}
  end
end
```
Power BIの日付テーブル作成メモ

## はじめに
　Power BIの基本的なことである日付テーブルの作成についてのメモです。日付テーブルは、カレンダーテーブルとも呼ばれます。
英語コンテンツでは、date table または calendar table 等と呼ばれています。

## 日付テーブルの要件
 [Docs : Power BI Desktop で日付テーブルを作成する](https://docs.microsoft.com/ja-jp/power-bi/guidance/model-date-tables)より、日付テーブルには要件があり以下です。

- "日付列" と呼ばれるデータ型 date (または date/time ) の列が必要
- 日付列には**一意**の値が含まれている必要
- 日付列に空白を含めることはできない。
- 日付列に欠落している日付があってはならない。
- 日付列は年間全体にわたっている必要がある。1 年は必ずしも暦年 (1 月から 12 月) である必要はなく、4月から翌年3月でもよい。
- 日付テーブルには日付テーブルとしてマークされている必要がある。

## DAXでの日付テーブルの例

計算テーブル（新しいテーブル）で作成する例です。[CALENDARAUTO関数](https://dax.guide/calendarauto/)を使っているので、ディメンションテーブルで古い日付を持っている場合などは適時書き換え等を行ったほうがよいです。

``` text:日付テーブル（カレンダーテーブル）の例
Dates = 
// テーブル名は「Dates」
// (方法1) CALENDARAUTO。データモデルのテーブルに日付があるとき、範囲が無駄に広くならないか要注意
var BaseCalendar = CALENDARAUTO()
// (方法2) 以下のように決め打ちの日付指定またはファクトテーブルに含まる日付持ってくる等
// var BaseCalendar = CALENDAR(DATE (2020, 1, 1), DATE (2021, 12, 31))
RETURN
GENERATE(
    BaseCalendar,
    var BaseDate = [Date]
    var YearNumber = YEAR(BaseDate)
    var MonthNumber = MONTH(BaseDate)
    var DateNumber = DAY(BaseDate)
    var DayNumber = WEEKDAY(BaseDate, 1)
    RETURN
    ROW(
        "年", YearNumber,
        "月", MonthNumber,
        "日", DateNumber,
        "年月_番号", FORMAT(BaseDate, "yyyymm"),
        "年月", FORMAT(BaseDate, "yyyy/mm"),
        "月日_番号", FORMAT(BaseDate, "yyyymmdd"),
        "月日", FORMAT(BaseDate, "mm/dd"),
        "曜日_番号", DayNumber,
        "曜日", SWITCH(DayNumber, 1, "日", 2, "月", 3, "火", 4, "水", 5, "木", 6, "金", 7, "土",""),
        "相対月数", DATEDIFF(TODAY(), BaseDate, MONTH)
    )
)
```

## 日付テーブルに関数する関連ページ

by Docs, Learn

https://docs.microsoft.com/ja-jp/power-bi/guidance/model-date-tables?WT.mc_id=DP-MVP-5004418

https://docs.microsoft.com/ja-jp/learn/modules/design-model-power-bi/3-date-table?WT.mc_id=DP-MVP-5004418

https://docs.microsoft.com/ja-jp/power-bi/transform-model/desktop-auto-date-time?WT.mc_id=DP-MVP-5004418

https://docs.microsoft.com/ja-jp/power-bi/guidance/auto-date-time

↑「Power BI Desktop の自動の日付/時刻」既定の自動で作るとどうなるか.. (私は設定2か所オフにしています）

自動で作られた日付テーブルはDAX Studio等で確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/8448318c-fbc4-4d78-585d-e195b3474922.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/419691/095a56b5-2242-624a-46c9-6b8075257232.png)


by [かたがさん](https://qiita.com/PowerBIxyz/)

https://qiita.com/PowerBIxyz/items/375573ebe78a48b6d7de

https://qiita.com/PowerBIxyz/items/924893764e6fdce30f92

https://qiita.com/PowerBIxyz/items/4b2b17a091bf7e8bfec6

https://qiita.com/PowerBIxyz/items/29b8662481577689a36d

https://qiita.com/PowerBIxyz/items/41b71651f9ddb9a16419

by [y-komuroさん](https://qiita.com/y-komuro)

https://qiita.com/y-komuro/items/de3e2cb3dea129260079
utf8とutf8mb4の違い

utf8
・簡単に言うと絵文字が使えない
・Unicodeに対応している
①アルファベット、数字、記号などの基本的な文字を表すASCIIコード
②世界中のあらゆる文字（例えばハングル文字やアラビア文字など）を加えた文字の集合体
→これらのことを指す
・世界中に普及している

utf8mb4
・絵文字が使える
・MySQLで扱うための文字コード

---

アプリ作成時に以下のコマンドを入力すると

```
% rails new アプリ名 -d mysql
```

以下のように、デフォルトでdatabase.ymlに「utf8mb4」が記載されている。


例）database.yml

```
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
```

utf8を使いたかったら上から三段目を変えれば良い。

```
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  socket: /tmp/mysql.sock
```

以上です。

---

おまけ
僕のTwitter：https://twitter.com/honaki_days?s=21
MongoDBのIndexの種類

MongoDBのインデックスには下記の種類があります。

| インデックスの種類 | Ver. 3.6 | Ver. 4.0 | Ver. 4.2 | Ver. 4.4 | Ver. 5.0 |
|:-------------------------------------------|:-:|:-:|:-:|:-:|:-:|
|単一フィールド(Single Field Indexes)        | ○ | ○ | ○ | ○ | ○ |
|複合インデックス(Compound Indexes)          | ○ | ○ | ○ | ○ | ○ |
|複数キーインデックス(Multikey Indexes)      | ○ | ○ | ○ | ○ | ○ |
|テキストインデックス(Text Indexes)          | ○ | ○ | ○ | ○ | ○ |
|ワイルドカードインデックス(Wildcard Indexes)| -  | -  | ○ | ○ | ○ |
|地理空間のインデックス(Geospatial Indexes)  | ○ | ○ | ○ | ○ | ○ |
|ハッシュインデックス(Hashed Indexes)        | ○ | ○ | ○ | ○ | ○ |


複合インデックスに含めることができるフィールドは、最大31個です。
また、ハッシュインデックスを含めることはできません。


地理空間のインデックス(Geospatial Indexes)には下記があります。

+ 平面上(2d Indexes)
+ 地球面上(2dsphere Indexes)
+ 狭いエリア用(geoHaystack Indexes)


MONGODB MANUAL / Index Types
[Version 3.6](https://docs.mongodb.com/v3.6/indexes/#index-types) / [Version 4.0](https://docs.mongodb.com/v4.0/indexes/#index-types) / [Version 4.2](https://docs.mongodb.com/v4.2/indexes/#index-types) /  [Version 4.4](https://docs.mongodb.com/v4.4/indexes/#index-types) / [Version 5.0](https://docs.mongodb.com/v5.0/indexes/#index-types)

参照させていただいたサイト：
[Azure Cosmos DB の MongoDB 用 API でのインデックス作成を管理する](https://github.com/MicrosoftDocs/azure-docs.ja-jp/blob/master/articles/cosmos-db/mongodb-indexing.md)
[MongoDB で インデックス を 適用する 方法](https://garafu.blogspot.com/2017/12/mongodb-create-index.html)
【第8章】Railsチュートリアルでハッシュとシンボルについて忘れていたので復習した

[Railsチュートリアル第8章(第6版)](https://railstutorial.jp/chapters/basic_login?version=6.0#cha-basic_login)でハッシュとシンボルを忘れていたので、復習した。

#①ハッシュとは
・基本的には配列と同じだが、インデックスとして整数値以外のものを使える。
・キーと値のペアを波カッコで囲んで表記する。
・ハッシュでは要素の並び順が保障されない。
・JavaでいうMapだと思っている。

```
>> user = {}                          # {}は空のハッシュ
=> {}
>> user["first_name"] = "Pai"     # キーが "first_name" で値が "Pai"
=> "Pai"
>> user["last_name"] = "Abble"        # キーが "last_name" で値が "Abble"
=> "Abble"
>> user["first_name"]                 # 要素へのアクセスは配列の場合と似ている
=> "Pai"
```
#②省略1
ハッシュの1要素を角カッコを使って定義する代わりに、```=>```(ハッシュロケット)を使ってリテラル表記する方が簡単。

```
>> user = { "first_name" => "Pai", "last_name" => "Abble" }
=> {"last_name"=>"Abble", "first_name"=>"Pai"}
```
#③省略2 -シンボル-
・Railsではハッシュのキーとして、文字列よりもシンボルを使うのが普通。
・シンボルはクォートで囲む代わりにコロンを前に置く。
・文字列と違って全ての文字が使えるわけではない。(一般的なアルファベットを使うかぎりは問題ないらしい)
・Ruby以外ではごく一部の言語にしか採用されていない特殊なデータ形式。

```
>> "name"                            #文字列
=> "name"
>> :name                             #シンボル
=> :name                             
>> :foo-bar　　　　　　　　　　　　　　#使えない文字
NameError: undefined local variable or method `bar' for main:Object
>> :2foo                             #使えない文字
SyntaxError
```
ハッシュのキーにシンボルを採用する場合の```user```

```
>> user = { :first_name => "Pai", :last_name => "Abble" }
=> {:last_name =>"Abble", :first_name =>"Pai"}
```

#④省略3
ハッシュではシンボルをキーとして扱うことが一般的なので、Ruby1.9からは新しい記法がサポートされた。
・シンボルとハッシュロケットの組み合わせを、キーの名前の前ではなく後にコロンを置き、その後に値が続くように置き換えることが出来る。

```
>> user = { first_name: "Pai", last_name: "Abble" }
=> {:last_name =>"Abble", :first_name =>"Pai"}
```

#⑤まとめ
①~④で忘れていた箇所を思い出せた。
pyautoguiでChromeを立ち上げて検索を行う

## 概要
使った事がないpyautoguiを試しに使ってみるために、実用性は皆無なコードを作成して遊んでみる

## 仕様
・タスクバーにあるGoogle Chromeをクリックして、ブラウザを立ち上げた後に「オリンピック」という文字を検索窓に入力して検索する。
・Google Chromeはタスクバーにピン止めしてある前提
・マルチディスプレイには非対応
・Google Chromeのアイコンの場所、検索窓の場所は画像認識（保存画像とディスプレイ上の画像の比較）で行う

## 事前準備
pyautoguiをインストール

```
pip install pyautogui
```

画像処理ライブラリPillowをインストール

```
pip install Pillow
```
OpenCVをインストール

```
pip install opencv-python
pip install opencv-contrib-python
```
画像認識用の画像を事前に準備する。
Windowsの場合は、［Windows］＋［Shift］＋［S］キーで画像を切り取って保存するのがおすすめです。

今回は以下の２つの画像を準備しています。
chrome.png
![chrome.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1499277/fdf8ab09-8c8e-dbd8-5a11-b2dc60f4caf1.png)

search.png
![search.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1499277/654b8f37-5128-5b88-2965-47d6ff228d00.png)

## コード
```python
#使用するモジュールをインポート
import pyautogui as pa
import pyperclip
import time

#タスクバーにあるGoogle Chromeを画像認識で座標取得
position = pa.locateOnScreen("chrome.png", confidence=0.8)#confidenceが低いほど曖昧マッチング

#画像認識した座標をダブルクリック
pa.doubleClick(position)

#ブラウザが開ききるまで
time.sleep(1)

#ブラウザ画面を最大化しとかないと何故かうまくいかなかったので、画面を最大化しておく
pa.hotkey("win", "up")

#ブラウザの検索窓を画像認識で取得
search_pos = pa.locateOnScreen("search.PNG", confidence=0.1) # 特徴的な画像ではないのでconfidenceを低くしないとうまくマッチングしない
pa.click(search_pos)

#「オリンピック」という文字列を検索窓に入力
pyperclip.copy("オリンピック")
pa.hotkey("ctrl", "v")

#エンターキーを押して検索を実行
pa.press("enter")
```
brew doctorをするとコマンドツールが古いとWARNINGが出た時の対処

# 状況と原因
・brew doctorの照会をすると以下の<font color="Red">**WARNING**</font>がが続出した。(当然のことながら、brewのupdateとupgradeは行った上でのこと。)
・ brew configでシステム構成を確認したところ、原因は<font color="Blue">***CLT と Xcodeのバージョンが一致していない***</font>ことらしいので、doctorの指示に従って　
   https://developer.apple.com/download/more/.
から Xcode12.5用のコマンドラインツールをダウンロードしてみたところ表示が消えた。


>_ちなみに、私の場合これを行う前にdoctorの指示にある
	softwareupdate --all --install —force
並びに
	sudo rm -rf / Library / Developer / CommandLineTools
   	sudo xcode-select —install
を先に行ったが、softwareupdateでは変化なく、ターミナルからのsudo rm -rf行ったところ時間がかかった挙句、システム復元が必要になった。_

「WARNINGの表示の一部」

```
hogehogeiMac ~ % brew doctor
Warning: Your Command Line Tools are too outdated.
Update them from Software Update in System Preferences or run:
  softwareupdate --all --install --force

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/more/.
You should download the Command Line Tools for Xcode 12.5

※ちなみに"hogehoge"は私の名前を隠しています。
```

これをgoogle翻訳すると
>警告：コマンドラインツールが古すぎます。
システム環境設定のソフトウェアアップデートから更新するか、以下を実行します。
   softwareupdate --all --install --force

>それでも更新が表示されない場合は、次を実行します。
   sudo rm -rf / Library / Developer / CommandLineTools
   sudo xcode-select --install

>または、次の場所から手動でダウンロードします。
   https://developer.apple.com/download/more/.
Xcode12.5用のコマンドラインツールをダウンロードする必要があります。(Google翻訳）

という意味らしい。

この他に後２件以下のWARNINGが表示された。

```
WARNING: A newer Command Line Tools release is available.
	(警告：新しいコマンドラインツールリリースが利用可能です。)
```

```
WARNING: Your Command Line Tools (CLT) does not support macOS 11.
	(警告：コマンドラインツール（CLT）はmacOS11をサポートしていません。古くなっているか、変更されています)。
```


# 対処
①brew configでシステム構成を確認

```
hogehogeiMac ~ % brew config
HOMEBREW_VERSION: 3.2.3
ORIGIN: https://github.com/Homebrew/brew
〜〜省略〜〜
macOS: 11.5-x86_64
CLT: 11.3.0.32.62		<—Xcodeのバージョンとアンマッチの状態になっている
Xcode: 12.5.1

```
②下記HPへappleIDでサインインして、Xcodeと同じバージョンのコマンドラインツールをインストール（今回は：Command Line Tools for Xcode 12.5.1.dmg を選択してインストールした）
	https://developer.apple.com/download/more/.
（WARNINGの中で指示あり）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634708/f08c6974-4006-e159-ab95-022b0b1c3fe0.png" alt="スクリーンショット 2021-07-26 11.18.16.png" width="600" height=“200">


③ダウンロードしたコマンドラインツールのdmgを解凍後インストール


# 確認
brew configを実施してCLTとXcodeが一致していることを確認

```
hogehogeiMac ~ % brew config
HOMEBREW_VERSION: 3.2.3
ORIGIN: https://github.com/Homebrew/brew
〜〜省略〜〜
macOS: 11.5-x86_64
CLT: 12.5.1.0.1.1623191612			<—一致した!!
Xcode: 12.5.1

```

brew doctorを実施してみるとwarningが消えていた。

```
hogehogeiMac ~ % brew doctor
Your system is ready to brew.

システムを作成する準備ができました(google翻訳)
```
私は、この方法で正常に戻りましたが、飽くまで自己責任の下でお願いします。

参考にしたHP：　https://code-graffiti.com/big-sur-and-homebrew-warning/
MacをBig SurにするとHomebrewでCLTについてのWarningが出ることへの対処法
PythonでPLINKの主成分分析結果を可視化する方法

PLINKの---pcaコマンドで主成分分析を実施すると、
1．output.eigenvec
2．output.eigenval
という2つのファイルが出力されます。
<br>



今回はこれらの2つのファイルを使用して、主成分分析の結果を可視化します。

<br><br>

####①Pythonで必要なライブラリをインポート

```python
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import japanize_matplotlib
```

<br><br>
####②データの読み込み

pandasのread_csvで、2ファイルを読み込みます。

.eigenvalの値から、PC1とPC2がどれだけの割合を説明できるのかを計算します。

ついでに、今回の主成分分析で使用したSNP数も.mapファイルから計算しておきます。
<br><br>

```python
#データの読み込み
df = pd.read_csv('output.eigenvec', sep=' ', header=None)

#PC1とPC2の説明量を計算する
PC = pd.read_csv('output.eigenval', sep=' ', header=None)
su = PC[0].sum()

p1 = PC.iloc[0, 0] 
PC1 =  p1 / su * 100

p2 = PC.iloc[1, 0] 
PC2 =  p2 / su * 100

#SNP数を計算する
ma = pd.read_csv('output.map', sep=' ', header=None)
snp = len(ma)
```

<br><br>

####③PCAプロットの作成

先ほど計算した、SNP数や説明量をグラフに反映させました。

```python
sns.set(font='Yu Gothic', context="talk", style='ticks')
plt.figure(figsize=(12,8))

sns.scatterplot(x=2, y=3, data=df, s=100)

plt.title("PCA Plot【%i SNPs】" %snp, fontweight="bold")
plt.xlabel('PC1 (%i ％)' %PC1)
plt.ylabel('PC2 (%i ％)' %PC2)

plt.savefig('Output.png') #PNGで画像を保存
```
![Output.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1801118/db2c2820-b5d0-3490-58db-c9c6777d4326.png)

集団が複数ある場合などは、sns.scatterplotのhueで色分けも行えます。

<br>


##全体
```python
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import japanize_matplotlib

#データの読み込み
df = pd.read_csv('output.eigenvec', sep=' ', header=None)

#PC1とPC2の説明量を計算する
PC = pd.read_csv('output.eigenval', sep=' ', header=None)
su = PC[0].sum()

p1 = PC.iloc[0, 0] 
PC1 =  p1 / su * 100

p2 = PC.iloc[1, 0] 
PC2 =  p2 / su * 100

#SNP数を計算する
ma = pd.read_csv('output.map', sep=' ', header=None)
snp = len(ma)

sns.set(font='Yu Gothic', context="talk", style='ticks')
plt.figure(figsize=(12,8))

sns.scatterplot(x=2, y=3, data=df, s=100)

plt.title("PCA Plot【%i SNPs】" %snp, fontweight="bold")
plt.xlabel('PC1 (%i ％)' %PC1)
plt.ylabel('PC2 (%i ％)' %PC2)

plt.savefig('Output.png') #PNGで画像を保存
```


以上、PLINKの主成分分析の結果からPCAプロットを作成する方法でした。
【yarn】特定のworkspaceにライブラリをインストールする

## はじめに

ルートではなく、特定のworkspaceだけにライブラリをインストールする方法についてです。
意外と記事が見つからなかったので残しておきます！
（公式に書いてありましたがw）

## コマンド

```
yarn workspace <workspace名> add <ライブラリ名>
```

例として、my_workspaceにだけaxiosをインストールしたい場合は、以下になります。
 
```
yarn workspace my_workspace add axios
```

## 参考
公式に普通に書いてありました(汗;
[yarn workspace](https://classic.yarnpkg.com/en/docs/cli/workspace/)
Wio LTE for Arduino で水分センサを使う

Wio LTE for Arduino で水分センサを使う方法です。
水分センサの Grove を A4 に接続します。

```text:moisture/moisture.ino
#include <WioLTEforArduino.h>
WioLTE Wio;
#define console SerialUSB

void setup() {
  delay(300);
  console.println("");
  console.println("*** moisture *** Jul/25/2021 PM 14:27");
  Wio.Init();
  Wio.PowerSupplyGrove(true);

  pinMode(WIOLTE_A4, INPUT_ANALOG);
}

void loop() {
  int moisture = analogRead(WIOLTE_A4);
  console.println("moisture = " + String(moisture));
  console.println("*** check PM 14:27 ***");

  delay(1500);
}
```

実行結果
![moisture_arduino.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/095eea27-38f3-3bf7-e346-16d80091feac.png)
myCobot Piの動作確認

# はじめに
先日から気になっていた myCobot Pi を購入しました。
早速動作確認を・・・と思ったのですが、世の中の情報はほとんどオリジナルのmyCobotのものばかりで、myCobot Piでさくっと動作確認するための情報がなかなか見つからず。
OSの言語設定も中国語がデフォルトだったりするので、きっとまた忘れてしまう将来の自分のために、備忘録としてハードウェアの動作確認を行うまでの手順をまとめておきたいと思います。

# SDカードのバックアップ

設定変更などで何度壊すか予想できないので、事前にSDカードのイメージをバックアップしました。
以下は手元のMacbook ProにSDカードリーダーをUSB接続して、実行したときのもの。

```
# このコマンドでSDカードがマウントされているパスを確認 ( 私の環境では /dev/disk2 )
% diskutil list

# このコマンドでSDカードをアンマウント
% diskutil umountDisk /dev/disk2

# このコマンドでバックアップ
% sudo dd if=/dev/disk2 of=mycobotpi.img bs=1m
```

```
# このコマンドでリストア
% sudo dd of=/dev/disk2 if=mycobotpi.img bs=1m
```

# Rasberry Pi OS環境の設定
付属のMicroSDカードには、既にRaspberry Piで動作するOS環境が焼きこまれていますが、デフォルトのロケールが中国語になっていたりして使いにくいので、最初にこれを修正しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/7f40e23a-0cd3-4f2c-8871-d6de3138582e.png)
左上のメニューから "Raspberry Pi Configuration" を選択し、Localisationタブの中身を編集します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/944dc1b2-3004-abe3-309b-deae60360851.png)

## Locale
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/215491e9-fe0b-cad5-1cb6-e1e3df78b30b.png)

## TimeZone
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/12fd6955-2427-c69a-993d-db0b8e45887f.png)

## Keyboard
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/b0d2fb79-7654-6d8c-e663-354a57d8f7ee.png)
キーボードはお持ちのものに合わせてお好みで。

## Wifi Country Code
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/b60f1b13-b798-6e42-6d49-aeff96fca099.png)

全ての変更が終わってリブートすると、日本語環境で立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/cb4b05e2-fb5b-5ab1-8d95-bd0564397b50.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/d6f94dc7-3b55-cbc3-48b3-334b2be919e3.png)

# 動作確認
デスクトップの myblockly アイコンをダブルクリックして起動します。
今のところ、命令の意味は全く分かっていないですが、とりあえずこの内容を記載して、右上の「运行」という緑色のアイコンをクリックすると、myCobot PiのLEDが赤く点灯して直立します。（実際にサーボが動くとちょっと感動）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/d936c71e-b8f2-a94e-a2fd-0b4b1984f2e7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46402/6197ff1e-feaf-1aa3-3d1a-64b33e01f75f.png)


# What's Next?
今度はROSを動かしてみたいところですが。
デフォルトでパスが通っていて roscore が動作するところまでは分かったんですが rviz などのツールも Raspberry Pi上で動作するのか、別に Ubuntu 環境を用意する必要があるのか、などは分かっておらず。
まだまだ先は長そうです・・・。
Wio LTE for Arduino で光センサを使う

Wio LTE for Arduino で光センサを使う方法です。
次のページを参考にしました。
[IoTでテレビのON/OFFをモニタリング](https://soracom.jp/recipes_index/4030/)
光センサの Grove は A6 に接続します。

```text:light_monitor/light_monitor.ino
#include <WioLTEforArduino.h>
WioLTE Wio;
#define console SerialUSB

void setup() {
  delay(3000);
  console.println("");
  console.println("*** START *** Jul/25/2021 PM 14:04");
  Wio.Init();
  Wio.PowerSupplyGrove(true);

  pinMode(WIOLTE_A6, INPUT_ANALOG);
}

void loop() {
  int val = analogRead(WIOLTE_A6);
  console.println("val = " + String(val));
  console.println("*** check PM 14:04 ***");

  delay(1500);
}
```

実行結果
![arduino_light.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/62180873-9360-2548-7410-b5821e0ecaf5.png)
M5StickCをWebSocketで操作するBLEセントラルデバイスにする

M5StickCを、BLEデバイスに任意の操作が可能なBLEセントラルデバイスにし、WebSocketサーバとして、ブラウザのJavascriptやNode.jsからつなげられるようにします。

本投稿は、以下の目的で整理したものです。
・ESP32でのBLEセントラルのひな型にする。
・ESP32でのWebSocketサーバのひな型にする。
・ESP32でのBLEデバイスのひな型にする。
・ブラウザからM5StickCに接続してBLEデバイスに任意の操作をする。

ひな型として、ソースコードを以下に上げておいたので、詳細はそちらを参照してください。

poruruba/ESP32_WebBLE

https://github.com/poruruba/ESP32_WebBLE

以下の3つからなります。
・BLEセントラルのM5StickC（WebBLE_Centralフォルダ）
・BLEセントラルのM5StickCにWebSocketで接続するWebページ(htmlフォルダ)
・BLEセントラルから接続されるサンプルのM5StickC(BLE_TestDeviceフォルダ)

Webページは以下からもアクセスできます。

https://poruruba.github.io/ESP32_WebBLE/html/

#WebSocketサーバへのリクエストパラメータ

|type|パラメータ|説明|
|---|---|---|
|scan||周辺のBLEデバイスを探索します|
||duration|探索期間(秒)|
||serviceuuid|サービスUUID(任意)|
|scanresult||発見されたBLEデバイスの情報を取得します。|
||address|デバイスBLEアドレス|
|connect||BLEデバイスに接続します。|
||address|デバイスBLEアドレス|
||addresstype|アドレスタイプ(任意)|
|primary||BLEデバイスのすべてのプライマリサービスを取得します。|
|service||BLEデバイスの指定のサービスUUIDのプライマリサービスを取得します。|
||serviceuuid|サービスUUID|
|chars||BLEデバイスの指定したサービスUUIDのすべてのキャラクタリスティックを取得します。|
||serviceuuid|サービスUUID|
|char||BLEデバイスの指定したサービスUUIDとキャラクタリスティックを取得します。|
||serviceuuid|サービスUUID|
||uuid|キャラクタリスティックUUID|
|read||BLEデバイスの指定したキャラクタリスティックから値を読み出します。|
||uuid|キャラクタリスティックUUID|
|write||BLEデバイスの指定したキャラクタリスティックに値を書き込みます。|
||uuid|キャラクタリスティックUUID|
||value|値(16進数文字列)|
||withresponse|Write with Responseかどうか|
|startnotify||BLEデバイスの指定したキャラクタリスティックのNotification/Indicateを有効化します。|
||uuid|キャラクタリスティックUUID|
|stopnotify||BLEデバイスの指定したキャラクタリスティックのNotification/Indicateを無効化します。|
||uuid|キャラクタリスティックUUID|

以上
reactテストでハマった話　getting TypeError: expect(...).toBeInTheDocument is not a function

タイトル通りです。
2021/07/25において確認された事象。
ライブラリのかみ合わせが良くなかった様子です。

```shell
npx create-react-app --template typescript
```

にてreact × typescriptのプロジェクトを作成した後。
各コマンドの確認を行おうと思い、

```shell
npm run test
```

を実行したら以下のようなエラーを吐きました。

```shell
getting TypeError: expect(linkElement).toBeInTheDocument is not a function
```

エラーをまんま検索すると、
ドンピシャで解決策ありました。
https://github.com/testing-library/jest-dom/issues/167

ちなみに初期のバージョンは以下

```json
    "@testing-library/jest-dom": "^5.14.1",
    "@testing-library/react": "^11.2.7",
```

これから、

```json
    "@testing-library/jest-dom": "^5.5.0",
    "@testing-library/react": "^10.0.3",
```

こちらに変更することで解決できました。
バージョンのかみ合わせが悪い場合のエラーはハマると中々抜け出せないので大変ですね。
インストール時にエラー吐かれるとホントに困るので早く修正してほしいです:frowning2:
MAMP環境でのLaravelとMySQLの接続エラー

今まではSQLiteを使用していましたが、今回はMySQLを使用することにしました。
しかし、開始早々接続エラーで苦戦したので、こちらに解決方法を記載しておきます。

<h1>環境</h1>
MAMP
OS：macOS
Laravel:8.51.0
PHP:7.4.12
MySQL:5.7.32

<h1>エラー画面</h1>
![スクリーンショット 2021-07-25 10.20.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159752/d53718ce-0701-ea79-64bc-f7b805e9822b.png)

phpmyadminでDBを作り、いざ接続しようとしたらこのエラーが出ました。
「Connection refused」ということで、うまく接続できていないようです。

どうやら**.env**ファイルと**database.php**ファイルの記述が間違えているようでした。

<h1>MAMPの情報を確認する</h1>
MAMPを起動した際に、こちらのページが表示されます。
![スクリーンショット 2021-07-25 13.06.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159752/e397cd6e-5ea3-6184-d66f-5476df9a3ed5.png)
こちらのページの下の方に「MySQL」という項目があるのでクリックします。
![スクリーンショット 2021-07-25 13.06.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159752/3bd69657-b0e7-7e8e-f639-5aa977d76ee9.png)
するとこちらの情報が出てきます。
この**port**、**Username**、**Password**、**Socket**がこのあと必要になるので、メモ等に控えておきます。

<h1>.envファイルの修正</h1>
修正前の記述がこちらです。

```html:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=
```
この中のDB_PORT、DB_USERNAME、DB_PASSWORDを先ほどメモしたものに変更します。
そして新たにDB_SOCKETの記述を追加します。
DB_DATABASEは自分で作成したデータベース名を入れます。

修正したものがこちらです。

```html:.env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=8889
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock
DB_DATABASE=データベース名
DB_USERNAME=root
DB_PASSWORD=root
```


<h1>database.phpの修正</h1>
次にdatabase.phpを修正します。
database.phpはconfigファイル内にあります。
その中でmysqlの記載部分を探します。

修正前がこちら。

```php:.database.php
'port' => env('DB_PORT', '3306'),
'database' => env('DB_DATABASE', 'forge'),
'username' => env('DB_USERNAME', 'forge'),
'password' => env('DB_PASSWORD', ''),
```

第2引数部分を、メモした通りに変更します。
databaseは先ほど同様、自分で作成したデータベース名を入れます。

```php:.database.php
'port' => env('DB_PORT', '8889'),
'database' => env('DB_DATABASE', 'データベース名'),
'username' => env('DB_USERNAME', 'root'),
'password' => env('DB_PASSWORD', 'root'),
```

以上を変更して、再起動をしてから再接続したところ、無事DB接続することができました。

<h1>ちなみにポート番号を変更するには？</h1>
今回DBの接続するにあたり、ポートが初期値のままだったことに気づきました。
MAMPのデフォルトのポートはApacheが8888、MySQLが8889です。

変更するにはMAMPのPreferencesのこちらの画面で変更することができます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1159752/154bf768-6f5f-ea61-7e87-a6e748d4aaeb.png" width="50%">

一般的なポートの設定をするにはSetWeb&MySQL Ports toの**「80 & 3306」**を押します。
するとApacheが80、MySQLが3306に変わります。
そうすることで、ローカル環境で接続する際に、URLが「http\://localhost:8888/」から「http\://localhost/」に変わります。

ちなみにデフォルトの番号に戻したいときは**「MAMP default」**で元に戻ります。

ポート番号を変更した際は、上記の**.env**と**database.php**の記載の修正を忘れずに。
深層強化学習(Double-QLearning)を用いたシステムトレーディング

# はじめに
　近年、人工知能ブームにより、人工知能を使ったトレーディング手法が盛んである。そこで、今回は深層強化学習を用いたシステムトレーディングを実施した。
　まず、実際の深層強化学習モデルである。agentの行動として、 BUY、HOLD、SELLの三つの内一つを選択する。環境の戻り値として、状態（今現在保有しているポジションの価格、市場価格、手持ちのキャッシュ）、報酬（手持ちのキャッシュの変化値（含む益も含む））、終了（取引の終了か否か）、情報（ターミナルにディスプレイする情報）を返す。

![rl_flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/9a9003ea-5706-9bd7-3a51-243d5d644308.png)


## 使用データについて

トレンド傾向の掴みやすさから、yahoo financeからGSPCの日足を使用した。

訓練データの期間：2015/1/1 - 2017/6/30
テストデータの期間：2017/7/1 - 2021/1/1

以下ソースコード

https://github.com/sugiyama404/ReinfoceLearningForTrading/blob/main/get_csv.ipynb

# Double-QLearning[^1]

Q-Learningモデル

```math
\tilde{Q}(S_t, a) = R_{t+1}+\gamma \max _{a} Q\left(S_{t+1}, a; \boldsymbol{\theta}_{t}\right)
```

Double-QLearningでは以下の二つの式を用いる。

学習過程

```math
\tilde{Q}(S_t, a) = R_{t+1}+\gamma Q\left(S_{t+1}, \operatorname{argmax}_{a} Q\left(S_{t+1}, a ; \boldsymbol{\theta}_{t}\right) ; \boldsymbol{\theta}_{t}'\right)
```
行動選択過程

```math
 a = \operatorname{argmax}_{a}  Q\left(S_{t+1}, (a + a')\right)
```

実際のコードは以下のようになる。

### 学習

```python
        if s_flag == 11:
            q = self.model.predict(state)  
            next_q = self.model_2.predict(next_state)
            t = np.copy(q)

            t[:, action] = reward + (1 - done) * self.gamma*np.max(next_q, axis=1)
            self.model.train_on_batch(state, t)
        else:
            q = self.model_2.predict(state)  
            next_q = self.model.predict(next_state)
            t = np.copy(q)

            t[:, action] = reward + (1 - done) * self.gamma*np.max(next_q, axis=1)
            self.model_2.train_on_batch(state, t)
```

２つもモデルを用意する。(Q1、Q2とする)
行動には、３つのパターンがある。
1. Q1、Q2を足し合わせた行動
2. Q1、Q1を足し合わせた行動
3. Q2、Q2を足し合わせた行動

実際の行動は１のみ。
学習を行うのは２、３のどちらか一方を1/2の確率で選択する。

### 行動選択

```python
    def act(self, state,s_flag=12):
        if np.random.rand() <= self.epsilon:
            return np.random.choice(self.action_size)
        act_values = self.brain._predict(state,s_flag)
        if self.epsilon > self.epsilon_min:
            self.epsilon *= self.r
        return np.argmax(act_values)
```

# 売買ルール

1.空売りは認めない
2.ポジションを持っている場合、追加注文を出せない。
3.最後のステップでポジションを全て売却する。
4.ポジションは全買い、全売り
5.所持金は1000000ドル

# 実装と結果

qlearningより、勝率、収益率の向上が見られる。

ソースコードはこちら

https://github.com/sugiyama404/ReinfoceLearningForTrading/blob/main/Double_Q-Learning/w_q_learning_test.ipynb

![Unknown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/731268/80b28367-44f1-0e11-3724-9f7d98701353.png)

ソースコードはこちら

https://github.com/sugiyama404/ReinfoceLearningForTrading/blob/main/make_data_analysys.ipynb


[^1]: H. van Hasselt, "Double Q-learning", Advances in Neural Information Processing Systems,(2010), 23:2613–2621
Mac with intel chip  Mac with Apple chip



## intel chipとApple chipどちらをインストールすればよいのか
![スクリーンショット 2021-07-25 13.19.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1355275/4855a704-399c-8ba5-8486-3a4226557477.png)


↓確認

![スクリーンショット 2021-07-25 13.16.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1355275/1bb89f93-5de9-a190-db23-bdb8ca2ecf52.png)

↓確認
![スクリーンショット 2021-07-25 13.22.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1355275/f356c211-f696-b1dc-ca7e-22fedcdef9bb.png)
　
### intelのコアなら、Mac with intel chip。AppleならMac with Aplle chip

*chip・・・シリコンなどの半導体でできた数mmから数cm角の基板の上に、多数の微細な電子素子や配線を実装した装置を「ICチップ」（IC chip）「マイクロチップ」（microchip）などと呼び、これを略してチップということが多い。
プロになるためのWEB技術入門(3~5章)

ここではプロになるためのWEB技術入門についてのまとめを行います

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1800687/6d8494c6-0cd2-70ff-a580-48f229f657d4.png">

３章はHTTPについて
４章はCGIからWEBアプリへの変遷
５章ではWEBアプリの構成要素となっている

3章まとめ
HTTPの知識はWEBアプリを開発するうえで非常に重要な要素となっている
wwwの世界でHTMLをやりとりするためのプロトコルが<b>HTTP(Hyper Text Transfer Protcol)</b>
HTTPのリクエストの１行目は<b>リクエストライン</b>といわれるもので<b>メゾット+URL+HTTPのver</b>でできている
メゾット-GETやPOST
URI-何が欲しいのか(URLとの違いはURIは場所を示し、URLは名前を示す。URLはURLとURNの抽象的概念)
HTTPのver-verによって利用できるメゾットの種類やリクエストヘッダの種類が変わる

２行目以降は<b>メッセージ・ヘッダ</b>といい<b><フィールド名>：<フィールド値></b>で構成
Accept-データの種類を示している*/*だったら人にの情報を受け取るしimg/jpgだったら画像を受け取る。こうすることで無駄なものは受け取らない
Host-リクエストの送信先ホスト名やポート番号

HTTPレスポンスの中身
１行目はステータスライン
HTTPのverとステータスコードとレスポンスフレーズでできている
<b>ステータスコード200番台が成功で300番台がさらなる動作が必要、400番台がクライアントエラーで500番台がサーバエラー</b>
２行目はメッセージヘッダで３行目はメッセージボディ

情報はいかにしてつながるか
インターネットに接続されたものはIPアドレスという数値で識別されている
<b>IPアドレスがわかると宛先のホストがわかるのでそのホストへ情報を届けるのがTCP/IP(郵便やみたいなもの)</b>
実際にはパケット分割される

ネット上で唯一のグローバルIPアドレスとほかのネットワークに接続されていないプライベートIPアドレス
ドメイン名からIPアドレスを割り出すのが<b>DNS(Domain Name System)</b>
これによってドメイン名とIPアドレスの対応表をネット上に配置しておいてDNSサーバに問い合わせればIPアドレスがわかる
これはルートサーバとその下のjpやcomなどのTLDを管理するサーバで構築される

TCP/IPには受信した情報がどのようなプロトコルかどれで処理すべきかわからないのでそこでポートが出てくる
よく知られているポートはウェルノウンポートといわれURLに書かなくてもOK

WEBサーバへ情報を伝えるためには<b>GETリクエスト</b>と<b>POSTリクエスト</b>を用いる
GETリクエストはクエリ文字列で何が発信されたかわかるが、POSTリクエストはわからないのでセキュリティは〇
またPOSTには長さ制限がない
GETのメリットは同じ要求をしても同じ結果を得ることができる
日本語はパーセントエンコードで伝える

感想-ここは基本情報を取得する際に学習したが、頭の中がごちゃごちゃになっていたのでこの際整理できてよかった

4章まとめ
ホームページ転送などで用いるFTPサーバはリクエストに伴って状態が変化するのでStateful Protocol
逆はStateless Protcol
Cookie-WEBサーバからブラウザへHTTPレスポンスのヘッダを利用して小さな情報を送る(名前=値という構成)
Cookieユーザーやは最終的にPC上にテキストとして保存されるのでユーザーやパスワードなどはセッションが使用される
<b>要はCookieを利用するが、Cookieの中に情報をそのまま入れるかSessionIDを入れているかの違い</b>

感想-ここは会社でも習ったので特に問題ありませんでした。


5章まとめ
CGIの時代ではブラウザがHTTPリクエストを飛ばしてそれを受け取ったサーバがCGOを実行し、HTMLが生成されレスポンスを返していたが、CGIを起動するとそのたびにPerlのインタプリタを起動する必要があるので効率が悪い
そのためサーバの中で直接PerlやPHPを実行できるように

データベースのところは基本情報ですでに理解しているので省略
結果論としては以下のようになる
<b>1.HTTPリクエストをブラウザが飛ばす
2.WEBサーバがプログラムを実行する
3.DBにSQL発行
4.DBがクエリ結果を返す
5.HTMLを生成
6.レスポンスとして返す</b>
クエリの発行や受け渡しにはDB製品特有の通信プロトコルが使用される

APについて
Javaを実行する際にはJavaVMの上でアプリケーションサーバがServletやJSpを動かしている
アプリケーションサーバは常に動いているのでCGIのように１回きりではなく、使いまわせる
WEBの３層構成のところも会社で理解できたので省略します。

感想
今後WEBシステムを会社で作ることになるかもしれないのでとてもいい勉強になりました。
UnityのLODグループでLevel of Detailサンプル作ってみた

オープンワールドゲーム作ってみたくないです？
著者はゼルダの伝説BotWからハマってGhost of Tsushimaは最高に好きです

オープンワールドを支える重要な技術の一つがLevel of Detail（LOD)です
これは被写体との距離などで表示するメッシュを切り替えることで
カメラ内のポリゴン数を減らし描画負荷を抑える技術です

Unityには簡単にLODを実現するツールがあるので
今回はこちらのサンプルを作りました

# 事前情報
Unity: 2020.3.11f1
LOD Group: https://docs.unity3d.com/ja/current/Manual/class-LODGroup.html

# 作業
## Blenderでメッシュを用意
今回は高ポリゴン・中ポリゴン・低ポリゴンをBlenderで用意
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/c594ffe8-f2c5-9c00-1167-382f95cce7fb.png" width="300" height=600px > <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/63554c02-be1a-d2ef-aac2-a7b8ab7efc55.png" width=300 height=600px > <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/a46545f6-1610-06f2-5daa-b8c4c0ad9d3a.png" width=300 height=600px >
青：UV SphereのSegments=12、Verts=182
緑：UV SphereのSegments=24、Verts:362
赤：UV SphereのSegments=48、Verts:722

## Unityにそれぞれのメッシュを配置
UnityでEmptyObjectを配置し、子要素に3パターンのオブジェクトを追加
![LODサンプル_Unity1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/646298e8-f22a-b85b-fb67-828aed02c494.png)
※わかりやすく横に配置してますが座標は同じにしてください

## LOD Groupを設定
親要素に対しInspectorウィンドウでLOD Groupを追加します
![LODサンプル_Unity2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/0e3975ea-e94d-645c-3e64-4982b2a01bef.png)

各フォームの詳しい説明は公式ドキュメントがわかりやすく解説してるので省きます
LOD Group: https://docs.unity3d.com/ja/current/Manual/class-LODGroup.html

UnityのLOD Groupでは被写体が画面内で何％占めているかでメッシュの出しわけをします
上記画像だと100%ならLOD 0、60%ならLOD 1、30%ならLOD 2、10%なら表示しません
各ゲージ部分をクリックすると対象のオブジェクトまたはRendererを指定できます

あとはカメラアイコンをスライドするとSceneビューにプレビューされます
Sceneビューでカメラ移動しても反映されてると思います

![LODサンプル.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/c3ce115e-9647-541b-b102-edf76a68f1f8.gif)

# 比較
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/10d651b6-e896-02ca-92a0-211fa18d48f3.png" width="400" height=600px > <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7680/0e690570-bf2f-7acf-ff01-4139e9c5b8ec.png" width="400" height=600px >

視覚的に球体の角張に差は殆どないのに
statsのTriangle数とVertex数が激減してるのがわかります


# 感想
LOD Groupのおかげで非常に簡単にLODを体験できました
ただ余りにも簡単かつ設定項目も少ないので
本格的に負荷軽減したいなら自作する必要がありそうです

## メリット
・簡単に作れるのでモック作成向け

## デメリット
・画面内の比率でメッシュ差し換えしているため、見切れてるときに低ポリゴンになる
　→Fade Modeでメッシュ切り替えを滑らかにすると緩和されるかもしれません

・メモリにはすべてのメッシュが載ってる気がするのでメモリも節約したい場合には向かないかも
　→Renderer指定にすれば動的ロードしてくれるかも？

# 08/19 追記
実際にメモリに全LODが展開されてるかチェックした

https://qiita.com/tsune2ne/items/f98e7efb5051a6f5bcc1
snapでインストールされたcurlに気をつけて(ubuntu)

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

Ubuntuには、curlコマンドが標準では入っていません。
なので、インストールすることになります。
しかし、その時にsnapでインストールしたcurlを使ったら
/tmp/以下にファイルをダウンロードできなかった。

というお話です。

# 1. curlをsnapでインストール

```shell-session
$ sudo snap install curl
```

# 2. GitHubからファイルを/tmpへダウンロード

ダウンロードしているファイルは問題ではありません。
保存先が問題です。

```shell-session
$ curl -sSLJ https://github.com/alexellis/arkade/releases/download/0.7.23/arkade --output /tmp/arkade
```

以下のようなエラーがでます。

```shell-session
curl: (23) Failure writing output to destination
```

# 3. GitHubからファイルを/home/$user/へダウンロード

次は、ログインユーザーのホームディレクトリへファイルを保存します。

```shell-session
$ /snap/bin/curl -sSLJ https://github.com/alexellis/arkade/releases/download/0.7.23/arkade --output /home/$USER/arkade
```

以下のようにエラーもなく保存できました。

```shell-session
$ ls -la /home/$USER/arkade
-rw-rw-r-- 1 user user 7811072  7月 25 12:12 /home/$USER/arkade
```

# 4. /tmp/へ保存できない理由

snapは独自のsandbox機構を持っています。
書き込める場所が制限されていてどこにでも書き込めるわけではありません。
該当のsnapパッケージ(ここではcurl)で書き込める/tmpは、`/tmp/snap.curl/tmp/`というディレクトリになります。

https://ubuntu.com/core/docs/security-and-sandboxing

# 5. 問題になるケース

以下のようなケースです。

最近増えているcurlでインストールするスクリプトをダウンロードしてコマンドをインストールする場合
`curl -sLS https://get.arkade.dev | sudo sh`

上記のcurlコマンドは`sudo sh`にリダイレクトされるので問題ありませんが、ダウンロードされたシェルスクリプト内でcurlが実行されており、ファイルが/tmp/配下にダウンロードされるように書かれている場合、/tmp/配下にはファイルをダウンロードできないので、エラーになります。

# 6. 対処方法

snapでインストールされたcurlをremoveしてaptでインストールし直しましょう。

```
$ sudo snap remove curl
$ sudo apt install curl
```

以下のIssueで報告があがっていますが、
Curl can't write files in dot-leading directories on 21.04 · Issue #2 · woutervb/snap-curl
https://github.com/woutervb/snap-curl/issues/2

Ubuntu社としては、--classicオプション(sandbox制限のないインストール)を認める気はないようです。
Classic confinement request for curl - store-requests - snapcraft.io
https://forum.snapcraft.io/t/classic-confinement-request-for-curl/24611