OmniAICreator/Qiita-1.07M huggingface dataset:
Macにnode.jsとnpmをinstallする

# 目的
MACにnode.jsとnpmをinstallする

# 環境
MAC OS Catalina 10.15.2で実施

# 作業ログ
```bash:bash
# xcodeのinstall (gccのinstallに必要)
$ xcode-select --install

# gccのinstall (nodebrewのinstallに必要)
$ brew install gcc

# nodebrewのinstall
$ brew install nodebrew

# nodebrewでinstallされるファイルが格納されるdirectoryを作成
$ mkdir -p ~/.nodebrew/src
$ nodebrew install-binary stable

# currentの表示されるのが使うversion
$ nodebrew list
v12.14.0

current: none

# stableを使うと指定
$ nodebrew use stable
use v12.14.0

# node.jsのversion確認
$ node -v
v12.14.0

# npmのversion確認
$ npm -v
6.13.4
```
Rails6 の Zeitwerk と  XXXHelper の DEPRECATION WARNINGと OmniAuth

あるプロジェクトを Rails 6 にアップグレードしたら、DEPRECATION WARNING が出るようになりました。

```
DEPRECATION WARNING: Initialization autoloaded the constants ApplicationHelper, AaaHelper, BbbHelper, ..., ActionText::ContentHelper, and ActionText::TagHelper.
```

# ApplicationHelper で grep する

