OmniAICreator/Qiita-1.07M huggingface dataset:
Laravel の Relation でCreateManyはバルクインサートしているわけではない

ただの確認不足だったのですが
クエリめっちゃ発行されるなと思い場所をたどったところ
リレーションしている、1:多の子のinsertにcreateManyを使っていた場所でした。

>createManyメソッドで複数のリレーションモデルを生成することができます。

```php
$post = App\Post::find(1);

$post->comments()->createMany([
    [
        'message' => 'A new comment.',
    ],
    [
        'message' => 'Another new comment.',
    ],
]);

```

```
insert into `comments` (`message`, `post_id`, `updated_at`, `created_at`) values ('A new comment.', 1, '2019-11-14 16:48:49', '2019-11-14 16:48:49')

insert into `comments` (`message`, `post_id`, `updated_at`, `created_at`) values ('Another new comment.', 1, '2019-11-14 16:48:49', '2019-11-14 16:48:49')

```

```php:HasOneOrMany
    /**
     * Attach a model instance to the parent model.
     *
     * @param  \Illuminate\Database\Eloquent\Model  $model
     * @return \Illuminate\Database\Eloquent\Model|false
     */
    public function save(Model $model)
    {
        $this->setForeignAttributesForCreate($model);

        return $model->save() ? $model : false;
    }

    /**
     * Create a new instance of the related model.
     *
     * @param  array  $attributes
     * @return \Illuminate\Database\Eloquent\Model
     */
    public function create(array $attributes = [])
    {
        return tap($this->related->newInstance($attributes), function ($instance) {
            $this->setForeignAttributesForCreate($instance);

            $instance->save();
        });
    }

    /**
     * Create a Collection of new instances of the related model.
     *
     * @param  iterable  $records
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function createMany(iterable $records)
    {
        $instances = $this->related->newCollection();

        foreach ($records as $record) {
            $instances->push($this->create($record));
        }

        return $instances;
    }

```

`createMany`は`create`を呼び出し、結果をコレクションに入れています。
`create`では`save`を呼び出し...

バルクインサートできるものと思って使っていたのですが、やはり一括でやりたい場合は`insert`なのでしょうかね

とはいえ、この手のクエリがほかのより以上に速いのはなぜなのでしょう...400μsくらいなんですよね
Laravel 6.0 + React の環境構築

1: Laravel セットアップ

```
$ composer create-project --prefer-dist laravel/laravel LaravelReact

```




2:React セットアップ

```
$ cd LaravelReact
$ php artisan preset react
$ npm install && npm run dev
```


3:簡易　WEBサバ起動 & ブラウザ確認（http://localhost:8000）

```
% php artisan serve
```

4:React動作確認

```/resources/views/welcome.blade.php

    <body>
        <div id="example"></div>
        <script src="{{mix('js/app.js')}}" ></script>
    </body>


```

![スクリーンショット 2019-11-14 17.07.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33953/322c7903-f9a4-cd71-0774-c7a2999030fc.png)
IBM Lift CLIを試してみた

IBM Lift を Windows PC にダウンロード・導入し、Liftコマンドを使用して、
Db2 Warehouse on Cloudにデータをアップロード＆loadした結果についてまとめました。

※当記事は、2019年3月に試したものです。現在の仕様とは異なる可能性があります。

<b>IBM Lift CLI</b>　
https://www.lift-cli.cloud.ibm.com/#download
:point_up_2_tone2:コチラから入手してダウンロード。
同URLの<b>Doc</b> の <b>Getting Started</b> や <b>Command Reference</b> を参照して試しました。

<b> 1. lift put で Db2 Warehouse on Cloud 上にデータファイルをアップロード </b>

・実行コマンド   

```
lift put --file C:\tpchdata\lineitem.tbl --properties-file C:\tpchdata\put.cfg
```
-put対象ファイルは lineitem.tbl
-コマンド・オプションは、任意で作成した設定ファイル put.cfg ファイルで指定

・put.cfg (設定ファイル) 

```
target-user=testuser
target-password=abcdabcdabcd
target-host=xxxx.bluemix.net
```

※下記のように、設定ファイルを使用せず、
コマンド実行時に、'--'を付けてそれぞれ指定することも可能

・例

```
lift put --file C:\tpchdata\lineitem.tbl --target-user=testuser　--target-password=abcdabcdabcd --target-host=xxxx.bluemix.net
```

参考) 実行完了時の出力

```
lift put --file C:\tpchdata\lineitem.tbl --properties-file C:\tpchdata\put.cfg
Putting file C:\tpchdata\lineitem.tbl (size 22GB) at a maximum throughput of 500.00 Mb/s.
[##########] Put 22/22 GB at 14.47 Mb/s (0 sec remain)
Transferred file C:\tpchdata\lineitem.tbl in 46 minutes 31 seconds at average throughput of 68.24 Mb/s.
The file transfer completed successfully.
```


※サマリーや製品ログファイルが、binディレクトリー配下に作成された「runxxxx」というフォルダに作成されていた


<b> 2.  lift load で BLUDBのテーブルにロード </b>

```
C:\Program Files\IBM\Lift\bin>lift load --filename lineitem.tbl --properties-file C:\tpchdata\load.cfg
```

-load対象ファイルは lineitem.tbl
-コマンド・オプションは、任意で作成した設定ファイル load.cfg ファイルで指定

・load.cfg (設定ファイル) 

```
target-schema=DB2INST1
target-table=LINEITEM
file-origin=user
target-user=testuser
target-password=abcdabcdabcd
target-host=xxxx.bluemix.net
field-delimiter=|
```
※target-schema と tagert-table を小文字で実行した際、「テーブルが存在しない」というエラーになりました。

参考) 実行完了時の出力

```
C:\Program Files\IBM\Lift\bin>lift load --filename lineitem.tbl --properties-file C:\tpchdata\load.cfg
Loading file lineitem.tbl into DB2INST1.LINEITEM
Loaded file lineitem.tbl into "DB2INST1"."LINEITEM" in 1085 seconds
Load Id: 1553011248620
Details
  Rows loaded: 179998372
  Rows skipped: 0
  Rows rejected: 0
  Rows deleted: 0
```



<b>【参考情報】</b> 
<b> ◆liftでputしたファイルの一覧を確認したいとき </b> 

```
lift ls 
```

※ --target-user xx --target-password xx --target-host xx の指定が必要。

以下は、put.cfgを指定した実行例

```
C:\Program Files\IBM\Lift\bin>lift ls --properties-file C:\tpchdata\put.cfg
lineitem.tbl
part.tbl
lineitem01.tbl.aspx ←途中でアップロードが中断した場合に作られたように思われる
…
```

<b>◆liftでputしたファイルの削除したいとき</b>

```
lift rm 
```

※ -f で削除対象のファイル名と--target-user xx --target-password xx --target-host xx の指定

以下は、put.cfgを指定した実行例

```
C:\Program Files\IBM\Lift\bin>lift rm -f lineitem01.tbl.aspx --properties-file C:\tpchdata\put.cfg
File 241_lineitem.tbl.aspx successfully deleted
1 files successfully deleted
```


<b> ◆lift コマンドのヘルプ </b>

"--help " でオプション各種が確認できます。

```
lift --help
```
【HTML】まずはこれだけ！HTMLを書こう! Lv.２                  「タグの役割」

# 【HTML】まずはこれだけ！HTMLを書いてみよう Lv.２「タグの役割」

前回は、テキストエディタでファイルの保存、コードを書きブラウザに表示
まで行いました。

今回から、少し詳しくHTMLの書き方について触れていきます。

　わかりやすく解説します。

## ペルソナ

- プログラミングをこれから勉強しようとしている方
- 初めてプログラミングを書こうと思っている方
- Webページを作ってみたい方


## 内容
HTMLの書き方（タグの使い方）

## Key Word

- タグ（開始タグ・閉じタグ）
- タグの役割（可読性）


# 目次

1.タグとは
・ 開始タグと閉じタグ
・ 参考（タグの役割：可読性）

２.まとめ


## Contents

### 1.タグとは？

前回実際にテキストエディタにコードを書いてブラウザに表示をさせましたね。
そのときに**タグ**をご紹介しました。

```HAML:index.html
<h1>Hello World</h1>
```
この
`<h1></h1>`
がタグといわれるものです。

#### 開始タグと閉じタグ

HTMLのタグにはそのタグで挟んだとき、そのタグが持つ役割を文章が持つようになります。
そのタグの始まりを**開始タグ**、終わりのタグを**閉じタグ**と言います。

開始タグ：`<h1>`
閉じタグ：`</h1>`

お気づきかもしれませんが、閉じタグには「/」が入ります。
開始タグと閉じタグの区別はこれだけです。（簡単ですね）

ではここで**h1タグ**の役割をご紹介します。

h１タグは見出しを作る働きがあります。
と行ってもただ字を太く、大きくするだけです。

同じく見出しを作る役割を持つタグに**h2タグ**や**h3タグ**があります。

気づきましたか？実はh1タグの「h」は「Heading」という意味でまさに見出しという意味があり**h1タグからh6タグ**まであります。数字が大きくなるにつれて文字が小さくなります。

