OmniAICreator/Qiita-1.07M huggingface dataset:
Rspecで突然謎のエラーが

circleCIで通常通り動いていたテストコードが突然動かなくなりましたが解決したのでその方法を書いていきます。

#開発環境
Ruby 2.6.2
Rails 5.2.3
Docker 18.09.2
docker-compose 1.23.2

#今回発生したエラー

```
Selenium::WebDriver::Error::UnknownError:
    unknown error: session deleted because of page crash
    from unknown error: cannot determine loading status
    from tab crashed
```

##原因
エラーを調べたところ日本語での記事が少なく詳しくはわからなかったのですが、メモリ不足によってクラッシュしてしまうとのこと。
ブラウザのサイズを小さくすれば解決するとの記事を見て試してみたのですが、僕の場合小さくしても解決しませんでした。

#解決方法
rails_helperのchromeOptionsのところに`--no-sandbox`と`--disable-dev-shm-usage`というargumentsを追加してください。`--disable-dev-shm-usage`と書くことでChromeは/tmpディレクトリを代わりに使用するようになるみたいです。メモリの代わりにディスクが使用されるので、実行が遅くなる場合があるみたいですがそんなに変わってない気がします。

```ruby:spec/rails_helper.rb
Capybara.register_driver :selenium_remote do |app|
  driver = Capybara::Selenium::Driver.new(
      app,
      browser: :remote,
        desired_capabilities: Selenium::WebDriver::Remote::Capabilities.chrome(
            chromeOptions: {
                args: [
                    'window-size=500,500', #念の為サイズも小さく
                    'headless',
                    '--no-sandbox', # crush回避
                    '--disable-dev-shm-usage' # crush回避
                ]
            }
        ),
        url: 'http://chrome:4444/wd/hub',
    )
end
```
これで解決すると思います。

もし間違いがあれば訂正お願いいたします。

#参考サイト
https://qiita.com/jb-vasseur/items/d3aa33e08ebba3b9231e
https://stackoverflow.com/questions/53902507/unknown-error-session-deleted-because-of-page-crash-from-unknown-error-cannot
GIF画像検索してブラウザでLGTM画像生成とアップロードをしてMarkdown記法でコピーできるツール作った話