なるほど〜。これは、[例の Zeitwerk のワーニングだな](https://qiita.com/jnchito/items/b8f40e7fe82b07bc3de8)とピンと来た私は、 
`config/initializers` 内のファイルとかで `ApplicationHelper` を参照しているのかと思い、`ApplicationHelper` で grep してみたのでした。

すんなり解決できるかと探してみましたが、 `app/helpers/application_helper.rb` 以外に 
 `ApplicationHelper` と書いて使っているところなんてどこにも見つからない...。
何が悪いの？

# Rails の ISSUE を見つける

Google で検索してみたところ、 Rails の ISSUEが見つかりました。
[zeitwerk doesn't autoreload the helpers](https://github.com/rails/rails/issues/35978)

まさにここに書いてある通り

```ruby
OmniAuth.config.on_failure = XxxxController.action(:failure)
```

としてました。

これを参考にして、

```ruby
OmniAuth.config.after_initialize do
  OmniAuth.config.on_failure = XxxxController.action(:failure)
end
```

に修正することで解消できました。

# 参考情報

* [zeitwerk doesn't autoreload the helpers](https://github.com/rails/rails/issues/35978)
AtCoderわからん日記_2　ABC148E

#はじめに
DができたからEもちょっと覗いてみよかな～と思って、パっと見難しすぎる数式がある感じでもないしいけるかな？　と思ってやってみました。結論から言うと、全くわからなかったです。これがE問題……アルゴリズムの基本をきちんと勉強するまでは、がんばるのはDまででいいかもしれないですね。
問題は[ABC148](https://atcoder.jp/contests/abc148)のE問題より。以下引用です。

# E - Double Factorial
0以上の整数nに対し、f(n)を次のように定義します。
f(n)=1(n<2のとき)
f(n)=nf(n−2)(n≥2のとき)
整数Nが与えられます。
f(N)を10進法で表記した時に末尾に何個の0が続くかを求めてください。

## 考えたこと
①とりあえず掛けて、末尾の0が何個あるか考えるか
振り返って書いてても恥ずかしくなるぐらい愚かですね。昨日計算量について教えてもらったばっかりなのに……。

###1回目

```py
import re
n = int(input())
i=n-2
while i >= 2:
    n *= i
    i -= 2
    ans = re.search('0+$' , str(n))
print(0 if n%10 !=0 or n < 2 else len(str(n))-ans.start())
```
TLEでした。また同じ間違いをしてしまった……。愚か。無駄にサーバーに負荷をかけちゃって申し訳ない。
わざわざ正規表現の勉強もしたし、こないだ学んだ三項演算子もさっそく使ったんだけど。


###2回目
①そもそも奇数から始まったら10もクソもないわ
②5も出てこないから出てくる10の数だけでええわ
今更気づきました。愚かの極みか？

```py
import re
n = int(input())
ans=0
#奇数のときと小さすぎるときはナシ
if n % 2 !=0 or n < 10:
    print(0)
else:
    while n >= 10:
        #とりあえず10の倍数になるまで減らす
        if n % 10 != 0:
            n -= 2
        #10減らして末尾の0を数えて足しまくる
        else:
            z = re.search('0+$' , str(n))
            ans += len(str(n)) - z.start()
            n -= 10


    print(ans)
```
TLEです。さっきよか減ったけど！　いけるかなと思ったんですけど……確かにもっと短くできそうな気はする。0の数に規則性があることは自明だものな。
全然わからん。カンニングします。

強人（つよびと）の解答
---
 - 2で割って、5で割った商を割り足し続けると答えになる[^1]

なんで？！　全然わからん。プログラマ、IQが300ある[^2]？？？
そういうなにがしかのアルゴリズムの基本なんだろうな。アルゴリズムの勉強ちゃんとします。

（追記）

 - 約数に5が現れてくると、周りの偶数に含まれる2でまた0が増える
 - 奇数を除いたため、約数に5が現れるのは2*5<sup>i</sup>のとき
 - なので、2*5<sup>i</sup>が現れるたびカウントすればよい
 
 →5で割り続ける or n//2*5<sup>i</sup>をし続ける
なるほどな～！

[^1]: 他にもいくつかあったけれど一番脳内で噛み砕けそうなのがこれでした
[^2]: 一行で終わっている強強人（つよつよびと）はたぶんIQ5000ぐらいある
laravelのセットアップ（Windows）

# はじめに
laravelとは、Webに特化したPHPフレームワーク。セキュリティ対策(CSRF対策など)もこれでできる。MVCアーキテクチャを採用している。

公式ページ：http://laravel.jp/

Macユーザーの方は、https://qiita.com/Alesion30/items/6996e18b3c183316d058

# セットアップの流れ
1. XAMPPのインストール
2. Composerのインストール
3. Composer経由でLaravelのインストール

# XAMPPのインストール
https://www.apachefriends.org/jp/index.html から、XAMPPをインストールする。

# Composerのインストール
https://getcomposer.org/doc/00-intro.md#installation-windows にアクセスし、Composer-Setup.exeをダウンロードする。Composer-Setup.exeを開き、インストールを始める。

Composerがちゃんとインストールされてるかどうか確認する。powershellを開いて、下のコマンドを打つ。

```
$ composer -v
```

こんな感じで、バージョンが表示されたら成功

<img width="888" alt="スクリーンショット 2019-12-27 5.59.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/b5e76618-0e9d-1c6a-5584-2f6afd8222c4.png">

# Laravelのインストール

ターミナルを開いて、下のコマンドを打つ。

```
$ composer global require “laravel/installer=~1.1”
```

コントロールパネルを開き、システムとセキュリティーをクリックする。

<img width="554" alt="スクリーンショット 2019-12-27 6.52.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/241f9403-78f0-f5f2-bf68-e24132b842d7.png">

システムをクリックする。

<img width="562" alt="スクリーンショット 2019-12-27 6.52.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/589f8c8c-4086-1a42-e963-59ba68ab46f1.png">

システムの詳細設定をクリックする。

<img width="562" alt="スクリーンショット 2019-12-27 6.53.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/6f340ddf-2426-4ee3-d391-33793ee8b8a4.png">

環境変数をクリックする。

<img width="370" alt="スクリーンショット 2019-12-27 6.54.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/86ca5e84-94c5-f83d-b26b-cb8299bbede5.png">

システム環境変数のPathを選んだ状態で編集をクリックする。

<img width="445" alt="スクリーンショット 2019-12-27 6.55.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/6fce1280-9f18-e3f4-50c6-ebc8f57a8b05.png">

新規をクリックして、下の内容を打ち込む。OKを押して、PCを再起動する。

```
C:¥Users¥ユーザー名¥AppData¥Roaming¥Composer¥vendor¥bin
```

<img width="344" alt="スクリーンショット 2019-12-27 6.55.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/a67dab13-63c9-0d40-5941-e4ce4bf90d23.png">

laravelがインストールされているかどうか確認する。powershellを開いて、下のコマンドを打つ。

```
$ laravel -v
```

バージョンが表示されていたら成功。

# Laravelのプロジェクトの作成

ターミナルを開き、デスクトップに移動して、下のコマンドを打つ。
```
$ laravel new laravelApp
```

composerのインストールはうまくいったけど、laravelのインストールはうまくいかなかった人は、代わりに下のコマンドを打つ。

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

先ほど作成したアプリに移動してphp artisan serve と打つ。

```
$ cd laravelApp
$ php artisan serve
```

下の例では、http://127.0.0.1:8000 と表示されているので、このURLにアクセスする。終わるときは必ず、**CTRL+C**でサーバーを止める。

<img width="639" alt="スクリーンショット 2019-12-27 6.25.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/f32c87e8-5d3c-517a-4f90-1c62a7400593.png">

この白い画面が出たら成功。

<img width="1385" alt="スクリーンショット 2019-12-27 6.36.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/cf0b8ec1-654e-47c1-fa9a-4259e01902cf.png">
「リファクタリング 第2版」Swiftでコーディング その2

# 7頁 第1章 amountFor関数、8頁 第1章 statement関数

## Swift版 main.swift

データ生成、結果表示付き。

```swift
import Foundation

makeData()

func statement(invoice:Invoice, plays:Dictionary<String, Play>) -> String {
    var volumeCredits = 0
    var totalAmount = 0
    var result = "Statement for \(invoice.customer)\n"
    let format = NumberFormatter()
    format.numberStyle = .currency
    format.locale = Locale(identifier: "en_US")

    for perf in invoice.performances {
        let play = plays[perf.playID]!
        let thisAcmount = amountFor(perf: perf, play: play)

        volumeCredits += max(perf.audience - 30, 0)
        if "comedy" == play.type {
            volumeCredits += Int(perf.audience / 5)
        }
        result += "  \(play.name): " + format.string(from: NSNumber(value: thisAcmount / 100))! + " (\(perf.audience) seats)\n"
        totalAmount += thisAcmount
    }
    result += "Amount owed is " + format.string(from: NSNumber(value: totalAmount / 100))! + "\n"
    result += "You earned \(volumeCredits) credits\n"
    return result
}

func amountFor(perf:Performance, play:Play) -> Int {
    var thisAcmount = 0

    switch play.type {
    case "tragedy":
        thisAcmount = 40000
        if perf.audience > 30 {
            thisAcmount += 1000 * (perf.audience - 30)
        }
    case "comedy":
        thisAcmount = 30000
        if perf.audience > 20 {
            thisAcmount += 10000 + 500 * (perf.audience - 20)
        }
        thisAcmount += 300 * perf.audience
    default:
        print("error")
    }
    return thisAcmount
}

let result = statement(invoice: invoices[0], plays: plays)
print(result)
```
Unityのcollaborateの容量がいっぱいだった時

Unityで個人開発をするときにcollaborate機能を使おうとしたところ、ストレージが足りないと警告が出たので削除しようとしました。
しかし、ややこしかったので共有。

collaborate機能について知りたい方はこちらを参考に
https://qiita.com/warapuri/items/bfb2a7cdbbcebaa172cc



1,Unity idにログインする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/b3d88545-f9aa-74ef-b815-fa58a1fccaee.png)

2,「プロジェクト」をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/a80cc0d1-910b-c541-c734-ce16d7a35cf8.png)

3,クリック後にUnity Dashboardに移動するので削除するプロジェクト名をクリック(画像は3D Vocal)
![Inkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/c4819875-57d9-5616-c7b0-4f000ee31168.jpeg)

4,「Setting」の「Usage」をクリック
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/fda1bd76-1a8a-f84a-1364-b492d1953985.png)

5,右側にある「ARCHIVE PROJECT」をクリックする
![InkedInkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/51cb4b09-09d7-7124-ba6c-adc99d72a593.jpeg)

どれが容量を取っているかグラフでわかるようになっている。
6,画面下側の赤い「Archive」のボタンをクリックする
![InkedInkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/24744da0-e88e-5ed6-12ce-f46a0372ed56.jpeg)


7,「You must type 'achive'in order to proceed」「archive」と入力すると「Yes,archive it」が押せるようになるのでクリックする。
![InkedInkedキャプチャ_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262130/ee2effe9-3af3-4792-5f3c-0b9f70eb0107.jpeg)


こちらを参考にさせてもらいました。
http://bibinbaleo.hatenablog.com/entry/2018/03/08/113316
laravelのセットアップ（Mac）

# はじめに
laravelとは、Webに特化したPHPフレームワーク。セキュリティ対策(CSRF対策など)もこれでできる。MVCアーキテクチャを採用している。

公式ページ：http://laravel.jp/

Windowsユーザーの方は、https://qiita.com/Alesion30/items/47c7c7fe110c440067f5

# セットアップの流れ
1. MAMPのインストール
2. Composerのインストール
3. Composer経由でLaravelのインストール

# MAMPのインストール
https://www.mamp.info/en/downloads/ から、MAMPをインストールする。

# Composerのインストール
https://getcomposer.org/download/ にアクセスして、Manual Downloadから最新版をダウンロードする。

<img width="1363" alt="スクリーンショット 2019-12-27 5.53.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/feb958ae-34a6-7910-aaeb-a00169f7f6da.png">

先ほどインストールしたものを/usr/local/bin/composerに移動させる。ターミナルを開いて、以下のコマンドを打つ。

```
$ cd ~/Downloads/
$ sudo mv composer.phar /usr/local/bin/composer
$ chmod a+x /usr/local/bin/composer
```

Composerがちゃんとインストールされてるかどうか確認する。

```
$ composer -v
```

こんな感じで、バージョンが表示されたら成功

<img width="888" alt="スクリーンショット 2019-12-27 5.59.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/b5e76618-0e9d-1c6a-5584-2f6afd8222c4.png">

# Laravelのインストール

ターミナルを開いて、下のコマンドを打つ。

```
$ composer global require “laravel/installer=~1.1”
```

pathを通すために、bash_profileを編集する。ターミナルを開いて、下のコマンドを打つ。

```
$ vim ~/.bash_profile
```

shift+Iで、編集モードに切り替えて、下のexport文をどこかに入れる。

```
export PATH=$PATH:~/.composer/vendor/bin
```

escで、編集モードを終了し、:wqで保存して、vimを終了する。ちなみに、:qで保存せずに終了することができる。

vimを使ったpathの追加は、[こちらのページ](https://qiita.com/nbkn/items/01a11392921119fa0153) を参考にしてください。

# Laravelのプロジェクトの作成

ターミナルを開き、デスクトップに移動して、下のコマンドを打つ。

```
$ laravel new laravelApp
```

composerのインストールはうまくいったけど、laravelのインストールはうまくいかなかった人は、代わりに下のコマンドを打つ。

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

先ほど作成したアプリに移動してphp artisan serve と打つ。

```
$ cd laravelApp
$ php artisan serve
```

下の例では、http://127.0.0.1:8000 と表示されているので、このURLにアクセスする。終わるときは必ず、**CTRL+C**でサーバーを止める。

<img width="639" alt="スクリーンショット 2019-12-27 6.25.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/f32c87e8-5d3c-517a-4f90-1c62a7400593.png">

この白い画面が出たら成功。

<img width="1385" alt="スクリーンショット 2019-12-27 6.36.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519787/cf0b8ec1-654e-47c1-fa9a-4259e01902cf.png">
ネットワークの不正検知モデル Kitsune についてまとめてみた。

## 概要
**ネットワークの不正検知モデル**で**SoTA**(多分今も？)のKitusneについて講義を受ける機会があったので、いいタイミングだと思い少しまとめてみることにしました。

## Kitsune とは
Kitsune は、[原論文](https://arxiv.org/pdf/1802.09089.pdf) Kitsune: An Ensemble of Autoencoders for Online
Network Intrusion Detectionで2018年に発表された、ネットワーク侵入検知システム(**Network Intrusion Detection System**: NIDS)で（たぶん2019年12月現在も）SoTAのスコアを叩き出している異常検知の機械学習モデルになります。ネットワーク侵入検知とは、通常のネットワークトラフィックと、外部から侵入などを受けた異常トラフィックを区別し、検知することです。
コードもOSSとして[ここに](https://github.com/ymirsky/Kitsune-py)あります。



論文のアブストラクトやイントロのところにも書いてある通り、既存のNNを用いた異常検知**モデルが非常に重く**、ネットワーク検知のニーズ（ルーターとかにモデルをデプロイしたいため、軽いモデルが必要）に合わなかったり、教師あり学習のモデルが使われていることが多く、ネットワークエンジニアが**ラベリングをする手間だったりかかる費用が膨大**になる、といったところを解決するのが、Kitsuneであるということです。

### 基本的なビルディングブロック
<img width="603" alt="Screen Shot 2019-12-26 at 22.29.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/5e68d086-27e9-f35b-b625-f0a7de7a88a1.png">
入力ベクトルに対して**Auto Encoder** (AE)を用いて、出てきたものと入力の誤差を**MSE**でとって、それの**誤差と閾値によって異常を検知する**、といういたってスタンダードなアイディアにはなっていますが、先ほど出てきたネットワーク検知の**ニーズにより合った工夫**がいくつもなされているので紹介します。

#### 入力の工夫
入力に入るべきものはネットワークのトラフィックデータです。ネットワーク検知に使われるマシンのスペックは、マシンの導入量が膨大であるなどの理由から安価な物で補えるだけのモデルの複雑さであればより好ましいです。したがって、メモリなども限られているので入ってくる全てのデータをログとして記憶するのではなく、**データの統計量をトラッキング**します。各統計量の詳しいところは原論文をお読みください。
<img width="578" alt="Screen Shot 2019-12-26 at 22.47.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/349ba3b6-dea6-e0dc-f389-99cc4c74445c.png">

また、**時間軸**には
<img width="148" alt="Screen Shot 2019-12-26 at 22.35.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/e1cf03ba-9d26-7250-3739-36d8a7eb95e3.png">
のように表現される簡単な時間で衰退するようなものを掛け合わせて、ある時間より古いものは入力データから完全に落としています。統計量は各時間ごとに更新され、古いものは消えるのでメモリにも優しいです。

#### AEの工夫
入力ベクトルを大きなAEに入れ込むのではなく、入力ベクトルを類似度計算し、その類似度が高いものから順に**樹形図でクラスタリング**します。
<img width="598" alt="Screen Shot 2019-12-26 at 22.41.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/eef2b5fe-1726-ec5d-0977-aef097400a37.png">
そのクラスタリングされたグループをそれぞれ別のAEに入れ、全体ではなくそのグループたちをAEで自己生成させます。こうする理由はパラメータ削減です。このように１つの大きなAEではなく複数の小さなAEを用いることから、**AEアンサンブル**というような題名がついているわけです。

#### アウトプット層の工夫
先述のいくつかのAEで作られた類似度の高いグループの自己生成されたものは、そのあとに大きなAEに入力され、その結果が異常スコアに使われることになっています。**異常スコアは閾値によって決定**され、指標としては単純に元の入力とのMSEが使われています。
<img width="347" alt="Screen Shot 2019-12-26 at 22.46.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/9f269010-1563-ac4c-a269-a17382c10e9b.png">

以上のような工夫を用いて、軽量でも以下のような素晴らしい結果を出しており、注目されているようです。
<img width="527" alt="Screen Shot 2019-12-26 at 22.48.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/519792/e9066aea-2aca-f164-1045-0b36f673fa2d.png">


##終わりに
めちゃくちゃ真新しいことが組まれているわけではないですが、マシンスペックのニーズに応じた制約の中で最大のアキュラシーを出すような工夫が詰まっている素晴らしいモデルだと感じました。興味のある人は原論文およびOSSになっているコードをぜひ見てみてください。今回はこの辺で。

おわり。
「チラ裏ですよ」Cocoapods使用時にXcode UIテストが落ちる

# 出力エラー

```bash
(en) The bundle “****************” couldn’t be loaded because it is damaged or missing necessary resources

(ja) バンドル“****************”は、壊れているか必要なリソースがないため読み込めませんでした。 バンドルを再インストールしてください。
```

# 環境

- Xcode 11.3 (11C29)
- CocoaPods 1.8.4

# 対策

`Target - > building settings - > ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES - > Value(Boolean) を $(inherited) に変更`

## 余談
pod install でワーニングが表示されてたのを予め解決しておく

```bash
[!] The `<project name> [Release]` target overrides the `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` build setting defined in `<.xcconfig location>'. This can lead to problems with the CocoaPods installation
    - Use the `$(inherited)` flag, or
    - Remove the build settings from the target.
```
【Rails】rails sのログに「Cannot render console from <IPアドレス>!」と出たときの対処法

## はじめに
以下エラーが**Docker環境**のRailsアプリ開発中に発生しました。
対処法について記載します。

画面は`rails s`のログから切り取ったものです。

```shell
Cannot render console from 172.23.0.1! Allowed networks: 127.0.0.0/127.255.255.255, ::1
```

## 環境
```yaml
OS: macOS Catalina 10.15.1
Ruby: 2.6.5
Rails: 6.0.2.1
Docker: 19.03.5
docker-compose: 1.24.1
```

## 結論：対処法
`config/environment/development.rb`に以下**ホワイトリスト**を追記します。

```
Rails.application.configure do
...略
  config.web_console.whitelisted_ips = '172.23.0.1' #追記
...略
end
```

これで**無事に動く**ようになります。

以降は念の為調べてみたメモです。

## （余談1）ホワイトリストとは？
> ホワイトリスト（英語: Whitelist）とは、警戒する必要のない対象の一覧表のこと。対義語はブラックリスト。

[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88%E3%83%AA%E3%82%B9%E3%83%88)より

## （余談2）このアドレスって何なのかを確認
**むやみに許可すると怖くない？**と思い、このIPアドレスについて調べました。

`docker network ls`で**開発中のアプリケーション名**がついているネットワークを確認。

```shell
$ docker network ls
NETWORK ID          NAME                         DRIVER              SCOPE
XXXXXXXXXXXX        bridge                       bridge              local
YYYYYYYYYYYY        host                         host                local
...略
ZZZZZZZZZZZZ        <アプリケーション名>_default               bridge              local
...略
```

↓

`docker network inspect <アプリケーション名>_default`で詳細を見てみる。

```shell
$ docker network inspect <アプリケーション名>_default
[
    {
        "Name": "<アプリケーション名>_default",
        "Id": "<一意のID>",
        "Created": "<作成された日付>",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.23.0.0/16",
                    "Gateway": "172.23.0.1" #今回許可したアドレス
                }
            ]
        },
```

## おわりに
最後まで読んで頂きありがとうございました:bow_tone1:

どなたかの参考になれば幸いです:relaxed:

## 参考にさせて頂いたサイト（いつもありがとうございます）
- [Railsで「Cannot render console from Allowed networks」と言われたら - Qiita](https://qiita.com/suin/items/9b567c63af73b235e458)
- [ホワイトリスト - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88%E3%83%AA%E3%82%B9%E3%83%88)
- [network コマンドを使う — Docker-docs-ja 17.06.Beta ドキュメント](http://docs.docker.jp/engine/userguide/networking/work-with-networks.html)
ブレッドボードの電位取得基板を作った

#はじめに
組込みシステム開発中のブレッドボードの状態を取得したかったので，基板を作成しました．使用したいイベントの前に基板が届かず，使用しなかったためQiitaにさらします．

#機能
* 小さめのブレッドボード（23列）の電位を0/1で入出力できる
* i2cで情報を読み取れる
* なんかスイッチがついている
* 電源供給がちょっと簡単にできる

<img width="200" alt="IMG_20190918_122544.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311590/4bff201c-1278-dd55-22ef-37c930c0e43d.jpeg">
使用中の画像がなかった．

#ブレボの回路のデバッグ
回路をデバッグするために，ソフト側を工夫してSerial出力したり，テスターで一つひとつピンを確認していくかと思います．その調べる過程は面倒くさいですし，一気に確認する方法を考えてみるとこれで実現できると考えました．回路的に問題があるとかいう文句は一切受け付けておりません．
[この作品](https://gugen.jp/entry2018/2018-112)のくそ雑魚版だと思ってもらえばいいと思います．

#回路
[IOエキスパンダー](http://akizukidenshi.com/catalog/g/gI-13522/)を3つ使用して，(23列+1スイッチ)の情報を読み取れるようにしています．電源が入ったらLEDが光ったり，タクトスイッチが使えたり，意外に利便性も高いです．ちゃんとI2Cのプルアップ抵抗をつけている点も我ながら偉いですね．
↓が回路です．電源スイッチが全く機能していないのは仕様です．
<img width="400" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/311590/7ce47637-d8ec-9ea8-94ed-efec80664b2b.png">

#さいごに
ほとんど使用したことがない基板ですが，紹介したもののように，回路のデバッグが簡単にできるものが，テスターやオシロスコープ以外にもあるべきだと強く思います．
基板の間違えを探すときは，ブレッドボードを見てるよりも3倍面倒くさいので，誰かいいものを考えてくれませんかね．

部品の詳細やプログラムが欲しい人はコメントでどうぞ．
うっかり事象メモ「GitHub Actionsのworkflowファイルが何回編集しても反映されない」

# たった1行で教訓要約
__GitHub Actionsで使う`./github/workflows/`だってバージョン管理されていることを忘れるな__

# わずかに5行で状況説明

- Gatsbyで作った静的サイトをGitHub Pagesに自動デプロイしようとした
- Releaseが作られたと同時にActionsが発火するように設定した
- ReleaseしてActionsが鎮火したあとでデプロイ先ミスってることがわかった
- Workflowを書き直して、__さっきのReleaseの文章をちょこっといじってEditで済ませた__
- __Workflowの編集が反映されてない！！！！！__

# ほんの1枚で理由解説

__さっきのReleaseにはWorkflowの編集は反映されてないじゃないか！！！！！！__

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411269/ace301a3-6799-b19d-e1e1-2d32835b1063.png)

(いるかわからんけど)私のようなうっかり屋がこの記事で減ってくれれば幸いです。
A-FrameとAR.jsでVR広告ARを作ってみた

# はじめに

前回の「[A-Frame v1.0 で クリスマスアニメーション](https://qiita.com/qvtec/items/556ce01b5fb3e55595d6)」はVRでしたが、今回はA-FrameにAR.jsも追加してARにしてみます。

VRが好きなので、VRの広告みたいなものを作ります。
VRの3Dモデルは簡易なものですが、1時間かけて作りました。

# HTMLベース

A-Frame と AR.js 読み込み
地面と背景とライトを配置

```html
<html>
  <head>
    <meta charset="utf-8">
    <title>A-Frame X'mas</title>
    <meta name="description" content="X'mas - A-Frame">
    <script src="https://aframe.io/releases/1.0.0/aframe.min.js"></script>
    <script src="https://jeromeetienne.github.io/AR.js/aframe/build/aframe-ar.js"></script>
  </head>
  <body>
    <a-scene embedded arjs="debugUIEnabled:false;" cursor="rayOrigin:mouse">

      <a-entity id="ground"
                geometry="primitive: circle; radius: 5;"
                rotation="-90 0 0"
                material="shader: flat; color: #ECECEC"></a-entity>

      <a-sky color="#00111a"></a-sky>
      <a-light type="directional" color="#fff" intensity="0.2" position="-1 2 1"></a-light>
      <a-light type="ambient" color="#fff"></a-light>
    </a-scene>
  </body>
</html>
```

# 3Dモデル配置

VRモデルを配置してずっと回転させる

```html
<a-assets>
  <a-asset-item id="vr-obj" src="./assets/obj/vr.obj"></a-asset-item>
  <a-asset-item id="vr-mtl" src="./assets/obj/vr.mtl"></a-asset-item>
</a-assets>

<a-entity id="vr" position="0 1.7 0" scale="0.4 0.4 0.4" rotation ="0 -270 20"
  animation__vr_rotation="property:rotation; from:0 -290 20; to:0 70 20; dur:8000; easing:linear; loop:true;">
  <a-obj-model src="#vr-obj" mtl="#vr-mtl" shadow="receive: true"></a-obj-model>
</a-entity>
```

# 画像を配置

紹介文の画像を配置
VRに向かって線を引くためlineを追加

```html
<a-assets>
  <img id="menu-frame1" src="./assets/txt1.png">
</a-assets>

<a-entity id="frame1" position="1.5 2.5 -3.5" scale="1 0 0"
  animation__frame1="property:object3D.scale.y; from:0.001; to:1; dur:500; easing:easeOutCubic;">
  <a-image src="#menu-frame1" width="2"></a-image>
  <a-entity line="start:-1 -0.8 0; end:-0.5 -0.5 0; color:#02ceff" visible="false"
    animation__frame1_line="property:visible; from:false; to:true; delay:4200;"></a-entity>
</a-entity>
```

# animation

[アニメーション](https://aframe.io/docs/1.0.0/components/animation.html)

よく使うものをピックアップしました。

**property**
位置や回転、マテリアルを変えるアニメーションを設定できる
今回はobject3D.scale.yとしてyだけの操作とした
position, rotation, visible

**from/to**
propertyで指定したものをfromからtoに変化させる

**delay**
ミリ秒待ってから実行する

**dur**
ミリ秒の間に変化させる

**easing**
変化の動き方
私はいつも https://easings.net/ を参考に動きをみています

**startEvents**
クリックやマウスオーバー時に実行させることができる
カンマで区切れば複数指定ができる
click, mouseenter, mouseleave

# AR.js対応ブラウザ

https://github.com/jeromeetienne/AR.js/blob/master/README.md#browser-support

iOS はSafari
Android はChrome

# DEMO

Netlifyにアップしているだけなので、24時間で消えます

https://fervent-boyd-2f63a6.netlify.com/

ARがない状態だとこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536619/52c744bf-b2be-87cf-d82e-3f0b6aa38c29.png)

# 最後に

アドベントカレンダーできて楽しかったです。
今までありがとうございました！
またVRで会いましょう。
AutowareをDockerで動かす


[Autoware 自動運転ソフトウェア入門](https://www.amazon.co.jp/Autoware-%E8%87%AA%E5%8B%95%E9%81%8B%E8%BB%A2%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E5%85%A5%E9%96%80-%E5%AE%89%E7%A9%8D-%E5%8D%93%E4%B9%9F/dp/4865941878/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=autoware&qid=1577378442&sr=8-1)にかかれている環境構築方法は古い。
リポジトリーがgit hubからgit labに変更されている。

以下ではDockerでAutowareを起動するまでを記載しています。

[Autoware wiki](https://gitlab.com/autowarefoundation/autoware.ai/autoware)にインストール方法からDemoの動かし方まで記載されています。



## Autoware Dockerコンテナ立ち上げ方法
[Autoware docker git lab]
(https://gitlab.com/autowarefoundation/autoware.ai/docker)

はじめにAutowareのDockerコンテナ立ち上げ方法を確認しておく。
`git clone`して`./run.sh`すればコンテナは立ち上がる。
[参照](https://gitlab.com/autowarefoundation/autoware.ai/autoware/-/wikis/Generic-x86-Docker)

```
$ git clone https://gitlab.com/autowarefoundation/autoware.ai/docker.git
$ cd docker/generic
$ ./run.sh
```

`run.sh`の中身を見ると`VOLUMES`で `--volume=$SHARED_HOST_DIR:$SHARED_DOCKER_DIR:rw"`と設定している。
コンテナを立てたときに`$SHARED_DOCKER_DIR=/home/autoware/shared_dir`
ディレクトリができ、それにローカルの`SHARED_HOST_DIR=$HOME/shared_dir`をマウントしている。


```
$ vim run.sh

XSOCK=/tmp/.X11-unix
XAUTH=$HOME/.Xauthority

SHARED_DOCKER_DIR=/home/autoware/shared_dir
SHARED_HOST_DIR=$HOME/shared_dir

AUTOWARE_DOCKER_DIR=/home/autoware/Autoware

VOLUMES="--volume=$XSOCK:$XSOCK:rw
         --volume=$XAUTH:$XAUTH:rw
         --volume=$SHARED_HOST_DIR:$SHARED_DOCKER_DIR:rw"

if [ "$BASE_ONLY" == "true" ]; then
    SUFFIX=$SUFFIX"-base"
    VOLUMES="$VOLUMES --volume=$AUTOWARE_HOST_DIR:$AUTOWARE_DOCKER_DIR "
fi

# Create the shared directory in advance to ensure it is owned by the host user
mkdir -p $SHARED_HOST_DIR
docker run \
    -it --rm \
    $VOLUMES \
    --env="XAUTHORITY=${XAUTH}" \
    --env="DISPLAY=${DISPLAY}" \
    --env="USER_ID=$USER_ID" \
    --privileged \
    --net=host \
    $RUNTIME \
    $IMAGE
```


## Demo用のデータ用意〜Autoware起動

それでは[上記](#autoware-dockerコンテナ立ち上げ方法)を踏まえて、Dockerを使ってAutowareを起動させる。

コンテナを立てる前にデータを用意する必要がある。
[Demo wiki](https://gitlab.com/autowarefoundation/autoware.ai/autoware/-/wikis/ROSBAG-Demo)のリンク先からデータをダウンロード

```
$ cd ~
$ mkdir .autoware
$ cd .autoware
$ cp ~/shared_dir/sample_moriyama_* .
$ tar zxfv sample_moriyama_150324.tar.gz
$ tar zxfv sample_moriyama_data.tar.gz
```

[上記](#autoware-dockerコンテナ立ち上げ方法)のようにマウントするローカルディレクトリは`$HOME/shared_dir`なのでそれに合わせてディレクトリ作成と解凍を行う。


データを用意したら、コンテナを立ち上げる

```
$ cd docker/generic
$ ./run.sh
```


コンテナ内からAutowareを起動させる

```
autoware@desktop:~$ cd Autoware
autoware@desktop:~/Autoware$ source install/setup.bash
autoware@desktop:~/Autoware$ roslaunch runtime_manager runtime_manager.launch
```


Autoware起動！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254458/2402c39b-51ca-b93a-8f4c-694d50a0871b.png)
Ceforeコマンド集

#はじめに
このページはCefore開発初心者が個人的によく使うコマンドのオプションをまとめたページです。
執筆中のCeforeバージョンは0.8.1なので、利用時には異なるオプション、コマンドが用意されている場合があります。適宜パッケージに付属するREADMEでも読んでください。このページのソースは0.7.aのマニュアルです。(それ以降のものは存在していない）
加えて、純粋にPC初心者のまとめページですのでセキュリティや他のアプリケーションへの影響を何も考えずにとりあえず動かすだけですので、その点はご了承ください。（指摘してくれてもいいです。）

#Ceforeとしてデフォルトで実装されるコマンド
##経路情報に関して
```
cefroute add/del [*uri] [*protocol] [*next_IP] [-d config_file_die] [-p port_num]
```
cefore起動中に経路情報を追加/削除するコマンド
よくわかんないんですけど、基本管理者権限でないと追加されません。
*は必須のパラメータになります（以下も同様）

|option |explain  |example  |
|---|---|---|
|uri  |ContentName  |ccn:/jp/univercity/todai/  |
|protocol  |protocl  |udp  |
|next_IP  |next node IP address  |10.0.0.1  |

多分uriは100階層ぐらいが限界だった気がする。
基本IPへのオーバレイ実装なので、プロトコルの指定はTCP/UDPが選べる模様。同様に次のノードへの転送はFaceではなくIP指定になってます。
ちなみにIPアドレスはカンマ区切りで複数のIPを一つのContentNameに紐づけられます。
※ただし、ポートまで指定していくのでFaceの実装であるということなのかもしれない。デフォルトだとcefnetd宛のポート番号が振られれます。

コンフィグファイルを読み込むとかいう謎のオプションは未知のオプションです。誰か調べて教えてください。

##実稼働的な部分に関係するコマンド
```
cefputfile [*uri] [-f file_name] [-b block_size] [-r rate] [-e expiry] [-t cache_time] [-d config_file_dir] [-p port_num] [-k]
```
CSにファイルをキャッシュさせるコマンド
とりあえずファイル名を階層的なContenNameで指定すればどうにかなります。キャッシュさせたいファイルがあるディレクトリでやるか、`-f`オプションでファイルがあるディレクトリを指定すればいいと思います。別に拡張子がなくても行けます。

```
cefgetfile [*uri] [-f file_name] [-o] [-m chunks] [-s pipeline] [-d config_file_dir] [-p port_num] [-k]
```
コンテンツ取得コマンド。
キャッシュコマンド同様にContentNameだけあればどうにか動く。
一回ContentNameの最下層の名前でファイルが書き出されるので実行ディレクトリ以下にContentNameのファイルと同名のものがあると上書きされるので注意。`-f`コマンドでファイル名を操作できるので気を付けて。
よくわかってないんですけど、50個まではpythonでsubprocessぶん回すと並列で叩けます。シェルとかで複数行叩くと直列処理になって死ぬほど時間を食うぞ。（毎回Dataパケット待ち処理が入る）
日本語小説向きのCSSフォント指定

#小説向きのCSSフォント指定

　おすすめの「フォント指定」みたいな記事を見て、何も考えずにそれをコピペして使用していませんか。
　特に「小説」を中心とした、日本語用サイトの場合、かなり気になるある問題があるのです。

　それは「……」「三点リーダー」が上下中央に来ない問題。
　そして「――」「ダッシュ(ダーシ)」がつながらなかったり、太い細い、長さがおかしいなど見た目が悪い問題、というのに直面することになります。
　もちろん他にも「○×」がなんか小さかったり大きかったりする、などの問題として、表面化してきます。

　他にも問題として「\」半角の円マークが、バックスラッシュになるというのもあります。

##原因

 　端的に言えば「英語フォントを優先指定しているため」に「アルファベット」と「日本語」両方で「やや違う意味で」使う文字があり、それらが英語優先になるため、日本語用の文字の一部が英語用表記になってしまっています。
　これはUnicodeが作成された当時、似た意味の文字を同一のコードポイントに集約し「細かい見た目などにこだわらないで一緒にしたから」です。
　昔の英語フォントはASCIIの範囲内だったので、ぶつかることはありませんでしたが、現在のフォントはUnicode化が進んできており、ぶつかる文字の数はどんどん増えています。
　「ASCII フォント」などと呼んでいますが、実際のところASCIIの範囲を大幅に超えているのが現在の有名フォントです。
　似たような問題として、中国語のフォントと日本語フォントで漢字のデザインに差がある場合などが知られています。多くの投稿サイトは言語指定が実装されていないので、日中台混在文章などでは、違和感なく記事を投稿できるユーザー投稿型サイトはほとんどありません。

```css
body {font-family: "Segoe UI", Meiryo; }
```
抜きだすと、こういう指定ですね。
これを極論ですが

```css
body {font-family: Meiryo, "Segoe UI"; }
```
　こうしてほしいな、と思うのです。
　特に「小説家になろう」や「カクヨム」といった大手投稿サイトでは、そういう文字も普通っぽく表示されています。日本語フォントを優先しているのです。
　しかしそれ以外の新興サイトや日本語へのこだわりの少ないサイトでは、なかなかそうではないパターンが多く見られて、閲覧する際にもモヤモヤする思いです。

##英語を妥協する

　もし、日本語文章の見た目にこだわりたいのであれば、英語の見た目をこだわるのを諦める必要があります。
　はるか昔のフォント指定と違い、Meiryoや遊ゴシック以降のフォントは、言われるほど英語の表示が汚いということもありません。というかＭＳゴシック、ビットマップフォント時代の話を、現在でも引きずっているのではないでしょうか。大半のユーザーはそこまで気にしていません。

　しかし一部のユーザーは「……」三点リーダーが上下中央に来るかどうかなど「小説を中心としたサイト」では非常に気にするのです。

　古くからweb開発に携わる人や強いこだわりがある人は、英語を妥協するなんて、と思うかも知れません。Qiitaのような日英、ソースコード混在のような環境ならそれも理解できます。しかし「小説」等日本語を読ませるサイトにおいては、英語以前に日本語がおかしいのは気にならないのでしょうか。ちょろっと日本語も気にしてほしいなと思うしだいです。

　「日本語文章」には「日本語のフォント優先指定を」今こそ、決断の時です。よろしくお願いいたします。
Oculus Quest 開発者モードで PC に認識されない問題


Oculus Quest を初めてPCにつなごうとした際の問題です
PC : Windows 8.1

1. スマホからQuest の開発者モードをオンにする
2. PC と Quest をつなぐ
3. **この時点でQuest 側に確認のダイアログがでていない**
3. `adb devices` でつながっているか確認する
4. **つながっていない**

※`adb`コマンドは後述のAndroid Studio についてくる Android SDK の中にあります

## まずしたこと

#### 開発者モードをオフにする

通常通りにつながる
Quest の中のファイルも閲覧できる状態

#### Windows のデバイスマネージャの確認

USB 関連のデバイスのところにある
開発者モードが**オフ**の状態だと `Quest` という名前で認識されていました　
開発者モードが**オン**の状態のときは `Quest` ではなく `XR~~` (~の部分は忘れた) みたいな名前になっていました

名前が変わっていただけで認識自体はされている状態

## 解決方法

ここまでの情報からそもそも Quest 固有の問題ではなくて Android の問題なのではないかと考えました

[1]:https://qiita.com/couzie/items/2dd854df9c8c74317078
すると、この記事にたどり着きました
[ADBドライバのインストールとUSBデバッグのセットアップ][1]


[2]:https://developer.android.com/studio
この記事に従って
まず [Android Studio][2] をインストールします

インストールが終わった後、そのまま起動して
 Android SDK Manager を起動し、
 Google USB Driver にチェックを入れ、インストールします。
このときに SDK があるパスをメモしておきます

開発者モードの Quest を繋いだ状態で
デバイスマネージャを開くと
黄色の ! がでている ADB interface (うろ覚え) みたいな名前のデバイスがあると思うので

>1. ドライバーの更新
2. すべてのデバイスを表示
3. ディスク使用を押す
4. 参照から先ほどメモした SDK が入っているディレクトリから、`android/sdk/extras/google/usb_driver` を選択
5.  Android ADB Interface を選択
6.  ドライバーの更新警告には はい を押す


自分の場合 ！が出ているデバイスが一つではなかったので何度かこの手順でドライバーを適用していきました

------------
自分の場合はこれで解決することができました
お役に立てれば幸いです
Vue.js

```vuejs:vue.js
<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <meta charset="UTF-8">
  </head>
  <body>
    <div id="app">
      <input type="text" v-model="text1">
      <input type="button" @click="add()" value="追加">
      <div>{{ itemCount }}</div>
      <table border="1" v-if="items.length > 0">
        <tr v-for="(item, i) in items">
          <td>{{ item }}</td>
          <td><input type="button" @click="del(i)" value="削除"></td>
          <td><input type="button" @click="update(i)" value="更新"></td>
        </tr>
      </table>
    </div>
  </body>
</html>

<script>
const app = new Vue({
  el: '#app',
  data: {
    text1: '',
    items: []
  },
  mounted() {
    this.text1 = 'test';
  },
  methods: {
    add() {
      this.items.push(this.text1);
    },
    del(i) {
      app.items.splice(i, 1);
    },
    update(i) {
      Vue.set(app.items, i, this.text1);
    }
  },
  computed: {
    itemCount() {
      return this.items.length + '個';
    }
  }
})
</script>
```
Excel VBA 最終行の下に非表示の行が存在する場合に削除するマクロ

#通常の手筋
ふつうはLastRowから行きます。
適当に書くと

```vb
Dim iRow , LastRow
LastRow = ActiveSheet.UsedRange.Rows.Count
For iRow = LastRow To 1 Step -1
If Rows(iRow).Hidden Then Rows(iRow).Delete
Next
```

#しかし
最終行の下にさらに隠し行がある場合、単純に削除ができない場合があることが発生

#そこで
ubara先生のサイトを参考に作ったのが以下のもの

```vb
Dim iRow As Long
Activesheet.Activate ' 目的のシートを表示させる(つまり選択する)
For iRow = Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row To Cells.SpecialCells(xlCellTypeLastCell).Row Step -1
If Rows(iRow).Hidden Then Rows(iRow).Delete
Next
```

https://excel-ubara.com/excelvba4/EXCEL222.html

`Cells.Find(What:="*", LookIn:=xlFormulas, SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row`でとにかく何らかの入力がある最終セルの行数を取得。これは隠し行でもカウントする...(1)
` Cells.SpecialCells(xlCellTypeLastCell).Row`は表示されているセルの最終行をとる...(2)
(1)が(2)より大きい（つまり必ず隠し行が発生する)場合(2)から(1)まで減算し、隠し行なら削除する。
また、この方式は１シートに表が複数あるとうまくいかない可能性があります。
Sparkでの性能改善（JOIN編）

お久しぶりです。
過去記事で書いたようなことを悩み、解決しながら、Sparkでのデータ処理がなんとか動くようになってきたので、今度は性能が気になり始めました。の巻

# 本日のメニュー
JOIN（関数で言うとjoinとかjoinWithとか）の性能改善です。

# いきなり結論
Sparkでjoinを実行した場合、joinのやり方はオプティマイザさんが決めてくれますが、ざっくり言って
- Sort Merge Join
- Broadcast Join
のどちらかが選ばれるはずですが、メモリの許す限り[^network]（かつ速さを重視する場合）はBroadcast Joinが使われるようにした方がいいです。
どちらが使われているかは、Web UIでも見れますし、Dataset::explain()でも見ることができます。

Broadcast Joinのなんたるかとか設定の方法とかは、[この辺](https://logmi.jp/tech/articles/321475)とかが分かりやすかったです。

Broadcast Joinがなぜ速いかっていうと、簡単に言うとJOINする対象の「大きい方」をソートしてパーティションを切りなおすっていう手間が必要なくなるからですね。

# Broadcast Join使われないんですが・・・
さて、
結論はそうなのですがBroadcast Joinが使われなかったりだのなんだので色々調べたのでべからず集にしてみました。

## joinTypeにfullはダメですよ
joinTypeはSQLでもおなじみのINNERとかLEFT,RIGHT,FULLとかってのですね。
FULL_JOINに対してはBroadcast Joinは使われません。

## Broadcast Hintはおススメしない
後述の理由でBroadcast Joinがどうしても使われなかった時に強引にこれを使ってみました。
確かにBroadcast Joinになるんですが。
が、[公式](https://spark.apache.org/docs/latest/sql-performance-tuning.html#broadcast-hint-for-sql-queries)に書いてある使い方を見ると、Hintとかいいつつこれ、単にbroadcastしてるだけですよね？
Broadcast自体はJOINに関係なく使えるもので有益なこともあるんですが、Broadcastの残念なところは、一旦使ってしまうとそのメモリは開放されない（多分sparkSessionを閉じるまで）ことです。
単発の処理ならともかく、私のように何度も何度も繰り返して処理をおこなうような使い方をしてるときにこれは困ります。
メモリリークです。

## サイズが見積もれないとそもそも候補にもならない
今回一番言いたかったのはコレです。
Broadcast Joinを使うかどうかはオプティマイザさんがデータのサイズを見て判断します。
ところで、Sparkでは、mapだのfilterだのやらせてもすぐに実行されなくて、action（countとかのこと）が呼ばれた時に初めて処理が実行されるのは前にも書きましたが、オプティマイザがサイズを見るのもこの時です。
この時、当たり前ですが前Jobの直接の結果だったりしてサイズが確定している必要があります。

ということは、Jobの途中にあるmapだのfilterだのの結果はサイズが未確定のためオプティマイザがそもそも見てくれないわけです[^toukei]。なんてこったい！

つまりどうすればいいかと言いますと

```scala
val a = <何かしらのDataset>
val b = <何かしらのDataset>

val c = b.map(r => <何かしらの変換>)

val d = a.joinWith(c, a("id") === c("id"), "left")
d.take(10).foreach(println) // action
```
みたいなことではオプティマイザの実行時(=action実行時)に`c`のサイズが分かりませんので、

```scala
val a = <何かしらのDataset>
val b = <何かしらのDataset>

val c = b.map(r => <何かしらの変換>)
c.persist().count()

val d = a.joinWith(c, a("id") === c("id"))
d.take(10).foreach(println) // action
```
こんな感じでcにもactionを実行してサイズを決めときましょう、と、そういうことです。

元々1つのJobが2つに分割されるわけなので複雑なクエリだとオプティマイザが十分に働けなかったり・・・するんですかね？少なくとも（程度はともかくとして）オーバーヘッドはあるでしょうね。
とはいえ、手元の環境では、1Job(対処前)で20秒ほどかかっていたJOIN処理が、2Job(対処後)合計で10秒ほどに短縮できました。

*2019/12/27追記*
Broadcast Joinが使われるようになってからかメモリ消費がはげしくなったような気がする。
もしかして、結局broadcast呼んだのと同じように動いちゃってんだろか。時間があったら追試します。

# 次回の予告
groupBy編をお届け・・・したい！どうすればいいかわからん！

[^network]: クラスタを組んでる場合はネットワークの帯域の許す限り、ですね。ただ、ソートしてパーティション切りなおすのだって通信が発生するはずなのでどっちがどれくらい効いてくるんでしょうねえ？私はスタンドアローンでしかまだ使ってないのでわかりません。
[^toukei]: 統計情報がちゃんと取れてて使える状況だとそんなことないんですかね？私のユースケースだと統計情報が有効に生きる気はあまりしませんが・・・。
[Android] 連続クリック対策 (DataBindingにも対応)

## 準備

こういう拡張関数を作っておく。（DataBinding 使わないなら `@BindingAdapter("onSafeClick")` の行は不要）

```kotlin
@BindingAdapter("android:onSafeClick")
fun View.setOnSafeClickListener(listener: View.OnClickListener) {
    this.setOnClickListener {
        it.isClickable = false
        it.postDelayed(300) { // 300ms内の連続クリックを無効に
            it.isClickable = true
        }
        listener.onClick(it)
    }
}
```

`isClickable` による制御が気になる場合は、`this.setOnClickListener {` の外側で前回クリックのタイムスタンプを保持しておいて比較、という対応でもいいかもしれない。

## 利用例

DataBinding を使う場合は次のようにリスナーをセットする。

```xml
<!-- View ならばなんでもいい -->
<TextView
    android:id="@+id/some_text_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:text="テスト"
    android:onSafeClick="@{() -> someViewModel.onSomeTextClicked()}"
/>
```

DataBinding 使わないなら、コードで次のようにリスナーをセットする。

```kotlin
someTextView.setOnSafeClickListener(View.OnClickListener {
    someViewModel.onSomeTextClicked()
})
```

コードでリスナーをセットする場合、次のような拡張関数を用意しておくとよりすっきり書ける。

```kotlin
fun View.setOnSafeClickListener(block: (View) -> Unit) {
    this.setOnSafeClickListener(View.OnClickListener {
        block.invoke(it)
    })
}

// ...

someTextView.setOnSafeClickListener {
    someViewModel.onSomeTextClicked()
}
```

## 補足

DataBinding を使う場合で、任意の引数を渡す場合は次のように書く。（この例だと整数`1`を渡している。）

```xml
android:onSafeClick="@{() -> someViewModel.onSomeTextClicked(1)}"
```

View のインスタンスを渡す場合は次のように。

```xml
android:onSafeClick="@{(view) -> someViewModel.onSomeTextClicked(view)}"
```

この場合(View のインスタンスを渡す場合)は、メソッドリファレンスに置き換えられる。

```xml
android:onSafeClick="@{someViewModel::onSomeTextClicked}"
```

## 改善案

`300`ms という数字を引数で渡せるようにするともっと便利かもしれない。（DataBinding でリスナーと数字、というふうに複数の引数を渡す必要があるので、その方法を調べる。）
Wordの「段落番号」インデントが崩れる問題の解決方法

# みんなが親の仇のように憎むWordの問題を一つ解決したぞ！！！

##■事象概要
Wordの段落番号(箇条書き)で「①から再開」を選択すると、インデントが崩れる

■再現手順
①段落番号（箇条書き）を作る

![段落番号①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/545e7b52-7335-9472-1d62-ff7d5665a3a8.png)

②段落番号用にスタイルを新規作成する。
　「①段落番号（箇条書き）を作る」を基準にして、「スタイル１」というスタイルを作る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/0fbc5c9a-0be9-2e34-72b7-72052af9fc4d.png)




③スタイルのインデントを変更する
![段落番号④.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/92deeac0-3934-2ec8-d638-85c7a30f7d29.png)

![段落番号⑤.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/472dab77-7d16-ef56-c750-f63d0d448aec.png)

![段落番号⑥.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/f428853e-3ec9-9df3-01c3-4163dad47d1f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/66d82e80-71b8-8d7a-220d-19528553b091.png)


④「①から再開」を選ぶとインデントが崩れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/4fa8d98d-84dd-06d6-3226-f2977c3fc902.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/8a6a5f42-a2bf-d168-e5ad-c58e13ea7622.png)

許せねぇ！！！



##■原因
　これ、作ったスタイルが崩れたわけでも、バグでもありません。***仕様です***。
　実は段落番号にはインデントの設定値が2つあり、「①から再開」を実行すると2つ目の設定値に従う仕様となっています。

 では現状でどのような設定になっているのか見てみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/e7e2aa9b-fb1c-d65c-bfb5-049df2701ea3.png)
ここを見てください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/3d4e288e-a720-5c8f-3189-7141bcc2dee3.png)

さっきインデントを「7mm」に設定したのに、その記述が見当たりません。
実は「基準になるスタイル」が「リスト段落」になっていると、こういうよくわからない記述になります。
なので、こちらを「標準」に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/cfcdc177-d792-5efb-6c9f-2bc0a59fa864.png)

出てきましたね。
「フォント」のインデントが7mmになっていることがわかると思います。
ただし、その下に「整列：0mm」という設定値が見つかると思います。
これがこのインデント崩れる問題の正体です。

「①から再開」を行うと、それ以降のインデントはこちらの設定値に従います。


##■解決策
スタイルから「段落番号」のフォントをいじれば治ります。
見てみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/ff223cdb-9e81-0741-d88d-fd8914a92925.png)
「箇条書きと段落番号(N)」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/f66f6536-97f2-afa9-cb60-b95a7912e8c4.png)
「新しい番号書式の定義…」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/2f82c999-c01d-753a-3bc3-e48872f291ef.png)
「フォント」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/4d1b681b-44e1-2951-6d44-8c6850fe931f.png)
はい、ここです。
「あれ？フォント空白じゃん。嘘つくなよ」って思った？
試しにデフォルトのフォントである「游明朝 (本文のフォント - 日本語)」に変更してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/92ba29b2-2631-aae8-73fd-db8ecb41b59a.png)


