OmniAICreator/Qiita-1.07M huggingface dataset:
ABC147＜bit全探索＞

自分用のメモ。教えてもらった。

# bit全探索

問題文はこれ
https://atcoder.jp/contests/abc147/tasks/abc147_c

```C++
//正直者は確定
//不親切は、正直か嘘かも不明
//Nたったの15人なので、15人が正直、嘘、で仮定する
//2^15の処理くらいなら間に合う
#include <bits/stdc++.h>
using namespace std;
int main(){
  int N; cin>>N;
  vector<vector<int>> say(N+1,vector<int>(N+1,-1));
  //証言の保存。-1は審議不明。0は嘘、1は正直 
  for(int i=1; i<=N; i++){
    int A; cin>>A;
    for(int j=0; j<A; j++){//A個の証言をする
      int x,y; cin>>x>>y;
      say[i][x]=y;//iさんが、xさんのことをyと言う
    }
  }
  int ans=0;
  for(int i=1; i<(1<<N); i++){ //(1<<4)=10000=2^4=16未満まで探索
    vector<bool> check(N+1,false);//正直者の配列を用意。
    for(int k=0; k<N; k++)
      if(1&(i>>k)) check[k+1]=true;//演算子、ビット%。1と等しいかどうか。等しければtrue。
    bool finish=false;
    for(int m=1; m<=N; m++){
      for(int n=1; n<=N; n++){//正直者の発言が正しいかどうか探索。嘘ならその時点でbreak
        if(check[m]){
          if((say[m][n]==0 && check[n]==1)//正直と仮定したmがnを嘘というが、nが正直なとき
           ||(say[m][n]==1 && check[n]==0)){//正直と仮定したmがnを正直というが、nが嘘なとき
              finish=true;
              break;
            }
         }
      }
      if(m==N && finish==false){
        int temp=__builtin_popcount(i);
        ans=max(ans, temp);
      }
    }
  }
  cout<<ans<<endl;
}

```
【PostgreSQL】月別や曜日別で集計する

PostgreSQLでログ件数などを時刻から月別、曜日別に集計します。</br>
そのためのSQLの作り方メモです。
## やりたいこと
下記のような「log」テーブルを想定し、user_id毎に「log」テーブルのレコードの件数を集計します。

 id | user_id |      logged_at     
----|---------|--------------------
  1 | AAA101  | 2020-01-06 00:00:00
  2 | AAA101  | 2020-01-07 00:00:00
  3 | AAA101  | 2020-02-06 00:00:00
  4 | AAA101  | 2020-03-12 00:00:00
  5 | AAA101  | 2020-03-19 00:00:00
  6 | BBB102  | 2020-01-12 00:00:00
  7 | BBB102  | 2020-02-09 00:00:00
  8 | BBB102  | 2020-03-11 00:00:00
  9 | BBB102  | 2020-03-21 00:00:00
 10 | BBB102  | 2020-03-28 00:00:00
 11 | CCC103  | 2020-01-19 00:00:00
 12 | CCC103  | 2020-01-20 00:00:00
 13 | CCC103  | 2020-01-21 00:00:00
 14 | CCC103  | 2020-01-22 00:00:00
 15 | CCC103  | 2020-02-20 00:00:00
 16 | CCC103  | 2020-02-21 00:00:00
 17 | CCC103  | 2020-03-28 00:00:00
例えば、月別に集計すると、、、

 user_id | 1月 | 2月 | 3月
---------|-----|-----|-----
 AAA101  |   2 |   1 |   2
 BBB102  |   1 |   1 |   3
 CCC103  |   4 |   2 |   1
例えば、曜日別に集計すると、、、

 user_id | 日曜日 | 月曜日 | 火曜日 | 水曜日 | 木曜日 | 金曜日 | 土曜日
---------|--------|--------|--------|--------|--------|--------|--------
 AAA101  |      0 |      1 |      1 |      0 |      3 |      0 |      0
 BBB102  |      2 |      0 |      0 |      1 |      0 |      0 |      2
 CCC103  |      1 |      1 |      1 |      1 |      1 |      1 |      1

といった感じです！

## Version
- PostgreSQL 11.4