## 今回の開発でわかったこと&この記事で言いたいこと
`JavaScript`はすごい。
`firebase`もすごい。
個人開発なら、なんでもかんでも自分で作ろうとしないこと。
世の中の[既存のサービス](https://free-for.dev/)にも目を向けること。
[GIFバイナリ](https://qiita.com/7shi/items/33117c6c369d37dc6cdd)は面白かった。
いやまじで`firebase`はすごい。

## ツール開発経緯
この記事に触発された。

[ちょっとそこのあなた！ 自分だけのオリジナルLGTMをチームで使ってみませんか？](https://qiita.com/dodonki1223/items/946f0204ba37c7029ad7)

そうだよね！LGTM画像って動く方がいいよね！めっちゃわかる

でもLGTMって書かれていないGIF画像って素っ気ないよね！

じゃGIF画像検索できて、それをすぐにLGTM画像に生成してMarkdown形式でコピペしたい！！

## 何ができたのか
できたツールがこれ。

[GIF検索してコピペできるLGTM画像生成ツールを作った](https://himakan.net/tool/lgtm-image-builder)

`Chrome`と`Firefox`でしか確認していません。。

## 大まかにどうやっているのか
1. GIF画像をバイナリで取得する。
2. バイナリを分析して一枚の画像ごとに分ける。
3. LGTMの文字と一枚の画像をcanvasに描画していく。
4. 全部くっつけてLGTM GIF画像が出来上がる。
5. サーバーにLGTM画像をアップロードしURL取得して終わり。

#### サーバーでは画像を保存することしかしていません。
#### ブラウザのみでGIF検索、LGTM画像生成、アップロード、Markdown記法クリップボードにコピーをしています。

## 具体的にどうやってるのか
1. [GIPHY API](https://developers.giphy.com/docs/)の`Search API`でGIF画像を検索する。
2. クリックされたら幅200pxのGIF画像を`arraybuffer`形式でファイルを取得する。
3. それを[omggif.js](https://github.com/deanm/omggif)を使用して一枚ずつの画像にする。
4. [gif.js](https://github.com/jnordberg/gif.js) で一枚になった画像とLGTM文字を`canvas`に`draw`する。
5. GIF画像の枚数分、LGTM文字付きの画像を[gif.js](https://github.com/jnordberg/gif.js)で`addFrame`したら`render`する。
6. [gif.js](https://github.com/jnordberg/gif.js) で`render`すると完成したGIF画像が`blob`に変換される。
7. `blob`を`firebase storage`にそのままアップロードする。
8. 最後に`firebase storage`の`downloadUrl`を取得してクリップボードに保存する。

## これを実装するまでの物語
目的：GIF画像検索してそれをLGTM画像にして簡単にMarkdown記法でコピーしてGithubに貼り付けたい！

よく`Ruby on Rails`使っていたので`rmagick`とかいう画像編集gemで実装してみる。
できたが、実装が悪いのかGIF画像生成に時間がかかった。
これではたくさん画像生成するとなると遅くなってしまう。。
うーむ。
もっと早く画像編集する方法を探る。
`Python`と`OpenCV`に出会う。
早い気がするが、結局画像生成に時間がかかる。
うーむ。
もっともっと早く画像編集したい！
[Halide](https://qiita.com/fukushima1981/items/fa3537234e19baffc761)に出会う。
少し触って、「あれ、なにしようとしてたんだっけ？？」ってなる。

--数年後--

[ちょっとそこのあなた！ 自分だけのオリジナルLGTMをチームで使ってみませんか？](https://qiita.com/dodonki1223/items/946f0204ba37c7029ad7)を見る。
そうだよな。LGTM画像ってLGTMの文字が入ってこそだよなぁ。
うーむ。

--数日後--

そっか、使ってもらう人に画像生成してもらえばサーバーの負荷減るなー。
今に至る。

完

## ライセンス
https://github.com/deanm/omggif MIT License
https://github.com/jnordberg/gif.js MIT License
AWS上のWindowsServerに対して、ローカルmacからansibleを実行 #5 パスワード変更用のplaybook

パスワード変更用のplaybook。
マニュアルは、https://docs.ansible.com/ansible/latest/modules/win_user_module.html

```conf:changePassword.yml
---
- hosts:
  - windows  # インベントリファイルで指定した名前

  tasks: 
  - name: change Administrator's password
    win_user: 
        # account_disabled:
        # account_locked: 
        # description: 
        # fullname: 
        # groups: 
        # groups_action: 
        name:  Administrator  # 必須
        password: パスワード名
        # password_expired: 
        # password_never_expires: 
        # state: 
        # user_cannot_change_password: 
```

必須パラメータはnameだけ。今回はパスワードを変えたいだけなので、
passwordだけ指定。

以下コマンドで実行。
`ansible-playbook -i ./ansible/hosts ./ansible/changePassword.yml`

```terminal:コマンド実行結果

PLAY [windows] ************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [ホスト名]

TASK [change Administrator's password] ************************************************************************************************
ok: [ホスト名]

PLAY RECAP ****************************************************************************************************************************
ホスト名 : ok=2    changed=0    unreachable=0    failed=0

```

2回目を実行したら、エラーが発生するようになった。
パスワードを変更したことにより、インベントリファイルのパスワードが変わっちゃったからである。
パスワード変更後は、インベントリファイルも修正するようにしよう。
エラーから逃げちゃダメだ。。。

#背景
オリジナルアプリの制作をしていると、エラーがたくさん出てくる。
「エラーメッセージを少しググって答えが出てこない」＝「分からない」状態を何とかしたい。

#僕がやっていたエラー解決方法
エラーが出たら考えることをやめ、すぐにエラー内容をコピペで検索し、解決法を片っ端から試す。
簡単なものは解決するが、複雑になってくると解決できない(現状)。

**解決したとしても、なぜ動いたのかを理解できずに進んでしまう。**

#本来取るべきエラー解決手順
1.エラーの意味を理解する
**ここは絶対に逃げてはいけない。**まず英文メッセージを読んで内容を理解しようとする。
翻訳機能を使えば、文章の意味は大体把握できるはず...

2.エラーの場所を特定する
どのファイルの何行目という記述を探す。出ていない場合はログも参照してみる。

3.エラー文をググる
ある程度、自分なりに原因を予測してからググる。
**公式ドキュメントの情報も逃げずに読む。**

4.それでも解決できないときは人に聞く、Q&Aサイトで質問する
最終手段。
人名、日時、場所、どこまで詳細に書くとよいか。仮説(99)

仕様書、契約書、説明書、公文書など、業務に付随する文章や正式の会合の場で、どう表記、表現すると誤解を与えにくく、一意性が容易に確保できるかどうか。

面倒だ、ややこしいと思った途端に、抜け漏れ、行き違いが生じるかもしれない。

文章や、顧客の前での挨拶では人名は姓名を書くのが基本。

会社名は、会社名に加えて、社長名と本店所在地を書くのが基本。

暴力団関係の対応のため、代表者の生年月日を記載させる書類があるらしい。
暴力団の組織かどうかを確認する必要のある仕事が存在する。

文章では、日時は、年月日を書くのが基本。できれば曜日を入れると誤解しにくい。

場所は、都道府県から書くのが基本。政令指定都市は都道府県を書かなくてもよいという慣習がある。そのかわりに、郵便番号を付記するとよい。

それぞれ、根拠法がある事項と、慣習に基づくものと、確率論的にそうした方がよいこととがある。一つの視点だけで、論を進めない方がよいかもしれない。


最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
仕事と教育（研究と教育）が両立する場合としない場合。仮説(76) 

# 仕事と教育
仕事と教育が両立する場合としない場合があることは、なんとなくピンと来ないだろうか。

仕事がうまくいく時に、参加者がすごく成長していくところを目撃したことがないだろうか。

いつでも仕事と教育が両立するわけではない。

参加している人の能力の分布と興味の方向性が、仕事で必要な方向性に合った時だけ。

期間に余裕があったり、予算に余裕があったり、人材に余裕があったりすることは稀。

それぞれ１０回に１回くらいは、余裕があるはずなのに、余裕があるとついつい別の仕事も入れちゃうのが問題。

余裕のある時に、もっと先の仕事のための仕込みを始めることができるかどうかが、仕事と教育の両立させる機会を掴むか、失うかの分かれ道。

仕事と教育が両立する機会は稀だが、その機会を捨てる人に、両立はしないと言って欲しくない気がする。

# 研究と教育
研究と教育も同じ。

個々の教育対象に、好きなことをやらせて、自分の研究に役立つことがあれば、そのうちの１０に１つでもあればよい。

すきなことで、研究に役立てば、１０倍速は硬い。だから、１０人に１人が、自分と同じかまたは同じ研究テーマに役立つことをしてもらえれば、あとの９人は全く別のことをしてもらっててもよい。

仕事と教育よりは、はるかに両立しやすい。経験則としては、２倍から１０倍くらい両立しやすい。

学部の４年生で、学会発表は原則２度。１度めは、こちらが半分以上書く。学生の題材のうち、自分の研究分野からの視点で文章を書く。文章からスライド資料の作り方は教えて、スライドはなるべく自分で作ってもらう。２度めは、一人で書ける学生には書いてもらう。ほぼ同じ題材の進捗を加えるだけだから、楽チン、スライド資料も同様。

# 文書履歴(document history)
ver. 0.01 初稿 20190529
ver. 0.02 標題追記 20190530

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
laravel-バリデーション正規表現(パイプ「|」利用)(頭が0つきの数字)

バリデーション時に、正規表現のパイプを利用し、00、01、02、0、１、2の値のみを通すようなバリデーションを作成しようと思います。

```:php
$this->validate($request, [
　　　　'number' =>['required', 'regex:/^([0-2]|0[0-2])$/'];
]);
```

パイプを使う際は、<b>'required|regex:/^([0-2]|0[0-2])+$/'</b>と一行で、バリデーションルールを書いてしまうと、Laravel上だと、バリデーションごとにパイプを挟んでいるため、正規表現の中のパイプが他のバリデーションルールに切り替わったのかなとLaravelは判断するため、エラーになってしまいます。そのため、配列で一つずつ指定してあげる必要があります。

/\^([0-2]|0[0-2])$/は「\^」が行頭、「\$」が行末、パイプがor、[]は○○から○○まで、つまり0～2までもしくは、00～02となります。
[前書いた正規表現記事](https://qiita.com/hekizi/items/5a5600a2f5a80a8d4d16)
[参考にさせていただいた記事-laravelバリデーション正規表現パイプ](https://tech.shellingsoft.com/2017/11/11/laravel%E3%81%AEvalidate%E3%81%A7%E6%AD%A3%E8%A6%8F%E8%A1%A8%E7%8F%BE%E3%81%AE%E3%83%91%E3%82%A4%E3%83%97%E3%82%92%E4%BD%BF%E3%81%86%E6%96%B9%E6%B3%95/)
ESP32をMQTTのブローカーにしてみた

# はじめに

[Mongoose](https://github.com/cesanta/mongoose)というweb server用のライブラリを使ってESP32をブローカーにしてみましたので、その情報共有です。※ESP-IDFで開発しています

これから記載する手順では、最終的に以下の図のように動作確認を行います。

![動作の概要.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/af56499c-90a8-5f85-2e7f-2787f286c823.png)

ESP32([ESPr® Developer 32](https://www.switch-science.com/catalog/3210/)を使用）をブローカーとして動作させて、MQTT Box(PCのアプリケーション)から送信した{'hello':'world'}という文字列をESP32を介して再びMQTT Boxで受け取るという、シンプルな構成と内容です。

※ESP32はSTAモードで動作させています
　
　
この動作確認ではMQTT BoxをPublisher(データ送信する人）とSubscriber（データを受信する人）として使っていますが、実際はESP32をPublisherやSubscriberにすることができます。

つまり、ESP32だけでMQTTの通信ができるということになります。おお、なんということでしょう。


# 使用したもの

* [ESPr® Developer 32](https://www.switch-science.com/catalog/3210/)
* ESP32のソフト開発に使用したOS：Ubuntu18.04 ( Windows7 Pro 64bit をホストOSとするVirtualBoxにインストール ) 
* PC（MQTTBoxをインストールした）のOS：Windows7 Pro 64bit

# 手順

### 前提
[以前作成したmongooseのサンプルプロジェクト](https://qiita.com/TwDaiki/items/50845d24677a8659f5e6)の環境をそのまま使うものとします
今回はそのプロジェクトの以下の２ファイル(★)を変更するだけで実現できます。

```
mongoose_example
┣ main
┃ ┗ main.c　★
┃ 
┣ components
┃ ┗ mongoose
┃ 　 ┗ mongoose.h　★
：
```
### １. main.cをMQTTのブローカー用コードに変更する
main.cを[このコード(github)](https://github.com/bigw00d/esp32_mongoose_sample/blob/master/main/main.c)の内容に全て置き換えます。  

※ただし、コード中の以下の①と②は自分の環境に合わせて変更する必要があります。

①使用環境のWiFi情報

```
#define WIFI_SSID "xxxxx"
#define WIFI_PASS "xxxxx"
```

②アクセス先(ESP32)のIPアドレス

```
IP4_ADDR(&ipInfo.ip, 192,168,99,3);
IP4_ADDR(&ipInfo.gw, 192,168,99,1);
```

### ２. mongooseライブラリでMQTTのブローカーを有効にする(mongoose.h)
mongoose.hにて以下のようにMG_ENABLE_MQTT_BROKERを有効(1)にします。

```
#ifndef MG_ENABLE_MQTT_BROKER
#define MG_ENABLE_MQTT_BROKER 1
#endif
```

### ３. 動作を確認する

プログラムをビルドしてESP32に書き込み＆モニター開始します

```
$ make
$ make flash
$ make monitor
```

次にMQTT Boxを立ち上げてESP32と接続した後、Publishするとデータを受け取ることができます。

MQTT Boxの具体的な操作：
①MQTTの設定※を行った後に「Connect」する
②Subscribeする
③TopicとPayloadを入力する
④Publishする
⑤送ったデータと受け取ったデータが表示される

![MQTTBoxスクリーンショット4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/00336eb7-42fa-e9ff-fc78-a9b4cfa54a64.png)


※MQTT Boxの設定内容：
![MQTTBoxスクリーンショット6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/339e10ad-9103-28f4-cd80-7017c11fb575.png)


一方、ESP32のモニター上では以下のような表示が出ます。
MQTT Boxの操作に合わせて「MG_EV_MQTT_XXX」と表示されます。
![esp32モニタースクリーンショット2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/155449/9a3f82d3-9d14-67d5-f134-2aca105c309a.png)


# 終わりに

ESP32をブローカーにするのは大変そうだなーと思っていたら、Mongooseというライブラリのおかげで意外と簡単に実現することができました。

そして、この手順でブローカーとして動作させているESP32はSTAモードで動作しているので、今のままでは無線ルーターが必要なので、もうちょい頑張ってAPモードにしたいところです。（必要に迫られないとたぶんやらない気がするなぁ）

見ていただいてありがとうございました。
тнайк чoμ_〆(・ω・｡)			
			
# 更新履歴
* 2019-05-29：新規作成
AWS上のWindowsServerに対して、ローカルmacからansibleを実行 #4 windows update用のplaybook

windows update用のplaybook。
マニュアルは、https://docs.ansible.com/ansible/latest/modules/win_updates_module.html

```conf:windowsUpdate.yml
---
- hosts:
  - windows  # インベントリファイルで指定した名前

  tasks: 
  - name: windows update
    win_updates: 
        # blacklist:  # パッチ適用除外リスト。今回は使わない。
        # category_names:  # パッチのカテゴリ。デフォルトのままでよい。
        log_path: c:\ansible_wu.log  # ログ出力先
        reboot:  yes  # 再起動するかどうか。
        # reboot_timeout:  # 再起動タイムアウト。デフォルトのままでよい。
        # server_selection:  # パッチ配信先サーバの指定。デフォルトのままでよい。
        # state:  # パッチを探すだけにするか、適用するか。デフォルトのままでよい。
        # use_scheduled_task:  # 即時適用ではなく、スケジューリングするかどうか。デフォルト。
        # whitelist:  # パッチ適用リスト。今回は使わない。
```

必須パラメータはないが、log_pathとrebootくらいは指定しておいたほうがいいかな。
あとは環境次第。WSUSありとか。

以下コマンドで実行。
`ansible-playbook -i ./ansible/hosts ./ansible/windowsUpdate.yml`

```terminal:コマンド実行結果

PLAY [windows] ************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [ホスト名]

TASK [windows update] *****************************************************************************************************************
changed: [ホスト名]

PLAY RECAP ****************************************************************************************************************************
ホスト名 : ok=2    changed=1    unreachable=0    failed=0

```
Jenkinsってなんなんだ

## 記事の立ち位置

仕事で必要になったけど、何者かわからんので試してみよう
備忘録的なやつ。

## Jenkinsとは？

- 継続的インテグレーション（CI）のためのOSSツール。
- コンパイル・ビルド・デプロイを自動的に行う。
- 様々な方法で起動することが出来る。（イベント・時間・URLリクエストetc...）
- プラグインが豊富で、機能拡張が容易である。

##### 参考資料
[日本人が生み出したソフト「Jenkins」の勢い　日経ビジネス（シリコンバレーNext）](https://business.nikkei.com/atcl/report/15/061700004/090500222/)

## 導入方法（MAC）

1. AdoptOpenJDKが導入されていることを確認する
2. brewからJenkinsをインストールする

``` tarminal
 $ brew install jenkins
```

以上。

## 実行方法

ターミナルから下記コマンドを実行

``` tarminal
$ jenkins
```

ここでアクセス用のパスワードが発行されるので確認すること。

``` localhost:8080 ```にアクセスする
SetupWizardが呼び出されているので、``` Install Pluginなんとか ```を押下する
画面左側のボタンかな？

色々とプラグインがインストールされるので、完了するまで待機。
あとは画面の指示に従って名前とかパスワードを設定。

これでJenkinsの導入は完了。


## 機能

TBC
PhpStorm-DB接続(MySql)

右上にある<b>Database</b>をクリック
画像のように<b>MySql</b>をクリック
<img width="348" alt="Screenshot_1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/40b00655-0f83-0a7c-8af5-fa6e1be33494.png">

画像のように
・Name　(なんでもいい)
・Host　(僕の場合Docker使用のため)
・User　(Mysqlにログインできるユーザー)
・Password　(Mysqlにログインできるユーザーのパスワード)
<img width="601" alt="Screenshot_2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/a6ff1192-5e01-682f-bfc5-94e0db570e56.png">

DriverFileがなければ、画像のような表示が出てきますので、<b>Downloadボタン</b>をクリック
<img width="249" alt="Screenshot_3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/9b1e4e40-fb74-2965-6f52-99ab3e777a6e.png">

完了し、パスワードが消えていたら、もう一度打ち直し、<b>Test Connection</b>ボタンをクリック
接続が完了すると、以下のように表示されます。
<img width="282" alt="Screenshot_4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/80aef067-5db1-46d0-560a-a28ad9ac769e.png">

もう一度、<b>Database</b>を開き、<b>0 of 7</b>をクリックし、表示させたいDBのチェックボックスにチェックを入れる。
<img width="301" alt="Screenshot_6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/d6c6d98e-2483-eb98-798b-b3f929762cac.png">

下記のように表示されました。DBの中身、テーブルの中身(カラムとデータ)も見ることができます。また、<b>＋ボタン</b>を押下し、その中の<b>Console</b>をクリックすると、Console画面が開き、そこでクエリを書くと「Ctrl」＋「Enter」で実行することができます。
<img width="203" alt="Screenshot_7.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/325600/2e92856b-dc49-57e1-5633-cec39757e45d.png">
0から始めるPHP:1日目

#本日の目標
定数や変数を扱えるようになる。

#定数
定数とは、定数である。つまり、ずっと同じ値を保つ。最初に定義したら、あとは中身は変わらない。

関数`define()`を用いて、定数を定義してみる。
defという定数を作り、その中にHelloを入れる。

```
<?php
    define("def","Hello");
    print(def);
?>
```
define("定数の名称",”定数の中身”) といったように書く。
実際に定義ができているか確認のため、関数`print()`で出力してみる。

#変数
変数とは、定数との逆で何かしら操作すると値が変わる。

PHPでは、変数を定義するときに型を指定する必要がなく、勝手にやってくれる(多分)
今回は例として整数の変数を定義してみる。

```
<php
    $var = 0;
?>
```
$変数名　= 代入する値　というよに書く。
変数の型は整数以外にも文字列や、論理型などがある。
#本日の成果
定数と変数の意味を理解して、定義できるようになった。
Rails5のAPIモードでOauthを使うためのDevise Token Auth + Omniauthセットアップ方法

新たに立ち上げるサービスをAPIとフロントを完全に分けて作る事になった。

自力で認証システムを作ることも考えたが、パスワード再発行やメール認証など定番の処理を0から実装する手間と、
保守上の観点からdevise token authとomniauthを使って立ち上げる際になかなか詰まったのでメモ。

# 手順
## Deviseをインストール
Gemfileに以下を追加。

```Gemfile:Gemfile
gem 'devise_token_auth'
```
その上で以下を実行。(認証をかけるモデルがUserの場合)
　
> $ bundle exec rails g devise:install
> $ bundle exec rails g devise_token_auth:install User auth


作られたmigrationファイル(*_devise_token_auth_create_users.rbなど)に以下を追加。

```ruby:*_devise_token_auth_create_users.rbなど
      ## Trackable
      t.integer  :sign_in_count, default: 0, null: false
      t.datetime :current_sign_in_at
      t.datetime :last_sign_in_at
      t.inet     :current_sign_in_ip
      t.inet     :last_sign_in_ip
```
これ、ドキュメントのどこにも書いてないがomniauthを使い二回目以降にログインすると

```ruby
NoMethodError: undefined method 'current_sign_in_at' for User
```

が出てしまう。trackableが使われているか不明だが、とりあえず全部追加した。

今回は、omniauthを使うのでapp/models/user.rbのomniauthableを追加。
また、メールの存在確認のための認証を入れる予定なのでconfirmableも追加した。

```ruby:app/models/user.rb
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable,
         :confirmable, :omniauthable
```

以下をdevelopment.rbに追加。

```ruby:config/environments/development.rb
  config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```


## Omniauth + Omniauth Twitterを追加
Gemfileに以下を追加

```Gemfile:Gemfile
gem 'omniauth-twitter'
```

以下のファイルをconfig/initializers/omniauth.rbに作成。

```ruby:config/initializers/omniauth.rb
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :twitter, ENV["TWITTER_KEY"], ENV["TWITTER_SECRET"]
end
```

更に、config/application.rbに以下を追加

```ruby:config/application.rb
config.session_store :cookie_store, key: '_<<<アプリケーション名>>>_session'
config.middleware.use ActionDispatch::Cookies # Required for all session management
config.middleware.use ActionDispatch::Session::CookieStore, config.session_options
```
これは、RailsのAPIモードだとセッション管理のミドルウェアが入らないから。
一方でomniauthはデフォで使うのでとりあえず設定しておく。

## render template を有効にする
RailsのAPI modeだとrender json:以外が描画されないため、devise token authのoauthが使えない。
その為、以下のようにコントローラをオーバーライドしてerbを描画できるようにする。
これはdevise token authのバグなのか、設定ミスでこれが必要になっているのかはわからない。

app/controllers/users/omniauth_callbacks_controller.rbに以下の内容でファイルを作成する。

```ruby:app/controllers/users/omniauth_callbacks_controller.rb
class Users::OmniauthCallbacksController < DeviseTokenAuth::OmniauthCallbacksController
  include ActionView::Rendering
end
```

その後、routesを以下のように修正する。(認証をかけるモデルがUserの場合)

```ruby:config/routes.rb
Rails.application.routes.draw do
  mount_devise_token_auth_for 'User', at: 'auth', controllers: {
    omniauth_callbacks: "users/omniauth_callbacks"
  }
end
```

## TIPS
### devise installしないとそもそも動かない
devise token authの公式サイトにはdeviseをwrapしているから不要っぽく書いてあるが、
devise installをしないと最初から下記のエラーが出てしまう。

```bash
NoMethodError: undefined method `devise' for User (call 'User.connection' to establish a connection):Class
```
オブジェクト指向の用語についての整理

1.オーバーライド：親クラス内のプロパティやメソッドを子クラスで上書きすること

2.アクセス
    - private：そのクラス内からのみアクセス可能
    - protected：そのクラス＋親子クラスからのみアクセス可能
    - public：どこからもアクセス可能

3.staticキーワード：インスタンス化しなくても利用できるプロパティやメソッドを定義する

```PHP:
User::getMessage();  //メソッドへのアクセス
self::$count++;  //プロパティへのアクセス
```

4.抽象クラス：それ自体はインスタンス化できず、継承先でプロパティやメソッドを実装するクラス。子クラスの実装をシンプルにしたり、子クラスの実装漏れを防ぐことができる。

5.インターフェイス：このメソッドを必ず実装しなければならないというルールをつけることができる

```PHP:
interface sayYeah {
  public function sayYeah();
}

interface sayWow {
  public function sayWow();
}

class User implements sayYeah, sayWow { //UserクラスでsayYeahと
--- 中略 ---                             //sayWowを実装しないとエラーになる
}
```

6.thisキーワード：現在のオブジェクトを表し、主にクラス内のメソッドでフィールドにアクセスする際に指定する。

```PHP:
public class Person {
   public String name;
   public int age;

   public Person(String name, int age) {
      this.name = name;
      this.age = age;
   }
}
```

以上、オブジェクト指向の用語について自分なりにしっかり理解できていない点をまとめて見ました。
今後も継続して不明点を調べていきたいと思います。
RailsでのセッションとCookieについて

Railsチュートリアルを進めていてセッションとCookieについて整理したかったので自分用メモとして書いた。

# セッション
WebアプリケーションではブラウザからサーバへHTTPリクエストを送り、HTTPレスポンスを受け取って画面表示を行う。しかしHTTPはステートレスなプロトコルであるため、同じユーザーから送られた1つ目のリクエストから2つ目のリクエストの情報を引き継ぐことができない。そのためセッションを用いることで、1つのブラウザから連続して送られている一連のリクエスト間で状態を共有できるようにしている。

Railsではsessionメソッドを使うことで実現できる。sessionはハッシュのように扱うことができ、セッションにデータを入れるには任意のキーを指定して値を格納する。
```
session[:user_id] = @user.id
```

値を取り出すには下記の通り書く。
```
@user.id = session[:user_id]
```

# Cookie
複数のリクエストの間で共有したい状態をブラウザ側に保存する仕組み。クライアントが情報を持っているのでブラウザを閉じても破棄されない。また暗号化しないと簡単に読み取られる。ログイン情報をセッションのみで扱うとブラウザを閉じるたびにログインしないといけなくなる。そのためCookieにもログイン情報を持たせてしまい、ブラウザを閉じても状態を保持させるという使い方が一般的。Railsではcookiesメソッドを使ってこの機能を実現する。

# RailsでのセッションとCookieの関係
Railsのセッションの仕組みの一部はCookieによって実現されている。ブラウザを閉じると破棄されるようなCookieという形で暗号化されたセッション情報をクライアント側に保存するという仕組み。またRailsではセッションデータの保管場所を複数の選択肢から選ぶことができるが、デフォルトでCookieになっている。そのためブラウザ側で対応するCookieを消せば、セッションはリセットされることになる。
やっと合格基本情報技術者試験

現役情報系大学生が基本情報技術者試験（FE)を５回目でやっと合格し、うれしいので記事にしました。勉強法の参考になると幸いです。
ちなみに初投稿です！！

#これまでの取り組み
１～３回目は高校の時に先生からの勧めで取り組んでいました。基本情報が進学や就職の際役に立つことは知っていましたがモチベーションが上がらず勉強をろくにせずに受験していました。合格するわけないですよね・・・
４回目は2018年春、私が大学進学が決まり入学までやることがなかったのでFEの勉強をしました。結果は午前はギリギリ合格、午後はボロボロといった結果でした。

#学習法＋その他の変更点
不合格だった１～４回目と合格した５回目の違う点、工夫した点を紹介します。この中に合格の秘訣があったのかもしれません。
##本とサイトでの学習
以前の学習方法として参考書（イメージ＆クレバー方式でよくわかる栢木先生の基本情報技術者教室）を一通り目を通した後、[基本情報技術者試験過去問道場](https://www.fe-siken.com/fekakomon.php)を用いて学習していましたが、今回は過去問道場をやりながら間違えた問題の解説を見てわからない単語を参考書を辞書のように用いて、参考書の解説をよく読む。それでもよくわからなかったら、ぐぐるという方法で学習しました。
##本番の形式の慣れ
以前は過去問道場を用いた勉強しかしておらず、実際に過去問を印刷して紙媒体での勉強をしませんでした。しかし、今回は試験が近くなってきた頃に[公式サイト](https://www.jitec.ipa.go.jp/1_04hanni_sukiru/_index_mondai.html)にアップされている過去問をプリンタで印刷し時間を計りながら解くということをしました。
##SNSへの成績公開
私の場合、Twitterに過去問を印刷し時間内に解き答え合わせをした結果の点数をつぶやきました。
成績の記録とモチベーション維持につながります。
##当日の持ち物
以前までは特に持ち物は気にせず必要なものだけをもっていきましたが今回は２つ特徴的なものを持って行きました。
一つ目はブドウ糖で、頭を使うと脳が糖分を欲するので即効性のあるブドウ糖を持って行き、午前午後の始まる前に口に含みました。
二つ目は冷えピタで、頭使うとぼーとするというのはこれまでの経験からわかっていたのでどれだけお昼休みにリフレッシュして午後問題に望めるかが大切だと考え、頭をリフレッシュできるであろう（？）冷えピタを持っていきました。つけるのは恥ずかしかったですが、脳がよい状態で午後問題に取り組めたと思います。

#まとめ
勉強法は参考書とサイトをうまく使い、試験間際は本番形式で学習するとよし！
当日は脳をリフレッシュさせる甘いものや冷えピタなどを持って行くとよし！
パラメータと軌跡（数学II）その２

## 数学の軌跡を求める問題
前回の問題をもう一度考えてみます。

### 問題
高校数学の数学IIの図形と方程式の問題です。


実数のパラメータ$t$によって，次のように定まる$x$，$y$を座標とする点Pの軌跡を求めます。
$$x=\frac{t}{1+t^2}\cdots\text{①},\quad y=\frac{1}{1+t^2}\cdots\text{②}$$


### 解答その２

Jupiter notebook で Wolfram Engine が使えるようになり，Mathematicaが多くの人が使えるようになりました。今回の図をまず書くことにします。

```mathematica:ParamatericPlot
ParametricPlot[{t/(1+t^2),1/(1+t^2)},{t,-10,10},PlotRange->{{-1,1},{-1,2}}]
```
<img width="1552" alt="スクリーンショット 2019-05-29 21.52.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426542/6c660b56-7219-383b-3c95-0c6b1c8db22c.png">

軌跡は円$$ x^2+\left(y-\frac12\right)^2=\frac14$$と予想されます。

```math
\begin{aligned}[t]
 x^2+\left(y-\frac12\right)^2&=\left(\frac{t}{1+t^2}\right)^2+\left(\frac{1}{1+t^2}-\frac12\right)^2\\
&=\frac{t^2}{(1+t^2)^2}+\frac{1}{(1+t^2)^2}-\frac{1}{1+t^2}+\frac14\\
&=\frac{t^2+1-1-t^2}{(1+t^2)^2}+\frac14\\
&=\frac14
\end{aligned}
```
$$ \therefore x^2+\left(y-\frac12\right)^2=\frac14\cdots\text{③}$$
よって，$t$の値によらず，点Pはこの円周上にあることになります。

前回の解答では，途中で，$y\ne0$としたので，

『$y=0$のときはまずいのかな？？？？』

とアラートが鳴りますが，この解答だと，$y=0$がダメな雰囲気はまったくありません。

### 2つの解答の検討

前回と今回の解答はともに，

$$\text{①}\wedge \text{②}\Rightarrow \text{③}$$

が示されています。ですので，この逆，

$$\text{③}\Rightarrow \text{①}\wedge \text{②}$$

が示せるのかを考えてみます。示すことができれば，この円全てが軌跡となります。また，示すことができないのであれば，除かれる点があることになります。そして，その点をを除外することで，必要十分な軌跡が求められます。
AWS上のWindowsServerに対して、ローカルmacからansibleを実行 #3 タイムゾーン用のplaybook

タイムゾーン変更用のplaybook。
マニュアルは、https://docs.ansible.com/ansible/latest/modules/win_timezone_module.html

```conf:setTimeZone.yml
---
- hosts:
  - windows  # インベントリファイルで指定した名前

  tasks: 
  - name: set time zone(Tokyo)
    win_timezone: 
        timezone: Tokyo Standard Time

```

timezoneは必須。どんなタイムゾーンが使えるかは、
https://msdn.microsoft.com/en-us/library/ms912391.aspx
でわかる。

以下コマンドで実行。
`ansible-playbook -i ./ansible/hosts ./ansible/setTimeZone.yml`

```terminal:コマンド実行結果

PLAY [windows] ************************************************************************************************************************

TASK [Gathering Facts] ****************************************************************************************************************
ok: [ホスト名]

TASK [set time zone(Tokyo)] ***********************************************************************************************************
changed: [ホスト名]

PLAY RECAP ****************************************************************************************************************************
ホスト名 : ok=2    changed=1    unreachable=0    failed=0

```
0から始めるPHP:0日目

#目的
独学でPHP言語を勉強し、何を勉強したかを記事にしていきます。
誰の役に立つか分かりませんが...備忘録として書いていくので、雑かもしれませんが悪しからず・・・

#環境
MAMPサーバでPHPを実行します。
エディタはBBeditのフリー機能のみで。
#PHPの書き方
```
<?php

?>
```
PHPは基本的に`<?php`と` >`の間に、関数やらなんやら記述する。
##文字列の出力
とりあえず、動かしてみよう
`print()`関数でHello Worldを表示させる。

``` 
<?php
    print("Hello World");
?>
```
文字列の出力には、他にも`printf()`や`echo()`といった関数がある。
それぞれの関数の仕様については後ほど、まとめる。（maybe...）
##改行の仕方
改行したい！というときには文末に`<br>\n`といれる。

```
<?php
    print("Hello World<br>\n");
?>
```
これで改行ができた。
#本日の成果
関数`print()`、`printf()`、`echo()`を用いて、文字列を出力できた
Prometheus + Grafana をMac上で試してみよう

# やること
今回は、自分のMACにPrometheusとGrafanaをインストールしたいと思います。

# 事前準備

https://docs.docker.com/docker-for-mac/install/
以上から、自分のMacにDockerをインストールしてください。

# 各種ファイルの準備

terminalで以下のディレクトリを任意の箇所に置いてください。
(今回は、/Users/”user名”/下にこのディレクトリを作成します。)

```
$ cd

$ mkdir prometheus

$ mkdir grafana
```

### prometheus.yml

/Users/"user名"/prometheusに以下のファイルを作成

```prometheus.yml
global:
  scrape_interval:     15s 
  evaluation_interval: 15s 
  external_labels:
      monitor: 'codelab-monitor'

rule_files:
#   - "/var/app/prometheus/alert.rules"

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: 
        - 'localhost:9090'
```

### Grafana.env

/Users/"user名"/grafanaに以下のファイルを作成

docker 経由で grafana を起動する上で必要になります。
ただし、こちらのファイルは参照されないので、コメントアウトしています。

```gafana.env
# [server]
# GF_SERVER_DOMAIN=localhost
# GF_SERVER_HTTP_PORT=3000
# GF_SERVER_PROTOCOL=http
```

### docker-compose.yml

/Users/"user名"/prometheusに以下のファイルを作成

```docker-compose.yml
version: '3'
services:
  prometheus:
    image: prom/prometheus
    container_name: prometheus
    volumes:
      - /Users/"user名"/prometheus/prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - 9090:9090
  grafana:
    image: grafana/grafana
    container_name: grafana
    ports:
      - 3000:3000
    env_file:
      - /Users/"user名"/grafana/grafana.env
```

# dockerの起動

```
$ docker-compose -f docker-compose.yml up
```

## prometheus

起動したら、まずprometheusを確認してみましょう。

http://localhost:9090/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/9f7b0c18-2aeb-57af-4d71-2169c3d7a9ac.png)

Status > Target　を確認してみましょう。
先ほど、prometheus.ymlのscrape_configsに書いた設定が反映されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/e98427da-adfa-5786-d937-cd9398c2e7f1.png)


ここまでを確認できましたでしょうか。

## Grafana

そうしたら、次はGrafanaを見てみましょう。

http://localhost:3000/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/adf3f0ac-8caf-5e57-70c5-e2d54ad30bb5.png)

え...　どうやってログインするの
ってなった方！！！朗報です。

両方「admin」と入力してみてください。

すると、passwordを設定する画面になりますので、自分の好きなpasswordを打ってください。

終わると、次の画面に映ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/75edb850-bd48-c4cb-8b5f-1632774640b6.png)

configuration > Data Sources　を選択して下さい。
Add data source　を選択して以下の画面に来ましたら、prometheusを選択して下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/e13da450-9dd3-adb2-451d-5a267541299e.png)

以下の状態になったら、
URL: http://localhost:9090
Access: Browser
と記入し、下の「Save & Test」を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/be92340c-a0dc-05f5-b8e3-88538e947bcc.png)

以下のものが表示されたら、完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/b56eb45f-4bd7-4a41-3157-3c812b0b8c97.png)

再度、Configuration > Data Sourse　を選択すると、先ほど登録したPrometheusが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416540/a7fb7ed0-2d18-e1e1-0919-f16d2ce256c9.png)


# この後やること
この後は、NodeExportetであったり、自作Exporterをprometheusと連携させて
自分好みの監視をしてみて下さい。
組織的なことと個人的なこと。仮説(77) 

# 前提
人間は社会的な生き物だから、組織的なことと個人的なことは分離できないという説がある。
社会的習慣と個人的な嗜好は分離できないことは多い。

プログラミングの仕事も、個人の活動をうまく組織化できる人がいれば、
個々人の間の接触はそんなに要らないことがある。

それまで、どういう仕事の仕方をしてきたかで、何がいいか、何が好きかが違うかもしれない。

どういう仕事の仕方をしていても、現在の制度として、こっちの方がよいという傾向はあるかもしれない。

この文章は、あくまで個人の嗜好を優先順位で表すことにより、
組織の中で、個人間の軋轢が生じないようにする役割の人が、うごきやすいようにするための資料です。

# 組織化
３人集まれば、真反対の嗜好を持つ人が存在する確率は高い。
真反対の嗜好をもつ二人を、もう一人がうまく均衡させてもいいじゃないか。

役割分担という組織化の方法。

昔働いていて「良いな」と思ったIT会社の文化
https://qiita.com/kobake@github/items/321a212119d2d1064034

拝見して、すごく重要なこととがかかれている。
もっと強調するとよいことがあるかも。

組織的に推奨するとよいことと、個人的に遠慮したいことがあるかもしれない。

# 優先順位
自分の嗜好で優先順位をつけてみました。

ちなみに、１は、やめてほしい。２は、できればやめてほしい。３は当たり前のこと。４と５が大事なこと。

１と２は、ほとんど個人的な好み。個人的には勘弁してほしいことなど。理由も書いて見ました。

### 個人の好み
個人の好みのことかもしれないことが、混在していると捉えるか、分布をみるための項目ととらえるか。

「全員朝の定時に揃ってる」ことと「相談したい相手が常に同フロアにいるという安心感。」
なんの関係がるかよくわからない。

個人的には全員朝の定時に揃ってほしくない。誰も休みが取れない。
自分の存在確率は５０％がベスト。

相談したい相手が、チャットで反応してくれれば同じフロアにいる必要もない。むしろ、同じフロアじゃないところに、自分の相談あいてがいるとすごく安心感がある。ここで阻害されても、まだ道はあると。

# 引用事項と優先順位
## 人間
愚痴を聞いてくれる人がいる,5
上層部が偉ぶってない, 3, 当たり前
知らない顔でもちゃんと挨拶する,2, 詐欺師に多い。
愛想が良い・紳士的,1, 詐欺師に多い。

## 習慣
ちゃんと休める,5 
相談したい相手が常に同フロアにいるという安心感。,4
チャットのレスポンスがめっちゃ早い, 3, 当たり前
定期的に自分たちで掃除してる,2, 偽善家に多い。
全員朝の定時に揃ってる,1, 仕事しない人に多い。

## 学習意欲
社内勉強会が定期的に（しかも定時内に）ある,5
社外勉強会もある,4
新規学習に躊躇が無い,3, 当たり前
ちゃんと勉強している人が多い,3 ,当たり前
ペアプロする余裕がある,1, ペアプロは困った時にするもの

## 透明性
障害は全部記録に残す,5, 
エキスパートの所在が明確,5
全体チャットで質問できる,4
他プロジェクトの情報もオープン,4
情報探索が楽,3, 当たり前
障害の犯人捜しをしない,3, 当たり前
チームリーダーがちゃんと仕事をする,3, 当たり前
会議室がガラス張り,1 , 居眠りもできない。

## 運用
プログラマ以外も Git 使ってる,4, 
プログラマ以外もスクリプト書いてる, 3, 当たり前

## 機材・福利厚生
カジュアルに高スペックマシンが使える, 5, いざという時ぶんまわすと解決することあり。
曖昧に休憩できるソファ等がある,3, (ごめんなさい寝ちゃいます。)
自販機・お菓子箱がある,2, 自販機じゃなくフリドリ。お菓子箱は要らない。
シンクライアント,2, どうせDOCKERで作業だからなんでもいい。

# 文書履歴(document history)
ver. 0.01 初稿 20190529 
ver. 0.02 加筆 20190530 午前
ver. 0.03 標題追記 20190530 夜

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

#### Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
DatadogでFargateを監視する

## 概要

DatadogでFargateのコンテナを監視するための設定の手順をまとめました。
AWS マネジメントコンソールから操作を行います。

## 手順

### DatadogにSignUp

こちらの手順は省略します。必要に応じた設定を行なってください。
`3. Agent Setup` でDatadog Agentを選択するように求められますが、特に設定しなくてもこれ以降のステップに進むことができます。

### integrationsを追加
`Amazon Fargate`を追加します。
最初、`AWS`のintegrationも必要かと勘違いしてしまいましたが、Fargateのみで大丈夫です。

<img width="297" alt="スクリーンショット 2019-05-29 21.41.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/4bc20304-81ce-8d33-1119-34aadf90c241.png">

### タスク定義にDocker Anget用コンテナの設定を追加

詳細の手順は、公式ドキュメント[CREATE AN ECS FARGATE TASK](https://docs.datadoghq.com/integrations/ecs_fargate/#create-an-ecs-fargate-task)をご確認ください。
作成済みのタスクの定義に、Datadogのコンテナを追加します。

Datadogのイメージに`datadog/agent:latest`を設定。
メモリ制限に、`ソフト制限` `256`を設定。
<img width="958" alt="スクリーンショット 2019-05-27 17.13.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/694873a1-3365-9c85-1fe9-ce7498d4760f.png">

CPU ユニット数に`10`を設定。
<img width="962" alt="スクリーンショット 2019-05-27 17.14.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/46d95f40-36e2-40e1-3d3c-7e862db507c7.png">

環境変数を設定。
`DD_API_KEY` : ご自身のAPI Key
`ECS_FARGATE` : true

![スクリーンショット 2019-05-27 17.17.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/154fd343-19d0-23f9-f9cf-ce6eca1288b0.png)

DatadogのAPI Kyeは、`integrations` > `APIs`より確認できます。
![スクリーンショット 2019-05-29 21.51.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/dc3754d5-724e-09a5-1c4e-b5898e416cb1.png)


### タスクの実行ロールにポリシーを追加
詳細は、公式ドキュメント[CREATE OR MODIFY YOUR IAM POLICY](https://docs.datadoghq.com/integrations/ecs_fargate/#create-or-modify-your-iam-policy)をご確認ください。

今回は下記のIAMポリシーを作成し、既存のタスクの実行ロールにアタッチしています。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ecs:ListClusters",
                "ecs:ListContainerInstances",
                "ecs:DescribeContainerInstances"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
```


## Datadogの確認
サイドメニューより、`Infrastructure` > `containers` を選択し、コンテナのページを確認します。

<img width="431" alt="スクリーンショット 2019-05-28 17.14.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/b2b7bb10-87c4-fba4-d6f8-be200e9d837c.png">

Fargateのメトリクスを下記の通り取得できます。
![スクリーンショット 2019-05-28 17.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206741/906f9fb9-cd22-b95d-d58f-3e8a8d4770d7.png)
「ググレカス」と思う前に、この記事を読めカス。　　　

#はじめに
古来より業界では、わからないことは自分で調べることが常識となっていますね。
僕も知的好奇心が旺盛なので、人に教わるよりも自分で調べるほうが好きです。
しかし、もし「"○○"って？」と聞いたときに「ggrks」と言われたとしたら、僕はきっと、感じるところがあるでしょう。
しかし後述する全ての項目を質問したら、細かい、しつこい、ウザいと思われるのは目に見えているので、グッとこらえる事でしょう。
将来、自分自身が教え下手人間とならないよう、「初心忘るべからず」という思いをこめて、この気持ちを記事に残します。

本記事のターゲットは、未来の自分です。
本記事上では現在の自分を「ぼく」、未来の自分を「あなた」と記します。
自分に対する、気づきの為のメモなので、上から目線で記している点をご了承ください。

**読者のみなさまへ：**
同じような境遇の方、どんどんコメントお願いいたします！
お気持ちを共有していただくことにより、近い将来、高い鼻鳴らして闊歩している自分に、より多くの気づきを授けることでしょう。

**記事タイトルについて：**
記事タイトルは [お前らの記事のタイトルは間違っている〜爆速で誰でもできるQiitaでバズらせる6個の必殺技まとめ](https://qiita.com/Ancient_Scapes/items/bba0fab1e55936e7234a) を参考にさせていただいた上で、お茶目に韻を踏もうと思って命名したのですが、すこし暴力的なタイトルになってしまい、読者の皆様に不快な思いをさせてしまったことを懺悔します。
特に採用活動などでQiitaを拝見してくださってる皆様には、
普段の私は全く暴力性の無い温厚で向上心があり好奇心旺盛でちょっとかわいい一面も持ち合わせた人間であることを弁解させていただくと共に、
業界の諸先輩方に対する失言ともとれる記事タイトルを付けてしまったことを、謹んでお詫び申し上げます。

#目次
ぼくだって、**基本的にはググってます。**
しかし、急いでいるときや、正確な学習のためにかいつまんだ説明がほしいとき、
もしくはGoogle先生よりもあなたのほうが確実に詳しそうなときなどには、
「"○○"って？」と聞き返すことも、よくあります。

あなたが「ggrks」と、ぼけ〜っと考えている間に、ぼくはこんなにも沢山のことを考えています。

**1.そもそも、ググるべき単語なの？ ~汎用的な単語であるのか~**
**3.それって、AND検索をする必要があるの？ ~文脈により意味が変わらないか~**
**4.ところで、どれが検索ワードとして最適なの？ ~不変的な単語であるのか~**

詳しいところを、後述していきます。

#結論
こんな記事を振り返る必要があるあなたは、ひじょ〜に忙しい方だと思うので、先に結論を言います。

「ggrks」と思う前に「"○○"でググれ」と考えてみてください。
すでに知識を持っているあなたですら、最適なワードを考え出すのに１分かかるとしたら、
それについての知識がないぼくがそのワードに辿り着くのに、最低１０分はかかるでしょう。
（さらにそこから、最適解を得るための時間がかかるのでしょう。）

あなたのお給料が、ぼくのお給料の１０倍以上ということは、さすがにないでしょう。
つまり、あなたがぼくに手助けをするべきと思うのは、ぼくのわがままではなく、合理的な判断でしょう。
もちろん、あなたが未だぼくの指導を期待されるポジションじゃなければ、この事は気にしなくて大丈夫です。
しかしそうじゃなければ、あなたの給料は、その知識と、未熟者の育成のためも考えて底上げされていることを、忘れないでください。

#そのワードって、ググるべき単語なの？
ぼく（そのワードって、この界隈における共通語なの？）
ぼく（たとえば、この業種・会社・グループ内だけで発達しているワードだったり、別の状況・環境では使い方が異なるワードだったりしないかな？）
ぼく（そのワードを初めて耳にするぼくには、そのあたりがイマイチわからない。）
ぼく（もしそのワードをそのままググるだけで、今必要な知識に辿り着けるなら、話を中断してすぐにでもググりたい。）
ぼく（だけど、共通語なのかどうか、それに後述する２つに該当しないかどうか、話を聞いただけじゃわからないな…。）

ぼく「"○○"って？」

#そのワードって、AND検索をする必要があるの？
ぼく（そのワードって、他所でも聞いたことあるけど、今言われているような意味・用途じゃなかった気がする。）
ぼく（もしかしてそれって、他にもいろんな用途があるの？）
ぼく（だとしたら、今回の状況に適切なAND検索のワードってなんだろう？）
ぼく（ていうか、解説が複雑になりそうだから、もしかしてあなたに直接聞かないと、色々紛らわしいんじゃないの？）

ぼく「"○○"って？」

#そのワードって、どれが検索ワードとして最適なの？
ぼく（「○○」だとか「□□」だとか、いろんな言い方をしているけど、どれが検索ワードとして最適なの？）
ぼく（もしや、文脈でわかるところを省略していたり、話をわかりやすくするために言い換えてくれてたりするの？）
ぼく（よくわからないから、かいつまんで説明してほしいな。）

ぼく「"○○"って？」

#おわりに
ぼくに対して、すぐに聞いてくるなあと、イライラしてしまうのは仕方ない。
だけど、ぼくがなんでそんな質問をするのか、理解して、手助けをしてあげることで、
ぼくのような者（かわいい部下とか、後輩とか）に大人気な、ナイスガイな大人になれると思う。
これからも、がんばろ！
UnityでOculusQuestの開発環境構築

# はじめに
最近OculusQuestを入手できたので、Unityで開発環境を構築しました。

#開発環境
Unity Hub ~~2.0.0~~ 2.0.4
Unity ~~2018.4.0f2~~ 2019.1.11f1
Oculus Integration- ~~1.37~~ 1.39

#参考にしたページ
[Oculus Quest に Unity で開発したアプリをいれる方法（Mac/Win）]
(https://qiita.com/Tomoyuki_Mikami/items/be9b3bf605a5d953be1b)
まずは、こちらの手順通りで実機で起動できることまで確認しました。

[【VR】Oculus Quest＋Unity開発](http://cycling.hateblo.jp/entry/2019/05/25/120551)
こちらに内容を参考に、視点の移動とTouchコントローラの表示ができるところまでできました。

[Oculus Quest Development Guide](https://developer.oculus.com/documentation/quest/latest/)
こちらは公式ドキュメントです。

#そのほか
~~・Unity 2019.1.2f1, Unity 2019.1.4f1では、ビルドはできるのですが、実機上ではすぐ終了してしまい動作できませんでした。こうすれば動作できるなど情報いただけると助かります。原因がわからないため、当面、2018.4.0f2を使い続けることになりそうです。~~
@Horukasuさんの記事にあった通り、OtherSettings のGraphicsAPI をVulkan からAutoGraphicsAPIに変えたところ、2019.1.4f1でも実機上で動作できるようになりました！
[QuestへのビルドがUnity2019.1.4f1で通らなかったお話（解決）]
(https://qiita.com/Horukasu/items/1809c57801018f449a02)
~~・Oculus Integrationのインストール中、OVRPluginのUpdateをするか聞いてくるのですが、自分の環境では、Yesを押した場合、後でビルド実行時にファイルの競合(OVRPlugin.dllとOVRPlugin.aar)が発生しましたので、Noにしたほうがよさそうです。なお、ファイルの競合が発生したときは、リネームすることでとりあえずは回避できました。~~
Oculus Integration-1.39では上記現象は発生しませんでした。
・(2019/7/28追記)
Oculus Questがアップデートされた後、コントローラの挙動がおかしくなるケースがあります。対処法について、@shienaさんがわかりやすくまとめられています。
[Oculus Quest Build 7.0アップデート後に自作アプリがおかしくなった時の対策]
(https://qiita.com/shiena/items/0b7735a80e7d4358e5fb)

#WiFi経由でADB接続
ビルドする度にUSBケーブルを接続するのが面倒なので、WiFi経由でADB接続を試してみました。
手順は、
1. OculusQuestと開発PCをUSBで接続
2. "adb shell ifconfig"を実行してOculusQuestのIPアドレスを調べます
3. "adb tcpip 5555"のあと"adb connect IPアドレス:5555"を実行してWiFi接続
4. USBを外します
この後は、unityからビルドして実行で、WiFi経由で書き込みできます。
しかし、OculusQuestがスリープ状態にはいると接続が切れて1.からやり直しになるので
いまいち便利ではなかったです。
と思っていたのですが、OculusQuestがスリープから復帰した後(USB接続無しで)"adb connect IPアドレス:5555"を実行すると、再度WiFi接続できました。
Winsows PCからの接続手順やその他ADBの便利な使い方について、@divideby_zeroさんがわかりやすい記事を書いています。
[Oculus Quest を ipアドレスで接続して楽々ケーブルレス開発]
(https://qiita.com/divideby_zero/items/1151ab760cbaa3d43d45)

#リモートデスクトップでUnity
リモートデスクトップ経由でPC上のUnityを使用して、ケーブルレスでOculusQuestをかぶったまま開発を実行できるようになりました。
[Oculusブラウザからリモートデスクトップ]
(https://qiita.com/Satoshi_Takahama/items/5f1b0e8d38377e4b99eb)
Insta360OneXの動画を使ったフォトグラメトリ

360動画を用いたPhotogrammetryの手順の一例を紹介します。

<blockquote class="twitter-tweet" lang="ja"><p>FlyThrough動画</p>&mdash; aya (@nakano_muramoto) <a href="https://twitter.com/nakano_muramoto/status/1133122243620364288">2019/05/27</a></blockquote>

データは@NaotakaFujii様から拝借しました。ありがとうございます。

大まかな手順はこちらになります。
1. EQ動画を静止画連番に変換する　Adobe Premiere Pro
2. EQ画像を平面画像に変換する　PTGui
3. 平面画像を3次元再構成する　Reality Capture

####1. EQ動画を静止画連番に変換
これは一般的な作業なので、説明は不要かもしれません。
![190529s1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/54a41a6b-bd2a-aa9f-7c0a-0551c5a0322e.png)

今回はjpegにしました。

####2. EQ画像を平面画像に変換
Reality Captureは画像のひずみ補正も自動で行ないますが、
後日に紹介する予定の理由から、あらかじめ中心射影に投影変換しました。

![190529s2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/87123889-a7f3-39ad-5b30-3e98a1a237f7.png)

今回はできるだけ広い角度として、FOV110degにしました。

水平方向に4種類の向き（20deg, -20deg, 180deg, 200deg）で切り出しました。
こちらの画面のyawの値で、切り出す視野を変更します。
![190529s2a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/fe2eef2a-e123-1203-f3e5-e67552bcc4af.png)

####3. 平面画像を3次元再構成
（大まかな手順は公式のホームページやYouTubeの紹介動画をご覧ください。）

入力した画像について、カメラの条件を入力しました。
"1Ds"のリストにある画像を選択した後、
WorkflowタブのApplicationにある、Settingをクリックして、
"Prior calibration"のFocal lengthを12.5mm（FOV 110deg相当）、
"Prior lens distortion"のModelを"No lens distortion"にしました。
この設定をすることで、三次元再構成するときのレンズの内部パラメータが制限されるようです。

![190529s3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/aa54ce79-b9ea-4eff-e4a3-84a7c3a87952.png)

※レンズのパラメータを設定しないと、つじつまが合いやすい結果が導出されるので、
　少し無理がある解析結果になることがあるようです。

自動で画像群が分類され、推定されるモデルごとにComponentが分かれますので、
コントロールポイントを設定して、できるだけモデルをまとめます。
今回は、854枚が一つのモデルにまとまりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/dca4f2b5-d1a8-5ded-c5c6-0f853e49d572.png)

RecsonstuctionタブにあるSimplify Tool, Smoothing tool, Unwrapを行い、
Textureを生成しました。
![190529s3c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/f4e1439c-027a-2d9c-ade3-330623dce511.png)

最後に、コントロールポイントを使って、距離情報を入力します。
今回は地図から推測した値を入力しましたが、
本来であれば、複数の方向の距離を実測した方がよいと思います。

また、"4D"ウィンドウを選択すると、ドリーやドローンのように、
カメラを移動させながらモデルの中を撮影したような動画を生成できます。

![190529s3d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/366e3f9f-4392-6a16-27b2-6f55fffdab12.png)

####まとめ
360カメラで撮影された動画を用い、Photogrammetryする手順の一例を紹介しました。
著者自身は、まだ3年くらいしかツールを使っていないので、不十分な理解で恐縮です。
よりよい方法がありましたら、ご紹介いただけると幸いです。

また、今回は有償のツールばかりを使いましたが、
UnityやMeshroomで代用することも可能だと思いますので、
後日、記事をまとめる予定です。


####あとがき
<blockquote class="twitter-tweet" lang="ja"><p>過去の事例</p>&mdash; aya (@nakano_muramoto) <a href="https://twitter.com/nakano_muramoto/status/796639935377842176
">2016/11/10</a></blockquote>

カメラやアプリ、PCが進化したことによって、よい結果を得やすくなった気がします。

通常のカメラを使ってインサイド・アウトでモデリングしようとすると、
Componentがまとまらないことが多いので、
360カメラで大まかに撮影して、
あとで細かいところを通常のカメラの画像で補うなど、
手段の選択肢が増えたと思いました。
Python１

＜Python学習＞
Pythonの学習を始めたので、基礎をメモ。

・文字列
　‘’もしくは””のどちらかで囲む。どちらを使用してもOK。

・コメント
　#を頭につける。

・変数
　変数の名前の頭に数字は使用できない。
　２つ以上の単語を使用する場合は、「_」でつなげる。

　変数1に変数2と変数3をかけた答えを代入する。
　変数1 = 変数2 * 変数3

　変数に値を入れ直す際の計算の記述方法。
　x = x + 10 → x += 10
　　　　　　　x -= 10
　　　　　　　x *= 10
　　　　　　　x /= 10
　　　　　　　x %= 10

　異なるデータ型同士を連結しようとするとエラーになる。
　Str()を用いて型変換を行う。
　数値　→　文字列
　price = 500
　print(‘りんごの価格は’ + str(price) + ‘円です’)

　文字列　→　数値
　count = ‘5’
　print(int(count) + 1 )

・条件分岐
　score = 100
　If score == 100:
	print(“よくできました”)

　==　等しい
　!=　等しくない

　※if文の条件式が成立した時の処理を書くときには、インデント（字下げ）をします。

　else:

　elif:
　例）
　　money = 100
　　apple_price = 100

　if money > apple_price:
    　print('りんごを買うことができます')

　elif money == apple_price:
    　print('りんごを買うことができますが所持金が0になります')

　else:
    　print('お金が足りません')


・真偽値
　print(3 == 3)　→　True
　print(3 == 5)　→　False

・比較演算子
　x > y　yより大きい
　x < y　yより小さい
　x => y　以上
　x =< y　以下

・条件式を組合わせる
　and
　or
　not　→　条件式がTrueであれば全体がFalseに、Falseであれば全体がTrueになる。

・入力を受け取る
　「変数 = input(‘コンソールに表示したい文字列')」のように使うとコンソールに入力された値が変数に代入される。
　文字列で受け取るので、数値の場合は型変換を行う。

・リスト
　fruits = [‘apple','banana','orange']　→　012の順で番号が振られている。

　リストに追加する
　「リスト.append(値)」と入力するとリストの末尾に追加される。

　リストに再代入する。
　fruits[0] = ‘cherry'

・for文

　リストの中身を繰り返して出力させる場合、「for 変数名 in リスト名」と記述する。
　for fruit in fruits:
    　print('好きな果物は' + fruit + ‘です')

・辞書
　キー　　　　値
　apple　→　red

　辞書の記述
　fruits = {‘apple’:’red’,キー2:値2}
　※辞書内の要素には順序がない！キーで管理する。

　print(fruits[‘apple’])　→　redと出力される。

　辞書の要素を書き換える。
　fruits[‘apple’] = ‘green’

　辞書に要素を追加する。
　fruits[新しいキー] = 新しい値２
　※元あるキーを使用すると書き換わってしますので注意。

　辞書の中身をすべて表示する。
　for 変数名 in 辞書:

　fruits = {'apple': 'りんご', 'banana': 'バナナ', 'grape': ‘ぶどう'}
　for fruit in fruits:
    　print(fruit + 'は' + fruits[fruit] + ‘という意味です')
　↓
　appleはりんごという意味です

・while文
　ある条件に当てはまる場合に繰り返す。
　※無限ループに注意する

・繰り返し処理
　breakで処理を抜けれる。
　continueでその周の処理のみ飛ばせる。

・関数
　def 関数名():
	　実行する処理

　「関数名()」で呼び出す。

・引数
　def 関数名(仮引数):
	　実行する処理

　関数に引数を渡す。
　関数名(引数)

　引数の初期値
　def 関数名(仮引数1,仮引数2=‘値’):

　戻り値
　return 返す値
　※関数内のreturn以降の処理は実行されない。

　下記のようにすると、if文の中が処理されない場合、「return True」が返る。
　def validate(hand):
    　if hand < 0 or hand > 2:
        　return False
     　return True
麻雀の「完全先付け」「2役縛り」と「メテオフォール型開発」は似ている

# WARNING
この記事は麻雀の「完全先付け」「2役縛り」というルールを否定するものではなく、そのルールで打ちたい人はそのルールで打てばいいと思います。
ただし、この2つのルールに対する呪詛を十二分に含みますので、「完全先付けじゃなきゃ麻雀じゃない」「2役縛りは当たり前」と考えてる方にとってこの記事は精神衛生上よろしくないと思います。
でも「メテオフォール型開発」、**テメーは滅びろ。**

## そもそもタイトルの3用語の意味は？(要件定義)
### 完全先付け
筆者は「最初の鳴きが役に関係していない」「全ての待ちに共通する確定役がない」場合にあがれなくなるという縛りを課すものと認識していますが、ルールの揺れが激しいようです。
要は「完全先付け」という用語に対する要件定義ができてないわけです。
要件定義ができていないプロジェクトは、メテオフォール型に付け入る隙を与えてしまいます。

### 2役縛り
~~3人打ちにおいて常に2役縛りとする場所もあるにはあるようですが、~~積み棒が一定数(4本場か5本場ぐらいから)を超えると~~何故か~~2役以上ないとあがれなくなってしまいます。
しかもこのルール、ありありにしていても**確定で2役ないとあがれなくなる**とかいう謎ルールがある(最終的に2役あればOKというルールもあるにはありますが少数派)上、メテオフォール的にこの縛りが課されることがあります。(というか筆者は2役縛りが発生したほとんどのゲームでメテオフォール的に課されてました)

### メテオフォール型開発
詳しい説明は[このページ](https://eiki.hatenablog.jp/entry/meteo_fall)に譲るとして、筆者が簡単に説明しますと……
 **"神"と呼ばれる1人または少数人数の都合にプロジェクトの全てが振り回される開発手法のこと**です。


……ということで、この「完全先付け」「2役縛り」と、「メテオフォール型開発」には共通点があり、その共通点を探っていこうという記事です。
ちなみに、解説に登場する人物の序列としては「A＞B」です。


## その1「要件定義がない、あっても雑すぎる」
### 麻雀でいうと
A「このゲームなしなしな！喰いタンなし、完全先付け！」
B「あの……完全先付けは何があがれなくなるんですか……？」
A「はぁー！？完全先付けって言ったら完全先付けだろ！」
B「だからその完全先付けって言ってもルールの揺れが激しくて、あがってみたらチョンボって言われても困るんですけど」
A「完全先付けは完全先付けだろ！ほら、場所決めるぞ！牌取れ！」

### 開発現場でいうと
A「この機能を組み込め！あーで、こーで、それだ！」(Aにしかわからない言葉の羅列)
B「あの……あーで、こーで、それって、どういう機能を作ればいいんですか？」
A「はぁー！？あーで、こーで、それって言ったらあーで、こーで、そういう機能だろ！」
B「だから言葉の意味が分かりません、それだけ言われても要件定義できないんですけど」
A「あーで、こーで、それはあーで、こーで、それだろ！ほら、開発始めろ！俺は外回り行ってくるからな！」

### 解説
どちらの例においても要件定義の段階でグダってます。
当然、麻雀においても開発においても要件定義ができなければ、ゲームになりませんし開発も進みません。
要件定義はどのような機能を作って、どのような形になれば完成になるのか、ということを決める重要なパートであって、おろそかにしていいものではありません。


## その2「序列だけで効率の悪い方法がまかり通ってしまう」
### 麻雀でいうと
B「ロン！　タンヤオ平和ドラ3、満貫で8000点です！」
A「おい！これ1萬であがったら平和だけ、3萬だったらタンヤオだけだろ！後付けでチョンボだ！」
B「えぇ……でも役があることは確定しているじゃないですか」
A「タンヤオか平和か確定してないだろ！チョンボの罰符払えオラッ！！」
(また別の局)
A「ツモ！　18000点！」(門前ツモ、ドラ5)
B「あの……これロンだと役ないですよね……これって後付けじゃないですか……？」
A「門前ツモが確定してるからいいんだよ！6000点出せオラッ！！」

### 開発現場でいうと
B「よし……これでサーバーへの負荷が軽くできたぞ、これをコミットしてっと……」
(翌日Aから来たIssuesを確認する)
A「昨日のBのコードどういう処理してんのかわけわかんねーよ！ロールバックしろ！」
B「えぇ……でも今までサーバーが悲鳴を上げてたのはこの関数の処理が重かったからですよ」
A「とにかく俺がこの処理がどうなってるのかわかんねえんだ！ロールバックしろオラッ！！」
(また次の日、別の箇所の修正をAがコミットした)
A「あの部分、修正しといたぞ。B、動作確認しろ！」
B「わかりました……えっ、動作遅い……CPU使用率100%になってる」
(コードを確認)
B「ああ……ここで変なループ入れてるから時間かかるんですね、ループ使わなくてもいい方法があるのに……」
A「こっちの方がわかりやすいんだよ！リーダブルコードだぞ！お前はリーダブルコード読んでないのか？動作の速さよりコードの読みやすさだオラッ！！」(と言っているが実際そこまでリーダブルなコードになってない)

### 解説
序列の高さだけで序列の高い人に都合のいい結果にしたり、効率の悪い方法がまかり通ってしまう結果になってます。
ゲームにおいても開発においても、条件は対等でなければいけません。
序列的に縦社会であっても、ゲームや開発においては全ての人間が横社会にならなければならないのです。


## その3「突然の変更」
### 麻雀でいうと
B「ツモ！　リーチ一発ツモメンホンダブ東、倍満8300オールです！次は東3局4本場です！」
A「よーし、ならこの局からは2役縛りな！」
B「えっ！？2役縛りって！そんなの説明してなかったじゃないですか！」
A「うるせえ！お前ばかり連荘してうぜえんだよ！2役縛りだ！」

### 開発現場でいうと
B「よし……システムテストOK……あとはリリースを待つだけだな」
A「おい！ここの仕様をこういう風に変えろ！」(現在の仕様とは大きくかけ離れた仕様を提示してきた)
B「えっ！？今までの仕様と大きく違いますよ！今から作り直してたら間に合いません！」
A「うるせえ！俺がこのプロジェクトのリーダーなんだ、作り直しを指示するのは当然だろ！ほら、修正しろ！」

### 解説
メテオフォールの真骨頂、「突然の変更」です。この「突然の変更」で何もかもがめちゃくちゃになる、それがまるで隕石でも落ちてきたかのようということから「メテオフォール」とも呼ばれます。
せっかくここまで積み上げてきたものを無にされたり、めちゃくちゃにされたりする……こんな悲劇はあってほしくないものです。


## 結論
メテオフォール型開発は、本来開発においてあってはならないことです。
麻雀においても、プロ団体やフリー雀荘においてはしっかりとルールの設定、つまり要件定義をしっかりとして、それに基づいてゲームを進めています。
要件定義、(このパートは説明できませんでしたが)設計、開発、その3つのいずれも、おろそかにしてはいけないものです。
メテオフォール型開発~~と完全先付けと2役縛り~~、これが一刻も早くなくなってくれることを願って、この記事の締めとさせていただきます。





……以上、自戒を込めて。
【2行で解決】R でも slack にコンニチワしてみよう

CRONでRスクリプトを定時実行してるのですが、
導入初期は色んなイレギュラーで止まったりしてデバッグが大変でした。

"slackr" パッケージを使うと焦るほど簡単にslackに通知が打てます！
随時状況を、slackに送ってくれるようにしたら捗る捗る。
てわけで記事にしましたよ：

# 焦るほど簡単な設定
```R:setup.R
pacman::p_load(slackr)
```
これだけ！

# 初期化も一行
```R:slackr_init.R
slackr_setup(channel = "#maidayo", 
             incoming_webhook_url = "https://hooks.slack.com/services/XXXXXXXXXX/XXXXXXXXXX/XXXXXXXXXXXXXXXXXXXX")
```
以上！

# もうこれだけで、ポンポン打てるんです
```R:cron_jobs.R
slackr_bot("本日のバッチ1をはじめるよー")
source("jobs/job1_update.R")
slackr_bot("本日のバッチ2をはじめるよー")
source("jobs/job2_extract.R")
slackr_bot("本日のバッチ3をはじめるよー")
source("jobs/job3_fitandexport.R")
slackr_bot("本日のバッチがおわったよー")
```
便利過ぎる。


# 最初にAPIキー取ってくるほうが多分めんどくさい
Slackボットには色んなタイプがあるのですが、ここで利用しているのは
一番単純なボットAPIでして、必要なのは
「incoming_webhook_url」のURLだけです。

具体的手順をqiitaに書いてる方が居ました：
https://qiita.com/kakiuchis/items/1d9ade2ef83709209dc4

「incoming_webhook」だけを有効に出来れば、後はホントに一瞬で動きますよ。
(slackrは対話型とか多機能なのにも対応出来ますが、設定がややこいのでまずは単純な通知ボットで試すのがオススメです。）


R、賢いパッケージが多いですよね。この手の処理が本当に一瞬で終わります。
偉大な先人たちに感謝感謝。
Node.jsで環境変数(AppDataの場所、PATH、その他)を取得したい

# 結論
`process.env`を使います。

[node.js - how to get the OS platforms user data folder - Stack Overflow](https://stackoverflow.com/questions/19275776/node-js-how-to-get-the-os-platforms-user-data-folder)


# 実践

ターミナルで`node`を叩くと始まるInteractive Rubyみたいなアレで実行してみましょう。

```
{ ALLUSERPROFILE : "C:\\ProgramData",
  APPDATA : "C:\\Users\\jotaro\\AppData\\Roaming",
  (省略
}
```

こんなObjectが返ってきました。これはもう要するに、`process.env.APPDATA`と書けば、`"C:\\Users\\jotaro\\AppData\\Roaming"`が返ってくるというわけですね。あとは`process.env.PATH`からPATHの編集も…は…できないようです。


# 制限

[Process - Node.js Documentation](https://nodejs.org/dist/latest-v10.x/docs/api/process.html#process_process_env) によれば、

> It is possible to modify this object, but such modifications will not be reflected outside the Node.js process. In other words, the following example would not work:
>
> ```
> $ node -e 'process.env.foo = "bar"' && echo $foo
> ```

「値を変更することはできるけど、Node.jsのプロセス内だけでしか変わらないよ」(超適当訳)とのこと。**PATHを通したり環境変数をいじることは不可能**なようです。うっかりPATH破壊でもしたらと思うと、納得がいきます。
もしかしたら環境変数の変更方法というのもあるのかもしれませんが、適当にググった結果ないと判断しました。


# 応用

### スタートメニュー
応用して、Windowsのユーザーのスタートメニューにアクセスしてみます。

```js:test.js
console.log(`${process.env.APPDATA}\\Microsoft\\Windows\\Start Menu\\Programs\\`);
```

スタートメニューにショートカットを作るのも楽ちんですね。おしまい。