念の為に日本語用のフォントと英数字用のフォント両方変更しています。
これをコミットします。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438703/6569daa2-237c-85c4-e5a6-0e4b5936a0e8.png)

はいズドン。治りました。
フォントに色々設定値入りすぎて空白になっちゃったパターンすかね。
なめやがって。

これで親の仇を一体ぶちのめすことに成功しました。

ではまたね。チャオ☆
SBTでオレオレCommandを作る

例えばsbtで

1. マルチプロジェクトで子プロジェクトの特定のMainクラスを実行
2. Settingを変更しつつコマンドを実行

などしたくなったこと有りませんか？
そんなときは、ルートプロジェクトでオレオレコマンドを定義すると一発で実行できるようになります。

## プロジェクトを切り替えて子プロジェクトのコマンドを実行

```bash
sbt:root> project core
sbt:core> runMain MainClass arg1 arg2
```

のようなコマンドを一発で実行したい場合は、以下のようにコマンドを定義することで

```scala:build.sbt

lazy val root = (project in file(".")).setting(
  commands ++= Seq(
    Command.args("codeGen","<args>")((state, args) => {
      // project coreを実行して、projectが切り替わったStateを取得
      val projectChanged: State = MainLoop.processCommand(Exec("project core", None), state)
      // projectが切り替わったStateを渡してコマンドを実行
      MainLoop.processCommand(Exec(s"runMain MainClass ${args.mkString(" ")}", None), projectChanged)
      state // project切り替え前のStateを戻すことで、実行時と同じprojectの状態に戻る
    })
  )
)

lazy val core = (project in file("core")).setting(
)

```

