OmniAICreator/Qiita-1.07M huggingface dataset:
偏微分（勾配）が法線を表すイメージ

## 概要

レイマーチングやその他、様々なところで話される「偏微分」。
そしてそれが「法線を意味する」というのも便利で興味深いところです。

が、なかなかイメージがしづらく、技術として使えていながらも明確にそのイメージを持てないとどうしても気持ち悪さがあります。

ということで、今回はこの**偏微分と法線**のイメージについてまとめたいと思います。

**※ 注釈**
あくまで「自分個人の理解」の話です。
なので、数学的な話や厳密な解説ではなく、あくまで「どうして法線になるのか」を解説しているに過ぎません。
（それが故に、そもそも自分の理解も間違っている可能性もあります）


## イメージ

まず、なぜ偏微分が法線となるのかそのイメージを書きたいと思います。
以下の図を見てください。
（この図は、こちらのPDFから引用させていただきました→「[勾配・発散・回転 (PDF)](https://www.kspub.co.jp/download/1565395b.pdf)」）

<img width="301" alt="スクリーンショット 2018-08-21 9.49.33.png" src="https://qiita-image-store.s3.amazonaws.com/0/5616/03750238-af5f-d1a7-7d4c-94fc5962713e.png">

赤い矢印が勾配ベクトルです。
そして、等高線の一本（ベクトルの根本がくっついている曲線）に対して「法線」となっているのが分かるかと思います。
勾配ベクトルが「法線」を表すイメージはまさにこれです。

### 3次元では

上の図は2次元の図に対するものでした。
では3次元ではどうでしょうか。

まず、$\phi(r)$という関数を定義します。関数の定義は以下です。

```math
\phi(r) = \phi(x_0, x_1, x_2)
```

上記の意味は$x_0, x_1, x_2$によってひとつの値（スカラー）が決まる関数、ということです。

そしてその関数と引数を含めた4要素を「$(x_0, x_1, x_2, φ(r))$」（$\phi(r) = \phi(x_0, x_1, x_2)$）として、4次元ベクトルとして表現してみます。

つまり$x_0, x_1, x_2$の3要素によってひとつの値（スカラー）が決まるわけです。
しかしながら、4次元を図に起こすことはできません。
そこで、$\phi = C$として$\phi$の値を固定して考えてみます。
すると以下の図のように、各値（$C_1, C_2, ...$）それぞれに曲面を図示することができるようになります。

![](http://hooktail.sub.jp/vectoranalysis/ScalarFieldGrad/Joh-ScalarField.gif)
※ [スカラー場と勾配 [物理のかぎしっぽ]](http://hooktail.sub.jp/vectoranalysis/ScalarFieldGrad/)より引用

ちなみに引用させていただいた記事によるとこれらの面を「**スカラー場の等位面**」と呼ぶそうです。
スカラー場にある$\phi = C$と固定したときの「等位」な面、ということですね。
前述の「等高線」の3D版と言うことができると思います。


### 勾配（grad φ）を考える

前述の例を元に、$\phi(r)$の勾配を考えてみます。勾配は英語でgradientと書き、$grad$と表現されます。
$grad \phi$が勾配ベクトルを表します。
これをナブラ（$\nabla$）を使って表すと、

```math
\nabla \phi = \biggr(\frac{∂\phi}{∂x_1}, \frac{∂\phi}{∂x_2}, \frac{∂\phi}{∂x_3}\biggl)
```

と表されます。（[参考](http://hooktail.sub.jp/vectoranalysis/Gradient/)）

ナブラは「微分演算子をベクトルに組み合わせた**ベクトル演算子**」です。
これを$\phi$に作用させることで勾配ベクトルとなるわけです。

では実際、$\nabla \phi$はなにを意味しているのでしょうか。
微分は関数に対して微小な値を足したときにどう変化するかということを示します。

さて、上の図をもう一度見てみましょう。

![](http://hooktail.sub.jp/vectoranalysis/ScalarFieldGrad/Joh-ScalarField.gif)

$\phi$は関数でした。（$\phi(r)$）
そして微分は関数に微小な値を足したものから計算します。

つまり、

```math
\frac{∂\phi}{∂r}
```

ですね。

さてここで、以下のように考えてみます。

```math
C_2 = \phi(r)  \\
C_1 = \phi(r + ∂r)
```

そして上の図で$C_1$と$C_2$を見てみると、曲面が少しだけ上に移動しているのが分かるかと思います。（$C_1 - C_2$の差分ベクトルのイメージ）
この移動方向をベクトルとして考えてみると曲面の法線方向に移動しているのがイメージできるかと思います。

これが「偏微分＝勾配」が「法線」を表していることのイメージです。

あえて一言追加するならば、4次元空間での勾配が3D空間での法線を意味する、という感じでしょうか。
（あくまで自分個人のイメージ、理解です）


## 参考にした記事一覧

上記の内容を書くのに、以下の記事を参考にさせていただきました。ありがとうございます。

- [スカラー場と勾配 [物理のかぎしっぽ]](http://hooktail.sub.jp/vectoranalysis/ScalarFieldGrad/)
- [grad [物理のかぎしっぽ]](http://hooktail.sub.jp/vectoranalysis/Gradient/)
- [ベクトル解析奮闘記1](http://hooktail.sub.jp/vectoranalysis/vecFuntou1/)
- [勾配・発散・回転 (PDF)](https://www.kspub.co.jp/download/1565395b.pdf)
fishで複数ファイルをリネーム

fishは補完効きまくって好きなので使ってます:santa_tone1:

jade→pugに100ファイルぐらいリネームする機会がありまして
現在のディレクトリからサブディレクトリまでリネームしているのは見つからなかったので投稿します。

# 結論、このコードです:santa_tone2:

```rename.sh
for jadefilepath in **.jade
  mv "$jadefilepath" (echo "$jadefilepath" | sed '$s/\.jade$/.pug/')
end
```

### 追記です
sed使うとわかりにくかったりするので、basenameで文字列を抜き出してという方法も書いておきます
こっちのほうが、正規表現をエスケープしないので、まだ見やすいかも(.jade→.pugに変換)

```rename.sh
for filename in *.jade
  mv -v -- "$filename" (basename $filename .jade).pug
end 
```

[参考サイト](https://stackoverflow.com/questions/38590165/how-to-rename-file-extentions-in-fish-in-a-for-loop)

# TL;DR
(なんだTL;DRって)

- .jade→.pugに拡張子を置換します

# 対象読者

- fishを使用します
- 今いる場所から、下に向かってひっかけて置換します


# アウトプット

こういうディレクトリがあったとします:santa_tone3:
※treeコマンドで可視化してます

```
$ tree
.
├── current.jade
├── dir1
│   └── hoge1.jade
└── dir2
    ├── dir3
    │   └── hoge3.jade
    ├── dir4
    │   └── dir6
    │       └── hoge6.jade
    ├── dir5
    │   └── hoge5.jade
    └── hoge2.jade

6 directories, 6 files
```

さっきのコマンドを叩いて、

```
$ tree

.
├── current.pug
├── dir1
│   └── hoge1.pug
└── dir2
    ├── dir3
    │   └── hoge3.pug
    ├── dir4
    │   └── dir6
    │       └── hoge6.pug
    ├── dir5
    │   └── hoge5.pug
    └── hoge2.pug

6 directories, 6 files
```

サブディレクトリも含めて拡張子を.jade→.pugに変換することが出来ました。

# インプット
自分のわかる範囲でコードを説明します:santa_tone4:

```rename.sh
for jadefilepath in **.jade
  mv "$jadefilepath" (echo "$jadefilepath" | sed '$s/\.jade$/.pug/')
end
```
1. for文で「.jade」が見つかる分だけ実行し、そのひっかけたパスを、jadefilepathに格納
2. mvで変数$jadefilepathに格納したpathをmvコマンドでリネーム
3. ()の中でsedコマンドを使って、.jade→.pugに置換（ここを参考にしました→[How to rename file extentions in fish in a for loop?
](https://stackoverflow.com/questions/38590165/how-to-rename-file-extentions-in-fish-in-a-for-loop)）



1行目の`**.pug`でカレントディレクトリから下のサブディレクトリすべてワイルドカードでひっかけるのがミソですかね:santa_tone4:

## カレントディレクトリのみを対象にしたい

1行目の`**.jade`→`*.jade`にしてアスタリスクをひとつ減らせばOKでした:santa_tone4:


# fishのワイルドカード

カレントディレクトリのみの検索はアスタリスク1個

```jadesearch.sh
$ ls *.jade

current.jade
```

サブディレクトリ含む検索はアスタリスク2個

```jadesearch.sh

$ ls **.jade

current.jade              dir1/hoge1.jade           dir2/dir3/hoge3.jade      dir2/dir4/dir6/hoge6.jade dir2/dir5/hoge5.jade      dir2/hoge2.jade
```






# 参考

- [全訳！fishシェル普及計画](http://fish.rubikitch.com/)
- [How to rename file extentions in fish in a for loop?
](https://stackoverflow.com/questions/38590165/how-to-rename-file-extentions-in-fish-in-a-for-loop)


# あとがき
fish普及計画を書いている人みたいに、熱中できる言語みつけたい:santa_tone5:
TypeScriptで0, 1, 2, ...99な配列を作る

# はじめに
連続した値の配列を作りたいことって結構ありませんか？C#の`Enumerable.Range(0, 100)`、Pythonの`range(0, 100)`や、Haskellの`[0..99]`に相当する機能です。僕は結構あります。
JavaScriptには相当する組み込み機能がなく、さらにググって出てくるコードぺとっと貼ってTypeScriptコードとしてトランスパイルするとts-lintが警告しまくってきたので、こうしたらいいという書き方を備忘しておきます。

## `[...new Array(100).keys()]`との出会い
ぐぐると、まずこれに出会うと思います。リーズナブルなコードですね。

```typescript
[...new Array(100).keys()];
```

- `undefined`を100個含む配列を生成して、(`new Array(100)`)
- 各要素のインデックスを取り出して、(`keys()`)
- オブジェクトをその場で展開して、(`...`)

配列にする、って感じですね。

### 参考
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array#%E6%A7%8B%E6%96%87
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/keys
- https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax

## `Replace Array constructor with an array literal`とかいうエラー
ts-lintのprefer-array-literalが`true`になっているせいです。筆者の場合は、`tslint-microsoft-contrib`由来で`true`になっていました。
もちろん、このプロパティを`false`にしてもいいのですが、それをやりはじめるとキリがないですし、解決法も極めてシンプルで`new`を取り除くだけです。

```typescript
// [...new Array(100).keys()];
[...Array(100).keys()]; //newを取り除きました
```

### newをとると何が起きるか
上記で問題ないので、余談ですが「いやいや、これnewをとるとコンストラクタが呼び出されるんじゃなくて関数呼び出しになっちゃうよね？その場合どうなるの？」と思いませんか？
ググってみたけど、なぜかイマイチ日本語情報が見つからない…と困っていたのですが、結局ECMA2018の標準に書いてありました。困ったときは規格チェックが一番ですね。

> also creates and initializes a new Array object when called as a function rather than as a constructor. Thus the function call Array(…) is equivalent to the object creation expression new Array(…) with the same arguments.
> http://www.ecma-international.org/ecma-262/9.0/index.html#sec-array-constructor

ということですので、`new Array(...)`と同じだよとのことです。

## `Type 'IterableIteratorShim<number>' must have a '[Symbol.iterator]()' method that returns an iterator.`とかいうエラー
tsconfig.jsonでのtargetによってはこのエラーが出ることがあります。
これは、`keys()`ではなくmapの第二引数でインデックスを取ることで解決できます。

```typescript
// [...new Array(100).keys()];
// [...Array(100).keys()];
[...Array(100)].map((_, i) => (i)); //第二引数はインデックス
```

## 結論
↓こういうのつくっておくとよい。

```typescript
const range = (begin: number, end: number) => ([...Array(to - from)].map((_, i) => (from + i)));
```
Oracle SQLでDB接続中のセッションを特定＆強制終了(KILL)

# DB接続中のセッションを特定

負荷のかかるSQLを実行した際に、クライアントがフリーズしてしまい、強制終了してしまった。
そのときに、セッションが残っているか確認したいときに使用したSQLです。

```sql
SELECT
    SID, SERIAL#, MACHINE, STATUS, PROGRAM
FROM
    V$SESSION
WHERE
  USERNAME = 'HOGE';
```

HOGEと記載しているところに、ログインしたユーザIDを指定します。
実行すると、下のような結果が出力される。


| SID | SERIAL# | MACHINE | STATUS | PROGRAM |
| :-- | :-- | :-- | :-- | :-- | :-- | 
| 48 | 141 | riekure1 | Active | SQL Developer |
| 139 | 157 | riekure2 | Inactive | A5M2.exe |


各項目の意味については、[Oracle公式](https://docs.oracle.com/cd/E60665_01/db112/REFRN/dynviews_3016.htm)が分かりやすいと思います。

# セッションを強制終了
もし、怪しいセッションが残っていて、強制終了したいときはSIDとSERIAL#を使用します。

```sql
ALTER SYSTEM KILL SESSION '48,141';
```

'SID, SERIAL'(カンマ区切り)で対象セッションを指定します。
ちなみに、自分自身を強制終了できませんでした。地味に親切でした。
GoogleAppsScriptでGoogleDriveのフォルダ間同期を行う

請負とかをやっていると、設計書をこっちのメンバーと顧客側で違うGoogleDriveに
配置して管理しないといけないことって良くありますよね。

そんな時に、このスクリプトを作って配置して、1時間おきとかに起動させれば
更新のあったファイルを自動的に別のフォルダに同期してくれます。

```javascript

function sync() {
  // コピー先フォルダID https://drive.google.com/drive/u/0/folders/XXXXXXXXXXX
  var save_folder = DriveApp.getFolderById("1eXXXXXXXXSWSXXXXXXXXUt");
  
  // コピー元フォルダID
  var folder = DriveApp.getFolderById("1LZXXXXXX4bUbXXXXXXXXXnFwE2");

  // 例：xlsのファイルを対象にファイルを探す。  
  // コピー元フォルダの全ファイル取得
  var files = folder.getFiles()
  var spreadsheet_ids = [];
  while (files.hasNext()) {
    var file = files.next();
    var file_name = file.getName() ;
    
    // .xlsか確認。全ファイル対象にするならこのif文を外す。
    if (file_name.match(/xls/)) {      
      var id = file.getId();
      var last_update = Utilities.formatDate(file.getLastUpdated(), 'Asia/Tokyo', 'yyyyMMddHHmmss');
      var fileItr = save_folder.getFilesByName(file_name);
      
      // コピー先フォルダにおなじ名前のファイルが無いか確認
      if (fileItr.hasNext()) {
        itr = fileItr.next();
        var itr_last_update = Utilities.formatDate(itr.getLastUpdated(), 'Asia/Tokyo', 'yyyyMMddHHmmss');
        
        // あった場合は更新日を見てコピー元のほうが最近更新されていたらアップする。
        if (itr_last_update < last_update) {
          save_folder.removeFile(fileItr.next());
          file.makeCopy(file_name, save_folder)
        }
        
        // コピー先フォルダに無い場合は強制的にアップする。
      } else {
        file.makeCopy(file_name, save_folder)
      }
    }
  }
  
}
```

ちなみに

```javascript
formatDate(date, timeZone, format)
```
は、GoogleAppsScriptの便利関数です。
https://developers.google.com/apps-script/reference/utilities/utilities#formatdatedate-timezone-format
Sublime Textのステータスバーにファイルの文字コードを表示する

# 開いているファイルの文字コードを表示する

とあるテキストファイルをSublime Textで開こうとしたところ、文字化けしてしまい正常に表示できなかったのだが、そもそもステータスバーに文字コードが表示されていないことに気付いたので設定追加した。


## settingsにshow_encodingを追加
メニューから [Sublime Text] > [Preferences] > [Settings] をクリック。
![スクリーンショット 2018-06-12 16.31.34.png](https://qiita-image-store.s3.amazonaws.com/0/6380/f4ada9a6-2983-2572-94d8-137138c4e944.png)

設定ファイルに以下を追加。

```
"show_encoding": true
```

これでステータスバーに文字コードが表示される。
![スクリーンショット_2018-08-21_13_08_29.jpg](https://qiita-image-store.s3.amazonaws.com/0/6380/5277cf49-b92c-bb06-bc9d-06bd10b2290b.jpeg)

ちなみにSublime TextのデフォルトエンコーディングはUTF-8で、文字コードが不明なファイルを開くと「Western (Windows 1252)」で開かれる。

```
"fallback_encoding": "Western (Windows 1252)",
"default_encoding": "UTF-8",
```
大学基礎数学のすすめ

ここでは，大学の基礎数学を学ぶ上で最低限必用な教科書とその問題をまとめます．
基本的に，文系の高校数学を学んだ方であれば，読めるようなラインナップにしています．
Amazonなどへのリンクはならないのでググってください． 

# 文章の書き方
人に伝わる文章を書かなくては意味がありません.

***おすすめ教科書*** 
木下是雄，「理科系の作文技術」，中央公論新社(1981)


# 集合位相
現代数学の基本となる考え方を集合位相で学びましょう.

***おすすめ教科書*** 
佐藤毅，「集合と位相」，大学数学の入門(2009)

# 線形代数
2次元以上のベクトルを扱うのに必須になります．

***おすすめ教科書 1*** 
矢野健太郎，石原繁，「線形代数」，裳華房(1990) 
[最低限の宿題](https://qiita.com/yuji0001/items/61afcfd552a1ee08449b)

高校のベクトル等の知識がなくても学べます．
しかしながら，グラムシュミットの直交化など，大学の線形代数に必用な知識が欠けています．
この本の後に，以下の本も勉強しましょう．

***おすすめ教科書 2,3*** 
入江昭二，「線形代数I,II」，共立出版株式会社(1966) 

# 微分積分
数列や極限の考えなど，解析学はここからスタートします．

***おすすめ教科書*** 
矢野健太郎，石原繁，「微分積分」，裳華房(1991) 
[最低限の宿題](https://qiita.com/yuji0001/items/fc009c7099a4f93d9e95)

# ベクトル解析
多次元の微分積分の考え方を学びましょう．
力学などの物理学を学ぶのに必須になります．

***おすすめ教科書*** 
矢野健太郎，石原繁，「ベクトル解析」，裳華房(1995) 

# 複素解析
ひょんなところに出てくる複素数ですが，次のフーリエ変換に必用な知識となります．

***おすすめ教科書*** 
矢野健太郎，石原繁，「複素解析」，裳華房(1995) 

# 関数解析
フーリエ変換，ラプラス変換をここで学びましょう．
次の微分方程式や偏微分方程式に用いられます．

***おすすめ教科書*** 
矢野健太郎，石原繁，「応用解析」，裳華房(1996)

# 微分方程式
時間を考慮する物理学では必須となります．

***おすすめ教科書*** 
矢野健太郎，石原繁，「微分方程式」，裳華房(1994)

# 統計学
推定，検定には必須の考え方です．

***おすすめ教科書*** 
竹村彰通，「現代数理統計学」，創文社(1991)
pythonista3のコンソール画面をクリアする。

Pythonista3でコンソール画面をクリアしたかったので調べたら、フォントやフォントサイズもフォントカラーも変更できることがわかりました。

###サンプルコード###
~~~python
import console

# コンソール画面をクリア
console.clear()

# フォントとフォントサイズを変更
console.set_font('Menlo',24)

# フォントカラーを変更
console.set_color(255,255,0)

print('Hello')

# デフォルトに戻す
console.set_font()
console.set_color()

print('Hello')

# 1文字ずつ指定することも可能です。
S='Hello'
console.set_font('Zapfino',48)
for i,c in enumerate(S,1):
  R, G, B = i&4 and 255, i&2 and 255, i&1 and 255
  console.set_color(R,G,B)
  print(c,end='')
'''
for i in range(1,6):
  C=bin(i)[2:].zfill(3)
  R=int(C[0]*255)
  G=int(C[1]*255)
  B=int(C[2]*255)
  console.set_color(R,G,B)
  print(S[i-1],end='')
  
# デフォルトに戻す
console.set_font()
console.set_color()
~~~

###実行結果###
![9EC219D6-2651-494C-B5CD-234698F1FDD1.jpeg](https://qiita-image-store.s3.amazonaws.com/0/280129/db4c0998-996f-dc6a-d6f2-57fe2479aaf6.jpeg)
Vue CLI 3で、minifyされてないHTMLを書き出す方法

方法をみつけるのに苦労したため書いておきます。

公式
https://cli.vuejs.org/guide/

vue.config.jsをプロジェクトルートに作成し下記記述。

```js
module.exports = {
  chainWebpack: config => {
    config.plugin('html').tap(options => {
      options[0].minify = { 
        removeComments: false,
        collapseWhitespace: false,
        removeAttributeQuotes: false,
        collapseBooleanAttributes: false,
        removeScriptTypeAttributes: false
      }
      return options
    })
  }
}
```

ちなみにファイル名後ろの乱数生成をさせないようにするには

```js
module.exports = {
  filenameHashing: false
}
```
毎日定時に起動する自動水やり機（micro:bit＋電動灯油ポンプ）の製作

#概要
アラーム時計を利用して、毎日定時に自動で植物に水まきをする仕組みを作りました。
1.アラームが鳴る（スピーカーに接続した電線に電気が流れる）
2.micro:bit（アナログ入力で上記を感知、リレースイッチをONにする）
3.リレースイッチから灯油ポンプを通電させて水を撒く
＊水を撒く時間はデフォルトで5秒間（Bボタンで5秒づつ稼働時間を変更可能。念のため最大30秒以上にしようとすると、デフォルトの5秒に戻ります）
＊アラームは1分間鳴り続けるので、１回起動後は10分間は待つようにしています。
![全体写真.JPG](https://qiita-image-store.s3.amazonaws.com/0/181708/7507b4e1-f122-7579-125c-044e0ec12926.jpeg)
スピーカーに半田でつなげています。
![alarmSM.jpeg](https://qiita-image-store.s3.amazonaws.com/0/181708/90da9749-10a6-a8f5-23d6-1644eb2c38ba.jpeg)
![alarmLight.jpg](https://qiita-image-store.s3.amazonaws.com/0/181708/4966a475-3ed0-60cc-1421-879480d81a5d.jpeg)


#背景
毎年夏休みに子供が学校から植物を持ち帰るのですが、帰省や旅行で何日か家を空けることがあるため水まきができない期間があります。
昨年はアナログな方法（サイフォン方式）でうまくいかなかったため、今年はデジタル方式で対応してみようと思いました。
自分の子供、さらに他の小学生の参考になればと思い、極力手に入りやすく、安価なもので作っています。

#使った材料、部材、機材など
①アラーム
　キャンドゥのデジタルアラームクロック
②リレー
　３Vで起動できるもの
③ポンプ
　灯油ポンプ 自動停止型 TP-20R

#プログラム
JavaScriptブロックエディタを使用して、ブロックを組み合わせてプログラミングを行いました。
![PG.JPG](https://qiita-image-store.s3.amazonaws.com/0/181708/5a707d28-d3ad-b5c1-9c0c-394dd365a783.jpeg)

コードはこちら
https://makecode.microbit.org/93760-65940-92505-53474
マイクロサービスのロギングベストプラクティス

Scalyrブログの[Microservices Logging Best Practices](https://blog.scalyr.com/2018/08/microservices-logging-best-practices/)の抄訳に、いくつか補足を加えたものです。

## 一意のIDをリクエストと関連付ける

複数のサービスの呼び出し関係をトレースできるように一意のIDをリクエストに含めます。

[ZalandoのRESTful APIガイドライン](https://restful-api-guidelines-ja.netlify.com/#183)をみると、X-Flow-IDというHTTPリクエストヘッダを付けるように規約化されています。

Microsoftにも「[マイクロサービスの設計: ログ記録と監視](https://docs.microsoft.com/ja-jp/azure/architecture/microservices/logging-monitoring)」というガイドがあります。

## 一意のIDをレスポンスに含める

レスポンスのペイロードにも一意のIDを持っておけば、問題が発生したときに、カスタマからの連絡にも即座に対応できるようになります。

Spring Cloud Sleuthは、それらのコンセプトと実装も提供しています。
https://github.com/spring-cloud/spring-cloud-sleuth

## ログを集中管理された場所に送る

すでにログに役に立つあらゆる情報が書かれてたとしても、集中管理された場所にログを送ることは大事なことです。

クラウドやコンテナ、そのハイブリッド環境の場合は、特に何の知らせもなくサーバが終了してしまうことがあるので、ログの集中管理は必須といってよいでしょう。

## 構造化ログを使う

ログのフォーマットをサービスごとに統一するのはほぼ不可能でしょう。かといって何も決めなければ、フィールドのデリミタに、カンマを使ったり、空白を使ったり、パイプ文字を使ったりとまちまちになってしまいます。

JSONのような標準的に使われる構造もったデータ形式で書いておけば、1つのログイベントにより多くのセマンティクスをもたせることができます。

Javaの場合、slf4jとlogbackを使っている場合でも、設定で構造化ログを出力することは可能です。
https://gquintana.github.io/2017/12/01/Structured-logging-with-SL-FJ-and-Logback.html
残念ながらログメッセージも、JSONにするにはアプリケーション側で、JSON化するより無さそうです…

## すべてのリクエストにコンテキストをつける

ログには問題をトレースするためのコンテキストをできるだけ追加するとよいですが、一部の情報は冗長なコードを生みがちなので、ロギングフレームワークで自動的に加えられるようにしましょう。

その一部とは、以下のようなものです。

- 日付と時刻
- エラーのスタックトレース
- サービス名
- エラーが発生した関数、クラス、ファイル名
- 外部サービスとのやりとりの名前
- サーバとクライアントのIPアドレス
- ユーザエージェント
- HTTPステータスコード

## ローカルストレージにログを書く

「ログを集中管理サーバに送る」からといって、アプリケーションのログ書き込み要求で即座に直接HTTPなどで送信してしまうと、ネットワークのアウトバウンドを圧迫し、他のマイクロサービス間の通信に影響を与えてしまうかもしれません。

AWSでは次のようにすることもできると、元記事のScalyrブログでは言っています。

![send_log.png](https://qiita-image-store.s3.amazonaws.com/0/8475/ab836a62-cb67-63fd-e00d-ba5266f40f2b.png)

何にせよ、ログを集約してフィルタリングして送信する責務は、別のプロセスやサービスにするべき、ということです。

従来のロギングフレームワークは、アプリケーションからはカテゴリをもとにLoggerを作って何のログかを指定し、ログの設定でそのカテゴリにアペンダを割り当てて、フォーマットを決めたりファイルを分けたりしていましたが、この責務がMicroservicesでは集中ログサーバにいくことになります。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/8475/3377f2ac-ec70-f1c1-928b-fdef0eda31c4.png)
StanとRでベイズ統計モデリング(アヒル本)をPythonにしてみる - 12.3 変化点検出

[実行環境](https://qiita.com/shngt/items/ce6f2c3ef348cd80f432)

### インポート

```python
import numpy as np
import pandas as pd
import pystan
import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
%matplotlib inline
```

### データ読み込み

```python
changepoint = pd.read_csv('./data/data-changepoint.txt')
```

# 12.3 変化点検出

```python
data = dict(
    T=changepoint.index.size,
    Y=changepoint['Y']
)
stanmodel = pystan.StanModel('./stan/model12-7.stan')
fit = stanmodel.sampling(data=data, pars=('mu', 's_mu', 's_Y'), seed=1234, n_jobs=-1)
```

```python
_, (ax1, ax2) = plt.subplots(1, 2, figsize=figaspect(3/8), sharex=True, sharey=True)

ax1.plot('X', 'Y', data=changepoint, color='k')
plt.setp(ax1, xlabel='Time (Second)', ylabel='Y')

ms = fit.extract()
probs = (2.5, 25, 50, 75, 97.5)
columns = ['p{}'.format(p) for p in probs]
d_est = pd.DataFrame(np.percentile(ms['mu'], probs, axis=0).T, columns=columns)
d_est['x'] = d_est.index + 1
ax2.fill_between('x', 'p2.5', 'p97.5', data=d_est, color='k', alpha=0.2)
ax2.fill_between('x', 'p25', 'p75', data=d_est, color='k', alpha=0.4)
for col in columns:
    ax2.plot('x', col, data=d_est, color='k')
ax2.plot('X', 'Y', data=changepoint, color='k', alpha=0.4)
plt.setp(ax2, xlabel='Time (Second)', ylabel='Y')

plt.show()
```
![fig12-5.png](https://qiita-image-store.s3.amazonaws.com/0/103085/e43ded11-ee5f-7917-9fec-06adf36fe77b.png)
Git— ”グローバル”のgit hooks が反映されない？ > テンプレートファイルは git init / git clone 時にコピーされる仕組み 

git config や gitignore にもカレントとグローバルの設定があるように、
git hooks などにも global な設定があるのかとぼんやり思っていたけれど、違う様子。

「テンプレートファイルがカレントレポジトリにコピーされる」という仕組みみたいだ。

## 落とし穴

- ファイルコピーは `git clone` と `git init` 時におこなわれる
  - 最初に git 管理を始める時以外に `git init` を使うという発想がなかった
- なおかつ `git init` では既に存在するファイルの上書きはおこなわれない (コピーが必要なものは、いったんファイルを削除する必要がある)
  - 例: `rm .git/hooks/pre-push`  `git init`
- git hooks はカレントレポジトリのものが使われる。(テンプレートファイルは直接使われない)
- 今思えば gitconfig に `template` とか `init` とかいう名前が付いている時点で気付いても良かった気もする


## gitconfig の例

`~/.gitconfig` には「テンプレートのディレクトリ」を指定する。

```
[init]
  templatedir = ~/.git_templates
```

## git hooks のテンプレート例

`~/.gitconfig` で指定したディレクトリに、テンプレートとしてコピーしたいファイルを作る。

ここでは試しに「どうやっても push 出来ない git hooks 」を作ってみる。

```sh
mkdir -p ~/.git_templates/hooks/

echo "echo Nobody can git push! && exit 1" > ~/.git_templates/hooks/pre-push

chmod +x ~/.git_templates/hooks/pre-push
```

ちなみに hooks/pre-push で push を止めるには exit を 0 以外で終わらせる必要があるっぽい。

## git clone の例

git clone すると、テンプレートファイルから `.git/hooks/pre-push` がレポジトリにコピーされるのが分かる。

```sh
git clone https://github.com/your/some_repository
cd some_repository
```

カレントの `.git` ディレクトリの中身を確認してみよう。

```
cat .git/hooks/pre-push
echo Nobody can git push! && exit 1
```

テンプレートファイルからコピーされているのが分かる。

## 既存レポジトリの git hooks 更新する場合

ローカルレポジトリに既に `.git/hooks/pre-push` が存在する場合は、いったん削除してから init し直せば良い。

```
rm .git/hooks/pre-push
```

```
git init
Reinitialized existing Git repository in /path/to/local/repository/.git/
```

自動での上書きはおこなわれない様子。

## 参考

### Document

>git-init - Create an empty Git repository or reinitialize an existing one
>...
>TEMPLATE DIRECTORY
>Files and directories in the template directory whose name do not start with a dot will be copied to the $GIT_DIR after it is created.

[Git - git-init Documentation](https://git-scm.com/docs/git-init)

### Qiita

- [gitでmasterへのpushを防ぐhook - Qiita](https://qiita.com/tmsanrinsha/items/e7f4d4b3ce615e32997a)
- [gitでmasterへのpushを禁止する - Qiita](https://qiita.com/ryoichi-u/items/7b20f9af6fc247a3fa99)
- [git で remote master ブランチへのプッシュを禁止する - Qiita](https://qiita.com/january108/items/05ab9e2f1d713f6efae3)

## Versions

- git version 2.17.1

## Links

- [Gist](https://gist.github.com/YumaInaura/8b482ee687832f7515f2a48db1c55130)








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Nuclide(React Native向きのエディタ環境)を始める?

# 前提
react nativeの文法を覚えるまでのサポートやデバッガ、フォーマッタなどを求めて。
atomを本格的に使ったことなかったら、ものは試しと思って始めてみた。

# atomをinstall
https://atom.io/

140MB。

# nuclideをinstall
https://nuclide.io/docs/quick-start/getting-started/

atomを開いて install package。

# vim-mode-plusをinstall
やっぱvimでしょ。

nuclideの時と同様にpreferences > install で installできる。

｢vim｣で検索すると｢vim-mode｣と｢vim-mode-plus｣が表示される。
｢vim-mode｣はDeprecatedになっているので｢vim-mode-plus｣をinstall。

# その他の推奨パッケージ
https://nuclide.io/docs/editor/setup/#post-installation

以下などは入れておくと良いだろう。

```
tool-bar to enable the Nuclide toolbar.
sort-lines to enable sorting lines of text.
language-ocaml to enable OCaml language syntax highlighting.
language-babel to enable language grammar for JS, Flow and React JS, etc.
````

更に、自分はWatchman,Flowなどinstall済みですが、
必要に応じて```npm install watchman```などしましょう。

これで準備はよいのか?

# 再起動してNuclideを始めよう?
Welcome to Nuclideが表示されないが…。
Nuclide Settingsはある、Macのtool-barにもNuclideがいる。

しかし、プロジェクトが作成出来そうな感じがしない。

Install Package > Nuclide Settings > Install Recommended Packages on Startup
ってのがあったので、チェックにしてAtomを再起動してみる。

ううむ出ない。

そして、プロジェクトが作成出来そうな感じがしない。

# NuclideでHello World
｢nuclide hello world｣
google先生に聞いてみる。

https://nuclide.io/docs/hello-world.html
内容は無いよう。

https://qiita.com/loverails/items/569aafd80889bb5d9328
_nuclideは正直言ってゴミ。（使い込まなかったが）_

｢そうか。｣

# まとめ
｢Nuclide。おまえは少し休んでいてオケ、ボクはvscodeに行く。｣
Discord Policeができるまで【後編】

前回はBOTをサーバーに招待するまでをやったので、後編はBOTを完成させる。
[前回の記事-Discord Policeができるまで【前編】](https://qiita.com/0505Keitan/items/e48496a483d16727c0c3)

# 4.権限の追加
前回のままだとBOTがメッセージを消去できないのでメッセージ管理権限を与える。

## 役職を作る
1.Discordの左上のメニューよりサーバー設定をクリックする
2.左側のメニューの`役職`をクリックする
3.真ん中らへんにある`@everyone`の右上にある+ボタンを押して、新しい役職を追加する
4.`new role`をクリックし、役職名を好きなものにする(例えばBOTなど)
5.役職の設定の下の方にある`メッセージの管理`をオンにする
6.下に出てきたセーブボタンを押して変更をセーブする

## BOTに役職を適用
1.先ほどの左側のメニューの下補の方にあるユーザー管理のメンバーをクリックする
2.招待したBOTの右側にある+ボタンから先ほど追加した役職を追加する
3.ESCキーを押してチャットに戻る。

これでメッセージを消せるようになりました。
# 5.完成
一応前編で起動してあるターミナルのコマンドを`Ctrl+c`で一旦停止させて、もう一度以下のコマンドを実行。

```console:ターミナル
$ node bot.js
```

ですが、このままだとPC上のターミナルを起動していないと動かないのでどっかのVPSか友人にサーバーを借りる。僕は幸いにも友人がサーバーを貸してくれたのでそれを使う。一応バックアップ用にConoHaのVPSも借りた。
# 6.サーバー上で実行する
ここではConoHaのVPSを使って説明する。
1.まずConoHaのサイトで会員登録をする。[ConoHa](https://www.conoha.jp/)
2.必要事項を記入し、続行
3.お支払い情報を入力。ここではプリペイドカードはチャージにしか使えない。
4.サーバーの構成を選ぶ。僕は512MBでUbuntuを選んだ。ここから先はUbuntuでのやり方を書く

とりあえずこれで一通りの準備は完了。次にファイルをアップロードしたりサーバー上で動かす設定をしていく。
## SSHでConoHaのサーバーに接続。
(※この前に色々rootとかの設定があるのですが、今回は割愛。詳しくはConoHaの公式サイトに載っています。)
ということでサーバーの準備はできたので早速サーバーの設定をしていく。
まずはsshでConoHaのサーバーにつなぐ
1.コントロールパネルの左側の`サーバー`をクリック
2.出てきた画面の真ん中らへんにあるコンソールをクリック
こうするとブラウザにコンソールが出てくるのでこれを使う
3.コンソールの`login:`のところに`root`と入力し続いてrootパスワードを入力しエンター
4.これでサーバーにログインできたので、サーバーでBOTを動かすために`node.js`と`discord.js`とforeverをインストール。
# サーバー上に色々インストール
## node.jsインストール
ではまず最初に`node.js`からいれていく。
ここからはコンソールの画面オンリーになるので上から順番に一つづつ実行してください。

```console:ウェブコンソール
$ sudo apt-get install -y nodejs npm
$ sudo npm cache clean
$ sudo npm install n -g
$ sudo n stable
$ sudo ln -sf /usr/local/bin/node /usr/bin/node
$ sudo apt-get purge -y nodejs npm
```

これで導入自体は完了しているので最新バージョンか確認

```console:ウェブコンソール
$ node -v
v10.8.0
```

これで`node.js`は導入完了
## foreverインストール
次にBOTを常時動かすために`forever`というずっと動作し続けるやつを導入。

```console:ウェブコンソール
$ sudo npm install -g forever
``` 
はい終了。これでインストールは終わったので次にファイルのアップロードをしていく。
# ファイルアップロード
ファイルアップロードはコンソールでもできるが、僕はFTPマネージャーを使った。
ではFTPマネージャーで接続をする。なおFTPマネージャーは使えれば多分なんでも可
(！注意！今回はrootで接続するため間違ってファイルを消すことがないように十分注意してください)
1.FTPマネージャーを起動し、新規接続
2.サーバーの欄にConoHaのコントロールパネルにあるIPアドレスを入力
3.ユーザ名を`root`。パスワードはルートパスワードを使う
4.接続。
接続できたらファイルがいっぱいあると思うのでメインフォルダに移動し適当なフォルダを作る
作れたらその中に作ったBOTのファイルをぶち込む

これでアップロードも終了。
# いよいよ起動
これであとはサーバー上で起動するだけになった。
それでは起動していく。
1.ConoHaに戻り、コンソールを開く
2.ログインされてなかったらログインし直す
3.さっきアップロードした場所へcdで移動
4.移動できたらそのフォルダで以下のコマンドを打つ

```console:ウェブコンソール
$ npm install discord.js
```
これで`discord.js`もインストールできたのでいよいよ実行する。

コンソールで次のコマンドを打って実行

```console:ウェブコンソール
$ forever start bot.js
```

これで全てが終了。
もう一度Discordサーバーに戻ってきちんと動いているか確認して、動いていたら完成！

# おまけ
一応foreverを止めたりする時用のコマンドも紹介しておく
・動いているBOTリストを表示させる

```console:コンソール
$ forever list
```

・BOTを止める

```console:コンソール
$ forever stop 【uid】
```

なお`uid`はリストから参照可能
Eclipse、Spring Boot の JDK 11 サポート予定の計画

# はじめに
ググっても全然出てこなかった。そして2,3回調べて毎回時間掛かっているので自分用メモ。
間違っていたらご指摘くれると嬉しいです。

# 対応予定 ~~(2018/08/21時点)~~ (2018/10/30時点)

| ソフトウェア/バージョン | 正式版(Stable)リリース時期 |状況|
|:------------|-------------------------:| :---:|
|Eclipse/4.9       |2018/09/19  |リリース済|
|Spring Boot/2.1.0 |2018/10/30 | リリース済み|
|OpenJDK/11        |2018/09/25|リリース済|

Spring Bootは、2.0.Xでも、1.5.Xでも、OpenJDK11では動きそう。(というより動いた)

OpenJDK11 + Alpineはオフィシャルではまだ未提供。
https://github.com/docker-library/openjdk/issues/211
でも…EAのdownloadリポジトリにあるbuild28と一緒だから現状はそれを使っていれば問題ないはず。
参考:https://github.com/h-r-k-matsumoto/alpine-openjdk-11/blob/master/Dockerfile

私と同じように、できれば小さいdockerイメージを作りたい。alpine使いたい (というよりも、Ubuntu嫌 )
と思っている方は、 `AdoptOpenJDK` の方が良いかもしれないです。

https://github.com/AdoptOpenJDK/openjdk-docker#openjdk-and-docker

> Dockerfiles and build scripts for generating various Docker Images related to OpenJDK. Currently this builds > OpenJDK images with hotspot and Eclipse OpenJ9 on Ubuntu and Alpine Linux.

IBMのRedHat買収問題がありますが、まぁ…気にしなくて良いでしょう。

**Docker Hub**
https://hub.docker.com/r/adoptopenjdk/openjdk11/tags/


# Eclipse 
Eclipse 4.9として提供される。
https://projects.eclipse.org/projects/eclipse/releases/4.9.0/plan
そこからリンクされていくJDT_Coreの対応を見て確認。
https://wiki.eclipse.org/JDT_Core/Plan/4.9

Eclipse 4.9で使うには、market placeからjava-11-supportのplugin を入れないと、コンパイル互換性のところに `11` が出てこないです。
https://www.eclipse.org/lists/jdt-dev/msg01049.html

![image.png](https://qiita-image-store.s3.amazonaws.com/0/268550/1c9b8d07-d8f0-02e1-52dd-61a05226d27f.png)



# Spring Boot

無事リリースされました。
https://spring.io/blog/2018/10/30/spring-boot-2-1-0

でも、↓のマイルストーンはちょいちょい見た方が良いかもです。問題解決のお役に立ちます。
https://github.com/spring-projects/spring-boot/milestone/125
https://github.com/spring-projects/spring-boot/milestone/106


# OpenJDK
http://openjdk.java.net/projects/jdk/11/
Chrome拡張「Puppeteer Recorder」を使って簡単にブラウザの自動操作を行う

[Puppeteer Recorder](https://chrome.google.com/webstore/detail/puppeteer-recorder/djeegiggegleadkkbgopoonhjimgehda)というChrome拡張がリリースされたので試しに使ってみました。

GitHub: [checkly/puppeteer-recorder](https://github.com/checkly/puppeteer-recorder)

## 概要

Puppeteer Recorderは、ブラウザで行った操作を記録してPuppeteerのコードを出力してくれるChrome拡張です。

似たようなChromeの拡張に[Selenium IDE](https://chrome.google.com/webstore/detail/selenium-ide/mooikfkahbdckldjjndioackbalphokd)があったりします。

## 使い方

READMEの画像にあるように、拡張機能を入れて「Record」をクリック、その後試したい操作をしてから「Stop」をクリックするとコードが出力されます。

![](https://raw.githubusercontent.com/checkly/puppeteer-recorder/master/src/images/recorder.png)


## 実際に使ってみた感想

すでに使ってみた感想を書いてくれている記事（[「Puppeteer Recorder」を試してみた - masalibの日記](https://masalib.hatenablog.com/entry/2018/08/17/105841)）がありますが、自分もだいたいこの記事と感想は同じでまだ不安定なところがあるな、という印象です。

例えば文字入力のイベントが取得されにくかったりします。これは、[README](https://github.com/checkly/puppeteer-recorder/blob/master/README.md)にもあるように入力後に`tab`を叩く必要があります（READMEの[Usage](https://github.com/checkly/puppeteer-recorder/blob/master/README.md#usage)に `Hit tab after you finish typing in an input element.` とある）。

これ以外にも若干意図した動作が記録されないことがありましたが、まぁリリースされたばかりなので仕方ないかな、と思います。

## さいごに

Puppeteerは使い勝手が良いので、この調子で周辺ツールが豊富になってくると嬉しいですね。

ちなみに余談ですが、Puppeteer Recorderは[Vue.js](https://jp.vuejs.org/index.html)で書かれています。ちょっとしたポップアップを作るには、やはりVueくらいの手軽さが優れていそうですね。
Unreal Engine 4メモ：タイマを使って簡単に非同期処理

演出などで、タイミングをちょっとだけ調整したい時等に、
コードはシーケンシャルに書けると言う利点があります。

```c++:TimerSample.cpp
// 1秒待つ
TFunction<void(void)> fp = []() {
	// 1秒後に実行したい、非同期処理
};
GetWorld()->GetTimerManager().SetTimer(RemoveTimerHandle, (TFunction<void(void)>&&)fp, 1.0f, false, -1.0f);
```
Android 8.0以降でNode.jsのrequire('os').cpus()が未定義エラー

こんにちわ。

先日、新しいAndroid端末を購入したので、とりあえずTermuxとNode.jsを入れたのですが、思わぬ壁が大きく立ちはだかる事となってしまいました。


# 概要
表題の通りですが、Android8.0でNode.jsの`require('os').cpus()`を走らせると`undefined`が返ってきます。

確認端末は[GALAXY S9+(SM-G9650)](https://www.phonemore.com/samsung-galaxy-s9-plus-sm-g9650/specs/3892)です。


# 原因
Android8.0から、`/proc/`配下の各仮想ファイルへのアクセスが大きく制限されてしまった事によります。

`cpus()`は`/proc/stat`を参照しますが、これがアクセス禁止対象となってしまったのです。

ちなみに、`/proc/cpuinfo`などは従来通り参照可能です。

Google曰く
>`/proc/stat`は別アプリケーションの稼働状態を推測可能にし、すなわちサイドチャネル攻撃の危険性がある為、アクセス禁止にした(意訳)

との事です。


# 弊害
まず`npm`コマンドが使えません。
内部で`cpus().length`が使われている為、異常終了してしまいます。

つまり、`npm install`さえ出来ないのです。

他モジュールについても、`cpus()`を使う物に関しては全滅です。

色々と致命的です。

# 対処方法(暫定)
`npm`コマンド禁止縛りは流石にお話にならないので、かなり強引ですが暫定処置があります。

```javascript:/data/data/com.termux/files/usr/lib/node_modules/npm/node_modules/worker-farm/lib/farm.js
// before
maxConcurrentWorkers: require('os').cpus().length

// after
maxConcurrentWorkers: 8 // CPUコア数で決め打ち(SDM845は8コア)
```
幸い`npm`内部で`cpus()`を使う場所はここだけなので、手っ取り早くハードコードしてしまいます。

```javascript
const execSync = require("child_process").execSync;

require("os").cpus = ()=>{
    return execSync("grep Hardware /proc/cpuinfo | sed -r -e \"s|^.*?: ||\"").toString();
}

require("os").cpus().length = Number(execSync("grep processor /proc/cpuinfo | wc -l").toString());
```
`cpus().length`は使用頻度が高い為、`/proc/cpuinfo`からコア数を抽出して、標準APIに上書きする事も可能です。

# おわりに
根本解決するには、Termux向けNode.jsのビルド時に別ファイルを参照するよう改変するか、端末をroot化するかの2択です。

上述にもある通り、Android8.0はセキュリティが大幅強化された為、root化は無茶苦茶しんどい上に、ファームウェアバージョン等の条件もかなり限定されます。
(SM-G9650のroot化も途中で断念しました)

そんなこんなで、根本解決は現状ほぼ不可能という、悲しい事実。

自由度の高さがウリだったAndroidも、だんだん林檎化が進んでいるように感じ、少し寂しく思います。

# 参考
- https://github.com/termux/termux-packages/issues/1798
- https://github.com/termux/termux-app/issues/299
pythonのioオブジェクトをtypingする

# TL;DR
Pythonのイマドキの書き方では、関数の引数および返り値の型を明示的に記載して書くことが多いと思う。
自分で作ったクラスや、よく使う型については問題ないんだが、IOに関連するオブジェクトのタイピングに戸惑った。
（教養のある人はたぶん、普通にわかる問題かもしれません）

※8/23 Union部分を修正しました

# 問題 
今回、面倒な気分になったのは以下の場面です。

```python:example.py
def func(fp):
    """
    Args:
        fp: file path 

    Returns:
        opened object
    """
    return open(fp, 'r')
```

要は、ファイルパスを渡して、開いたファイルを返すみたいなケース。

これの返り値の型指定に戸惑った。。。

# 結果
解決策はこういう感じ

```python:sol.py
from typing import Union, IO
import os

def func(fp: Union[str, bytes, os.PathLike]) -> IO:
    """
    Args:
        fp (str, bytes or os.PathLike object) : File Path 

    Returns:
        IO
    """
    return open(fp, 'r')
```

[typing](https://docs.python.jp/3/library/typing.html#typing.io)のIOがTextIOを包括してくれるようでした。
Typingのドキュメントちゃんと読んでおけばもっと楽だったかもしれません。


# 詰まったところ
ちょっと戯れにストーリー仕立てにしてみます。
## openの返り値わからない問題
> わたし：
まあPythonがtyping出してるくらいやし、普通にOpen見たら型とか全部わかるやろ。
...（しばらくの間）
あれ？

---

[python公式](https://docs.python.jp/3/library/functions.html#open)でとりあえず確認してみようと思い、見て見たらなんと、返り値の型の記載がないのです笑

まあ、厳密に言えば、下の方に
>file を開き、対応する ファイルオブジェクト を返します。ファイルを開くことができなければ、OSError が送出されます。

とあるので、ファイルオブジェクトに飛ぶと

> ファイルオブジェクトには実際には 3 種類あります: 生の バイナリーファイル、バッファされた バイナリーファイル、そして テキストファイル です。インターフェイスは io モジュールで定義されています。ファイルオブジェクトを作る標準的な方法は open() 関数を使うことです。

インターフェースはioで書かれているらしい。
バッファ付きでファイルロードとかその辺の話はJavaとかを思い出します。。。

## ioから型をとってきたけど、Pycharmが許してくれない問題

> わたし: 
O...OK。わかったIOで見てみようじゃないか。
...
どれやねん...

---
[ioモジュール](https://docs.python.jp/3/library/io.html#module-io)を見ると、

> I/O には主に3つの種類があります; テキスト I/O, バイナリ I/O, raw I/O です。

ほ、ほう。。。
じゃあ、openの方にはなんかかいてあったっけ？

> open() 関数が返す file object の型はモードに依存します。 open() をファイルをテキストモード ('w', 'r', 'wt', 'rt', など) で開くのに使ったときは io.TextIOBase (特に io.TextIOWrapper) のサブクラスを返します。 ファイルをバッファリング付きのバイナリモードで開くのに使ったときは io.BufferedIOBase のサブクラスを返します。 実際のクラスは様々です。 読み込みバイナリモードでは io.BufferedReader を返します。 書き込みバイナリモードや追記バイナリモードでは io.BufferedWriter を返します。 読み書きモードでは io.BufferedRandom を返します。 バッファリングが無効なときはrawストリーム、すなわち io.RawIOBase のサブクラスである io.FileIO を返します。

えっ...（絶句）
これを書くのはめんどい。。。

じゃあ、とりあえず今開いてるファイルの型に合わせてtypingするか

```python:
>>> type(open(fp, 'r'))
<class '_io.TextIOWrapper'>
```

OK、じゃあ、[io.TextIOWrapper](https://docs.python.jp/3/library/io.html#io.TextIOWrapper)をとってくればいいんやな。

```python: 
from io import TextIOWrapper
from typing import Union
import os

def func(fp: Union[str, bytes, os.PathLike]) -> TextIOWrapper:
    """
    Args:
        fp (str, bytes or os.PathLike) : file path 

    Returns:
        opened object
    """
    return open(fp, 'r')
```

これを書いたら、pycharmが
> TextIOWrapperが期待されてるけど、返ってくるのTextIOだよ

と教えてくれました笑
TextIOってのはioモジュールの中にはなく、あるのはTextIOWrapperかTextIOBase。。。
そんなこんなでtypingに戻ってみたら見つかるという流れでした

# おわりに
pythonの公式ドキュメントはあんまりちゃんと読んでいないのが致命的でした笑
typingするとコードを受け取った人がすごく読みやすい（例えばOpenCVのC++部分とか読みやすい）し、APIとしても使いやすくなるので僕としては積極的に使っていきたいと思っています。
StanとRでベイズ統計モデリング(アヒル本)をPythonにしてみる - 12.2-季節調整項

[実行環境](https://qiita.com/shngt/items/ce6f2c3ef348cd80f432)

### インポート

```python
import numpy as np
import pandas as pd
import pystan
import matplotlib.pyplot as plt
from matplotlib.figure import figaspect
%matplotlib inline
```

### データ読み込み

```python
ss2 = pd.read_csv('./data/data-ss2.txt')
```

# 12.2 季節調整項
## 12.2.3 Stanで実装

```python
data = dict(
    T=ss2.index.size,
    Y=ss2['Y']
)
stanmodel = pystan.StanModel('./stan/model12-6.stan')
fit = stanmodel.sampling(data=data, iter=4000, thin=5, seed=1234)
stanmodel_b = pystan.StanModel('./stan/model12-6b.stan')
fit_b = stanmodel_b.sampling(data=data, pars=('mu', 'season', 's_mu', 's_season', 's_Y', 'y_mean'), iter=4000, thin=5, seed=1234)
```

## 12.2.4 推定結果の解釈

```python
ms = fit.extract()

probs  = (10, 25, 50, 75, 90)
_, (ax1, ax2) = plt.subplots(1, 2, figsize=figaspect(3/8), sharex=True)

d_est = pd.DataFrame(np.percentile(ms['mu'], probs, axis=0).T, columns=['p{}'.format(p) for p in probs])
d_est['x'] = d_est.index + 1
ax1.plot('X', 'Y', 'o-', data=ss2, color='k')
ax1.plot('x', 'p50', data=d_est, color='k')
ax1.fill_between('x', 'p10', 'p90', data=d_est, color='k', alpha=0.2)
ax1.fill_between('x', 'p25', 'p75', data=d_est, color='k', alpha=0.4)
plt.setp(ax1, xlabel='Time (Quarter)', ylabel='Y', xlim=(1, 44))

d_est = pd.DataFrame(np.percentile(ms['season'], probs, axis=0).T, columns=['p{}'.format(p) for p in probs])
d_est['x'] = d_est.index + 1
ax2.plot('x', 'p50', data=d_est, color='k')
ax2.fill_between('x', 'p10', 'p90', data=d_est, color='k', alpha=0.2)
ax2.fill_between('x', 'p25', 'p75', data=d_est, color='k', alpha=0.4)
plt.setp(ax2, xlabel='Time (Quarter)', ylabel='Y', xlim=(1, 44))

plt.show()
```
![fig12-4.png](https://qiita-image-store.s3.amazonaws.com/0/103085/03af6940-2423-0fda-4f65-f16ea5ef522b.png)
Nefry(ESP32)をBlynkでスマホから遠隔操作【メモ】

# Blynkとは
iOSやAndroidで動作するBlynkというアプリ
Blynkを使えばArduinoやRaspberrypiをアプリから操作できます。
Nefryに関する詳細
https://dotstud.io/docs/nefrybt/

##BlynkとArduino側の連携
本ページではNefry-Blynk連携での注意点を記載します。
Blynk自体の詳細な初期設定は以下URLを参照して下さい。
http://jh1lhv.hatenablog.jp/entry/2015/05/25/215552

#Nefry側の設定
LED x 3個をNefryからON/OFF操作します。
NefryのD0,D1,D2ピンとLED(+330Ω抵抗)を連結します。
![IMG_2348.jpg](https://qiita-image-store.s3.amazonaws.com/0/259333/007eb2b9-5f8a-0b01-9b6c-0f34794bd9fc.jpeg)

この時、Blynk側のピン設定に注意が必要です。
NefryピンD0,1,2,,,をNefryが基にしているESP32のピンに対応させる必要があります。
![NefryBTr2_r3_pinmap.png](https://qiita-image-store.s3.amazonaws.com/0/259333/f657b086-7586-cb13-055e-0c434a14ad19.png)
上図を基にピンを設定していきます。
[Nefry]D0→[Blynk]Digital GP22
[Nefry]D1→[Blynk]Digital GP21
[Nefry]D2→[Blynk]Digital GP23
![ui.png](https://qiita-image-store.s3.amazonaws.com/0/259333/cde962a3-77f3-1781-ff93-68cc5a0c8a0f.png)

<br>

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">Blynkというアプリを使ってスマホからNefryを操作してみました。スマホから遠隔操作はやっぱり楽しい。<br>参考:<a href="https://t.co/HJpGrHiEft">https://t.co/HJpGrHiEft</a> …<br>Nefryピンと基にしてるESP-32のピンの対応が多少面倒。→<a href="https://t.co/ZnQMq4K2p8">https://t.co/ZnQMq4K2p8</a> Virtual Pinとの対応はまだよく分かってません<a href="https://twitter.com/hashtag/Arduino?src=hash&amp;ref_src=twsrc%5Etfw">#Arduino</a> <a href="https://twitter.com/hashtag/%E9%9B%BB%E5%AD%90%E5%B7%A5%E4%BD%9C?src=hash&amp;ref_src=twsrc%5Etfw">#電子工作</a> <a href="https://twitter.com/hashtag/Blynk?src=hash&amp;ref_src=twsrc%5Etfw">#Blynk</a> <a href="https://t.co/luS2hRYze0">pic.twitter.com/luS2hRYze0</a></p>&mdash; ミノワケイタ (@3nowa) <a href="https://twitter.com/3nowa/status/1028850939602456576?ref_src=twsrc%5Etfw">2018年8月13日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

twitterで言っているVirtual Pinがわからないの詳細説明が以下になります。
Blynk:Vertual Pin 説明ドキュメント
http://docs.blynk.cc/#blynk-firmware-virtual-pins-control
PowerShellでファイル名一括置換

# 基本的な使い方

```
ls | Rename-Item -NewName { $_.Name -replace '置換対象文字列','置換後文字列'}
```

# 例

```
> ls

HOGE1.txt
HOGE2.txt
HOGE3.txt
```
とあった場合、HOGEをFUGAにしたいときは下記のようにする。

```
> ls | Rename-Item -NewName { $_.Name -replace 'HOGE(.*)','FUGA$1'}

FUGA1.txt
FUGA2.txt
FUGA3.txt
```

ファイル名にカッコが含まれる場合、「\」でエスケープ。

```
HOGE1(12345).txt
HOGE2(23456).txt
HOGE3(34567).txt
```

```
> ls | Rename-Item -NewName { $_.Name -replace '\(.*\)',''}

HOGE1.txt
HOGE2.txt
HOGE3.txt
```
AIの勉強メモ

#趣旨
本格的に機械学習を勉強開始:relaxed:
そのために使っている本や見つけた良いサイトなどを都度メモしていく。

##AIを学ぶためには
SkillUp AIさん主催の入門セミナーに行ってわかったのは、
やっぱり数学必要だという事。
・微積分、線形代数、確率統計、etc...
![Screenshot_2018-08-27 スキルアップAI ディープラーニング研修.png](https://qiita-image-store.s3.amazonaws.com/0/270579/a50f2bbb-48d2-d1dc-a9f1-3b5e1899fb6f.png)

まー、そりゃあそうだよねぇ。
機械学習させるにあたってのパラメータ調整とか、数学知識ないと手探りになるだろうし。

プログラミング言語は、PythonかRだけど、時代の潮流はPythonにあるとの事。

##書籍
- [ゼロから作るDeep Learning](https://www.oreilly.co.jp/books/9784873117584/) 2018/8/21～ 70Pくらい
- [ゼロから作るDeep Learning ❷――自然言語処理編](https://www.oreilly.co.jp/books/9784873118369/)

- [星空の見方がわかる本](https://hon.gakken.jp/book/1340657400)
- [こよみハンドブック(2018年4月-2020年4月版)](http://www.sci-museum.jp/shop/)

##サイト
やる夫シリーズ[^1]大好きなのでめちゃわかりやすい！

[やる夫で学ぶディジタル信号処理](http://www.ic.is.tohoku.ac.jp/~swk/lecture/yaruodsp/main.html)
[やる夫で学ぶ機械学習シリーズ](http://tkengo.github.io/blog/2016/06/06/yaruo-machine-learning0/)

学びなおし数学

[sci-pursuit.com](https://sci-pursuit.com/index.html) 基礎数学の学びなおしに最強なのでは…？
[微分とは何か？ － 中学生でも分かる微分のイメージ](https://sci-pursuit.com/math/differential-1.html)

※数学系サイトは上記お勧めを含め、途中式とかちょいちょい記載ミスがある。
　途中で疑問を感じたら、複数サイトから情報を収集するか、文責が伴う書籍を利用する事。

##なぜAIを勉強するのか

###ビジョン
ゆめみちゃん[^2]を作りだす！

###具体的に
日本語をうまく処理できる、自然言語処理AIを作る。
主語なしでも意図を推測したり、読み取ったりとか。

###学ぶスキル
- 機械学習
- 数学(分析等に用いるため)
- 自然言語処理
- 心理学、行動学
- 天文学

##さいごに
お勧めあればぜひ教えてください:blush:

[^1]: 特にやらない夫がお気に入り
[^2]: 劇場版planetarianをAmazonPrimeで見て火が点いた
【Xcode】PlaygroundでUIKitのimportエラーになったときの対応方法

PlaygroundでUIKitをimportしようとすると、つぎのようなエラーがでました。

> Playground execution failed:
>
> error: MyPlayground.playground:3:8: error: no such module 'UIKit'
> import UIKit

どこかに設定があるのかと思って調べてみたら、ユーティリティエリアのファイルインスペクターにありました！

<img width="261" alt="スクリーンショット 2018-08-21 11.12.09.png" src="https://qiita-image-store.s3.amazonaws.com/0/38924/125b6f3b-64b9-25d3-c035-9e4e30d5ea96.png">


Playground SettingsにPlatformの選択があって、そこがmacOSになっていました（初期値はmacOS？→初期値の話を下に追記しました）。

<img width="258" alt="スクリーンショット 2018-08-21 11.14.27.png" src="https://qiita-image-store.s3.amazonaws.com/0/38924/e19164da-fd80-cd1e-703e-f4d489130791.png">


この設定をiOSに変更すると、無事にエラーが解消されて、UIKitの機能を使えるようになりました。
めでたしめでたし。

## 追記
[AnzNetJp](https://qiita.com/AnzNetJp)さんにコメントで「Playground作るときに選べるよ」と教えていただきました。ありがとうございます！

![003.png](https://qiita-image-store.s3.amazonaws.com/0/38924/69e164d5-e721-d853-c4fa-a14bb238b7bc.png)

というわけで、Playground作成画面を確認したら、ここにiOS・tvOS・macOSの選択がありました。
いままでまったく気がついてませんでした😅

次回からは、しっかりiOSを選択して、バッチリUIKitもimportできます。
よかったよかった。
SEQUENCE のリセット機能を試す（Oracle Database 18c）

Oracle Database 18c の新機能である SEQUENCE のリセット機能を試してみました。

# SEQUENCE オブジェクト
SEQUENCE オブジェクト（日本語マニュアルでは「順序」）は、一意な数値を生成するスキーマ・オブジェクトです。CREATE SEQUENCE 文を使って作成します（作成には CREATE SEQUENCE システム権限が必要です）。
初期値、増分、上限、数値を再利用するか等の属性を持ちます。新しい数値を生成するには NEXTVAL 疑似列を指定します。現在の値を確認するには CURRVAL 疑似列を指定します。
 下記の例は 100 から初めて 2 ずつ増加させる SEQUENCE を作成して、値を取得しています。

```

SQL> CREATE SEQUENCE seq1 START WITH 100 INCREMENT BY 2;

Sequence created.

SQL> SELECT seq1.NEXTVAL FROM DUAL;

   NEXTVAL
----------
       100

SQL> SELECT seq1.NEXTVAL FROM DUAL;

   NEXTVAL
----------
       102

SQL> SELECT seq1.CURRVAL FROM DUAL;

   CURRVAL
----------
       102
```

# 値のリセット
　これまでのバージョンでは、SEQUENCE の生成した値を初期値に戻すことはできず、削除と再作成が必要でした。Oracle Database 18c では、ALTER SEQUENCE RESTART 文を実行することで、SEQUENCE の値を初期値まで戻すことができるようになりました。
　不便なことに ALTER SEQUENCE RESTART 文は、作成時に実行した CREATE SEQUENCE 文の START WITH 句を無視します。このため、単純に RESTART 句を指定するだけだと START WITH 句のデフォルト値 1 から値が開始されます。開始数値を変更したい場合は ALTER SEQUENCE 文に RESTART 句と START WITH 句を両方指定する必要があります。

```
SQL> SELECT seq1.NEXTVAL FROM DUAL;

   NEXTVAL
----------
       104

SQL> ALTER SEQUENCE seq1 RESTART;

Sequence altered.

SQL> SELECT seq1.NEXTVAL FROM DUAL;

   NEXTVAL
----------
         1

SQL> ALTER SEQUENCE seq1 RESTART　START WITH 100;

Sequence altered.

SQL> SELECT seq1.NEXTVAL FROM DUAL;

   NEXTVAL
----------
       100

```

# マニュアル上の記載
 実はこの新機能は、マニュアル [SQL言語リファレンス] (https://docs.oracle.com/cd/E96517_01/sqlrf/ALTER-SEQUENCE.html#GUID-A6468B63-E7C9-4EF0-B048-82FE2449B26D "SQL言語リファレンス") には構文が記載されていません （2018年8月21日現在）。
 SEQUENCE の値を戻す方法については、以下のように記載されています。

 日本語版マニュアル
 > 異なる順序番号で再開する場合、順序を削除して再作成する必要があります。

 英語版マニュアル
 > To restart the sequence at a different number, you must drop and re-create it.

 しかし、別のマニュアル「データベース管理者ガイド」には、新機能として記載されていますし、[実行例] (https://docs.oracle.com/cd/E96517_01/admin/managing-views-sequences-and-synonyms.html#GUID-5ABC0615-BE0C-48CE-BD18-C86AAF7DF953) も「24.23 順序の変更」に記載されています。修正されることを望みます。
lottie-android導入時にExecution failed for task ':app:transformClassesWithMultidexlistForDevDebug'

## Lottie
*Render After Effects animations natively on Android and iOS, Web, and React Native http://airbnb.io/lottie/*

LottieはAirbnbが提供するアニメーション表示用のライブラリです。After Effectsで作成したアニメーションをネイティブアプリで表示することができます。
https://github.com/airbnb/lottie-android

## `Execution failed for task ':app:transformClassesWithMultidexlistForDevDebug'`
`com.airbnb.android:lottie:2.6.0-beta19`導入時に発生しました。Projectのライブラリ依存状態によって起きる場合と起きない場合があります。

## 解決策
Lottie内の`com.android.support:appcompat-v7`をexculueして解決しました。

### 1. `./gradlew app:dependencies`でライブラリの依存関係を調査
Lottie配下に`com.android.support:appcompat-v7`があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/38442/27bbbc05-3680-1f44-ae31-dfe3ef9792b3.png)

### 2. ライブラリをexculdeする
`app/build.gradle`に記載するlottie-androidを下記のように書き換えます。

```gradle
implementation('com.airbnb.android:lottie:2.6.0-beta19', {
    exclude group: 'com.android.support', module: 'appcompat-v7'
})
```

## 参考
- https://qiita.com/Capotasto/items/ad1824722da7c3d9da97
IP アドレスを変換

[元ネタ](https://programamemo2.blogspot.com/2007/11/intip-ipint.html)
[元ネタ2](http://www.geekpage.jp/programming/linux-network/gethostbyname.php)

# IP を int に

```
static int toInt(int b0, int b1, int b2, int b3){
    int l = b0 << 24;
    l += b1 << 16;
    l += b2 << 8;
    l += b3;
    return l;
}
```

# int を IP に

```
static void printIPAddress(int i){
    int b0 = (i >> 24) & 0xff;
    int b1 = (i >> 16) & 0xff;
    int b2 = (i >> 8) & 0xff;
    int b3 = i & 0xff;
    System.out.printf("%d.%d.%d.%d%n", b0, b1, b2, b3);
}
```
# サンプルコード

``` sample.c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>

int
main(int argc, char *argv[])
{
 struct sockaddr_in server;
 int sock;
 char buf[32];
 char *deststr;
 int n;

 if (argc != 2) {
         printf("Usage : %s dest\n", argv[0]);
         return 1;
 }
 deststr = argv[1];

 sock = socket(AF_INET, SOCK_STREAM, 0);

 server.sin_family = AF_INET;
 server.sin_port = htons(12345);

 server.sin_addr.s_addr = inet_addr(deststr);
 if (server.sin_addr.s_addr == 0xffffffff) {
         struct hostent *host;

         host = gethostbyname(deststr);
         if (host == NULL) {
                 return 1;
         }
/*
         server.sin_addr.s_addr =
             *(unsigned int *)host->h_addr_list[0];
*/
         printf("%d\n", *(unsigned int *)host->h_addr_list[0]);
         printf("%d\n", *(unsigned int *)host->h_addr_list[1]);

         int i = 0;
         for(i = 0; i < 2; i++) {
          int ip1 = *(unsigned int *)host->h_addr_list[i];
          int b0 = (ip1 >> 24) & 0xff;
          int b1 = (ip1 >> 16) & 0xff;
          int b2 = (ip1 >> 8) & 0xff;
          int b3 = ip1 & 0xff;
          printf("%d.%d.%d.%d\n", b0, b1, b2, b3);
         }
 }
}
```

host.conf の multi on の確認に
Gem を使わずにデコレータを作る

# はじめに

Rails にはデコレータを作るための代表的な Gem として [Draper](https://github.com/drapergem/draper) や [ActiveDecorator](https://github.com/amatsuda/active_decorator) があります。これらの Gem は Rails のモデルオブジェクトを View に特化したオブジェクトにデコレートすることを目的としています。これらは便利ですが、Rails の View 以外、あるいは Rails 以外で使うには、より汎用的な仕組みがほしいです。

実は Ruby の標準ライブラリにそのような仕組みが存在します。それが [SimpleDelegator](https://docs.ruby-lang.org/ja/latest/class/SimpleDelegator.html) です。今回はこの SimpleDelegator を使ってデコレータを作ってみます。

# 例

SimpleDelegator を使ってデコレータクラスを作る方法は、SimpleDelegator を継承したクラスを用意するだけです。

```rb
class GirlDecorator < SimpleDelegator
  def full_name
    "#{last_name} #{first_name}"
  end
end
```

```rb
class Girl
  attr_reader :last_name, :first_name
  
  def initialize(last_name, first_name)
    @last_name = last_name
    @first_name = first_name
  end
end

girl = Girl.new('中川', '夏紀')

decorated_girl = GirlDecorator.new(girl)
decorated_girl.full_name #=> "中川 夏紀"
```

# おまけ

次のようなモジュールを定義すると便利かもしれません (クラス間の結合度は上がりますが) 。

```rb
# クラス名 + Decorator という名前のデコレータクラスを定義していることが前提。
module Decoratable
  # Draper の API を真似て
  # デコレートされたオブジェクトを返すインスタンスメソッドを定義する。
  def decorate
    # Active Support を使っている場合は
    # Object.const_get の代わりに "#{self.class}Decorator".constantize で OK。
    decorator_class = Object.const_get("#{self.class}Decorator")
    decorator_class.new(self)
  end
end
```

```rb
class Girl
  include Decoratable
  
  attr_reader :last_name, :first_name
  
  def initialize(last_name, first_name)
    @last_name = last_name
    @first_name = first_name
  end
end

girl = Girl.new('中川', '夏紀')

decorated_girl = girl.decorate
decorated_girl.full_name #=> "中川 夏紀"
```
LPICとLinucの関係調べたのでできる限り中立にメモ

#結論
よくある「お家騒動」。
現状（2018年8月時点）ではどっち受けても変わらなさそう


#ポイント
もともと、LPI-JapanがLPICの日本代理店だったが、いざこざで分裂。
夏からLPI本部が「LPIC日本支部」（LPI-Japanとは別組織）を立ち上げた。
「LPICが廃止された（Linucに移行した）」わけじゃなく、「団体が分裂した影響で、資格が2つになった」と認識すべし。

#所管
LPI-Japan（元LPI代理店）：Linuc
LPIC日本支部：LPIC


#時系列
- LPI-Japan ( Linuc )
2018初春にLinucを新資格を立ち上げ
2018夏までLPIC有資格者はLinucを無料で取得できる移行措置を実施
しばらくはLPICとほぼ同等範囲の受験範囲（フェーズ1）
2019に”日本市場に特化した（売り文句）”テストとしてリニューアル予定（フェーズ2）
2018年8月にLPI本部とのDB接続を切断される
（…むしろ何で半年くらい繋がってたの？）

- LPI日本支部 ( LPIC )
2018年6月に日本支部を立ち上げ。
2018夏から新LPICの認定を開始。（2018年7月に新LPICのβテスト）

#協賛企業
- LPI-Japan ( Linuc )
参考URL：http://www.lpi.or.jp/sponsor/list/
富士通
日立
NEC
Citrix
サイバートラスト
他

- LPI日本支部 ( LPIC )
参考URL：http://www.lpi.org/ja/
IBM
SUSE
CISCO
LINUX international
PEASON
intel
オライリー
Linuxマガジン
他


#感想
お家騒動で分割するのは別に（どうでも）いいんだけど、さもLPICが廃止されてLinucに移行するかのような報道はやめて欲しいですね。
どんだけ金積まれてるかわからんですがEvilすぎやしませんか
Capybaraと仲良くなる（タブ・ウィンドウの操作について）

## 別タブで開いた画面をテストする
※ここではタブ≒ウィンドウのニュアンス

### 別タブをスコープにして操作する方法
テスト実行しているカレントはそのままに別タブをスコープとして操作できる。
この方法だとテスト対象とするタブをスコープとして操作しているのでタブ間を行ったり来たりする操作、別タブを操作して元のウィンドウに戻る操作のときに対象がわかりやすい。

```ruby
click_on '別タブでページを開く'

# 最後に開いたタブを指定している
handle = page.driver.browser.window_handles.last
page.driver.browser.within_window(handle) do
  expect(page).to have_content('この文字列が見つかるかな？')

  click_on 'モーダルを開く'
  expect(page).to have_content('別タブ内のモーダルなどの操作もできる')
  click_on 'モーダルを閉じる'
end
```

```ruby
click_on '別タブでページを開く'

# 最後に開いたタブを指定している
within_window(windows.last) do
  expect(page).to have_content('この文字列が見つかるかな？')

  click_on 'モーダルを開く'
  expect(page).to have_content('別タブ内のモーダルなどの操作もできる')
  click_on 'モーダルを閉じる'
end
```

### 別タブに移動して操作する方法
テスト実行しているカレントも別タブに移動して操作する。
なので元々操作していた画面をテストするにはタブ移動するかスコープ定義する必要がある。
行ったり来たりするテストを書くとどの画面をテストしているのかの可読性が低くなりそう😑

```ruby
click_on '別タブでページを開く'

# 最後に開いたタブに移動している
switch_to_window(windows.last)
expect(page).to have_content('この文字列が見つかるかな？')

click_on 'モーダルを開く'
expect(page).to have_content('別タブ内のモーダルなどの操作もできる')
click_on 'モーダルを閉じる'
```

## アラートウィンドウを操作する
テストではアラートウィンドウを表示・操作するケースもあります。
そんなときは下記のように操作します。

```ruby
# OK操作
page.driver.browser.switch_to.alert.accept

# キャンセル操作
page.driver.browser.switch_to.alert.dismiss
```

## 画面サイズを指定する
自分が知っているのは以下の2パターン。
driverの違いがまだ理解できていない。。。😇

```ruby
width = 400
height = 800
Capybara.current_session.driver.browser.manage.window.resize_to(width, height)
```

```ruby
width = 400
height = 800
Capybara.page.driver.resize(width, height)
```