## SQL
### 利用する関数
関数|種類|説明
---|---|---
DATE_TRUNC|[日付/時刻関数と演算子](https://www.postgresql.jp/document/11/html/functions-datetime.html)|指定された精度で切り捨てます。今回は'month'を指定したので月より後ろが「01 00:00:00」(1日の0時)として切り捨てられています。
EXTRACT|[日付/時刻関数と演算子](https://www.postgresql.jp/document/11/html/functions-datetime.html)|日付/時刻の値から年や時刻などの部分フィールドを抽出する。今回は'dow'を指定したので日曜日~土曜日が「0~6」として返却されます。
CASE|[条件式](https://www.postgresql.jp/document/11/html/functions-conditional.html)|条件式を記載できます。今回は月別では切り捨てた月初日であれば1、それ以外は0として、曜日別では各曜日で１or０を返却しています。
SUM|[集約関数](https://www.postgresql.jp/document/11/html/functions-aggregate.html)|合計します。今回は条件式の結果を集計しています。

### 月別
```SQL
SELECT
 user_id,
 SUM(CASE DATE_TRUNC('month', logged_at) WHEN '2020-01-01' THEN 1 ELSE 0 END) AS "1月",
 SUM(CASE DATE_TRUNC('month', logged_at) WHEN '2020-02-01' THEN 1 ELSE 0 END) AS "2月",
 SUM(CASE DATE_TRUNC('month', logged_at) WHEN '2020-03-01' THEN 1 ELSE 0 END) AS "3月"
FROM
 log
GROUP BY
 user_id
ORDER BY
 user_id;
```
'month'(月)のほかにも'hour'(時)、'century'(世紀)なども使えます。
### 曜日別
```SQL
SELECT
 user_id,
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 0 THEN 1 ELSE 0 END) AS "日曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 1 THEN 1 ELSE 0 END) AS "月曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 2 THEN 1 ELSE 0 END) AS "火曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 3 THEN 1 ELSE 0 END) AS "水曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 4 THEN 1 ELSE 0 END) AS "木曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 5 THEN 1 ELSE 0 END) AS "金曜日",
 SUM(CASE EXTRACT(dow FROM logged_at) WHEN 6 THEN 1 ELSE 0 END) AS "土曜日"
FROM
 log
GROUP BY
 user_id
ORDER BY
 user_id;
```
'dow'(曜日)のほかにも'day'(日)、'decade'(十年)なども使えます。
単一責任の原則

##単一責任の原則 (Single responsibility principle)

クラスは1つのことだけ責任を負う

もし複数の責任を負っているとすれば、それは伝播する
つまり、1つの変更内容が伝播してしまう

### ある日の会話
私「この原則を徹底すると、クラスを大量に作成しないといけないから、ファイル管理が大変にならない？」

兄「そうだね。実際コードを書いて説明するよ」
兄「まず悪い例ね」

```php:悪い例1
class BadSampleConstructChange
{
    public function __construct(array $users)
    {
        $this->user = $users;
    }

    public function A(){}
    public function B(){}
    public function C(){}
}
```
兄「コンストラクタに渡すものに修正が入ると、A、B、Cメソッド全てに変更が必要になる」

兄（メソッド内容とメソッド名は省略するわ）

私（おけ）

```php:悪い例2
class BadSampleOneChange
{
    public function __construct(string $userName)
    {
        $this->userName = $userName;
    }

    public function A(): string
    {
        return $this->something_A($this->userName);
    }

    public function B(): string
    {
        return $this->something_B($this->userName);
    }

    public function C(): string
    {
        return $this->something_C($this->userName);
    }
}
```
```php:悪い例2-Bメソッドを変更する
    public function B(): ?string
    {
        if (something_if) {
            $this->userName = null;
        }
        return $this->userName;
    }
```
兄「悪い例2は、お互いプロパティを触り合っているから、どこか1つ変更があると他が壊れちゃう」

私「たまにバグの原因になったりするやつね・・」

```php:悪い例3
class BadSampleComplexity
{
    public function ABC()
    {
        $this->A();
        $this->B();
        $this->C();
    }

    public function A(){}
    public function B(){}
    public function C(){}
}
```
```php:悪い例3-SampleOneControllerで使用
$BadSampleComplexity = (new BadSampleComplexity())->ABC();
```
```php:悪い例3-SampleTwoControllerで使用
$BadSampleComplexity = (new BadSampleComplexity())->ABC();
```
兄「あとは、1つの関数内で⾊々やってて何かすると他の利⽤者が困るやつもダメだね」

兄「例えば、SampleTwoControllerで呼び出すときはBメソッドの処理がいらないってなった時、ABCメソッドにif文をいれると**呼び出し箇所すべてで条件分岐の判定が入る**から、パフォーマンスが下がる。」

私「if文入れない場合でも、ACメソッドっていうほぼ同じメソッドがコピペされることになっちゃうね」

私「じゃあ、やっぱり1クラス、1処理が正解なのかな？」

兄「うーん。正解とも一概には言えなくもないけど。。」

兄「**実際に開発するときは、単一責任の原則と、クラス分割の兼ね合い**が大事だと思うよ」

兄「要は、**変更内容の伝播が発生しなければOK**」

私「なるほどねー！理解が進みました。ありがとう」

おわり
IBMのTensorFlow-LMSで大きなネットワークを学習する


[前回の記事](https://qiita.com/takeajioka/items/26439b848f66f43bb1d3)では、PyTorchでモデル並列化をして巨大なネットワークの学習法を記事にしましたが、
今回はTensorFlowで巨大なネットワークの学習を行います。

方法としては[Unified Memoryを使う方法](http://system-medicine.blog.jp/archives/6811037.html)もありますが、今回はIBMのTensorFlow-LMS(Large Model Support)を使用する方法を行います。
TensorFlow-LMSはUnified Memoryではなく、データ・スワッピング手法を使っているので高速で出来るようです。（詳しくは論文を参照）

github：https://github.com/IBM/tensorflow-large-model-support
論文：https://arxiv.org/abs/1807.02037

これは、IBMのWMLCE(Watson Machine Learning Community Edition)の一部として利用することが出来ます。

# インストール
環境は
Linux(Red Hat Enterprise)
CUDA 9.0
Anaconda
python3.6
tensorflow-gpu 1.10
keras 2.3.1
です。

今回は最新版ではなく、version 1を使用します。
これはgithubでのtflmsv1のブランチに相当します。
インストール方法や使用方法は下記のURLで説明されています。
https://github.com/IBM/tensorflow-large-model-support/tree/tflmsv1

```shell
git clone https://github.com/IBM/tensorflow-large-model-support.git -b tflmsv1
pip install ./tensorflow-large-model-support
```
これでインストール出来ました。
2行目のpip installコマンドが上手くいかない場合は

```shell
python ./tensorflow-large-model-support/setup.py install
```
でもインストール出来ます。

# デモを動かす
exampleフォルダ内の3つのサンプルコードを試してみます。
1つ目

```shell
python ./tensorflow-large-model-support/examples/mnist_deep_lms.py
```
2つ目

```shell
python ./tensorflow-large-model-support/examples/cnn_mnist_lms.py
```

3つ目
これはkerasを用いた実装です。--image_sizeの引数は自由な値に出来ます。

```shell
python ./tensorflow-large-model-support/examples/Keras_ResNet50.py --image_size 200 --lms
```
image_sizeを大きめにしても、時間は掛かりますが学習することが出来ました。
これでLarge Model Supportのモードで学習できることが確認できました。

###エラー情報
デモを動かしたときに以下のエラーが出て止まってしまうことがあります。

```
Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
```
この場合の対処法は、ターミナルで以下のコマンドで設定を変更するとエラーは無くなります。

```shell
export TF_FORCE_GPU_ALLOW_GROWTH=true
```
参考：https://www.tensorflow.org/guide/gpu 　https://qiita.com/ysuzuki19/items/b727bbcb45f1cad37630



# Kerasでの実装方法
kerasを使用した自分のコードでLarge Model Supportを設定する場合は、以下のコードを冒頭につけるようです。

```Python
import tensorflow as tf
from tensorflow.core.protobuf import rewriter_config_pb2
from tensorflow.python.keras import backend as K
config = tf.ConfigProto()
config.graph_options.rewrite_options.memory_optimization = rewriter_config_pb2.RewriterConfig.SCHEDULING_HEURISTICS
config.graph_options.rewrite_options.dependency_optimization = rewriter_config_pb2.RewriterConfig.OFF
K.set_session(tf.Session(config=config))
```
後は通常のkerasのコードにLMSKerasCallback()を渡すだけのようです。
詳細な説明は開発元のgithubのREADMEにあります。

＊追記(2020/5/4)
Large Model Supportで3D U-Netを実装したものを[githubで公開しました](https://github.com/atakehiro/3D-U-Net-TFLMS-Keras)。
(Unified Memoryのコードもついでに入っています。)

#最新のTensorFlow-LMSを使いたい場合は
今回使ったのはTensorFlowの1.10ですが、最新版は2.xになります。
2.xバージョンでのインストール方法は[公式ホームページにあります。](https://www.ibm.com/support/knowledgecenter/SS5SF7_1.7.0/navigation/wmlce_install.htm)
インストールは、channelをIBMのサイトに指定してcondaで出来るようです。-cでチャンネルを指定します。

```shell
conda install -c https://public.dhe.ibm.com/ibmdl/export/pub/software/server/ibm-ai/conda/ tensorflow-gpu
```
使い方も1.xバージョンとは異なるようです。

# 終わりに
ちなみにIBMのWMLCEは他にもパッケージがあって興味深いです。PowerAIも使ってみたいですね。
UGE (Univa Grid Engine)の使い方____jobのメモリ利用量の確認 (qreport)と指定

#UGEにおけるメモリ利用量の確認と指定

スーパーコンピューターを使う時に、UGEでjobが割り振られるシステムが用いられる事がある。
qsubでjobを投げるが、それについては別の機会にMemoできれば。

今回は、メモリの確認と指定をMemo
qsubでjobを投げると、ソフトリミットによりUGEjobの利用可能な最大メモリ量が制限されている場合がある（5.3GBや8.0GBまでなど）。

ソフトリミットを解除するには
qsub -l s_vmem=数値G,mem_req=数値G
と使用メモリを指定して宣言する必要がある。
mem_req=8Gと指定すると、ホストの搭載メモリ量が128GBだった場合、
ホストの残りメモリ量が、mem_req=120Gとなる。

qreportを用いれば、投入予定のjobの最大メモリ量を確認できる。
と言っても、一度qsubでjobを投げなければいけない模様。
qsub memory.sh
qstat
と打って、jobIDを確認する（一番左に表示される）。
ジョブの終了を待つ（終了しなければ、最大量が分からない）。
qreport -j jobID | grep maxvmum
と打つと、memory.shを実行した際に使用した最大仮想メモリサイズ(maxvmem)が表示される。

けどこれって、完了できるjobのメモリ使用量しか分からないと思う。当然ながら仕方ないけど。メモリエラーでコアダンプが表示された場合は、どうすれば良いのか悩ましい。
一度、メモリ大きめに指定して動かすのが良いのだろうか。＞記事作成後の今は、1回目はメモリ指定を大きめに取ることにして、次回から必要量だけ指定することにしている。
パスやファイル名を指定して、コマンドライン上からデータベースにdumpファイルをインポートする

DBからエクスポートしたデータ、バックアップファイル、要するにdumpやsqlファイルを別のDBへインポートする方法です。
### mysqlの外から実行
```sql
-- 取り込みたいデータファイルと同じ場所まで移動して実行
$ mysql -u [MySQLのユーザ名] -p db_name < example.sql

-- 取り込みたいデータファイルのパスを指定して実行
$ mysql -u [MySQLのユーザ名] -p db_name < /Users/user_name/Desktop/example.sql
```

#### もう少し詳しく解説

GUI（phpMyAdminなどの管理画面）で入れるやり方もありますが、ここではコマンドライン上でデータを読み込む方法を記載しています。当方の実行環境は以下の通りです。

- MySql: 5.7.26
- phpMyAdmin: 4.9.3
- MAMP: 5.6
- macOS: Mojave (10.14.6)

```sql
$ mysql -u [MySQLのユーザ名] -p db_name < example.sql
```

```db_name``` の部分にはデータベース名を入力し、```example.sql``` の部分には取り込みたいデータのパスを指定します。そのためDBが既に作成済みであることが前提となります。まだ作成していない場合はDB作成後に実行してください。
パスは、今いる場所から見たパスになるので、```mysql -u xxx -p db_name < example.sql``` のようにファイル名だけ指定して実行させるとしたら、そのファイルがある場所まで移動すれば可能ということになります。
例えばデスクトップにあるダンプやsqlをインポートすると仮定すれば、```cd Desktop/``` のように移動してから ```mysql -u xxx -p db_name < example.sql``` を実行します。
ファイルがある場所以外（今回はデスクトップ以外の場所）から実行したい場合は、 ```mysql -u xxx -p db_name < /Users/user_name/Desktop/example.sql``` のように絶対パスを指定してあげれば大丈夫です。

以上が、mysqlのコマンドラインによる標準入力でdumpファイルを指定する方法でした。
ただし**ファイルサイズが大きすぎると、時間がかかりすぎるかエラーになってしまう**こともあり、そういう場合はコマンドライン上でDBにログインした後に、sourceコマンドでMySQL内部からファイルを読み込むことも可能です。
### mysqlの中から実行

```sql
/* MySQLへログイン */
$ mysql -u [MySQLのユーザ名] -p

/* （中略） */

/* 使用するDB名を指定 */
mysql> use db_name

/* 読み込みたいファイルのパスを指定 */
mysql> source /Users/user_name/Desktop/example.sql
```

## パスの確認方法
余談ですがファイルのパスを確認したい場合は以下のような方法があります。

### Macのファインダーからパスを確認
1. ファインダーで該当のdump/sqlファイルを選択
2. ファインダー画面下のパスバーを確認
3. パスバー末端のファイル名を右クリックまたは control + クリックしてパス名をコピー
<img width="811" alt="2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/530967f0-7c16-85d0-ecc5-51e460e76978.png">

（パスバーが見えていない場合は、表示メニューから「パスバーを表示」を選択）
<img width="956" alt="3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/da8de5c0-0938-01ba-1354-44b5ef1eb5d5.png">

### Visual Studio Code などのエディタからパスを確認
自分はエディタにVSCodeを使用していますが、エディタ上からファイルパスを確認する方法もあります。

1. VSCodeで該当のファイルを開くか、親となるディレクトリを開く
2. ファイル名の記載があるタブで右クリックまたは control + クリックしてパス名をコピー
<img width="752" alt="4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/49408855-45fd-24ed-481e-f700f9aae823.png">

3. または、画面左側の一覧から該当のファイルを右クリックや control + クリックでパス名をコピー
<img width="753" alt="5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94442/dfe0bfbe-93a4-e475-7d43-a34f0eff7a0d.png">






#### 参考URL
[MySQLのデータベースをまるっとお引越し。 (エクスポート/インポート)](https://qiita.com/sango/items/84a45e5911d719a2c08c)
[巨大ファイルのインポートにはmysqlのsourceコマンドを](https://torikasyu.com/?p=411)
[MAMP で大きい MySQL ファイルをインポート/エクスポートする方法](http://ja.katzueno.com/2015/04/3451/)
[【MAMP】コマンドで .sql ファイルをインポートする方法（Windows & Mac対応）](https://codeforfun.jp/how-to-import-sql-with-mamp/)
Macのターミナルで先頭に(base)と表示されたときの対処法

Macのターミナルを起動したら、
Anaconda prompt で見覚えのある **(base)** の文字が先頭に。
そういえば最近、Anaconda を使ってたなぁ。

```
(base)username:~$ 
```

## 原因
Anaconda で構築した仮想環境を自動で有効化する設定が効いている可能性があるので、
以下のコマンドを実行して確認してみました。

```
$ conda config --show | grep auto_activate_base
```

`True` が返ってきたので、設定を変更しなければならないことがわかります。

```
auto_activate_base: True
```

## 環境
・macOS Catalina 10.15.3

## 解決方法
それでは、自動で有効化する設定を `False` にしましょう。
以下のコマンドを実行すると、設定を書き換えることができます。

```
$ conda config --set auto_activate_base False
```


実行しても(base)が表示されたままで解決しなかった場合は、
開いているターミナルを一旦閉じて、新しいターミナルを開いてください。
(base)が消えた状態になっていると思います。


## 謝辞
執筆にあたり、こちらを参考にさせていただきました。ありがとうございます。
・[MacOS(OSX) - macのターミナルに(base)と表示され場合の対応方法](https://qiita.com/Atsushi_/items/253d3df5be8ce799dbf0)
WordPressの翻訳で使えるPoeditの使い方。POT,PO,MOファイルって何？

注意事項
個人のメモ程度に思ってください。
Windows10home

##調べた理由
WordPressの勉強中にPoeditでpo,moファイル作ってみましょうとあったから。


##pot,po,moファイルについて調べたらこんな感じ。
potによりPoedit（多分他のソフトでもできる。）でpo,moが作られる。
いきなりpoで保存してもいい。
potは翻訳される元言語だけ記載される。
翻訳先の言語はpoで記載。
poは一つの言語につき一つのファイルが保存されるから、複数の言語に翻訳するならpotから作成したほうがいい。
Poeditでpoファイル保存すると、自動的にPOファイルをコンパイルしたmoファイルが作成される。
実際にpc(?)が読み込むのはmoファイル。



##実際にPoeditでpo,moファイル作成した流れ

これが一番わかりやすかった。
Windowsだったし。
https://nelog.jp/wordpress-theme-multi-language

ちなみにこれでもできたけど写真なしでよく分からなかった。
https://wordpress.stackexchange.com/questions/149212/how-to-create-pot-files-with-poedit

特にpathの指定が分かりにくい。
ベースのpathはpoがある場所ではなく、翻訳したいソースコードがある場所になる。

「テーマディレクトリ」--「languages」--po,mo
　　　　　　　　　   　　  -- ソースコード
上の格納状況だと、poファイルには
![Qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344711/3c25072f-3eec-809d-9809-dd7699f4dec5.png)
このように表示された。

SerachPathはソースコードを探す場所になるから、同一の場所になる。
正直ここの解釈はよく分からない。

できるまでかなり時間がかかった。
最初はPoeditでできなかったので、TortoiseSVNをインストールしてcmdでPOT作成しようとしてできなかったりと色々と回り道をした。
その後Poeditにまた戻ったけどソースコードがありませんとかなって。
そのときにこのパス指定したと思うけど……。
まあできてよかった。
どうしてQiitaでストックされてもContributionが増えないの？

ちょっと前ぐらいにQiitaのいいねがLGTMに変わったとかで話題になったけど、
そもそもなんでストックがContributionに反映されないんだろうか

私の使い方だと、

* あとから見返す必要はないけど、面白かった記事、一発ネタ　→　LGTM
* 技術的に役に立った記事、あとから見返したい記事　→　ストック

という使い方なんだけど、良い技術記事を書いた人にContributionをあげるという意味では、LGTMじゃなくてストックされた人に上げたほうがいいと思うんだよね

だって、他人にストックされるぐらい役に立つ記事を書いたということなんでしょ？

「いいねをLGTMに変えたから、押す前によく考えてね」とかいうよくわからないリリースを出すぐらいなら、LGTMの半分でもいいからストックされた記事にポイント上げるほうが、よっぽどランキングとか健全になると思うんだけどなあ

みつお
formでBoolean型のセレクトボックスを作った時のメモ

Boolean型のチェックボックスの記事はあったけどプルダウンメニューのセレクトボックスが探してもなかったので備忘録。


真偽値なので0と1で値を送りたいけど、ユーザーが選択する部分では文字を表示したい。
探すとちょうどいい感じの記事が。
https://310nae.com/rails-selectbox/


```irb:new.html.erb
  <%= form_with model:@post, local: true do |form| %>
    <%= form.label "タイトル" %><%= form.text_area :title %>
    <%= form.label "状態" %><%= form.select :is_released, [['非公開',0],['公開',1]], { include_blank: true, selected: 0 } %>
    <%= form.submit "送信" %>
  <% end %>
```

これで選択する際は「公開」「非公開」を選択できるようになり、paramsで送られてくる値は0か1になる。



表示するときはビューで切り替え。

```irb:index.html.erb
  一覧表示
  <% @posts.each do |post| %>
    <div>
      タイトル: <%= post.title %>
      掲載状態:<%= post.is_released == true ? "公開" : "非公開" %>
    <div>
  <% end %>
```

もっときれいな書き方もあるのかも。




ちなみに真偽値はバリデーションかけるとき注意。（presence: trueにすると偽の場合保存できなくなる）
以下参照。
https://qiita.com/mktakuya/items/a13c2175f0f0d9871038
nginx で laravel get , post の値取得できない

原因は、NGINXの設定でした。



```

    location / {
       root  /var/www/html/yamada/public;
       index index.php index.html index.htm;
#       try_files $uri $uri/ /index.php$query_string;
       try_files $uri $uri/ /index.php$is_args$args;//これにする
}

```
juliaで簡単にパラメータを保存するマクロ

# パラメータをファイルに書きだしたい
数値シュミレーションを異なるパラメータで回したときに、そのパラメータをファイルに書きだしておきたいことは日常的にある。そんなときには次のようなコードを書くだろう。

```julia:param_output.jl
a=1
open("data.dat","w") do ofile
   println(ofile,"a=",a)
end
```

しかしこの方法ではパラメータが多くなれば、書くのも面倒だしコードも長くなる。
それとは別に、シミュレーションの都合上、一時的にパラメータが定義されていないときには、エラーが出てしまう。それをいちいちコメントアウトするのも面倒だ。なので次のようなmacroを書いた。

```julia:param_output_macro.jl
macro output_parameter(file,param)
    esc(:(
        if(@isdefined $param)
        println($file,$(string(param)),"=",$param)
        else
        println($file,$(string(param)),"=nil")
        end
    ))
end
#Usage
a=1
b=2
open("data.dat","w") do ofile
   @output_parameter(ofile,a)
   @output_parameter(ofile,b)
end
# data.dat
#a=1
#b=2
```

このmacroはファイルとパラメータ名だけ渡せばファイルに、いい感じに出力される。しかもパラメータが未定義の場合はエラーをはかずに=nilを出力する。

更に多くのパラメータがあっても、コードを増やさないために、上のmacroの上に次のmacroを書いた。

```julia:params_output_macro.jl
macro output_parameters(file,params)
    str="begin\n"
    for i in eval(params)
        str*="@output_parameter($file,$i)\n"
    end
    str*="end"
    esc(Meta.parse(str))
end

＃Usage
a=[1,2]
b="str"
open("data.dat","w") do ofile
   @output_parameters(ofile,[:a,:b])
end

# data.dat
#a=[1,2]
#b="str"
```
これでパラメータが増えても、[:a,:b,...]と増やしていくだけで、いい感じにファイルにアウトプットされる。

juliaのmacro初心者なので、何度がつまづいた。
今回つまづいたのは、begin ... end というので書こまないとエラーが出るところ、そしてesc(...)を忘れると、macroが展開されたときに外側の環境が引きつげなくて、"a" is not defined 的なエラーが出るところである。
[ReactNative] VirtualizedList: missing keys for items, make sure to specify a key property on each item or provide a custom keyExtractor.

# 問題

FlatList使用時に以下の警告が出る
![スクリーンショット 2020-04-15 13.37.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/131286/fd543362-7b8d-95f5-d010-4cd6a6233f68.png)

# 解決

FlatListの各要素にkey属性を指定してあげれば良いと考えたが、警告が無くならない。以下の形式で、keyExtractorを利用すれば良い。

```jsx

    <FlatList
        data={items}
        renderItem={({ item }) => (
          <ListItem
            key={item.key}
            attr={item.attr}
          />
        )}
        keyExtractor={(item, index) => index.toString()})
     />
```
メルスペクトログラムをwavファイルに戻す方法


#メルスペクトログラムを元の.wavファイルに戻す
```
import numpy as np
import librosa

#npyファイルのメルペクトログラム読み込み
mel = np.load("melspe.npy")

#mel -> audio
audio = librosa.feature.inverse.mel_to_audio(mel)

#wavの書き出し
librosa.output.write_wav("audio.wav",audio,22050)
```

#あとがき
ちょうど使う機会があったものの記事が見当たらんかったので書いてみました。
良かったらいいね...じゃなくてL...なんとかお願いします
box-shadow 上だけ消す

疑似要素で重ねるのはデザイン的に向いてなさそうなケースがあるので、重ねて指定する方法でどうだろう

```css:style.css
    box-shadow: 0px 10px 7px -7px rgba(0,0,0,0.1),
                7px 7px 7px -7px rgba(0,0,0,0.1); /* 上だけ出さない、左右と下を陰つける */
```

一応見本。上側に複雑なパーツが乗っても大丈夫そう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25349/1fe453b1-3807-6114-ceab-eb60af880218.png)

上のタブ部分はざっくりとbox-shadowかけただけなので、タブ部分要素の下側のshadowは直後の本文エリア要素の裏側に回ってるだけだと思う。
【laravel】サービスプロバイダ

# 概要
Laravelではサービスコンテナに登録されているサービスを利用してアプリケーションを開発します。

Laravelにはメールの送信、文字列の暗号、ファイル操作するといったサービスがあります。
これらのサービスは入れ物となるサービスコンテナへ事前に登録することで利用できるようになります。

そして、これらのサービスを登録する役目をもつものがサービスプロバイダです。


# サービスプロバイダの作成
手作業でも作成できますがartisanコマンドを利用すればProvidersフォルダ内に自動でサービスプロバイダのファイルが作成されます。

```:コマンド
php artisan make:provider SampleServisProvider
```

## ディレクトリ構造
app\Providers内に作成されます。
既存のファイルについては省略します。

```:ディレクトリ
app
├─ Providers
|  ├─ SampleServisProvider.php
```

## 作成されるファイル
生成されたファイルの中身は以下のようになっています。

```php:ServiceProvider
namespace App\Providers;

use Illuminate\Support\ServiceProvider;

class RiakServiceProvider extends ServiceProvider
{
    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }

    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }
}
```

## ServiceProviderの中身

サービスプロバイダはServiceProviderクラスを継承して作成され、registerとbootのメソッドが用意されます。
どちらのメソッドもvoid型です。

### regiterメソッド
サービスプロバイダへ登録を行う処理のみを記述します。
他の処理を記述すると、サービスプロバイダがロードしていないサービスを意図せずに使用する原因になります。

```php:ServiceProvider
public function register()
{
    // 登録したいサービスの処理を記述
}
```

### bootメソッド
アプリケーションへのブートストラップ処理を記述します。
ブートストラップ処理とは、アプリケーションが起動する際に実行される処理のことです。
ここに処理を設定することで、ビューを生成する際に自動的にコンポーサーが呼び出されるようになります。

```php:ServiceProvider
public function boot()
{
    // ブートストラップ処理を記述
}
```

# サービスプロバイダの登録
作成したサービスプロバイダを実行できるようにアプリケーションへ登録します。
configフォルダにあるapp.phpに作成したサービスプロバイダクラスを追加します。

```:ディレクトリ
config
├─ app.php
```

```php:app 
'providers' => [
  // ...中略...
  App\Providers\EventServiceProvider::class,
  App\Providers\RouteServiceProvider::class,
// ここから
  App\Providers\SampleServiceProvider::class,
// ここまで
]
```

# 参考
[Laravel 6.x サービスプロバイダ](https://readouble.com/laravel/6.x/ja/providers.html)
[Laravel サービスプロバイダついに理解](https://reffect.co.jp/laravel/laravel-service-provider-understand)
iOSでスプラッシュ画面を変更しても古いスプラッシュ画面が表示されないようにする方法

iOSでスプラッシュ画面を変更しても、起動時に古いスプラッシュ画面が出続けてしまうことがあります。

アプリを削除してインストールしなおしたりすると治りますが、実装でどうにかする方法もあります。

以下のように、スプラッシュスクリーンを差し替えたときは、iOS13は`/Library/SplashBoard/Snapshots/`以下を、iOS13未満は`/Library/Caches/Snapshots/`を消すことで２回目以降のアプリの起動では古いスプラッシュ画面が表示されるといったことはなくなります。


```swift

    func clearLaunchScreenCache() {
        do {
            if #available(iOS 13.0, *) {
                try FileManager.default.removeItem(atPath: NSHomeDirectory()+"/Library/SplashBoard/Snapshots")
            } else {
                try FileManager.default.removeItem(atPath: NSHomeDirectory()+"/Library/Caches/Snapshots")
            }
        } catch {
            print("Failed to delete launch screen cache: \(error)")
        }
    }
```

ほんとにこれ消しちゃって大丈夫なんだっけ？と不安な方は、以下のように表示して確認してみると良いと思います。

```
$ open -a preview Snapshotsのパス
```

## 参考
https://stackoverflow.com/questions/33002829/ios-keeping-old-launch-screen-and-app-icon-after-update
standard_init_linux.go:211: exec user process caused "no such file or directory"の解決方法

# はじめに
Intellij + Docker + SpringBoot (Maven) で環境構築している際にstandard_init_linux.go:211: exec user process caused "no such file or directory"のエラーが発生したためこれの解決方法を記載します
![screenshot.7 - コピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619433/bc66f7ab-ddd1-9fab-8e91-be2a70ca2cae.jpeg)

だいたい調べると
改行文字がCRLFになっていると出てきます。

# ここで本題
「intellij + 改行コード変換」でググって全ファイルをintellij内からCRLFからLFに変更
再度docker-compose.ymlからdockerを起動しても同じくstandard_init_linux.go:211のエラーが出てしまう。。。
もしかしたらgit cloneした時点でLFにしないといけない？

気をつけて！Git for Windowsにおける改行コード
https://qiita.com/uggds/items/00a1974ec4f115616580

上記でgit for windowsを使用する上での注意点が記載されていた
`git config --global core.autocrlf input`で設定を書き換える

この状態でgit cloneすればLFでファイル落とせるので
dockerを起動すれば無事に解決です。

# 最後に
intellij内からCRLF→LFにしても動かない。。。と思っている方がいれば参考になれば幸いです。

以上、初投稿でした＼(^o^)／
Windows10にVagrantを入れてCentOS7をインストールしよう（5. zip/unzipをインストール）

# はじめに
作成した仮想マシンでいろいろと試すにあたって、zip/unzipは入れていて損はないでしょう。
zip/unzipを例に、コマンドインストールの方法を学びます。

# 使用ツール
- Tera Term

# 手順
[~~1. VirtualBoxインストール~~](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4#1-virtualbox%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
[~~2. Vagrantインストール~~](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4#2-vagrant%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
[~~3. Vagrantfileを設置~~](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4#3-vagrantfile%E3%82%92%E8%A8%AD%E7%BD%AE)
[~~4. 仮想マシンの操作~~](https://qiita.com/erik_t/items/909efb63fd389f486ec3#4-%E4%BB%AE%E6%83%B3%E3%83%9E%E3%82%B7%E3%83%B3%E3%81%AE%E6%93%8D%E4%BD%9C)
[~~5. Tera Termに接続~~](https://qiita.com/erik_t/items/2e3c43cfe8731621b82d#5-tera-term%E3%81%AB%E6%8E%A5%E7%B6%9A)
[~~6. WinSCPに接続~~](https://qiita.com/erik_t/items/2e3c43cfe8731621b82d#6-winscp%E3%81%AB%E6%8E%A5%E7%B6%9A)
[~~7. vagrantユーザーをrootに切り替え~~](https://qiita.com/erik_t/items/8d006b599815c8fbf38b#7-vagrant%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC%E3%82%92root%E3%81%AB%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88)
[~~8. パスワード設定~~](https://qiita.com/erik_t/items/8d006b599815c8fbf38b#8-%E3%83%91%E3%82%B9%E3%83%AF%E3%83%BC%E3%83%89%E8%A8%AD%E5%AE%9A)
[~~9. SSH接続許可（rootユーザー)~~](https://qiita.com/erik_t/items/8d006b599815c8fbf38b#9-ssh%E6%8E%A5%E7%B6%9A%E8%A8%B1%E5%8F%AFroot%E3%83%A6%E3%83%BC%E3%82%B6%E3%83%BC)
[**10. zip/unzipをインストール**](https://qiita.com/erik_t/items/9fbe7b5630b1f62893a1#10-zipunzip%E3%82%92%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)
[11. Vagrantにて仮想環境を配布](https://qiita.com/erik_t/items/11f24633f4248e4f33f0#11-vagrant%E3%81%AB%E3%81%A6%E4%BB%AE%E6%83%B3%E7%92%B0%E5%A2%83%E3%82%92%E9%85%8D%E5%B8%83)


# やってみよう
## 10. zip/unzipをインストール
### コマンドがインストールされているか確認
以下のコマンドでzip/unzipがインストールされているか確認します。

```
yum list installed | grep zip
```

zipもunzipもインストールされていません。
![zipunzip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409907/69a26995-ecfe-41c5-9f19-42e045a7ffa2.png)

### インストール
以下のコマンドでインストールします。
確認の選択肢が出てきたらすべて「y」を入力します。

```
yum install zip
yum install unzip
```

インストールできているか確認してみましょう。
![zipunzip2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/409907/2d639f5d-0cb0-c0b3-4bcf-2a4ebbab48cd.png)
できてますね。

# 参考サイト
[CentOS に zip を yum で普通にインストールしました。今更です！](https://oki2a24.com/2012/07/27/install-zip-with-yum-in-centos/)

# 関連ページ
## Windows10にVagrantをを入れてCentOS7をインストールしよう
[1. VagrantインストールからVagrantfileを設置まで](https://qiita.com/erik_t/items/d7f7abbf7deafa4c6fe4)
[2. 仮想マシンの操作](https://qiita.com/erik_t/items/909efb63fd389f486ec3)
[3. WinSCP、Tera Termに秘密鍵でログイン ](https://qiita.com/erik_t/items/2e3c43cfe8731621b82d)
[4. WinSCP、Tera Termにrootユーザーでパスワードログイン](https://qiita.com/erik_t/items/8d006b599815c8fbf38b)
5．zip/unzipをインストール
[6. Vagrantにて仮想環境を配布](https://qiita.com/erik_t/items/11f24633f4248e4f33f0)
windows更新したらWSL2が起動しなくなったんだが

windows更新したらWSL2が起動しなくなった際の対処法を一応メモ
結論はカーネル更新したら直った。

##環境
Windows10 Pro　Version 10.0.19041.172
WSL2(ubuntu)を利用

##対処法
https://docs.microsoft.com/ja-jp/windows/wsl/wsl2-kernel
にアクセスして更新プログラムを実行して適用するだけ。

##補足
コマンドプロンプトでwslを実行すれば

```
WSL 2 を実行するには、カーネル コンポーネントの更新が必要です。
詳細については https://aka.ms/wsl2kernel を参照してください
```
と表示されます。
iOSでgitのcommit hashを取得し表示する

iOSアプリを開発していて、アプリの画面内にバージョン情報を表記することがあると思います。
この際、gitのcommit hashを表示したかったので、方法をまとめました。
こんな感じでバージョン情報を表記できます。
`1.0.0_d6d4de6`

Xcodeのバージョンは `Version 11.4 (11E146)` です。

# Info.plistの編集

`Info.plist` に `CommitHash` というkeyを追加します。
valueには `undefine` というStringを入れておきます。
<img width="594" alt="Info.plist" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/784c8d7b-bb98-0b09-8c8c-eb3582951496.png">

# Build Settingsの編集

Build Settings の `Preprocess Info.plist File` を `YES` に変更します。
![BuildSettings](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/902324e2-060c-c21a-664b-95ac29761c0c.png)

# Build Phasesの編集

Build Phases の `Compile Sources` の前に `Run Script Phase` を追加します。
今回は `Get Commit Hash` という名前で作成しています。

コマンドは下記を追加します。

```sh
plistBuddy="/usr/libexec/PlistBuddy"
infoPlistFile="${TEMP_DIR}/Preprocessed-Info.plist"

commitHash=$(git rev-parse --short HEAD)
$plistBuddy -c "Set :CommitHash $commitHash" $infoPlistFile
```

Input Filesの項目に
`${TEMP_DIR}/Preprocessed-Info.plist`
を設定します。

下記画像のような設定になっていればOKです！
<img width="1013" alt="BuildPhases" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/279032/97156a55-69b7-99cb-f3e8-3acde21d13a9.png">

# コードからバージョン情報とcommit hashを呼び出す

swiftのコードからバージョン情報とcommit hashを呼び出すには下記のようにします。

```swift
let info = Bundle.main.infoDictionary!
let versionName = "\(info["CFBundleShortVersionString"]!)_\(info["CommitHash"]!)"
```

以上です！
AWS lambdaで setTimeout を待つ(await, callback２つの手法)

`lambda` で、 `setTimeout` を利用する場合、何も意識しない場合 `lambda` の実行が終わってしまいます。

それを待つには、 `await` を使う方法がパッと思いつきますが、 `callback` を使っても待つことが出来ます。


## await を利用するパターン

`Promise` を使って書きます。

```
exports.handler = async (event, context, callback) => {
    await new Promise(resolve => {
        setTimeout(() => {
            console.log('waited!!!!!!!!!!!!')
            resolve();
        }, 2000);
    });
};
```

## callback を利用するパターン

`callback` メソッドは、実行前に `node` のイベントループが空になるまで待つようになっているので、 `setTimeout` が終わるまで待ちます。
( `callbackWaitsForEmptyEventLoop` がデフォルトだと `true` なので )
https://docs.aws.amazon.com/lambda/latest/dg/nodejs-context.html

```
exports.handler = async (event, context, callback) => {
    setTimeout(() => {
        console.log('waited!!!!!!!!!!!!')
    }, 2000);
    callback()
};
```
Ruby on Rails チュートリアル 3日目

##3日目
三日目にしてやっと、一章が終わりました。[1.4.3 Bitbucket](https://railstutorial.jp/chapters/beginning?version=5.1#sec-bitbucket)でだけ少しつまずきましたのでそれのメモだけしておこうと、思います。
SSH公開鍵を作るとき、最初は設定から鍵の生成ができることがわかりませんでした。
明日からは、2章をやっていこうと思います。
タイムマネジメント

タイムマネジメントは、マルチタスクをこなすデータエンジニアにとって重要なテーマです。例えば、企業内で働くデータエンジニアであれば、障害だったり、同僚や上司からの横やりが入り、現在行っている作業が中断するなんてことは日常茶飯事です。

そんな中、

- 集中して仕事できない！
- どれも中途半端で作業がなかなか進まない！

なんて悩みを抱えてらっしゃる方も多いかと思います。

そこで、今回はそんな悩みを解決してくれるであろうタイムマネジメントについて考えてみたいと思います。


#タイムマネジメントとは？
正直私もこのブログを書くまでは「<b>タイムマネジメント</b>」について考える機会がありませんでした。

ある[記事](https://www.mindtools.com/pages/article/newHTE_00.htm)によると、

>タイムマネジメントとは、各々の活動に時間をどの様に配分するかを整理したり、計画したりするプロセスのこと

と解説されています。
良いタイムマネジメントが出来ていると、よりスマートに仕事ができ、忙しい時やプレッシャーを感じている場面であっても少しの時間で成果を出すことができ、逆にそれが出来ていない場合、仕事効率に影響が出たりストレスを感じてしまうようです。

とはいえ、この定義を読んだだけでは、実際にどんなことを行えば良いのか分かりませんよね？

ここからは、タイムマネジメントを行うにはどういったポイントを意識すれば良いのかについて紹介したいと思います。

#タイムマネジメントのポイント
**[Forbesの記事](https://www.forbes.com/sites/johnrampton/2018/05/01/manipulate-time-with-these-powerful-20-time-management-tips/#79969dcc57ab)**によると、 タイムマネジメントを実行する上でのポイントとして以下が挙げられています。 

時間が実際どのように使われているかについて追跡監視する
各タスクについて期限を決める
To-doリストを使う。
事前に計画する
朝の時間を最重要タスクに使う
タスクを委任したり、アウトソースする方法を学ぶ
1つの仕事に集中する
自分に合った時間の使い方を探してみる
この他にも様々なTipsが記事の中で紹介されていますが、詳しくは記事をご覧ください。

さらにこれ以外にも、Trelloのブログで紹介されているようにポモドーロテクニックを活用し生産性を高めるタイムマネジメントのやり方もあります。
**[ポモドーロテクニックを活用したタイムマネジメント術](https://blog.trello.com/ja/how-to-improve-productivity-with-pomodoro-technique)**


#タイムマネジメントのメリット
タイムマネジメントを行うことにより、以下のメリットを享受できます。

####1. ストレスが減る

仕事のスケジュールを自身でコントロールできていれば、ストレスは低くなります。

####2. 多くの仕事をこなせる

タイムマネジメントを行う目的の１つはまさにこれです。効率的に少ない時間で仕事をこなすことができます。

####3. 手戻りを防げる

タイムマネジメントが出来ていないと仕事の質が低下します。作業漏れやミスによって手戻りを強いられた経験のある方は多いのではないでしょうか？

####4. 身の回りで起こる問題が減る

アポを忘れてしまった、遅刻した、納期に間に合わなくなったといった問題はタイムマネジメントができていないために起こる問題だと言えます。

####5. 自由時間が増える

どんな人にも１日は等しく24時間です。作業場所や移動時間、無駄な打ち合わせを極力避けることで多くの時間を確保できます。

####6. チャンスを掴みやすくなる

作業が忙しくて本来やりたかった仕事や出世に繋がる仕事を失うなんて経験をしたことはないでしょうか？幸運を掴むには、幸運を受け入れる準備ができてなければなりません。

#バーンアウト対策にも有効？
バーンアウト（燃え尽き症候群）という言葉を聞いたことはないでしょうか？日本では昨今よく目にする言葉なのでご存知の方も多いかと思います。ただ、皆さんの認識では、誰にでも起こりうる一般的な病気だという認識はないのではないでしょうか？

[RescueTime社のブログ記事](https://blog.rescuetime.com/burnout-syndrome-recovery/)によると、バーンアウトは昨今一般的なものになってきており、研究によると23-54%の労働者が過去もしくは現在バーンアウトを経験していると言われているそうです。このデータはあくまでアメリカのものですが、日本でもバーンアウトは、もはや特定の人だけに起こりうる特殊な問題ではないことは、この数字からも理解いただけるのではないかと思います。記事内にもある通り、タイムマネジメントはこういった問題に対処する上で有効です。

#まとめ
今回のブログをご覧になって、タイムマネジメントを実践してみたいと思った方は、先ほど紹介したポモドーロテクニックやタイムマネジメントに特化したアプリを利用してみてはいかがでしょうか？
以下のリンクで紹介されているアプリはタイムマネジメントを実施していく上でみなさんを強力にサポートしてくれます。（製品の機能紹介はここでは省きます。）

**[作業効率をアップさせる「時間管理」の考え方とアプリ・ツール９選](https://blog.hatena.ne.jp/datapipeline/datapipeline.hatenablog.com/edit?entry=26006613515840246)**

タイムマネジメント以外のソフトスキルについて興味がございましたら、「**[データエンジニアの成功に不可欠な6つのソフトスキル](https://www.xplenty.com/jp/blog/soft-skills-data-engineers-need-to-succeed-ja/)**」もぜひお読みください。
ジョンズ・ホプキンズ大の新型コロナウイルスのデータをPower BIで可視化してみよう（4/5）

# 前回の記事（3/5）のまとめ

[前回の記事](https://qiita.com/yoshiwatanabe/items/264c253f448858f13c76)では新たにいくつかのテーブルを定義し、テーブルの間にリレーションを定義しました。

* 一番最近の日のデータのみを持つ```Latest``` テーブル
* 場所を表す```Location``` テーブル
* Confirmed、Deaths、Recoveredなどのステータスを表す```Status``` テーブル
* メジャーの定義を一か所で整理できるように```_Measure```テーブルを作る
* 可視化した際に役に立つテーブルのリレーションシップ

# 今回の記事（4/5）のゴール

今回の出発点はモデルです。このモデルにはまだ```Measure```(メジャー）がひとつもありません。この状態でグラフやチャートなどのビジュアルを作成することは可能ですし、もしかしたらそれだけで要求を満たすかもしれません。ですが、メジャーを使ってなんらかの「集計情報」を計算して可視化することでレポートにより意味のある情報を加えることができます。

以下のメジャーを作成します

* Cases すべてのケース（感染確認数＋死亡数＋回復数）
* Confirmed 感染確認数
* Deaths 死亡数
* Recovered 回復数
* Mortality rate 死亡数／感染確認数
* Recovery rate 回復数／感染確認数
* Daily Increase 増加数／日

# メジャーの作り方

メジャーはどのテーブルの下でも作成できますが```_Measures```テーブルにまとめて作成します。

下図のように```New measure```メニューを選択します。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103139/a8b55eef-183d-3397-05ee-d1bf0c0df41a.png)

新規メジャーが作成され、```_Measure```テーブルの下に追加されます。Formula Barが表示されてプロンプトがユーザーの入力を待っている状態になります。```=```記号の左側にメジャーの名前を指定します。```=```記号で始まる右側はDAX（Data Analysis Expression)フォーミュラと呼ばれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103139/79d5676e-a390-26f3-528f-586f7e8279bc.png)

下は```Cases```メジャーの定義です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103139/e3e0fb90-590b-b738-db58-72e6908b358b.png)

```
Cases = SUM(Latest[Value])
```

LatestテーブルのValueカラムの値の和、ということになります。

# 他のメジャーを定義する

同じ要領で他のメジャーも定義しましょう。メジャーはデータモデルそのものを変更するわけではないので、エラーが出たりしても問題ありません。

ところでメジャーは他のメジャーを元に計算することも出来ます。```Deaths```メジャーは上記の```Cases```メジャーを再利用しています。

```
Confirmed = 
CALCULATE(
    [Cases],
    Latest[Status] = "Confirmed"
    )
```

> DAXフォーミュラを複数の行に渡って記述するには改行に「Shift+Enter」を使います。

どんどん定義していきましょう～。

```
Deaths = 
CALCULATE(
    [Cases],
    Latest[Status] = "Deaths"
)
```

```
Recovered = 
CALCULATE(
    [Cases],
    Latest[Status] = "Recovered"
)
```

```
Mortality Rate = DIVIDE([Deaths], [Confirmed])
```

```
Recovery Rate = DIVIDE([Recovered], [Confirmed])
```

最後に、少し複雑なDaily Increaseメジャーを定義します。ここでは今日と昨日の日を変数として格納して、今日までの合計から昨日までの合計を引いています。（もっと効率の良いDAXフォーミュラもあると思うので知ってる人はぜひコメント欄で教えてください）

```
DailyIncrease = 
 VAR today = MAX (master[date])
 VAR yesterday = MAX ( master[date] ) -1
 RETURN CALCULATE ( SUM (Master[Value] ), Master[Date] = today ) - CALCULATE ( SUM ( Master[Value] ), Master[Date] = yesterday )
```

全てのメジャーが定義し終えたら下図のようになっているはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103139/cda68a29-56c8-ee12-d990-48db62ea2cd3.png)

# 5/5に続く

さていよいよ、[次の記事](https://qiita.com/yoshiwatanabe/items/79106465dce84378cd67)ではモデルとメジャーを使って情報の可視化を行います。
GitHubのチーム利用でも無制限でプライベートリポジトリが利用可能になったので、TeamからFreeにしてもいいか考察した

# TL;DR

以下の条件のいずれかに該当する場合、Freeにするのはやめたほうが無難です

* `master`、`release`等、作業ブランチ以外での事故が多い
* Pagesを使って公開している
* GitHub Actionsで毎日合計1時間以上使っている

# 本題

GitHubがチーム利用でも無制限でプライベートリポジトリが利用可能になりました
https://github.blog/2020-04-14-github-is-now-free-for-teams/

詳細は↓になります
https://github.com/pricing

詳細を見ると、確かにプライベートリポジトリが無制限に使えるようにはなっているものの、最少額の有料プランTeamともちろん差があります
なので、今Teamプラン契約しているけど、Freeプランに移行しても問題ないのか考えてみました

# FreeとTeamの差分

https://github.com/pricing の表を元に違う部分だけ書き出します

## Code workflow

|項目|Freeプラン|Teamプラン|
|----|----|----|
|GitHub Actions|2,000分/月|3,000分/月 [^1] |
|Protected branches|パブリックのみ|プライベートも利用可能|
|Code owners|パブリックのみ|プライベートも利用可能|
|Draft pull requests|パブリックのみ|プライベートも利用可能|
|Multiple pull request assignees|パブリックのみ|プライベートも利用可能|
|Scheduled reminders|パブリックのみ|プライベートも利用可能|
|Automatic code review assignment|パブリックのみ|プライベートも利用可能|

[^1]: 2020/5/14以降に適用


## Collaboration

|項目|Freeプラン|Teamプラン|
|----|----|----|
|Pages and wikis|パブリックのみ|プライベートも利用可能|
|Repository insights|パブリックのみ|プライベートも利用可能|
|Multiple issue assignees|パブリックのみ|プライベートも利用可能|

## Security and compliance

|項目|Freeプラン|Teamプラン|
|----|----|----|
|Required reviews|パブリックのみ|プライベートも利用可能|
|Required status checks|パブリックのみ|プライベートも利用可能|

## Support and deployment
|項目|Freeプラン|Teamプラン|
|----|----|----|
|Standard Support|利用不可|利用可能|

# 考察

差分を元に重要な部分をかいつまんで考察します
一部、私が使ったことがない機能がある(もしくは使っているけど名称と紐付いてない)ので、これ重要じゃね?というところがあればコメント下さい・・・

## GitHub Actions

3,000分/月(50時間)から2,000分/月(約33.3時間)に短縮されます
毎日1時間程度であれば、無料に落としても問題無い感じです

## Protected branches

ブランチの保護が出来なくなります
うっかり`master`にプッシュしちゃった、消しちゃった・・・という事故が増えます
`master`は極端な例ですが、同様に`develop`や`release`にも同じことが言えるので、注意を払う必要があります

## Pages and wikis	

使えなくなります
PageでWebサイトを公開している、Wikiをナレッジとして利用している場合、Freeにしないか、別で用意してからFreeにするのが良さそうです

# まとめ

小規模なプロジェクトなら、Freeにしても問題なさそうな様子です
これからスタートするプロジェクトでも、Pagesを使わない様にするならFreeからでも良さそうです
東京オリンピックのエンブレムを遊びつくす！(3)〜ひし形充填の基本〜

前回はエンブレムは正十二角形を**ひし形で敷き詰める**ことでできているという事がわかりました。今回は前回に引き続いて、では正十二角形をどのようにひし形を敷き詰めるのかを考えていきましょう。

#そもそもひし形とは
ひし形は次の二つの性質を持っています。
・**四つの辺の長さが等しい(定義)**
・**向かい合う辺が平行**
![fig3_1-02.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/0ef5abce-1355-12eb-20b8-b185f172fd99.tiff)
何を今更という感じではありますが、これからの複雑な話を理解する際に大事なのでしっかり確認しておきましょう。

#充填に必要なひし形の条件
ひし形の特徴を復習したところで、充填するひし形はどのような制約を受けるのか考えてみましょう。
まずは辺の長さから考えてみると、辺の長さは充填される正十二角形の一辺の長さをk等分した長さであればいいということは直感的にわかるかと思います。ひし形の辺の長さは全て同じなわけですから、この条件を満たさないと少なくとも正十二角形の辺の部分でひし形がはみ出してしまいます。
![fig3_2.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/36401053-5c2d-dcdf-c8cd-717ff647d8d7.tiff)
次に角度について考えてみましょう。角度についてはなかなか難しそうですね。ひし形の性質を思い出してみると向かい合う辺が平行と言うものがあります。そこでひし形の2辺の間の角度ではなく、各辺の傾きについて考えてみましょう。
辺の傾きに注目して改めて充填された図形を眺めると、平行な辺が連なっていることに気づくと思います。
![fig3_3-01.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/4f18c73b-a60b-eca6-376c-1371603b7c24.tiff)
当然と言えば当然のことですね。隣り合うひし形は一つの辺を共有しています。隣り合うひし形は一つの辺を共有します。そして各ひし形の共有する辺の対辺は共有する辺と平行です。それはつまり1組の隣り合うひし形の両端の辺と共有する辺は平行と言うことです。
![fig3_4-04.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/bb9945be-a103-a165-645d-7a028bdcab5e.tiff)

図のように平行な辺が連なっているよう見えたのはこの連鎖だったと言うわけです。
このままでは辺の連なりがわかりにくいので、辺の中点どうしを結び、端の辺を残したユニットを**帯**と呼ぶことにします。また帯の両端の辺を**始辺**、**終辺**と呼ぶことにします。
![fig3_5-05.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/8a24495b-cbfd-0afc-411a-41f5d8cb7a79.tiff)
図より明らかなように、この始辺と終辺にあたる辺は正十二角形の辺と重なります。ということはこの帯に属する辺は全て正十二角形のいづれかの辺と平行と言うことになります。

ここで充填するひし形の辺の内、どの帯にも属さない辺はあるのでしょうか？答えはノーです。ひし形は必ずその四辺を他のひし形か正十二角形の辺と共有することになります。仮にどの帯にも属さない辺があったとして、その辺は隣り合うひし形と重なるので、どの帯にも属さない傾きの辺の連なりができることになります。しかしこの連なりは正十二角形の辺と重ならない限り途切れることはありません。そして途切れるとき、その最後の辺は正十二角形の辺と重ならなければなりません。重なるのであればそれは帯に属していると言うことなので帯に属さないと言うことに矛盾します。よってすべてのひし形の辺はいずれかの帯に属すと言うわけです。
各ひし形は2通りの傾きの辺からなっています。つまり各ひし形は2つの帯に属し、その帯が分ればひし形の形状を決定できるということです。
![figure3_6-06.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/272069df-a771-01a4-6b38-dae33945aca8.tiff)


#帯について
ここで図のように番号と角度を決めて、帯を
**角度_番号**の帯
と呼ぶことにします。
![figure3_7-07.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/3aff243e-22bb-ff25-138d-211d9f0a2736.tiff)

帯の始辺と終辺は正十二角形の対辺という関係があります。帯が正十二角形に収まっていることを考えれば、一つの帯は始辺の角度が違う全ての帯と交わります。その交点にできるひし形は、先ほど説明した通り2つの帯の傾きによって決まります。
![figure3_9-09.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/ef90e835-952f-4a9b-e4a1-bfbbb833d3a9.tiff)
#ひし形の配置について
今までの説明で個々のひし形については理解できたと思います。しかしひし形を敷き詰めるにはどこにどのひし形を配置するかがわからなければなりません。
が、これはもうほとんど答えは出ています。先ほどから出ている帯というのはひし形の形だけでなく、どのようにひし形が連なっているか、つまりどのようにひし形を配置するかを示すものでもあります。ただ注意しなければならないのは帯によって決まるのはひし形の座標ではなく、ひし形同士の関係、つまりどのひし形がどのひし形の隣に来て…といった部分のみということです。
実際に敷き詰めるには順番通りにひし形の辺をくっつけてあげる必要があります。
(詳しくは次回説明します)
![figure3_10-10.tif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498495/58a040d6-85e7-3d9d-dcdc-43cd6f543630.tiff)


#まとめ
今までのことをまとめると
1.ひし形の帯を決めて
2.帯の交点に交わる帯に応じてひし形を描いて
3.ひし形をうまくくっつき合わせる
と正十二角形をひし形で敷き詰めることができます。

ひし形充填のやり方がわかったところで今回はここまで！次回はさらに発展して色々なひし形の敷き詰め方を作る&grasshopperで書くための伏線を張ります！
美しいWeb API設計について復習する

#はじめに
エンジニアになり1年が経過するが、APIという単語は実によく聞きます。
経験者では当たり前の知識でも、これから詳細設計を担当する新人にとっては色々なルールがあるんだよということを伝えるために書き残します。

APIとは、「特定のURIにアクセスすることで、サーバー側の情報を書き変えたり、サーバー側の置かれた情報を取得できるウェブシステム」のことです。

もっとわかりやすく、Twitterで考えてみましょう。
Twitterで特定のユーザーのタイムラインの情報を取得したい時、

https:// api.twitter.com/~~~ユーザー情報/

というURLで指定したユーザーの情報を表示することができますよね。(APIはjson形式でデータ取得します)

もし自分が開発するアプリで東京の天気予報の情報だけ欲しい場合、「Yahoo!天気」で東京の天気予報のAPIのみを取得することが可能になります。
つまり、わざわざ全国の天気を取得する必要がなく東京だけ欲しい！という要望が叶うのです。

#美しいAPI設計とは何か
では、APIを設計する上で大切な「美しいAPI」について書いていきます。

美しいAPIとは以下のように定義されています。
・使いやすい
・変更しやすい
・頑強である
・恥ずかしくない

これらの定義に従い、APIのエンドポイントについて考えていきましょう。
＊エンドポイントはAPIにアクセスするためのURIのことです。

エンドポイントを決める際に必要な原則は以下です。

**覚えやすく、どんな機能を持つURIなのかがひと目でわかる**

##短く入力しやすいURI
エンドポイントは短く入力しやすくシンプルで覚えやすいことが大切です。

×　https:// api.twitter.com/service/twitter/search
○　https:// api.twitter.com/search

×のエンドポイントでは余計な情報が入っちゃっていますよね。
service/twitterは必要なく、api.twitter.com/searchだけでTwitterの検索機能のAPIだと判断できます。

##人間が読んで理解できるURI
エンドポイントを見れば、すぐに何をするAPIか理解できることが大切です。

上記例、https:// api.twitter.com/searchはひと目見ればすぐにTwitterの検索機能だなと判断できます。

例えば、以下のようなエンドポイントでは何がしたいのかすぐに理解できないでしょう。

×　https:// api.twitter.com/service/twitter/u/s

なにこれ？？ってなりますよね。
uはuser?? sはsearch??って無理やりに理解はできますが、一見何がしたいのかわかりません。

#大文字小文字が混在していないURI
エンドポイントの中にアルファベットの大文字・小文字を混在させないことが大切です。

×　https:// Api.Twitter.com/Search 
○　https:// api.twitter.com/search

大文字・小文字の混在はAPIをわかりづらく、間違えやすくします。

#ハックしにくいURI
ハッキングできないエンドポイントにすることが大切です。大切というか必須です！

例えば、以下のようなURIは最低最悪です。

×　https:// api.twitter.com/search/item/12345

このエンドポイントをみて、ひと目でidが12345のitemを検索しているとわかります。
そして、idの部分を変えれば他のidのitem情報を取得できるんだと推測できますよね。

#【最後に】開発者にわかりやすくを意識する
仕様設計者がせっかく作成したドキュメントであっても、開発者はドキュメントを熟読せず、開発をどんどん進めがちです。

仕様書に書いてあるわ！！
ってイライラする場面が現場で多々見受けられますが、こうしたことを避けるためにも設計者は美しいAPIの設計を意識することが非常に大切です。


###参考文献
Web API The Good Parts　水野貴明　著
[SASS] 最大ブラウザ幅以上になるとvwをpxに変換するmixin


「リキッドデザインにしたい！でもブラウザ幅が大きくなりすぎると要素も大きくなり過ぎて見辛い！」となったので、最大ブラウザ幅を越えるとvw値からpx値に変換してくれるmixinを作りました。
（一定幅から固定値になるレイアウト指定を、フレキシブルデザインというらしい）

#やっていること
- デザインデータのアートボードサイズと要素のpx値から、vwを計算
- ブラウザ幅が一定値を超えたら、px値に変換してサイズを固定する
- この時↑のpx値は、ブラウザ幅が最大の時のvw計算時のpxの値


##使い方
例えば、デザイン上で要素が330pxのとき

```code:sass
 //引数に、プロパティとpx値を渡す
 .sample {
   @include mq-liquid(width, 330);
 }
```

コンパイル後↓

```code:caa
 //ブラウザ幅が最大（768px）以下のとき
 .sample {
   width: 85.27132vw;
 }
 
  //ブラウザ幅が最大（768px）以上のとき
 .sample {
   width: 654.88372px;
 }
```



#mixinを作る
```code:sass

 //①ブレークポイントを変数に代入する 
 $base-width: 387;  //アートボードサイズ
 $max-width: 768;

 //②breakpointのMapを作る
 $breakpoints: (
   m: 'only screen and ( min-width: calc(#{$base-width} + 1px) )', //769px以上の時
 );

 //③要素のpxから、vwを求める関数
 @function calc-vw($item-width) {
   @return $item-width / $base-width * 100vw;
 }
 
 //④要素のpxから、$max-width（最大画面幅）の時のvwを求める関数
 @function calc-vw-isMax($item-width) {
   @return $item-width / $base-width * $max-width;
 }

 //⑤画面幅に応じて適応される関数が変わるmixinを作る。
 //引数は、（cssプロパティ、値、ブレイクポイント）
 @mixin mq-liquid($property, $value, $breakpoint:m) {
   @media only screen and #{map-get($breakpoints, $breakpoint)} {
     #{$property}: calc-vw-isMax($value); 
   }
   #{$property}: calc-vw($value);
 }
```
RPAエンジニアになるために必要な素質

結論から言ってしまえば、Perl開発者のラリー・ウォール氏が提唱した「プログラマの三大美徳」に当てはまる人です。
ただ、これで終わりでは意味が無いので、ひとつひとつ脚色しながら説明していきましょう。

## 怠惰
プログラマの三大美徳である怠惰について説明します。

怠惰な人は一回行った作業は二度と行いません。
今後複数回行う可能性がある作業は真っ先に自動化します。

怠惰な人は同じことは二度も言いません。
質問されそうなことを全て網羅した丁寧なドキュメントを準備します。

怠惰な人は勤勉です。
怠惰に仕事をこなすために必要なスキルを日々研鑽しています。

## 短気
プログラマの三大美徳である短気について説明します。

短気な人は高速なワークフローを作ります。
動作が遅いと人はイライラします。それを避けるために高速に動くワークフローを作ります。

短気な人は拡張や修正がしやすいワークフローを作ります。
後々要件が変更になったときに拡張や修正が難しければイライラします。それを避けるために拡張や修正がしやすいワークフローを作ります。

短気な人は情報収集を怠りません。
要件漏れによる修正が発生しないように異常なほど情報収集を行います。

## 傲慢
プログラマの三大美徳である傲慢について説明します。

傲慢な人は簡潔で見やすいワークフローを作ります。
威張り散らすために、誰にも指摘されない完璧なワークフローを目指す傾向があります。

傲慢な人は思考を深堀りします。
誰にも指摘されない完璧なワークフローを目指しているため、誰よりも長く深く考えます。

傲慢な人は失敗を素直に受け止めます。
自分が作ったワークフローに責任を持ち、なにか失敗があれば素直に受け止めます。
また、誰かに直してもらうなんてことは絶対にしません。


## おわり
いかがだったでしょうか。
あなたは怠惰で短気で傲慢な人間でしたか？
wiresharkインストール（Mac）

#はじめに
こちらではwiresharkのインストールと基本的な使い方を紹介したいとおもいます。

#環境
MacBookPro

#手順
```
$  brew cask install wireshark
```

おわったら
起動


調べたいネットーワークを選択

任意の操作を行ます。
ここではpingをとばしてみます。

```
$ ping (任意のipアドレス)
```

通信を行っているのがわかるとおもいます。


#まとめ
いかがだったでしょうか他には色々機能があります。
是非[公式](https://www.wireshark.org/)を確認してみてください
Matplotlibで図の下側に情報を追記する

[一覧表に戻る](https://qiita.com/h398qy988q5/items/4af78a3afe73b6f38419)

図の周りに文字情報を追記したい場合があります。`plt.text`で文字情報を追記出来ますが、いちいち場所を指定しないといけないので面倒です。以下のコードは`legend`を使うことで場所の指定なしで追記しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278468/9bad9a0d-83f9-1af5-73a4-badeee3e60ce.png)

```python
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
%matplotlib inline
plt.rcParams['font.size'] = 15

def r2(y1, y2):
    r2 = str(np.round(np.corrcoef(y1, y2)[0,1],3))
    return r2

xa_train = [1,3,5,7]
xa_test  = [2,4,6,9]
ya_train = xa_train + np.random.randn(4)
ya_test  = xa_test  + np.random.randn(4)

xb_train = [1,3,5,7]
xb_test  = [2,4,6,9]
yb_train = xb_train + np.random.randn(4)
yb_test  = xb_test  + np.random.randn(4)

plt.figure()
plt.subplots_adjust(wspace=0.2, hspace=0.4)

gs = gridspec.GridSpec(2, 2, width_ratios=[1,1], height_ratios=[4,1])

plt.subplot(gs[0])
plt.scatter(xa_train, ya_train, color='k', label='train')
plt.scatter(xa_test, ya_test, color='r', label='test')
plt.xlim(0,10)
plt.ylim(0,10)
plt.xticks([0,2,4,6,8,10])
plt.yticks([0,2,4,6,8,10])
plt.plot([0,10],[0,10], color='gray', lw=0.5)
plt.grid()
plt.title('train')
plt.xlabel('measured')
plt.ylabel('predicted')

plt.subplot(gs[1])
plt.scatter(xb_train, yb_train, color='k',label='train')
plt.scatter(xb_test, yb_test, color='r', label='test')
plt.xlim(0,10)
plt.ylim(0,10)
plt.xticks([0,2,4,6,8,10])
plt.yticks([0,2,4,6,8,10])
plt.plot([0,0],[10,10])
plt.plot([0,10],[0,10], color='gray', lw=0.5)
plt.grid()
plt.title('test')
plt.xlabel('measured')
plt.tick_params(left=False,labelleft=False)
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left', borderaxespad=0)

plt.subplot(gs[2])
plt.tick_params(left=False, labelleft=False,bottom=False, labelbottom=False)
for i in ['top','bottom','left','right'] : plt.gca().spines[i].set_visible(False)
plt.scatter(0,0,label='$R^2_{train}=$'+r2(xa_train,ya_train)+'\n$R^2_{test}=$'+r2(xa_test,ya_test),alpha=0)
plt.legend(frameon=False, loc='upper left')

plt.subplot(gs[3])
plt.tick_params(left=False, labelleft=False,bottom=False, labelbottom=False)
for i in ['top','bottom','left','right'] : plt.gca().spines[i].set_visible(False)
plt.scatter(0,0,label='$R^2_{train}=$'+r2(xb_train,yb_train)+'\n$R^2_{test}=$'+r2(xb_test,yb_test),alpha=0)
plt.legend(frameon=False, loc='upper left')

plt.show()
```
Googleが提供しているサービス「Teachable Machine」でヨガポーズの学習モデルを作って遊んでみた

#概要

コロナウイルスの影響で在宅ワークしているのですが、運動量が減って健康に悪いなと思い、簡単にヨガのポーズを診断してくれるものを作ってみました！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Teachable Machineでヨガポーズの学習させてみた。<br>※ヨガ未経験です(~_~;)<br> <a href="https://twitter.com/hashtag/%E3%81%86%E3%81%A1%E3%81%A7%E4%BD%9C%E3%82%8D%E3%81%86?src=hash&amp;ref_src=twsrc%5Etfw">#うちで作ろう</a> <a href="https://twitter.com/hashtag/protoout?src=hash&amp;ref_src=twsrc%5Etfw">#protoout</a> <a href="https://t.co/cr8B4wVuXj">pic.twitter.com/cr8B4wVuXj</a></p>&mdash; まえぷー@出窓菜園 BWG (@kmaepu) <a href="https://twitter.com/kmaepu/status/1250251162315415552?ref_src=twsrc%5Etfw">April 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


今回は、Googleが提供している画像認識・機械学習のサービス「[Teachable Machine](https://teachablemachine.withgoogle.com/train)」で学習モデル作る方法に触れます。

　このTeachable Machine、何が良いかというと**学習したモデルを、Node.jsやArduinoで使用できる状態でエクスポートできる** ことです！
　学習させたモデルを使う方法は[こちら](https://qiita.com/kmaepu/items/5adfa1532eaa66e9acc5)に書きました。

以下手順です。
 - ポーズを決める
 - 学習用画像の収集
 - 学習の実行
 - テスト

##ポーズを決める
　どんなポーズを学習させるかですが、ヨガ未経験なので次のサイトを参考に簡単そうな「三角のポーズ」と「山のポーズ」の２つにしました。
[ヨガポーズの参考サイト](https://www.zehitomo.com/blog/client/yoga-pose-begginer-easy)

- 三角のポーズ
![三角のポーズ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/133dce94-f7de-9cf0-d6cb-fa20b1c29e34.jpeg)
- 山のポーズ
![山のポーズ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/0f54dc2e-4c1f-2c60-cf20-f668a4297f2b.jpeg)

##学習用の画像収集
　学習のための画像収集ですが、Webカメラを使用しTeacable Machine上で行うことができます。画像収集の準備を進めていきます。

　Teachable Machineを開くと３種類の入力パターンがありますが、今回は「Pose Project」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/424d3e0c-8fa5-0007-a625-5173858ed86e.png)

　次のような画面に移るので、「WebCam」をクリックしてWebカメラモードにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/aba1046c-608b-5f07-cfe4-284f42b6cad4.png)

PCに備え付けのカメラを有効にするか問われるので、有効にします。その後、学習させたいポーズをとり「Record 6 Seconds」ボタンをクリックします。これで学習用の画像を６秒間撮影されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/9436da8e-59c5-16db-3a00-6c5beedf1957.png)

同じことをClass2の方でも行います。もちろんポーズは変えて。これで画像の準備は完了です！

　ちなみに、ネットから拾ってきた画像でもいけるのでは？と思い試しましたが駄目でした...。私は機械学習に詳しくなく表現が難しいのですが、どうやら画像認識で棒人間がオーバーレイされた画像が対象のようです。


##学習の実行
　画像が用意できたら、中央の「Train Model」ボタンをクリックし、学習を実行させます。画像の量やポーズの種類の多さによって時間がながくなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/45f2c2aa-fcc4-da4c-63de-5b2edf3032b1.png)

##テスト
　学習が完了すると右側の「Preview」にカメラ画像が映し出され、どちらのポーズかバーで割合が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/7dbab243-c3cb-a5a4-adb1-66e7264b07b6.png)

#おわりに
　ノンプログラミングでここまでできるとは...。次は学習したモデルをエクスポートして実際にアプリに使っていこうともいます。
　蛇足ですが、ヨガポーズを調べていていろいろ試しまし、使っていない筋肉を伸ばすポーズばかりで「あぁ～伸びる～」と悶絶しながらやっていました(笑)

#参考
[Teachable Machine](https://teachablemachine.withgoogle.com/train)
[ヨガポーズの参考サイト](https://www.zehitomo.com/blog/client/yoga-pose-begginer-easy)