以下のコマンドで一発実行できるようになります

```bash
sbt:root> myRun arg1 arg2
# MainClass has run
sbt:root>
```

commandに関連するメソッドは戻り地にStateを帰すようになっています。Stateは普遍なオブジェクトで、戻り値のStateはコマンドなどの実行などで状態が変化したStateが帰ってきます。

## Settingを変更してコマンドを実行

設定値を元に他の設定を変更しコマンド実行

```bash
sbt:root> show myOption1
sbt:root> set myOption2 := "hoge"
sbt:root> runMain Main1
```
※ myOption2にセットする値は、myOption1の値に依存

```scala:build.sbt
lazy val root = (project in file(".")).setting(
  commands ++= Seq(
    Command.command("updateAndRun")(state => {
      val extracted = Project.extract(state)
      // settingの値を取得
      val value = extracted.get(myOption1)
      // 取得した値に応じて、他のKeyを変更
      val settingUpdated: State = value match {
        case "update to hoge" => extracted.appendWithSession(Seq(myOption2 := "hoge"), state)
        case "update to fuga" => extracted.appendWithSession(Seq(myOption2 := "fuga"), state)
      }
      MainLoop.processCommand(Exec(s"runMain Main", None), settingUpdated)
    })
  )
)
```

と定義しておけば、