つまりタグとは、**開始タグと閉じタグで文章を挟み、その文章にタグの役割を付与するもの**です


####　参考

実はh1タグを使わなくても文字を太くしたり、文字の大きさを大きくすることはできます。
それでもh1タグを使うのは「これは見出しです」とコードを見た人に教えるためです。

大きなプログラムとなるとそのコードの量は膨大で、何千、何万行となります。
そこで重要になることが**「可読性」**です。

膨大なコードから必要な情報を素早くキャッチするには、
そのコードが何を表しているのかわかりやすくする必要があります。

今後、勉強するほどたくさんの書き方に出会うと思います。
そのときの状況によって書き方を変えてく必要がありますが、
タグには**それがどんな役割を持っているのか明確にするという役目がある**
ということは覚えておいてください。

今は「ふーん。そうなんだ」くらいの認識だけで大丈夫です。


####　h1からh６まで書いてみましょう

余談でした。
では実際にh1からh6までコードを書いてみましょう！

```HAML:index.html
<h1>Hello World</h1>
<h2>Hello World</h2>
<h3>Hello World</h3>
<h4>Hello World</h4>
<h5>Hello World</h5>
<h6>Hello World</h6>
```

テキストエディタへの書き方、ブラウザへの表示の仕方は大丈夫ですね？
わからなくなった方は、前回の[まずはこれだけ！HTMLを書いてみよう Lv.1](https://qiita.com/rrrrr1231/items/0715112eb04ffc452712)を確認しましょう。

うまく書けたでしょうか？

一つテキストエディタの便利な機能をご紹介します。
タグを作るのに一回一回`<h1></h1>`とかくの面倒ですよね。

そこでh1と書いたところで**tabキー**を押してみてください。
感動的なことが起きますよ！
[![Image from Gyazo](https://i.gyazo.com/82c3872fdedd5fff604f247ecea68d69.gif)](https://gyazo.com/82c3872fdedd5fff604f247ecea68d69)

ブラウザへの表示までしてみましょう！
[![Image from Gyazo](https://i.gyazo.com/6576a5f91fd7ad35569e2970ba2a900b.png)](https://gyazo.com/6576a5f91fd7ad35569e2970ba2a900b)


こんな感じになりましたか？
先ほどお伝えしたように、h1からh６と数字が大きくなるにつれて
文字が小さくなっていますね。



### ２.まとめ


今回のポイントは

**開始タグ・閉じタグ、タグの役割**についてでした！

- 開始タグと閉じタグで囲むとその文章がタグの与える役割を持つ
- タグにはそれだけで何の役割があるか一目でわかる（可読性のアップ）

ということが理解できたでしょうか？


今回はタグの役割を理解しやすいように`<h1>`タグについて触れました。
次回以降は他のタグにも触れながら実際のWebページを作るための予備知識を身につけていきましょう。

今回も最後までありがとうございました！！
Chromebook(ASUS C100PA)でVScodeを使う(ENG SUB)

# 0.さきがき
くっそ大変だった。主にVScodeのインストールが。ASUS C100PAは32bitOSだが、VScode先生はすでに32bitのLinuxは見捨てておられる。過去バージョンをインストールしようにもエラー。全部で２時間弱かかった、、、はぁ。

コミュニティビルドを提供してくれている[headmeltedさん](https://github.com/headmelted)に感謝。


# 1.Chroutonを用いてUbuntuを導入する

参考：[Crouton を使って ChromeBook に Xubuntu 環境を構築する](http://neos21.hatenablog.com/entry/2017/01/08/234540)

# 2.Ubuntu上にVScodeを導入する

参考：[headmeltedさんのサイト](https://code.headmelted.com)
[headmeltedさん](https://github.com/headmelted)さんがchromebookやら見捨てられた32bitOSやら向けのコミュニティビルドを公開してくれている。
このうち、Linux向けのページに飛んでインストール用のshellをwgetしてくる。+xを忘れずに。
最新のビルドではインストールはできるが、うまく動作しなかったため、過去のビルドを指定してインストールする。


```.sh
#最新のビルドだとwindowがenptyになったので、過去のバージョンを指定する
#ln:19  code_executable_name="code-oss";
code_executable_name="code-oss=1.29.0-1539702286";

#headmeltedさんを信頼する(#Out/ln:49 In/ln:50)
#ln:49 apt-get install -t ${repo_name} -y ${code_executable_name};
apt-get install -t ${repo_name} -y --allow-unauthenticated ${code_executable_name}
```

# 3. code-oss コマンドで起動

```.sh
$ code-oss
```



---
ENG

# 0. First of all
It was so tough work to install vscode. ASUS C100PA works as 32bit and 
 Mr.VScode dropped 32bit linux at the latest build. It took about 2 hours to make it...

Thank you for [https://github.com/headmelted](https://github.com/headmelted).


# 1.Install Ubuntu with Chrouton

Reference：[Crouton を使って ChromeBook に Xubuntu 環境を構築する](http://neos21.hatenablog.com/entry/2017/01/08/234540)

# 2.Install vscode on Ubuntu

参考：[https://code.headmelted.com](https://code.headmelted.com)
[headmelted](https://github.com/headmelted) published the community builds for chromebook, 32bit linux, and so on.
Wget the install shell. Do not forget +x.
At the latest build, it is possible to install, but enpty window.
So specifying some old version.



```.sh
# Specifying older version
#ln:19  code_executable_name="code-oss";
code_executable_name="code-oss=1.29.0-1539702286";

# Just trust Mr.headmelted(#Out/ln:49 In/ln:50)
#ln:49 apt-get install -t ${repo_name} -y ${code_executable_name};
apt-get install -t ${repo_name} -y --allow-unauthenticated ${code_executable_name}
```

# 3. Execute with `code-oss`

Thats it.

```.sh
$ code-oss
```
VisualStudio＆Gradleでマルチアーキテクチャ向けのAPKを作る

# 前回の記事
- [VisualStudioでAntを使ってNativeなAPKを作ってみる](https://qiita.com/furui/items/57df2533d1faa2a38b6f)
- [VisualStudioでGradleを使ってNativeなAPKを作ってみる](https://qiita.com/furui/items/59b5a290b2539bd0c8c3)

# はじめに
armeabi-v7a と arm64-v8a の両方のダイナミックライブラリ(*.so)をを含めたAPKを作る方法を色々検証し、作成する方法が分かりましたのでまとめていきます。

ただし、この方法ですと色々問題があります。
「**どのようなもんだいがあるのか**」「**私の場合はどのように対応したのか**」も一緒にまとめていきます。

今回は「[VisualStudioでGradleを使ってNativeなAPKを作ってみる](https://qiita.com/furui/items/59b5a290b2539bd0c8c3)」のプロジェクトを使って説明します。

# マルチアーキテクチャ対応APKの作り方

### 1. build.gradle.template を書き換える。
複数のアーキテクチャを含めるように **$(SolutionDir)AndroidGradle\app\build.gradle.template** を下記のように書きまえます。

``` build.gradle.template
android.productFlavors {
    create("arm7") {
        ndk.abiFilters.add("armeabi-v7a")
        // 追記
        ndk.abiFilters.add("arm64-v8a")
    }
    create("arm8") {
        ndk.abiFilters.add("arm64-v8a")
        // 追記
        ndk.abiFilters.add("armeabi-v7a")
    }
    create("x86") {
        ndk.abiFilters.add("x86")
    }
    create("x86-64") {
        ndk.abiFilters.add("x86_64")
    }
    create("all")
}
```

これで **$(SolutionDir)AndroidGradle\app\src\main\jniLibs** フォルダ内に「arm64-v8a」と「armeabi-v7a」が存在する状態で、VisualStudioのソリューションプラットフォームが「ARM」か「ARM64」のときにビルドすると双方のアーキテクチャをAPKに含めてくれるようになります。

### 2. ソリューションをビルドする。
ソリューションプラットフォームをARMとARM64でそれぞれビルドを行う。
![00.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75533/f6ca4655-ad52-3e87-5648-915a4be123e9.gif)

これで「arm64-v8a」と「armeabi-v7a」の双方のダイナミックライブラリ(.so)が入ったAPKが生成できているはずです。
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75533/7b5cb4ea-db24-7ab4-05f5-10cdb0b55f63.png)

# この対応の問題点
gradleファイルを修正するだけで簡単にマルチアーキテクチャに対応できるのですが、ここで問題点があります。

### ブレイクポイントがうまく止まらないパターンが有る
これは開発を進めてもらえればすぐにぶつかる問題だと思います。
Android端末に合ったv7aかv8aが実行されます。
私の持っているXperia XZ Premium(SO-04J)はv8aのほうが優先的に実行されます。
v7aとv8aの双方のライブラリが入った状態でソリューションプラットフォームを「ARM」で実行するとエラーになります。
![01.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75533/5bcfecf2-ff80-b144-2b61-f7d17255d2bf.gif)

**ブレイクポイントを止めるためにv7a向けのシンボルファイルを生成しているのですが、APKの中にv8aが有るために実行時にv8aのダイナミックライブラリ(.so)がロードされてしまい、シンボルファイルが不一致を起こしてしまっているため** このようなことが起きると考えられます。

### どのように対応すればよいか
開発の段階（ソリューション構成がDebugのとき）は、v7aかv8aのどちらか片方しか含めないようにします。

### 修正方法
ビルド前タスクの機能を使います。
Sharedプロジェクトのプロパティから「構成プロパティ」->「ビルドイベント」->「**ビルド前のイベント**」へ移動します。
「構成(C)」を「**Debug**」に「プラットフォーム(P)」を「**すべてのプラットフォーム**」にした状態でコマンドラインに下記コードを貼り付けます。

``` コマンドライン
set dir=$(SolutionDir)AndroidGradle\app\src\main\jniLibs\
if exist %dir% (
  for /d %%d in (%dir%*) do (
    echo delete %%d
    rd /s /q %%d
  )
)
```
jniLibsフォルダ以下のフォルダを全て消すバッチ処理になります。
これでブレイクポイントが止まらないということは起きなくなります。

# まとめ
後半の対応はbuild.gradleをうまく使えばもっとスマートにできそうなのでgradle勉強してより良い方法が分かったら新しく記事あげていこうと思います。
Rで使う比較演算子

##  論理テスト
論理テストとは「2は3より大きいか」のような比較のことです．

| 演算子       | 構文 |    テスト    |
|:-----------------:|:------------------:|:------------------:|
| >    | a > b             | aはbよりも大きいか？|
| >=   | a >= b            | aはb以上か？|
| <    | a < b             | aはbよりも小さいか？|
| <=   | a <= b            | aはb以下か？|
| ==   | a == b            | aはbと等しいか？    |
| !=   | a != b            | aはbと等しくないか？|
| %in% | a %in% c(a, b, c) | aはc(a, b, c)のグループに含まれるか？|  

これらの比較演算子はTRUEかFALSEを返す．ベクトルを比較する演算子を使った場合はRは算術演算子と同じように要素ごとに比較をおこないます．

### 参考文献
Garrett Grolemund,大橋真也,長尾高弘（2015）：『RStudioではじめるRプログラミング入門』，89p，オライリージャパン
datadogでdocker containerを監視する

#### マニュアルはここ
https://docs.datadoghq.com/ja/integrations/docker_daemon/#%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB

#### Dockerのインテグレーションを済ませておく
https://app.datadoghq.com/account/settings#integrations/docker


#### 前提
- dockerが動いている

#### 監視方法は２通り
1. hostでdatadog agentを動かす
2. コンテナとしてdatadog agentを動かす

どちらか一方でよい。これを勘違いしていてhostでもcontainerでも動かしていて
containerのdd-agentがstoppedになってしまっていた。
コンテナはスケールアウトすることを考えるので2でやることが多い。hostにインストールはしない。


#### hostでdatadog-agentを動かす場合
通常のインストール後に下記を実行

```
# usermod -a -G docker dd-agent
```

#### containerで動かす場合
**docker-compose.ymlで起動する場合の例**

- 準備   

```
mkdir -p /usr/local/src/dd-agent
cd /usr/local/src/dd-agent
vi docker-compose.yml
```

```docker-compose.yml
version: "3.4"
services:
  dd-agent:
    image: datadog/agent:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc/:/host/proc/:ro
      - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro
    environment:
      - DD_API_KEY=xxxxxxxx
      - DD_TAGS="hogeserver role:hoge env:stg"
      - SD_BACKEND=docker
```


**不要な監視の除外設定**

```/etc/datadog-agent/conf.d/disk.d/conf.yaml
init_config:
instances:
  - use_mount: false
    file_system_blacklist:
      - tmpfs
      - none
      - shm
      - nsfs
      - netns
      - binfmt_misc
      - autofs
    mount_point_blacklist:
      - /var/lib/docker/(containers|overlay2)/
      - /run/docker/
      - /sys/kernel/debug/
      - /run/user/1000/
```

↑これを書かないと /var/log/datadog/agent.log に [Errno 13] Permission deniedがたくさん出ていた

**下記は書かなくても動くらしいけど念の為**

```/etc/datadog-agent/conf.d/docker.d/conf.yaml
init_config:

instances:
    - url: "unix://var/run/docker.sock"
      new_tag_names: true
```

#### dd-agentを起動する
`docker-compose up -d`



#### 確認

```
# datadog-agent status | grep -A 7 docker
    docker
    ------
      Instance ID: docker [OK]
      Configuration Source: file:/etc/datadog-agent/conf.d/docker.d/conf.yaml
      Total Runs: 202
      Metric Samples: Last Run: 114, Total: 23,028
      Events: Last Run: 0, Total: 0
      Service Checks: Last Run: 1, Total: 202
      Average Execution Time : 11ms
```




#### 起動後
- /var/log/datadog/agent.logを確認する
- メトリクスは docker-xx が取れているか確認する
- ホストでdocker statsコマンドでdd-agentが動いているか確認する


## 参考
https://github.com/DataDog/dd-agent/issues/2932
Android 9(Pie)以降で画面起動時に特定のViewに初期フォーカスを当てる方法

今さっき知ったのですが(遅)、Android 9(Pie)で[Viewのフォーカスに関する仕様変更](https://developer.android.com/about/versions/pie/android-9.0-changes-28?hl=JA#focus)があり、**タップモードにおいてActivityは初期フォーカスを暗黙的に指定しなくなっていました**。
この初期フォーカスが自動で当たる機能は入力フォーム画面や検索画面では便利で、使っていた方も多いのではないでしょうか。

Oreo以前であれば、以下のxmlを持つActivityが起動したとき、暗黙的に`EditText`に初期フォーカスが当たっていましたが、Pie以降で同様のことを実現する場合、**明示的に初期フォーカスを当てるViewを指定しなければならなくなりました**。

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- Android Pie以降ではsearchWindowに初期フォーカスが当たらない -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    ...

</androidx.constraintlayout.widget.ConstraintLayout>
```

<br>
手動で初期フォーカスを当てるViewを指定する方法は簡単で、**対象のViewに`<requestFocus />`をネストさせるだけ**です。

```xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- searchWindowに初期フォーカスが当たるようになる -->
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
        <requestFocus />
    </EditText>

    ...

</androidx.constraintlayout.widget.ConstraintLayout>
```

この`<requestFocus />`はOreo以前でも有効なので、対応としてはこれで十分だと思います。
pandasを用いてcsvファイルを読み込もうとすると、毎回numpyのエラーが発生してしまう。

pandasを用いてcsvファイルを読み込みを行おうとしたところ、以下のようなエラーメッセージが表示されました。

```
Traceback (most recent call last):
  File "C:\python\iris_pandas.py", line 1, in <module>
    import pandas as pd
  File "C:\python\pandas\__init__.py", line 22, in <module>
    from pandas.compat.numpy import (
  File "C:\python\pandas\compat\numpy\__init__.py", line 9, in <module>
    _np_version = np.__version__
AttributeError: module 'numpy' has no attribute '__version__'
```

コードは以下の通りです。

```py
import pandas as pd
df = pd.read_csv('IRIS.csv')
df
```

エラーメッセージからnumpyに何か問題があると考えられたので、pandasをnumpyに書き替えた場合には以下のエラーメッセージが表示されました。

```
Traceback (most recent call last):
  File "C:\python\iris_pandas.py", line 3, in <module>
    df = pd.read_csv('IRIS.csv')
AttributeError: module 'numpy' has no attribute 'read_csv'
```

何か解決策などあれば教えていただきたいです。
Google Colaboratoryで動画処理をするときによく使うコードスニペット

# Google Driveをマウントする
```python
gdrive_path = "/content/gdrive" # マウント先のパス

from google.colab import drive
drive.mount(gdrive_path)
```

# イテレーション
## 任意の範囲を任意の間隔でループ
```python 
for a in range(0, 1280, 10):
  print(a)
```

# 特定のディレクトリ以下の画像ファイルをリストアップする
```python 
import glob
files = glob.glob("/content/gdrive/My Drive/ColabExp/*.png") # 拡張子がpngのファイルのみ
files.sort() # 見つかったファイルをソートする
```

# 一時ディレクトリを作って作業する
```python 
import tempfile
with tempfile.TemporaryDirectory() as tmpdir:
  # ファイルをtmpdirに書き出す
```

または

```python
import tempfile
tmpdir = tempfile.TemporaryDirectory().name
```

# ファイルパスからファイル名を取得する
```python 
import os
os.path.basename(files[i])
```

# 処理の進捗を表示する
```python
from tqdm import tqdm
for i, file in enumerate(tqdm(src_files)):
  # 処理
```

# 画像処理
## PILでキャンバスを作る
```python
from PIL import Image
img = Image.new('RGB', (1280, 720), (255, 255, 255)) # 1280 x 720px
```

## PILで図形を描画する
```python 
from PIL import ImageDraw

draw = ImageDraw.Draw(img)

draw.rectangle(((x0, y0), (x1, y1)), fill=(255, 0, 0)) # 四角形
```

## OpenCVで画像を保存する
```python 
import cv2
cv2.imwrite(save_path, image)
```

### PIL/Pillowで画像を保存する
```python 
img.save(path)
```

## 画像の配列を動画にする
```python 
!ffmpeg -framerate 30 -i "$dst_img_dir/%06d.png" -vcodec h264 -pix_fmt yuv420p -vf "scale=trunc(iw/2)*2:trunc(ih/2)*2" "$dst_mov_dir/out.mp4"
```

# CSV
## CSVをファイルから読み込む(DataFrame)
```python 
df = pd.read_csv(filepath)
```

## CSVを埋め込んで読み込む(DataFrame)
```python 
CSV_DATA = StringIO("""x,y
10.0, 20.0
15.0, 30.0
20.0, 45.0
35.0, 80.0
""")

df = pd.read_csv(CSV_DATA, sep=",")
```

## DataFrameの内容をCSVファイルに保存する
```python 
df.to_csv("out.csv")
```

# 時刻
## 現在時刻のタイムスタンプを秒で
```python 
from datetime import datetime
now_ts = int(datetime.now().timestamp())
```
ローカル開発環境を構築する

##目的
- Rubyをいざやるぞとなったところ、ローカル開発環境ができていなかったので、ローカル開発環境を行う。
- 転職するたびに、開発PCが変わるので開発環境をつくるのめんどくさい。
- ドットインストールの講義 https://dotinstall.com/lessons/basic_localdev_mac_v2/38502


##今回やること
- ローカル開発環境を構築する。
    - Rubyをいじるための
- Virtulbox と Vagrantを使用する。

## Virtualboxとは
- 使用しているPCに仮想環境を構築して、他のOSをインストールすることのできる仮想ソフト。
    - 導入することで、Mac環境でWinやLinuxなどの複数のOSを切り替えて使用することが可能。
- 参考 : https://www.sejuku.net/blog/72833

##Virtualboxのインストール
- 今回は、Virtualboxの6.0.14 platform pkgをDL
    - 講義だと、かなり前のものを使っている感じらしい。(３〜４年前？)
- Macなので、OS X hosts 

##Vagrant とは
- Virtualbox を扱いやすくすためのツール。
- インストール先 : https://www.vagrantup.com/downloads.html
    - 今回はMac版の６４ビットの2.2.6

##仮想マシンの構築
階層構造は下記の画像のものを作る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533077/012d42b8-f400-41b4-e9b2-b4d05d10e6f0.png)

上記の階層構造のうち、MyCentOSのディレクトリを作成する。
ターミナルを開いて基本的にコピペすれば可能。

```
# ホームディレクトリに移動
cd

# 今後複数の仮想マシンを作ることを想定して、それらをまとめるフォルダ（MyVagrant）を作る
mkdir MyVagrant

# MyVagrantに移動する
cd MyVagrant

# 仮想マシンを作るフォルダを作る（MyCentOS）
mkdir MyCentOS

# MyCentOSに移動する
cd MyCentOS

# 仮想マシン設定用のVagrantfileを作る
vagrant init bento/centos-6.8

# Vagrantfileを編集して仮想マシンのIPアドレスを192.168.33.10にする
sed -i '' -e 's/# config.vm.network "private_network", ip: "192.168.33.10"/config.vm.network "private_network", ip: "192.168.33.10"/' Vagrantfile

# 仮想マシンを起動する（少し時間かかります）
vagrant up

# 仮想マシンの状態を確認する
vagrant status

// ここで、runnningになれば成功。

```
この画面になれば、仮想環境に入れている。
> [vagrant@localhost ~]$ 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533077/6b9009dc-5741-004e-191a-f81cf6eca0d0.png)


##今回学んだこと
- ターミナルコピペで意味わからなくても大抵のことができる。
AppShellモデル (プログレッシブ ウェブアプリ)

プログレッシブウェブアプリを学ぶにあたっての学習メモです。

# PWA (progressive web apps)とは
 - google製。直訳で「先進的なwebアプリケーション」
 - webの技術を用いて開発可能。
 - webアプリ(SPA等)とネイティブアプリのイイトコドリな形で構築可能。
 - ブラウザとアプリの中間
 - アプリのような挙動をするWebページ

★Service Worker を活用すれば、オフラインやネットワーク環境が悪い時でも動作可能でプッシュ通知を送る事なども出来る。

# App Shell モデルとは
 - PWAを構築する１つの方法論。
 - webアプリのUIが機能するために必要な最小限の HTML、CSS、JavaScript のセットの事。
 - データや値は持っていない、骨組みのようなイメージ。
 - この最低限のソースをオフラインで使用できるようにキャッシュさせ(Service Worker)れば、より高速なパフォーマンスが可能になる。
 - ユーザーインターフェースが機能する最低限のhtml、css、jsをキャッシュしておき、ページにアクセスするときに必要なコンテンツだけを読み込む


# ついでに
- Accelerated Mobile Pages
 - はやい、はやいぞ！
 - 新聞など静的なものを出すのに向いています

## 参考資料
### PWAの勉強をするにあたり、勉強になるリンク集
- [はじめてのプログレッシブ ウェブアプリ](https://developers.google.com/web/fundamentals/codelabs/your-first-pwapp/?hl=ja)
- [プログレッシブウェブアプリについて~デモアプリで効果を検証~](http://blog.excite.co.jp/exdev/25539651/)
- [App Shell モデルの素振り（前編）webpack と Workbox を利用した構築](https://havelog.ayumusato.com/develop/pwa/e742-appshell_practice_with_webpack_and_workbox.html)
- [Web App Manifest](https://www.w3.org/TR/appmanifest/)
- [Service Workers](https://www.w3.org/TR/service-workers/)

### おまけにAMP(Accelerated Mobile Pages)
- [Progressive Web Apps](https://developers.google.com/web/progressive-web-apps/)
- [Building the future web, together.(AMP)](https://www.ampproject.org/)
iOSでFlutterアプリの実行が失敗する時

flutter runコマンドがiOSで失敗するときは、`git clean -xdf`してからやるとうまくいく可能性が高い。

```
git clean -xdf
flutter run
```

ちなみに

git clean -xdfするとバージョン管理していないファイルやディレクトリが削除されます。.gitignoreに.vscodeフォルダを入れていたりすると消えちゃうので注意しましょう。
capybara-webkitのビルドで'cstddef' file not foundが出て失敗する

古いシステムのメンテナンスで、ひさびさに環境をつくったらハマったのでメモ。
macOS 10.13/Xcode10以降で、`fatal error: 'cstddef' file not found`が出てビルドに失敗する。

#### 結論（2019/11/12時点での確認）
`1.15.1`以上になるよう指定する。とりあえず1.15.1以降であればOK。

```
gem 'capybara-webkit', '~> 1.15.1'
```
とか

```
gem 'capybara-webkit', '>= 1.15.1', '< 1.16'
```
みたいにバージョンを指定してからbundle installでOK。`'< 2'`でもいい。
個別にやるなら以下で。

```gem install capybara-webkit -v '1.15.1' --source 'https://rubygems.org/'```

---
#### 参考
この記事そのままで解消できましたので感謝。
原因、および公式のPull Requestのリンクなど。qt5.5の問題がまだ解決されてなければそちらもチェック。

- [macOS Mojave にアップデートしたら capybara-webkit のビルドに失敗する](https://qiita.com/labocho/items/e12bafbcf7f31ccfb76c)
javaでOptionalのstreamからempty以外のコレクションを得る

javaで```Optional```のstreamから空で無いものを得ようとするのは結構面倒だった。https://www.baeldung.com/java-filter-stream-of-optional にあるように```filter()```か```flatMap()```で頑張るしかなかった。が、java 9から```Optional::stream```が追加されてだいぶ楽になった。

いま、以下のような、もし空文字であれば```Optional.empty()```を返す関数がある、とする。これを文字列リストの各要素に適用し、非空文字のリストを得たい、とする。

```java
	static Optional<String> map(String s) {
		if (s.length() == 0) {
			return Optional.empty();
		}
		return Optional.of(s);
	}
```

<code>filter</code>で頑張るのはこんな感じ。

```java
		List.of("1", "2", ,"", "3").stream()
			.map(Hoge::map)
			.filter(Optional::isPresent)
			.map(Optional::get)
		    .collect(Collectors.toList());
```

java 9の```Optional::stream```を使うとこうなる。

```java
		List.of("1", "2", "", "3").stream()
			.map(Hoge::map)
			.flatMap(Optional::stream)
			.collect(Collectors.toList());
```
データベースを使ったJavaプロジェクトを前回までにVPSに作ったサーバへ配置

はじめてのサーバへのアプリの配置。

#ここまでの環境

 [さくらVPSにJava実行環境を構築する](https://qiita.com/otsuno/private/d474cb93522206bc8aa9)までで作った環境を引き続き使っています。

- さくらVPS
- SentOS7
- Apache/2.4.6

#つまづいたところ

何か変更したら再起動が必要。という初歩的なことも知らず結構悩みました。

#warファイルの書き出し、配備

WARファイルを用意する。下図はEclipseでの書き出し。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/22a1a8e9-d522-6d31-c650-b3559cccb60a.png)

[公式のサンプルファイル](https://tomcat.apache.org/tomcat-8.5-doc/appdev/sample/)。手頃なwarが用意できない場合はデータベースの動作確認はできないけれどとりあえずこれ置いて確認するのもいいかも。

###FTPでWARファイルをアップ
前回設定したGUI(Tomcat Web アプリケーションマネージャ)で配備するのが一番簡単だが、その後使えなくしたので手動で配備します。
後で移動するのでアップするところはどこでも。とりあえずWinCSPでFTPの権限を設定してあったWWW下のテストフォルダアップ。

/var/www/html/test
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/30f4eeb9-dfee-ec47-904b-3f1c50423692.png)

###warファイルをwebapps下に移動させる
例:html下に一時的に置いたwarファイルをwebapps下に移動させる

```
# mv /var/www/html/test/sample.war /usr/local/apache-tomcat-8.5.34/webapps/
```
しばらくすると自動で展開されて、データベース使っていないプロジェクトならここまででブラウザからアクセスできるようになってます。

例:

```
https://VPSのIPアドレス/sample/
```

これ以降の手順はデータベース使っているプロジェクトの場合に必要。

#SQLファイルの書き出し、配備

###SQLファイルの書き出し。
下図は MySQL Workbench。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/78b4dec7-fa59-9c92-37e4-4c4b1cf1335b.png)

###SQLファイルの配備
視覚的にわかりやすいのでphpMyAdminを使って配備します。
https://VPSのIPアドレス/phpMyAdmin（URL変更推奨）/

データベースタブでデータベースを新規作成。照合順は開発環境のデータベースと同じに合わせます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/87415b57-8ecc-f76a-ac2d-f12751b9a9e0.png)
さきほど書き出したSQLファイルをインポートする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/7a6edae1-ffa5-0e62-aad3-3feaadf59e39.png)


#サーバの設定を記述する
下記の2ファイルサーバの設定を記述します

- /usr/local/tomcat/conf/server.xml
- /usr/local/tomcat/conf/context.xml

Eclipse内で同名のファイルがあるのでそこから該当箇所をコピー・アンド・ペースト。データベース名と、パスワードを適宜変更します。

下図はEclipse内でのファイルの位置

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/223715/01880a06-24a2-6757-0d32-d264e780d2d1.png)

GlobalNamingResourcesの中にResourceを記述

```/usr/local/tomcat/conf/server.xml 
 <GlobalNamingResources>
    <!-- Editable user database that can also be used by
         UserDatabaseRealm to authenticate users
    -->


		<Resource driverClassName="com.mysql.jdbc.Driver" initialSize="1" maxIdle="3" maxTotal="5" maxWaitMillis="5000" name="jdbc/【DB名】" password="【パスワード】" type="javax.sql.DataSource" url="jdbc:mysql://127.0.0.1:3306/【DB名】?useUnicode=true&amp;characterEncoding=utf8" username="root" validationQuery="SELECT 1"/>
```
```/usr/local/tomcat/conf/context.xml

     <ResourceLink name="jdbc/【DB名】"
 global="jdbc/【DB名】"
 type="javax.sql.DataSource" />
```

再起動して確認。
ReButtonをAzureIoTCentralに繋いでみた

#背景
ReButtonが手元にあったので、とりあえずAzureIoTCentralに繋いでみました。AzureIoTCentral自体は使ったことがあったので、ある程度の予備知識がありましたが、いろいろ情報を調べながらトライしてもだいたい１時間ぐらいで繋がります。とても簡単。

#参考記事
以下のサイトを主に見ながらやりました。
ボタンの押し方に結構クセがあるので、ボタン操作の練習から始まる意味がのちのち良く分かりました(笑)
[Seeed ReButtonを動かしてみる](http://matsujirushi.hatenablog.jp/entry/2019/01/23/171257)


#ReButtonで対応しているMeasurements
Field Nameはデバイス側で設定されているので、必ず一致させること。
[ここ](http://omoshiroinc.com/blog/2019/02/23/readytogorebutton/)のブログが良く纏まっていて分かりやすかったです。

|Measurements|Field Name    |内容|
|:-:         |:-:           |:-:|
|Telemetory  |batteryVoltage|バッテリ電圧||
|State       |actionNum     |クリック種類||
|Event       |message       |クリックイベント||

#ちょっと気になったところだけピックアップ
・アプリケーションの選択では、「Custom app」を選択する。少し前の画面と変更になっていたので、ちょっと戸惑いましたが、落ち着いて見れば大丈夫(19/11/14現在)。
![002.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/32fa0912-979a-5cba-0466-fa9f45c5bcb1.png)

・Eventでも各イベントごとにクリックすると、Valueの値にクリックの種類が格納されています。
![003.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/46f87f55-f4b9-caac-cddf-011b61d511d5.png)

・Measurementsを全部表示するとこんな感じになります
![005.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/13c27830-ad63-faca-75b5-b857c3efb559.png)

・中身はこんな感じでした。シンプル。
![DSC_0439.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475457/8782389a-99e9-0a81-166e-b086ce19c118.jpeg)
pytorchのtensorをsort,  同じ順で別のtensorを並べ替え, sortしたtensorを元に戻す.

# 環境
python3
pytorch 1.3.0

# 準備
```
>>> import torch
>>> a = torch.rand(3,3)
>>> a
tensor([[0.8395, 0.2678, 0.5021],
        [0.1397, 0.9839, 0.8991],
        [0.6298, 0.6101, 0.6841]])
```

# torch.sortで並べ替える
```
# 指定した次元の方向にsortする
# sortする次元はdimで指定
>>> sorted, idx = torch.sort(a, dim = -1) # デフォルトはdim = -1 (-1は最後の次元. 3次元なら3と書くのと同じ)

# 戻り値は2つ
>>> sorted # 並び替えられたtensor
tensor([[0.2678, 0.5021, 0.8395],
        [0.1397, 0.8991, 0.9839],
        [0.6101, 0.6298, 0.6841]])

>>> idx # もとの行列をどういう順番に並び替えたのかの情報(後述のtorch.argsortの戻り値と同じ)
tensor([[1, 2, 0],
        [0, 2, 1],
        [1, 0, 2]])

# 例えば今回の例では, aとsortedの関係は, idxを使って
# sorted[0] = a[0,1], a[0,2], a[0,0]
# sorted[1] = a[1,0], a[1,2], a[1,1]
# sorted[2] = a[2,1], a[2,0], a[2,2]

# 降順に並び替える. descending
>>> sorted, idx = torch.sort(a, descending = True)
>>> sorted
tensor([[0.8395, 0.5021, 0.2678],
        [0.9839, 0.8991, 0.1397],
        [0.6841, 0.6298, 0.6101]]
```

# torch.argsort: どういう風に並べ替えたのかの情報を得る
```
# torch.sortの2つめの戻り値と同じ
>>> idx = torch.argsort(a)
tensor([[1, 2, 0],
        [0, 2, 1],
        [1, 0, 2]])

```

# torch.gather: argsortの結果を使って, 別のtensorを同じように並べ替える
```
# tensor a と同じサイズのtensor bを用意
>>> b = torch.rand_like(a) # 3*3 random

# まずtensor aを並べ替えます
>>> sorted, idx = torch.sort(a, dim = -1)

# torch.gather(input, dim, idx)
# tensor a を並べ替えたときの情報idxを用いて, aと同じ順でbを並べかえ
>>> torch.gather(b, -1, idx) # sort時と並べ替える方向は合わせてdim=-1

# つまりtorch.gatherでaをidxを用いて並べ替えた結果はsortedと同じ
>>> torch.gather(a, -1, idx) 
tensor([[0.2678, 0.5021, 0.8395],
        [0.1397, 0.8991, 0.9839],
        [0.6101, 0.6298, 0.6841]]) 
```

# sortした配列をもとに戻す
```
# idxをargsortした結果(idxのidx)をgatherに突っ込む
>>> invidx = torch.argsort(idx) # idxのidx
>>> torch.gather(sorted, -1, invidx)
tensor([[0.8395, 0.2678, 0.5021],
        [0.1397, 0.9839, 0.8991],
        [0.6298, 0.6101, 0.6841]]) # aと同じになる
```
postfixのマルチインスタンス設定を用いた複数サーバー運用


#背景
１つのマシンに２つ以上のMTAを構築したい場合がある。
例えば、大した負荷がかかるわけではないが、冗長化しておきたいメールシステムが、２構成以上ある場合、
小さなマシンを複数個立てるよりも２台のマシンに２構成を同居させたいような場合だ。
そのようなことをしたい状況が実際に起こった。
調べてみるとpostfixにはマルチインスタンス機能というものがあるらしく、これを使えば上記のようなことができそうだったので
Postfixの構築は経験豊富と到底言えない私が環境を構築してみた。

#やりたいこと
１台のPostfixに２つの別々の設定で動くMTAを構築する。
実際にはそのマシンを複製し、外側にロードバランサを立てて、そいつが通信を受け付ける。

#前提
- OSはCentOS7系
- 既にpostfixは構築済みで通常の送受信ができている
- SELinux関連の設定は省略（本件では無効化済み）

#手順

とりあえず現状チェック
systemctl status postfix

以下コマンドで、２環境目のpostfixを用意します。

```bash
postmulti -e init
postmulti -I postfix-2nd -e create
```

以下二つのファイルが出来上がります
/etc/postfix-2nd/main.cf
/etc/postfix-2nd/master.cf

```bash
ls /etc/postfix-2nd/
```
などで確認してみましょう。
上記の２ファイルは、新しくできた環境の設定ファイルなので自由に書き換えます。

ちなみに、私は以下の設定を行いました。
<span style=“font-size:135%;”>**■/etc/postfix-2nd/main.cf**</span>
有効化
master_service_disable = inet
　→　コメントアウト

インターネットに公開
inet_interfaces = localhost
　→　inet_interfaces = all

アクセス許可
mynetworks =　にリレーを可能するマシンのIPを入れる

<span style=“font-size:135%;”>**■/etc/postfix-2nd/master.cf**</span>
SMTPポートの変更（通常ポートで開くと元からいた環境とかち合うため）
10025 inet n - n - - smtpd
サブミッションポートの変更（同上の理由）
10587 inet n - n - - smtpd -o smtpd_tls_security_level=encrypt

設定が完了したら、新しい環境を有効化していきます。

```bash
postmulti -i postfix-2nd -e enable
```
これで終了。なんと簡単な。
ちなみにこんなことする人はそう相違ないかと思いますが、-e initや -e enableなどを実行した後にファイルを上書いたりすると、
コマンド打った意味がなくなるので注意しましょう。（私は一回やらかしました）

続いて起動をしていきます。

```bash
postmulti -a -p status
postmulti -i postfix-2nd -p start
postmulti -a -p status
```
自動起動は、startをしておけば後は勝手に起動してくれるらしい。
気になる人は以下をして確認をしてみる。

```bash
systemctl restart postfix
postmulti -a -p status
reboot
postmulti -a -p status
```

#まとめ
かなり簡単に２台目のPostfixが用意できた。

#参考サイト
水銀室 Postfixをマルチインスタンスで起動する -CentOS最短構築支援-
http://hp.vector.co.jp/authors/VA022911/tec/centos/postfix_multi_instance.htm
flutter test で Too many open files が出る場合は ulimit

`flutter test` したところ、以下のように `Too many open files` というエラーがでた。

```

...

05:05 +2049 ~15 -364: loading /Applications/flutter/packages/flutter/test/widgets/editable_text_cursor_test.dart [E]
  Failed to load "/Applications/flutter/packages/flutter/test/widgets/editable_text_cursor_test.dart":
  Too many open files
    Command: /Applications/flutter/bin/cache/artifacts/engine/darwin-x64/flutter_tester --disable-observatory --enable-checked-mode --verify-entry-points --enable-software-rendering --skia-deterministic-rendering --enable-dart-profiling --non-interactive --use-test-fonts --packages=/Applications/flutter/packages/flutter/.packages /var/folders/56/pjxy3nxx16v_bcn0jrkx4d6c0000gn/T/flutter_test_listener.P9AoAx/listener.dart.dill
05:15 +2075 ~15 -364: Some tests failed.
```

ulimitで一時的に上限を増やしましょう。

```
ulimit -S -n 2048
```


See: https://flutter.dev/docs/testing/debugging
超初歩シンプルコーディング分類器（アヤメちゃん）

#はじめに
- Python3
- 初学者
- シンプル
- 改善の余地あり
- メモ程度の記事

##きっかけ
　研究室でやれとの命令（過激）
　SIGNATEのプラクティスをいろいろ試してみて、その中からいくつか発表をする為。
　
###本題
　今回は学習の超初歩で有名な　アヤメの分類　を行った。

* データの読み込み

```Python:Iris-Learning.py

iris_data = pd.read_table("train.tsv")
iris_test = pd.read_table("test.tsv")
```
一応、タブをセパレート指定することでread_csvが使えるがこっちのほうが素直な気がしたのでこのまま。

* 特徴量データと教師データに分離

```Python:Iris-Learning.py
X = iris_data.loc[:,["sepal length in cm","sepal width in cm","petal length in cm","petal width in cm"]].values
y = iris_data.loc[:,"class"].values
```
また、この段階でテストデータも成型してあげます。

```Python:Iris-Learning.py
Xt = iris_test.loc[:,["sepal length in cm","sepal width in cm","petal length in cm","petal width in cm"]].values
```
* 学習データとテストデータに分割

```Python:Iris-Learning.py
X_train, X_test, y_train, y_test = train_test_split(X,y,test_size = 0.2)
```
trainデータを8:2の割合で分割する。

* モデルの学習

```Python:Iris-Learning.py
clf = svm.SVC()
clf.fit(X_train,y_train)
```
今回用いたのは`SVC`で、`LinearSVC`と何が違うねんって話ですが、一応LinearSVCのほうがサンプル数に比例して処理速度と精度が上がるらしい。

* モデルの評価

```Python:Iris-Learning.py
y_pred = clf.predict(X_test)
accuracy = accuracy_score(y_test, y_pred)
print("正解率 = ",accuracy)
```
`accuracy関数` を用いて上のモデルを評価します。

ここまでくれば、あとは先に成型しておいたテストデータを走らせれば・・・

* テストデータの分類

```Python:Iris-Learning.py
data = Xt
X_pred = np.array(data)
y_pred = clf.predict(X_pred)
print(y_pred)
```

####結果
`暫定評価 97.333点` `81/158位` とシンプルなコードでそこそこいい感じの結果になりました。

#####改善点
`SVC` を `LinearSVC`　や他のアルゴリズムに変えてみる。
AWSのタスクスケジュールの起動タスクを最新にする方法

## なぜ書くのか
AWSのECSを使う際にタスクスケジュールはcronみたいな使い方ができて、めちゃ便利なんすけど
その際にタスクをlatestに指定する方法がなかなか見つからなかったので書きます

## 対象
- AWSのECSをFargateを使って運用してる
- ECSでタスクスケジュールを定期的に移動するものとして使いたい

## 書くこと
- タスクスケジュールの起動タスクのリビジョンを最新にする方法

## 書かないこと
- AWSの説明
- ECSの説明
- タスクスケジュールの作り方

## 流れ
- タスクスケジュールは何してる？
- タスクスケジュールの起動種類
- タスクスケジュールのリビジョン最新化

## タスクスケジュールは何してる？
すごくざっくりの僕理解で書きます。
ECSはDockerで動くもので、タスクスケジュールは特定のことを
任意のタイミングのみで実行したいときに基本使うんだと理解してます。
で起動条件をCloudWatchイベントで管理しています。
なんでかというと起動の種類が時間単位とかなのでCloudwatchなんだと勝手に思っています。

間違ってたら遠慮なくツッコンでください。

## タスクスケジュールの起動種類
- Cron
    - cronです、cronを知らない人はお手数ですが調べてください
- 定期処理
    - 1分毎とか1時間毎とかで選べます

## タスクスケジュールのリビジョン最新化
というわけで、ECSのタスクスケジュールからタスクスケジュールは作成するくせに
起動条件はCloudwatchにできあがるということですぐには見つかりません。（どこかに書いてあるのかも）
で、タスクスケジュールを作ると作った時のリビジョンでひたすら繰り返されてしまい、プログラムを更新しても
一切反映されないのです。おっと話がそれました。

では実際どこから変えるのかというとCloudwatchにイベントという項目があるので
そこから変えることができます。タスクスケジュールでつくったものと同名のものが
Cloudwatchのイベントにあるのでそれを選択して編集をします。

編集に行けばわかると思うので詳しくは書きませんが
そこでリビジョンを「latest」というものに設定することができます。
これで毎回最新のプログラムで起動されるようになります。

## 注意事項
常に最新になるのはいいのですが、間違えて動かないプログラミングとかをあげてしまうと
ひたすらタスクが立ち上がるという地獄的にお金がかかる状況になるかもしれないのでお気をつけください。
いま起動タスクの上限を監視できないのか調べてるのでわかったらまた書きます！

ではまた
Golang 文字列結合どれが早い？！

文字列結合、実はどの言語でも発生する処理でして。
どの方法が早いのか、を調べてみました。
今までは、他の人が書いた記事を見て、ふーん、ってだけだったんで、たまには自分でコード書いてみないと！！笑

#比較対象
- 単純に「＋」でつなぐ
- 配列を「strings.Join」でつなぐ
- strings.Builderを使う

#結果
```ruby:10回
planePlus     1.052µs
useJoin       546ns
useSB         588ns
```
```ruby:100回
planePlus     45.696µs
useJoin       1.402µs
useSB         4.492µs
```
```ruby:1000回
lanePlus     1.026428ms
useJoin       14.021µs
useSB         8.59µs
```

思った通り、単純に「＋」でくっつけるのは激重ですね。。。
回数が多くなればなるほど、その傾向は如実に出てます。

意外だったのは、１００回くらいまでなら「strings.Join」の方が「strings.Builder」より早かったこと。
１０００回になると逆転しますが。
このあたりの閾値も調べてみたいとこで、ちまちまやってみましたが、300回あたりでやるたびに変わるので、正確なところは分からず。。。

回数によってどっちを使うか、を選定するのもアリですねー。

 
#コード
検証に使ったコードはこちらです。
よかったらご自身の環境でも試してみてくださいね＾＾
コードもおかしいところはご指摘お待ちしてます！

```ruby:stringAdd.go
package main

import (
	"fmt"
	"strings"
	"time"
)

func main() {

	data := createInitData()

	/* 「＋」結合 */
	start := time.Now()
	planePlus(data)
	end := time.Now()
	fmt.Print("planePlus     ")
	fmt.Println(end.Sub(start))

	/* JOIN */
	start = time.Now()
	useJoin(data)
	end = time.Now()
	fmt.Print("useJoin       ")
	fmt.Println(end.Sub(start))

	/* strings.Builder */
	start = time.Now()
	useSB(data)
	end = time.Now()
	fmt.Print("useSB         ")
	fmt.Println(end.Sub(start))

}

/*
 初期データを作成する
*/
func createInitData() []string {

	num := 10 //追加数(10,100,1000と変更）

	i := 0
	data := "abc" // 挿入データ

	// 返却用スライスの新規作成 -- make(型, len：長さ, cap：キャパシテイ)
	/*
	 len: 長さは最初に用意される箱の数
	 cap: キャパシティは、最初に参照される箱の場所
	*/
	retArray := make([]string, 0, num)
	for i < num {
		retArray = append(retArray, data)
		i++
	}
	return retArray
}

/* 単純に「＋」で結合 */
func planePlus(data []string) {
	base := ""
	for _, value := range data {
		base = base + value
	}
}

/* JOINで結合する */
func useJoin(data []string) {
	strings.Join(data, "")
}

/* strings.Builderを使用 */
func useSB(data []string) {
	var sb strings.Builder
	for _, value := range data {
		sb.WriteString(value)
	}
	sb.String() /* stringに変換するまでが対象 */
}

```
【GCP】環境変数をプロジェクトごとに切り替える方法


##経緯
最初にバックエンドを開発し何も考えず下記のコマンドで環境変数を設定していた。
バックエンドの開発が落ち着いたのでフロントエンド開発しようってなったときに環境変数の切り替えどうするんだ？
configファイルを分ける？、キーで分ける？
ってなったのでメモです。


## 基本的なコマンド
そもそもGCPへ環境変数はconfigというファイルを作成して
作成したconfigに環境変数を追加していくスタイル。

###configの作成
```terminal
$ gcloud beta runtime-config configs create [config名]
```

###現在作成されているconfigファイルの確認
```terminal
$ gcloud beta runtime-config configs list
```

###環境変数の追加
```termina
$ gcloud beta runtime-config configs variables set [変数名] [値] --config-name [config名] --is-text
```

###登録されている環境変数のキーの確認
```terminal
$ gcloud beta runtime-config configs variables list --config-name [congig名]
```
###登録されている環境変数の値の確認
```terminal
$ gcloud beta runtime-config configs variables get-value [環境変数の変数名] --config-name [config名]
```

## 対象プロジェクトの切り替え

・下記のコマンドでプロジェクトの切り替えを行える。
切り替えを行うとconfigの作成対象のプロジェクトも切り替わります

###プロジェクトの切り替え
```termina
$ gcloud config set project [プロジェクト名]
```

・対象プロジェクトをオプションでも指定できます。

###config作成コマンド+プロジェクト指定
```termina
$ gcloud beta runtime-config configs create [config名] --project=[プロジェクト名]
```




####　・参考にしたサイト
(GCPへ環境変数を登録する方法：　http://kourin.hatenadiary.com/entry/2018/05/01/014804)
[UE4] ブループリントの変数Get／Set、楽に！

![2019-11-14_14h38_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369484/ed36b67e-6b26-6d91-7c25-0334355ea5f8.png)

ブループリントでCTRLキーを押しながら変数をクリックとドラッグしたら、その変数をゲットできます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369484/2554a9b9-c701-72e6-10a9-b9daf8575d0d.jpeg" alt="drawing" width="200"/>

同じ感じでALTを押したら、セットを出来ます。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/369484/f7709438-3c1c-86b7-4803-5617e5754792.jpeg" alt="drawing" width="200"/>
田舎ポンコツ大学生がRubyに目覚めた話

#初めに

**※※田舎ポンコツ学生による日々のアウトプットと、始めたばかりの初心者にむけた記事です。
間違っていることなど先輩方からアドバイスいただけるとありがたいです。※※**

私は現在福島県会津若松にある株式会社Eyes,JAPANでリモートワークでアルバイトをしています。

私は初め、働くといっても私は独学でプログラミングを学んだだけの学生です。なにができるのだろうか、という気持ちでした。

#Udemy

私は２０１９年の１月から６月頃まで独学でHTML、CSS、JavaScript、jQuery、PHPの基礎を一通り学びました。

しかしアルバイトをするにしても、独学で基礎を学んだだけ、いかんせん能力がないです。しかもリモートワーク。

ということで

これまでの独学の情報確認とスキルアップのため、Udemy (https://www.udemy.com/ )と呼ばれるオンライン学習サービスを使い、現在学習中です。

学習すればするだけできることが多くなりこなせる仕事も多くなります、自然とその人の価値が上がってくると思うので頑張っていきます！

#Ruby

会社ではよくRubyを使うとのことで、AWS（https://aws.amazon.com/jp/ )のCloud9を使用した学習スタートです。
（一年間無料で使用できるのでそちらを使用しています。）

Googleで検索をかけたところ、**Rubyはなんと日本人がつくったのではありませんか！**知らなかったです！

というかRubyとRuby on Railsってなんやねん兄弟か？とも思っていたのですが、Rubyをより簡単に扱いやすくしたものがRuby on Railsだそうです。

簡単に調べました。
Rubyとはプログラミング言語でWebアプリケーションやブログ、スマホアプリを作成することができます。
身近なものだと食べログやクックパッドなどがRubyによって作られているそうです。

こちらは学んだことのアウトプットです。
ファイル名「 hello.rb 」というRubyで書かれたファイルの中に

```
puts "hello world!"
```

と書き、

```
ruby hello.rb
```
と実行することで

```
hello world
```

といった感じに出力されます。「 puts 〇〇〇 」とは、表示してくださいという状態で、
「 Ruby 〇〇〇.rb 」とは表示してくださいというお願いを実行することです。

実行した結果、hello world と表示されるわけです。

ウェブで考えるとわかりやすいのですが、ウェブページを作るためのコードが書かれているファイルの中に「複数の表示してください」があったとします。
ここで実行、出力することで、皆さんがいつも見ている綺麗なウェブページへと変化します。
わかりにくかったでしょうか？笑

#コマンド操作
何度も何度も私の前に立ちはだかってくる憎いやつです。特定の操作でファイルの作成や移動、ファイルのダウンロードを行うのですが、いかんせんとても分かりづらいです。今はGUIというとてもわかりやすいものがあるので、使わなくていいんじゃね、ってことで避けてました....

しかし、Rubyでコマンド操作をする分にはやっていることが簡単だったので、使っているうちに「cd」や「ls」「mkdir」「touch」などの基本操作になれることができました。これはとても良い収穫でした。

#わからなかったこと

ほとんどは後々調べてわかったことですが、躓いたところを残していきたいと思います。
先程書いたコマンド操作で

irbでexitが効かなくなりました。

（irbとはRubyのコードの動作を確認するためのものです。先程の「ruby hello.rb」を実行する際に使ったものです！）


というか何を入力しても反応しなくなり焦ったのですが、Cntl＋Cキーの強制終了で大丈夫でした。

次はdef、self、returnってなんやねん。アクセサメソッド？ていうかPHPとRubyの違いって何？

ということで最初の3つはなんとなく理解できたのですが、アクセサメソッドがいまいちちゃんと掴むことができていません。

>オブジェクト内部のメンバ変数（属性、プロパティ）に外部からアクセスするために用意されたメソッド。

http://e-words.jp/w/%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B5.html

と書いてあるのですが、そもそもメソッドや属性、プロパティ、外部？ということに関してなんとなく使っていたことに気づきました。
社員の方からなんとなくで覚えてほしくないとの指摘もされました。

一通りRubyに関して基礎が終了次第、言葉の確認作業に入りたいと思います。

#まとめ

PHPとは結構違いまして、焦りました。

しかしまだRuby on Railsに関しても学んでいくので、手を動かしながらRubyのほうは頭に入れていきます。

Rubyは在宅・リモートワークで働きたい人におすすめであるそうなので、もう少し踏み込んでこれから記事を書いていきたいと思いました。

今はまだないのですが、ただ学ぶだけじゃなくて、

Rubyを使ってなにをしたいのか、という部分も考えていきたいと思います。
[UE4] BlueprintのDeprecatedによる非推奨設定


Blueprint Classにオプションとして非推奨の設定が追加されました。

![2019-11-14_14h43_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/1d802811-fc5c-63ca-c63e-d3f4acb240ac.png)

この設定が有効な場合、非推奨としてマークされ対象クラスの動作が以下のように制限されます。

**[主な制約事項]**
Actor継承のクラスが非推奨な場合、Blueprintのコンパイルで必ず失敗(非推奨を通知)するようになります。
非推奨なActorを継承したクラスも作成することはできません。
非推奨なActorについてはレベル上に配置することができません。
UserWidget継承などのクラスが非推奨な場合、PIEなどゲームの実行時に対象クラスとのリファレンスがあるとエラーとなります。

![2019-11-14_14h43_59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/0f1ede14-63f8-9fc5-50be-817a9980eb18.png)

使用しなくなったBlueprintを明示的に示すのに便利です。
[BluePrism]Excelの、列名が重複していてCollectionに取り込めないデータの重複列を削除するオブジェクトを作成しました。

#これを書いた理由

Blue Prismで、ExcelデータをCollectionに取り込むVBOは、MS Excel VBOの「Get Worksheet as Collection」です。
![vbo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/a6c21a92-4642-a97e-ab52-07ffa4a3dd76.png)

でも、Excelの帳票で、同じ列名が何個もあるものは、そのままだとCollectionに取り込めません。
（なんで同じデータが何回も書いてあるのかとかちゃんとした帳票作れとかそういうお話はとりあえず棚上げしておくとして）


どうにかして重複列をないようにしないといけないのですが
今回は簡単に、2回目以降に出現する重複列名の列を削除してしまうものを作成しました。

これの記事の、「カラム名の重複を削除したいとき」と同じような働きをするものです。
[【Python3】pandas.DataFrameのカラム重複削除(Qiita)](https://qiita.com/mynkit/items/6e8ddfa1c73363f6117e)

#作成したオブジェクト
![duplicate.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/1ab50513-56e7-5c5d-cfa0-0c41598e6ef7.png)

たとえばこういうExcelデータを入れます。赤で囲った列が重複（削除したい列）です。
![testdata.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/53f1b35e-8aa5-330e-3206-2b53dc02016f.png)

1. 1行目をヘッダにせず、データとしてデータテーブルに読み込みます。
「Get Worksheet as Collection」ではなくて「Get Worksheet as Collection Offset」を使い、Use HeaderをFalseにします。
こうすることで、1行目を列名でなくて普通のデータの1行目としてCollectionに取り込みます。
列名は「Column1]「Column2」……という具合にBlue Prismが自動でつけてくれます。
![vbo2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/33c4fc94-458a-bcd5-615a-2d68f7f295d4.png)
読まれたらこんな感じ
![yomaretadeta01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/07da4a97-10e4-d03f-b963-40d191c90ce0.png)

2. これで取りこんだデータの1行目だけをコピーして、別のCollectionに入れます。1行だけのCollectionになります。
![yomaretadata02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/c30b558d-bd99-5a51-a336-7b78de787e9b.png)
3. VBOの「Collection Manipulation」の中に「Transpose Collection」というのがあって、
これはいわゆる「行列の転置」かと思いきや全然違って、Collectionを2列にしてくれる（1列目が列名で2列目がデータ）だけのものです。
これを使って、2で作成した1行だけのCollectionを、2列のCollectionに変換します。
![yomaretadata03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/d26dc31d-b9b5-8e07-cdb5-9a85e69ff90e.png)
4. Value（列名になるところ）を並べ替えます。同じ名前のものに隣接してもらうためです。下図の青枠です。
5. 重複チェック用に1列追加します。下図の緑枠です。
![yomaretadata04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/a4f95ced-33dd-544d-12d3-860128dbe2ab.png)
6. 重複列に1を立てます。
![kai01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/07f7fcba-19e3-43fd-1a54-2e43b4d19aa9.png)
7. フィルタをかけて6で1を立てた列だけにして、Name（「Column〇」の列）を降順でソートします。下図の青枠です。
![kai02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/cab32701-a4f6-e1a9-3d80-5feae206832a.png)
8. 7で示した図の青枠に、削除すべき列の列名があるので、これを使って1で示したデータの列を削除します。
重複列が削除されたデータこれ
![kai03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/b8b77100-1217-e4ae-f090-3e4517e5b1fe.png)

9. あとは1行目を列名にしたらできあがりです。
![kai04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142092/fe24d755-0649-5bce-5e29-d2356d5806b4.png)



#終わりです
Transpose Collectionってなんの役にたつんだろう……てかこれをこの仕様で作ることにしたの誰……
くらいに思ってたんですが、今回初めて使いました。

昔コボラーだったのでこんなダサいやりかたなんですが、今のもっといいやりかたがあったら教えてください。ありがとうございます。

テストデータはここで作成しました。→　[疑似個人情報生成](https://hogehoge.tk/personal/generator/)
[UE4] Quick Jump機能を使ったBlueprintの反復

#1. 概要
BlueprintのGraph状態(タブ、位置、ズーム設定など)をショートカットキーに登録しておくことで反復操作が可能なショートカットキーです。

#2. キーの登録

[Editor Preferences]->[General]->[Keyboard Shortcuts]の”Graph Editor”に指定されています。
Ctrl+N(N:数字キー)で保存、Shift+N(N:数字キー)で移動ができ、反復移動をスムーズに行うことができます。

**デフォルトのショートカットキー割り当て**
![2019-11-14_14h29_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/d30a03bf-875f-9f69-e945-de82cfed1052.png)

**Quick Jumpを使った移動**
既にCtrl+1, Ctrl+2, Ctrl+3でBlueprint内のViewを保存している時、Shift+1, Shift+2, Shift+3を入力することで、Ctrl+Nで保存したGraphに移動することができます。
![2019-11-14_14h34_09.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364110/5b64da65-423f-a188-0365-02f8c7f7ccee.gif)

#3. まとめ
このコンソールコマンドを利用することで、良く編集するモジュールやデバッグを記憶しておくと、Blueprint Graph間の反復移動が効率的にできるようになります。これらをうまく活用してデバッグを効率的に行いましょう。
Elixirのガード節を試してみる

Elixirの関数には引数によって処理を分ける機能(Guard節)というのが存在する。
このガード節、結構いろいろな条件で処理を分岐できるのですが引数の型でも処理分けできるので今日はそれを試してみる


## 準備する

とりあえずライブラリ生成のお約束に則って

```bash
# Bundle gemみたいなコマンド
mix new hoge

# 生成されたディレクトリへ
cd hoge

# とりあえずテストを回しておこう
mix test
```


## テストする

Elixirはテスト用のライブラリがしっかり入っているのでそれを持って先にテストを書いておく
とりあえず今回は引数を渡すと引数の型名を文字列で返してくれる関数を実装するということで
テストはこんな感じに

```elixir
# test/hoge_test.exs
test 'Hoge.type関数は引数の型名を文字列で返す' do
  assert Hoge.type(:a) == "Atom"
  assert Hoge.type(nil) == "Nil"
  assert Hoge.type(1) == "Int"
  assert Hoge.type(1.1) == "Float"
  assert Hoge.type(true) == "Boolean"
  assert Hoge.type("s") == "String"
  assert Hoge.type([1,2,3]) == "List"
  assert Hoge.type(%{a: 1}) == "Map"
  assert Hoge.type({:A, 1}) == "Tupple"
  assert Hoge.type(fn -> IO.puts :a end) == "Function"
end
```

テストがかけたのでとりあえず `Hoge`モジュールに何もしない関数を書いてからテストを流すか

```elixir
# lib/hoge.ex

def type(x) do

end
```

これでテストを流す
テストコマンドは `mix test`

```bash
mix test

  1) test 1 is number (HogeTest)
     test/hoge_test.exs:13
     Assertion with == failed
     code:  assert Hoge.type(1) == "Int"
     left:  nil
     right: "Int"
     stacktrace:
       test/hoge_test.exs:14: (test)

...
```
ちゃんと落ちることが確認できた


## 実装する

テストが失敗することがわかったので実装する

```elixir

def type(x) when is_integer(x), do: "Int"
def type(x) when is_float(x), do: "Float"
def type(x) when is_bitstring(x), do: "String"
def type(x) when is_boolean(x), do: "Boolean" # NOTE: Booleanは内部的にはAtomなのでAtomより先に評価しないとAtom判定される
def type(x) when is_nil(x), do: "Nil" # NOTE: Nilは内部的にはAtomなのでAtomより先に評価しないとAtom判定される
def type(x) when is_atom(x), do: "Atom"
def type(x) when is_list(x), do: "List"
def type(x) when is_tuple(x), do: "Tupple"
def type(x) when is_map(x), do: "Map"
def type(x) when is_function(x), do: "Function"
```

気をつけないといけないのは `Boolean`と `Nil`と `Atom`の関係
これ試して初めて気づいたけどどうもBooleanとNilはAtomで表現されているらしい :thinking: 
なのでBooleanやNilよりもAtomのGuard節を上に書くと悲しいことに全部Atomとして結果が返ってくる

とりあえず実装はできたと思うのでテストを流す

```bash
mix test

Finished in 0.04 seconds
1 doctest, 1 tests, 0 failures
```
良さそう！

## 感想
引数ベースで処理を分けるのは他の言語だとバッドプラクティスという話を聞くけどElixirもといErlangがそういう言語仕様だからこうなるのは仕方ないね
せっかく言語にこういう書き方が実装されてるんだから積極的に使っていきたい所存
今回は条件分けに等値演算子などは使わなかったですが本当はそういうのを使ってもっといろいろな条件分岐していくこともできるそうな
いいなぁ...