```bash
sbt:root> updateAndRun
```

で一連の操作が実行されます。
vscode で Haskell の開発環境作る時に "print-build-platform" (exit 1): failed が出たときの対処法

この記事には何の根拠性もないので役に立つかわかりません（信じるか信じないかはあなた次第です。

Haskell Language Server ていう extension 使って vscode で Haskell の開発環境作った。https://marketplace.visualstudio.com/items?itemName=alanz.vscode-hie-server

よし、いざ開発と思いきやコード書く度に **"print-build-platform" (exit 1): failed** っていう警告が飛び出してくるのがとてもうっとおしかった。

`~/.bash_profile` に `export PATH=$(stack path --compiler-bin):$PATH` を書けば解決するという話もあったけどそれをやってもダメ...。

で諦めていた矢先、偶然 Visual Studio Code を version up するついでに brew cask install できるらしいからやってみようと思い、おもむろにブラウザから DLしてきたやつ `rm -rf` して `brew cask install visual-studio-code` したらなんか知らんけど解決した...。

いままで Vim で書いてたけどカーソル当てるだけで関数のシグネチャをウィンドしてくれたり自動で型宣言を展開してくれたりフォーマッタも効くようになってだいぶ快適になった。

# 終

![a.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142263/34e0d607-a000-eb93-0713-633691c4b891.gif)
Herokuコマンド備忘録

自分の備忘録として

###Herokuアプリを作成

```sh
heroku create 付けたいアプリ名
```
アプリ名を指定しない場合は自動でアプリ名が付けられる

###Herokuのリモートリポジトリとローカルリポジトリを紐付け
```sh
heroku git:remote -a アプリ名
```
Herokuアプリは存在するのにHerokuへpushできない！となる時はだいたい紐付けしてなかった

###Herokuへpush
```sh
git push heroku master
```

###Heroku上でコマンドを実行
```sh
# よく使うコマンドたち
heroku run rake db:migrate
heroku run rake db:seed
heroku run console
```
###Herokuの再起動
```sh
heroku restart -a アプリ名
```
`db:migrate`実行後に`ActiveRecord::UnknownAttributeError`になったら再起動すると解決した

###環境変数を設定
```sh
heroku config:set 変数 = 値
```

###確認
```sh
#起動しているプロセスを確認
heroku ps

#ログを確認（-tをつけるとリアルタイム表示）
heroku logs -t

#環境変数を確認
heroku config
```
ATT Email problems and settings

Att email is an extremely secure paid email that is basically used for the communication and exchange important data as well as important mail. Here we are discussing At&t email and if we compare with other emails then we’ll get that every email has their own important features and services. As I already mentioned that we are here for Att mail, so if you are technical glitches in At&t and need to troubleshoot then first you should try to check At&t settings.
Here we are listing some issues of ATT email:
Not able to download any attachment
Multiple configuration Issues
Not able to access AT&T account
AT&T account hacked
Password related problems
if you are getting any of these issues then dial AT&T mail settings support number. And visit the given website link for more information.
Visit the website:
http://www.email-customer-care.com/att-support
Ref. URL:

https://tehhelpsupport.blogspot.com/2019/12/att-email-problems-and-settings.html
pm2でdeployしようとするとbash: npx: command not foundで失敗する

## 原因
- bash_profileにnvmの設定を記述していた
- bash_profileは対話モードじゃないと読み込まれない
[参考](https://qiita.com/dark-space/items/cf25001f89c41341a9fd#bash_profile%E3%81%A8bashrc%E3%81%A7%E5%B7%AE%E3%81%8C%E5%87%BA%E3%82%8B%E3%82%BF%E3%82%A4%E3%83%9F%E3%83%B3%E3%82%B0)
- しょうがないので/usr/local以下のnvmとは関係ない古いnpmが呼ばれる

→npxコマンドが存在しない

## 現状
ecosystem.json

```json
  "deploy" : {
    "production" : {
      "user" : "dev",
      "host" : "**********",
      "ref"  : "origin/master",
      "repo" : "**********",
      "path" : "/home/dev/www/",
      "post-deploy" : "npm install && npx sequelize db:migrate"
    }
```

## 対策
その１：nvmの設定をbash_profileではなくbashrcに記述する
その２：post-deployにsource ~/.bash_profileを追加する

```json

"post-deploy" : "source ~/.bash_profile && npm install && npx sequelize db:migrate"
```

検索しても同じ状況の人が全然見つからなかったのでたどり着くのに時間がかかりました・・・。
java クラスの使い方

昨日は三つの用語について
書きましたが、今日は実際の使い方について
書いて行きます。

# 基本
クラスの基本的な使い方を確認するために、以下の内容のプログラムを作成します。

* 参照クラスのオブジェクト変数を生成
* そのクラスのメンバ変数の参照
* メソッドの呼出し
* 取得した値を出力

## メンバ変数
クラス定義をしている"{"と"}"の中
つまり波括弧の中に記述され
そしてメソッドの外に記述されている変数のことです。
インスタンス変数とも言います。

```java:メンバ変数
void nowTime(){
    System.out.println("現在 " + time + " です");
  }
```

# コードの例

```java:TestClass.java
class TestClass {
    // メンバ変数
    public String name = "Samurai";
    
    // メソッド
    public String testMethod(){
        return "Engineer";
    }
}
```

```java:Main.java
public class Main {
 
    public static void main(String[] args) {
        //クラスのオブジェクトを生成
        TestClass c = new TestClass();
        
        //メンバ変数を参照する
        String str1 = c.name;
        
        //メソッドの呼出し
        String str2 = c.testMethod();
        
        //結果を出力
        System.out.println(str1 + str2);
    } 
}
```

結果として

```bash:出力結果
> javac Main.java
> java Main
SamuraiEngineer
```

## 簡単な説明

基本的な流れ細かく説明すると

```java:TestClass.java
    // ①メンバ変数を設定します
    public String name = "Samurai";
    // 
```

```java:TestClass.java
    // ②メソッドを定義してEnginerrを返します。
    public String testMethod(){
        return "Engineer";
    }
}
```

```java:Main.java
        //③TestClass.javaよりクラスのオブジェクトを生成
        TestClass c = new TestClass();
```


```java:Main.java
        //④メンバ変数を参照する、これは②で設定してあります。
        String str1 = c.name;
```
  
```java:Main.java     
        //⑤設定してある②のメソッドの呼出し
        String str2 = c.testMethod();
```


```java:Main.java      
        //⑥変数に設定した結果を出力します。
        System.out.println(str1 + str2);
```
せっかちな人のための Graph Convolution Network

# この記事では
Graph Convolution Network (以下、GCN) について「概要だけ理解したい」「数式なんていらないから直感的に教えて」という方のために

- GCN って何やってんの？
- GCN は何に使われているの？
- 終わりに

についてかなりざっくり書いていきたい思います

論文 https://arxiv.org/pdf/1703.06103.pdf

# GCN って何やってんの？
### そもそも Convolution ってなんだっけ？
よく画像系のタスクで見かける Convolution の操作、一言で言うと「画像をフィルターにかけて畳み込み、特徴量を出しましょう」というものです(詳しくは自分でググってください)。このとき、画像は以下のような格子型ネットワークとして見ることができます。

<img width="423" alt="スクリーンショット 2019-12-26 23.49.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/0c843252-8b8e-15aa-4800-0918b4f3e063.png">

GCN はこのような格子型ネットワークだけでなく、様々な形をしたネットワークの近接情報を畳み込むことでノードの特徴量を抽出するものになります。

### じゃあ、どうするの？

ざっくり言うと周囲のノードの情報をたたみ込んでノードに情報を付与します。

このようなネットワークがあったとします。

<img width="712" alt="スクリーンショット 2019-12-26 23.58.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/f8c29f20-fd37-aaa6-f0e9-0369b299523e.png">

この時、青のノードに注目して周囲の黄色のノードを畳み込みむと緑色の隠れ層ができます。

<img width="659" alt="スクリーンショット 2019-12-27 0.07.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/aa054328-1baf-8c79-7822-d822792503c3.png">

同様にその他のノードも畳み込んじゃいましょう。

<img width="642" alt="スクリーンショット 2019-12-27 0.11.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/256448c0-4547-35d9-7727-4c9e714b32e7.png">

次に青に注目して隣接する緑ノードを畳み込んで行きましょう。

<img width="673" alt="スクリーンショット 2019-12-27 0.14.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298787/13e8ad32-f28c-2553-032d-bffa366f3330.png">

隣接する黄色ノードの隠れ層(緑ノード)を参照してオレンジノードの層ができました。

これが GCN の利点になります。

隣接する緑ノードは青ノードが知り得ない灰色ノードの情報を知っています。つまり、オレンジの層は隣接しない灰色ノードの情報を知っていることになります。このように GCN は層を深くすることで隣接しない、本来なら知り得ないノードの情報を対象のノードに加えることができるのです。

# GCN は何に使われているの？
以下で応用されているらしい…

- 化学分野
- 推薦システム
- ノードの分類

ここら辺は自分の理解が追いついていないため、機会があればまとめたいけど今回は勘弁してください。

# 終わりに
ソーシャルネットワーク解析や人材評価など結構応用範囲が広そうだなぁ〜って思った。今後の動向が気になりますね。
matplotlibのsubplotsをfor文で使うと便利

**subplot と subplots を間違えないように気をつける**

## subplotsをfor文で使うと便利

```python
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('seaborn-whitegrid')
%matplotlib inline

# データを用意
t = np.linspace(-np.pi, np.pi, 1000)
x1 = np.sin(2*t)
x2 = np.cos(2*t)
x3 = np.tan(2*t)
x4 = 1 / x1
x5 = 1 / x2
x6 = 1 / x3
```


- (例１)６つのデータを２行３列でプロット

```python
fig, axes = plt.subplots(2, 3, figsize=(16,12))
l = [[x1, x2, x3], [x4, x5, x6]]
for i in range(2):
    for j in range(3):
        axes[i][j].plot(t, l[i][j])
        axes[i][j].set_xlim(-np.pi, np.pi)
        axes[i][j].set_ylim(-1, 1)
```
![tmp2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274754/a75d15e4-f667-122b-f818-b744dc930edb.png)


- (例２)６つのデータを３行２列でプロット

```python
fig, axes = plt.subplots(3, 2, figsize=(8,12))
l = [[x1, x2], [x3, x4], [x5, x6]]
for i in range(3):
    for j in range(2):
        axes[i][j].plot(t, l[i][j], color='r')
        axes[i][j].set_xlim(-np.pi, np.pi)
        axes[i][j].set_ylim(-1, 1)
```
![tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274754/108a2dc8-1954-24d5-cd10-d3c1b5501886.png)

## 簡単に解説
- subplotsの第一,二引数はグラフの行,列
- figsizeはグラフ一つあたりのサイズ(インチ)
- axesとl(可視化したいデータのリスト)をスライス操作の感覚で使う