OmniAICreator/Qiita-1.07M huggingface dataset:
Rails あいまい検索機能　LIKE句

#はじめに
今回はあいまい検索(ぴったり文字があっていなくても検索結果でますよ)のやり方を書いていきます:man_tone2::man_tone2:
参考程度にどうぞ〜。今回はProductテーブルにある商品名の検索をしていきます。
読んだらいいねいただけると嬉しいです！！！モチベになります！！！！

#検索フォーム
まずは検索のフォームを作成しましょう。
場所はどこでもよいです。どのコントローラーのどのアクションでも良いです。
入力した文字列をsearchというネームでsearches#indexに送信しています。

```ruby:form.html.haml
.fuzzy_search
  = form_tag(searches_path,method: :get) do
    = text_field_tag :search, "",placeholder:"何かお探しですか？"
    = submit_tag 'search', :name => nil
```


<img width="876" alt="スクリーンショット 2019-10-06 16.19.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501638/d2b838a3-d45d-bee7-7bd7-e8d7c2ee1ec2.png">



#コントローラー/ルーティング/ビューの作成

**①searchesコントローラーの作成**

```ruby:ターミーナル
rails g controller searches
```

**②ルーティングの設定**
indexアクションで検索したレコードを表示します。

```ruby:route.rb
resources :searches,only:[:index]
```


**③メソッドの作成**
Productテーブルのnameカラムでの検索を想定しています。
他のカラムの文字列を参照する場合は"name"の部分を変更してください。

```ruby:product.rb
  def self.search(search)
    return Product.all unless search
    Product.where(['name LIKE ?', "%#{search}%"])
  end
```

**④searchesコントローラーのアクション**
@productsに検索に合致した値を代入しています。
@searchに検索した文字列を代入しています。

```ruby:searches_controller.rb
  def index
    @products = Product.search(params[:search]).limit(132)
    @search = params[:search]
  end
```

**⑤ビューの作成**
render @productsは部分テンプレートを用いています。

```ruby:searches/index.html.haml
任意のビューを作成ください。
以下は例です。

.search
  .search-container
    .search-left
      = render 'searches/form-bar'
    .search-right
      %section.items-box-container
        -if @search.present?
          %h2.search-result-head
            =@search
            %span.search-result-head-text
              の検索結果
          .search-result-number
            ="1-#{@products.count}件表示"
        -else
          %h2.search-result-nil
            新着商品
        .items-box-content
          = render @products
```

⑥完成です。
※コーヒーと検索
<img width="862" alt="スクリーンショット 2019-10-06 16.21.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501638/cd34e969-20e6-0961-fdd0-3ba9c5d1b5bc.png">

※検索ワードと合致したものが出てきます。
![スクリーンショット 2019-10-06 16.20.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/501638/0b739f25-500e-6ac7-37fe-71d6c101d761.png)

#おわりに
今回はあいまい検索のやり方を記載しました。
次回はransackを用いた詳細検索を記事にします。よろしくお願いします。
https://qiita.com/nakanishi03/items/2fbcc8ba06b336291321
では:sailboat::sailboat:
IntelliJのコミット時の'secrets' is not a git commandを解決する

クレデンシャルを公開しないようにしてくれるgit-secretsは便利ですが、IDEで追加設定をしないと使えない場合があります。

## 問題
MacでIntelliJを使用時、git-secretsで管理されているフォルダでコミットすると、以下のようなエラーでコミットできません。

```
0 files committed, 1 file failed to commit: add gatling sample git: 'secrets' is not a git command. See 'git --help'.
```

## 解決

原因は、intelliJのgit実行のパスにあります。デフォルトだと`/usr/bin/git`を使用します。

一方、macのbrewでgit-secretsを入れた場合は、git-secretsパスは`/usr/local/bin/`になるので、デフォルトだと見てくれません。

そこで、gitの実行パスを変えましょう。

IntelliJで Preference → Version Control → Git と行き、
Path to Git executableのパスを`/usr/local/bin/git`と変更しApplyします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30677/1ad56d80-3051-cb81-ec6b-3ef41783c043.png)

無事コミットできればOKです。

## 参考
- [クラウド破産しないように git-secrets を使う - Qiita](https://qiita.com/pottava/items/4c602c97aacf10c058f1)
メモ：Laravelで複数のSPAを作成する

やりかけたけど、結局使わなかったので、軽くメモ。
（用語の使い方とか、あってるか微妙。）

# やりたいこと
Laravel で SPA のエントリーポイントを分割したい。

具体的には、一般の人がアクセスする SPA と、管理者がアクセスする SPA を分けたい。

# 方法

## webpack.mix.js を編集

以下のように編集し、管理画面用のファイルが設置されるようにする。
これによって、ビルド時に mix-manifest.json に index が作成され、次手順のように Blade テンプレートから呼び出せるようになる。
以下の例では、管理者用画面として、adminApp.js と adminApp.scss を読み込むようにしている。

```js:webpack.mix.js:diff
  let mix = require('laravel-mix');

  mix.js('resources/assets/js/app.js', 'public/js')
     .sass('resources/assets/sass/app.scss', 'public/css')
+    .js('resources/assets/js/adminApp.js', 'public/js')
+    .sass('resources/assets/sass/adminApp.scss', 'public/css');
```

## adminApp.jsとadminApp.scssを用意する

既存の app.js と app.scss をもとに作成する。

## Blade テンプレートを作成

管理者用画面の Blade テンプレートに、以下を追記する。

```php:adminApp.blade.php
<script src="{{ mix('js/adminApp.js') }}"></script>
```


# 参考

以下のURLを参考にしたが、この手順では、mix-manifest.json を複数作成することになり、読み込みの設定等が必要になった。
https://codeday.me/jp/qa/20190505/777151.html
matplotlibのサブプロットの比率・間隔を一発で調節する

# やりたいこと

こんな感じで、幅違いのsubplotを好みの間隔でプロットできるようにしたい。
![gridspec_kw.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403073/c996a345-e125-4625-b7c6-bc5ddc718190.png)

# 結論

`plt.subplots()` の **`gridspec_kw`** なる引数 で一発解決！

# 説明

余白を調整しつつ幅や高さの違うsubplotを作るには、例えば[@simonritchie様のQiita記事](https://qiita.com/simonritchie/items/da54ff0879ad8155f441)で紹介されているように`GridSpec()`を使えばよいです。[公式ユーザーガイド](https://matplotlib.org/3.1.1/tutorials/intermediate/gridspec.html)もほぼ同じ方法を紹介しているようです。

ただし、これらの記事では複雑なレイアウトの図を作っていて、結構記述量の多い処理になっています。ただ単に比率が違うだけの図を作りたいだけなのに、同じような処理を書くのは結構面倒です。「もっと簡単な方法ないかなー」と思って、何気なく `plt.subplots()` の引数を眺めていたら見つけました。`gridspec_kw` です！いかにもですね！

`plt.subplots()` が内部的に `GridSpec()` を呼んでいて、そのときに食わせる引数が指定できるパターンです。しめしめ。

[公式API](https://matplotlib.org/3.1.0/api/_as_gen/matplotlib.gridspec.GridSpec.html) で `GridSpec`の引数を調べてやると、幅／高さの調整は`width_ratios`／`height_ratios`で、横／縦の間隔の調節は`wspace`／`hspace`でやるらしいことがわかります。

ということで、`gridspeck_kw` にこれらの値を指定する辞書を食わせればOKです！
もちろん `sharex`／`sharey` といった`plt.subplots()` の他の引数とも併用可能です。

```{python3}
import matplotlib.pyplot as plt

fig, axes = plt.subplots(
    3, 2, # 縦 x 横
    gridspec_kw=dict(width_ratios=[1,5], height_ratios=[1,4,4], wspace=0.1, hspace=0.3), # 今回のミソ
    sharex='col', sharey='row', figsize=(6, 7) # もちろん他の引数と併用可
)

## ところで、なんで subplotsの順番は nrows x ncolなのに、figsizeは (横, 縦) なんだろう？
```

あとは手に入れた `axes` に対してお好みのプロット操作をするだけです。

（ちなみに、「左上のaxいらん」という場合には `fig.delaxes(axes[0][0])` です。）


以上です。最後まで読んで下さりありがとうございました！

追記：
記事中で述べた[公式ユーザーガイド](https://matplotlib.org/3.1.1/tutorials/intermediate/gridspec.html)の一節にも、gridspeck_kwについての言及がありましたことを補足させていただきます。
また、同様の方法は他の記事でも既に紹介されていたのを見つけたので、参考としてリンクを貼ります。
https://stackoverflow.com/questions/10388462/matplotlib-different-size-subplots
kotlinでwhen文を使ってみる

## kotlinのwhen文ってどんなもの？
Javaのswitch文と似ているものであり、if-else文としても使用することができる。
本記事にはwhenの記述方法に関して、記述していく。

## when文の使い方
Javaのswitch文の場合

```java
int value = 2;

switch (value) {
case 0:
    // valueが0の場合の処理
    break;
case 1:
    // valueが1の場合の処理
    break;
case 2:
    // valueが2の場合の処理(今回はここに入る)
    break;
default:
    // 上記のcase文に入らなかった場合の処理
}

```

kotlinのwhen文で書き換えてみる

```kotlin
val value = 2

when (value) {
    0 -> {// valueが0の場合の処理}
    1 -> {// valueが1の場合の処理}
    2 -> {// valueが2の場合の処理(今回はここに入る)}
    else -> {// 上記のcase文に入らなかった場合の処理}
}
```

さらにwhen文の場合には、変数を指定せずに、直接条件式を記述することもできる。
この書き方はswitch文というよりかは、ie-else文の感覚に近い。

```kotlin

val value = 2

when {
    value == 0 -> {// valueが0の場合の処理}
    value == 1 -> {// valueが1の場合の処理}
    value == 2 -> {// valueが2の場合の処理(今回はここに入る)}
    else -> {// 上記の条件文に入らなかった場合の処理}
}
```
上記のような条件式でOR/ANDを書きたい場合には、`,`と`&&`を使用することをお勧めします。
ANDは特にないが、ORを表したい場合に、when文の引数あるかないかで使用できる演算子が変わってきてしまう。
どちらでも使用できるのが`,`なので、こちらを使用していく。

```kotlin
val value = 2

when {
    value != null && value == 1 -> {// valueがnullではなく、0の場合の処理}
    value == 1, value == 2 -> {// valueが1か2の場合の処理}
    else -> {// 上記の条件文に入らなかった場合の処理}
}
```

## まとめ
kotlinで開発していく上で、when文はとても使いやすいものなので、この機会にぜひ試しに使ってみていただけたらと思います。
EC2にPublic IP（DNS名）でSSHログインできない

## 概要
私が時々AWSを触る際に、EC2にSSHログインできない場合の状況を簡単にまとめました。
公式のドキュメント等から書き写したわけではないので、正確さやセキュリティの視点を欠いているかと思います。


## 対応方法一覧

#### VPCにIGWがアタッチされていない
VPCにインターネットの口がない状態です。IGWを作成してVPCにアタッチしてください。
（ちなみに、アカウント作成時のデフォルトVPCには、IGWはアタッチされています。）

#### EC2があるSubnetのRoute TableにIGWが設定されていない
サブネットがprivateな状態になっており、インターネットから疎通できない。
publicにする場合には`0.0.0.0/0`にIGWが対応するルートテーブルを作成して、サブネットにアタッチしてください。

#### EC2に割り当てられているSecurity GroupにSSHが設定されていない
Security GroupのインバウンドにSSHの項目を作成してください。
インターネットに開いていれば、どこからでも疎通可能。
セキュリティ的には、Source IPは制限した方が良い。

#### SSH時において、IPアドレス（DNS Name）の前にユーザ名を指定していない
Amazon Linuxだと`ec2-user`（OSによって変わる）。
`ssh -i <pemファイル名> ec2-user@<public IP(DNS名)>` 。

#### SSH時において、Public IP or Public DNS を指定していない
インターネット経由で疎通する場合はPublic IP (DNS名)を指定する。
(ちなみに、EC2を停止、再起動するとPublic IPは変更されます。
不変にする場合はElastic IPを作成してEC2にアタッチしてください。)

#### SSH時において、pemファイルの操作権限が適切でない
`chmod 400 <pemファイル名>` などしてあげる。
`chmod 600`でやっている人もいた。


## 参考
私は読んでいませんが、公式にも参考になるページはあるかと思うので探してみてください。
https://aws.amazon.com/jp/premiumsupport/knowledge-center/ec2-linux-ssh-troubleshooting/
２台以上のvelodyneを同時に接続する方法

2つ以上のvelodyneを同時に起動した場合どうするのか．
この疑問を解決するためにインターネットの深淵まで覗いてきたので備忘録として方法を書いていこうと思います．
ちなみに１台をつなぐ場合はこの記事 (https://qiita.com/Takayamashi/items/970b232e732f5675f6be) をご覧ください．

といってもこのissue (https://github.com/ros-drivers/velodyne/issues/108) を読めば全部わかるでしょうが．．．
ちなみに今回説明するのはVLP16を2台使用する方法ですが，複数台のときも少し工夫するだけでOKです．

環境はUbuntu16.04，ROS kineticです．

# 概要
まず2台以上velodyneを接続する際に重要なことは各機のIPアドレス等の設定(velodyne側の設定)とROS側の設定です．慣れていない方はROSでセンサを使う際にROS側の設定とセンサ側の設定をごっちゃにしてしまって難しいように感じてしまうかと思いますが，ここをきちんと分けて考えていきましょう．
というわけでまずは２台のvelodyneを接続する方法を考えていきましょう．

# velodyne側の設定
まずvelodyne側のIPアドレスが被ってしまいますと同時には接続できません．
というわけで以下が設定です．

Sensor 1:
Network Address 192.168.1.201
Network Mask 24 (255.255.255.0)
Network Gateway 0.0.0.0
Host Address 192.168.1.100
Data Port 2368
Telemetry Port 8308

Sensor 2:
Network Address 192.168.2.201
Network Mask 24 (255.255.255.0)
Network Gateway 0.0.0.0
Host Address 192.168.2.100
Data Port 2268
Telemetry Port 8208

基本的に変更するのはNetwork AddressとHost Address，Portの部分ですね．このあたりを変えておくことでそれぞれを別のvelodyneだと認識してくれます．

そして次はvelodyneとPC間の接続の設定です．

Ethernet connection 1 (Sensor 1との接続):
Address 192.168.1.100
Mask 24 (255.255.255.0)
Gateway 0.0.0.0

Ethernet connection 2 (Sensor 2との接続):
Address 192.168.2.100
Mask 24 (255.255.255.0)
Gateway 0.0.0.0

これでvelodyne側の設定は完了です．
ここまできてブラウザでSensor 1, 2のIPアドレスを入力するとvelodyneの設定画面が出てくるかと思います．

# ROSの設定
さて次にROSの設定です．
前回はROS側の設定は行わなかったですが今回は一緒にやっていきましょう．といっても最終目標はトピックを複数起動する用のlaunchファイルを作るだけです．
まずvelodyneのドライバをインストールしちゃいましょう．

```bash:velodyneドライバのインストール
sudo apt-get install ros-VERSION-velodyne
```

これをインストールするだけで今回作成するlaunchファイルを使うには十分なんですが，せっかくなんでvelodyne関係のworkspaceを作成してまとめておきましょう．

```bash:workspaceの作成とmake
mkdir -p catkin_ws/src
cd ~/catkin_ws/src/ && git clone https://github.com/ros-drivers/velodyne.git
cd .. && rosdep install --from-paths src --ignore-src --rosdistro YOURDISTRO -y
catkin_make
```

次にこのworkspaceの `~/catkin_ws/src/velodyne/velodyne_pointcloud/launch` 内に以下のファイルを作成しましょう．

```xml:multiVLP16.launch
<launch>

  <!-- calibration file path -->
  <arg name="velodyne_calib" default="$(find velodyne_pointcloud)/params/VLP16db.yaml"/>

<group ns="vlp_1">

    <include file="$(find velodyne_pointcloud)/launch/VLP16_points.launch">
      <arg name="calibration" value="$(arg velodyne_calib)"/>
      <arg name="device_ip" value="192.168.1.201"/>
      <arg name="frame_id" value="vlp201"/>
      <arg name="port" value="2368"/>
    </include>
</group>

<group ns="vlp_2">
    <include file="$(find velodyne_pointcloud)/launch/VLP16_points.launch">
      <arg name="calibration" value="$(arg velodyne_calib)"/>
      <arg name="device_ip" value="192.168.2.201"/>
      <arg name="frame_id" value="vlp202"/>
      <arg name="port" value="2268"/>
    </include>
</group>

</launch>
```

これでROS側の設定は完了です！！

# 起動
velodyneの接続を行った後以下のコマンドでROSのトピックを発信しましょう．

```bash:ROSトピックの発信
source ~/catkin_ws/devel/setup.bash
roslaunch velodyne_pointcloud multiVLP16.launch
```

これでrviz等で複数トピックを閲覧できるようになっているかと思います！！
3台以上接続したいときは新しいvelodyneのIPアドレスとポートの変更， `multiVLP16.launch` の編集を同様に行うと大丈夫です！！

# 参考文献
https://github.com/ros-drivers/velodyne/issues/108
VBAを簡単に読み解けるようになる基本

# VBAがわかる人は、どう処理を読み解いているか

例えば、下記のVBAを読み解く場合、全く知識が無い状態では解読が難しいと思います。
しかし、わかる人がこれを解読する際に、どんな風に読んでいくのかが分かれば、すぐにでも読めるようになるのです！

![B742C767-A56D-40EB-AD30-49EBE931E764.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414345/a6216a8b-b334-2bf2-67c2-df3ffe3d4fb5.jpeg)


↓わかる人の頭の中....↓

「Withがあるから、、、End Withまでの間に書かれているピリオド(.)が先頭についたCellsはシートが"データ追加"のセルで、、、」

「Forがあるから、Nextまでの間の処理を反復する。その反復する処理ってのが、、、」

「まず、6列目だからF列のセルに、、、Left関数で、A列のセルの左から4文字を取って入力、、、」（括弧の左側が6だから6列目、右側のiが2と定義されているから、セルは「F2」指定だということ。）

「次に、7列めだからG列のセルに、、、Vlookup関数でなんか入れてる。B列のセルを検索値にして、"マスタ"シートのA：Bの2列目を参照しているのか、、、」

「で、If Then構文だから条件分岐、、、5列目ってことは、E列の値が50万以上だったら8列目、、、つまりH列へのデータ入力を2行目から、A列のデータ最終行まで繰り返せというわけか、、、」


というように、わかる人の頭の中ではこのように読み解かれていきます。

この読み解き方を基に、読み解く上での必須知識を下記に記します。

### 必須知識

- セルの指定方法
  - Range...変数を使わない場合に使用。
            括弧の中をダブルクォー
            テーションで囲む。
            例> Range("A5")



  - Cells...変数を使う場合に使用。
            括弧の左側に変数を入れ、
            カンマ(,)で区切り、右側に列
            番号を入れる。
            例> Cells(i,5)


- 関数を使う際の注意点

  プロシージャ内で使う関数は大きく分けて関数名の前に「WorksheetFunction.」と入力する必要があるもの、ないものの2種類があります。

   - 必要ある関数の代表例
   Sum,Counta,Sumif,Countif,Vlookup
   Muchなどの文字列操作関数や日付関数


   - 必要ない関数の代表例
   Year,Month,Day,Left,Mid,Rightなど
   の数値集計の関数


上記のように分けられますが、明確な基準はありません。手っ取り早い確認方法としては、WorksheetFunctionと入力後にピリオドを押すと、WorksheetFunctionをつけなければいけない関数候補リストが出てきます。ここに出てくるものはWorksheetFunctionが必要だし、ここに出てこないLeft関数などはつけなくてもよい、ということになります。


- 「Cells(Rows.Count,1).End(xlUp).Row」
 
 ↑この文の意味とは


そもそも手作業で、表データの一番下に移動する時はどのような操作をしていますか？
手操作で、A列の最終行に移動する場合は、
A1セルが選択されている状態で、

- Ctrl + ↓

これで、最終行に移動できます。

これをマクロVBAでは、

- Cells(1, 1).End(xlDown)

このように書きます。

しかし、途中に空欄のセルがある場合、表の途中に空欄が不特定に入っている場合は、いったんシートの最終行である、「A1048576」セルに移動してから、Ctrl + ↑とすれば、表の最終行に移動できます。

これをマクロVBAでは、

- Cells(Rows.Count, 1).End(xlUp)

このように書きます。
つまり、シートのA列の最終行から、上に向かって、Ctrl+↑で移動しているという訳です。
最後に.Rowsをくっつけることで、セルの値ではなく、セルの行数を表せることになります。これは定型文として丸暗記しましょう。

- 予備知識

.End(xlUp) : Ctrl+↑上へ移動
.End(xlDown) : Ctrl+↓下へ移動
.End(xlToLeft) : Ctrl+←左へ移動
.End(xlToRight) : Ctrl+→右へ移動


これらの知識を持って、もう一度上記のVBAを眺めてみると、自然と流れが読めてしまいませんか？？？

まだ疑問が残るという方は、

- For Next構文
- With構文
- If Then構文
- Dimという単語の意味

について独自で調べてみると良いかもしれません。以下の参考文献で、直ぐにでもVBAの基本が分かってしまうと思います！

#### 参考文献

-たった1秒で仕事が片付くExcel自動化の教科書
https://sugoikaizen.com/excelvba/


-エクセルの神髄
https://excel-ubara.com/excelvba1/EXCELVBA318.html
ESP32で3時間DeepSleepしたら実際にどのくらい眠るのか調べた

#はじめに
ESP32 のバッテリー駆動のときに良く使うdeepsleepですが、実際にどのくらいの誤差があるのか調べてみた。
キッカケは、12時間ほど寝かせたら数分の差が出たので、もうちょっとだけ正確な方がいいかなと思った。

元ネタとなり、参考とさせて頂いた ESP8266版がこちらになります。

>[ESP8266で300秒deepSleepしたら実際に何秒眠るのか調べた](https://ambidata.io/blog/2016/12/17/deepsleep/)

ESP8266ですとおよそ、2.3% ほど早く指定時間より早くWakeupするそうです。

#ESP32
実際に使用したESP32。上２つは開発ボード。スイッチサイエンス版はDIP化して使用。

| ESP32 | 購入先 |
|:-:|:-:|
| [ＥＳＰ３２－ＤｅｖＫｉｔＣ　ＥＳＰ－ＷＲＯＯＭ－３２開発ボード](http://akizukidenshi.com/catalog/g/gM-11819/)  |  秋月電子通商 |
| [HiLetgo ESP32 ESP-32S NodeMCU開発ボード](https://www.amazon.co.jp/gp/product/B0718T232Z/)  |  HiLetgo |
| [ESP32-WROOM-32D Wi-Fi + BLEモジュール](https://www.switch-science.com/catalog/3753/)  |  スイッチサイエンス |


#調査方法
元ネタは、RTCモジュールを使っているのですが、面倒なのでAmbientサーバの時刻の差で簡単に測ってみることにしました。3時間を3回連続で。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/203949/5fe20aea-83c0-8936-a341-3def341da60c.png)

Ambientは受信時刻を記録しているので、他に、Ambientに送信してから寝るまでの時間(AS)と起きてから送信するまでの時間(WA)をデータとしてAmbientに送っておきます。よって、

実際に寝ていた時間SW2 = AA - (AS2 + WA2)

ということになります。

起きてから送信するまでの時間(WA)は、Ambient に送信する前に millis() で起動からの時間を使いました。

```
  WA = millis();
  ambient.send(WA, AS);
```

送信してから寝るまでの時間(AS)は、DeepSeep 直前で、

```
  AS = millis() - WA;
  esp_deep_sleep_start();
```

※3時間で1分ぐらいの差が出る想定ですので、Ambientへの送受信時間は無視しました。許容範囲かと。
※結果的には、WA,ASも無視してよい時間でした。WiFi接続に掛かる時間も1秒ぐらいでしたし。


#結果
###Ambient データ
```:秋月電子通商
2019-10-05T09:57:40.541Z,0,1169,,,,,,
2019-10-05T12:56:56.192Z,89,1076,,,,,,
2019-10-05T15:55:50.333Z,86,1123,,,,,,
2019-10-05T18:54:56.422Z,91,1100,,,,,,
2019-10-05T21:53:31.936Z,83,1176,,,,,,
2019-10-06T00:52:39.708Z,82,1125,,,,,,
2019-10-06T03:51:34.157Z,85,1101,,,,,,
```

```:HiLetgo
2019-10-05T09:57:33.102Z,0,1131,,,,,,
2019-10-05T12:56:23.105Z,85,1071,,,,,,
2019-10-05T15:55:10.675Z,82,1106,,,,,,
2019-10-05T18:54:11.482Z,84,1071,,,,,,
2019-10-05T21:52:43.656Z,91,1108,,,,,,
2019-10-06T00:51:52.953Z,82,1082,,,,,,
2019-10-06T03:50:46.230Z,89,1871,,,,,,
```

```:スイッチサイエンス
2019-10-05T12:24:26.746Z,0,1229,,,,,,
2019-10-05T15:22:40.139Z,90,1874,,,,,,
2019-10-05T18:21:44.531Z,85,1118,,,,,,
2019-10-05T21:20:28.176Z,92,1081,,,,,,
2019-10-06T00:19:33.532Z,91,1074,,,,,,
2019-10-06T03:18:36.512Z,82,1117,,,,,,
```

以下が集計結果です。1～6回計測。
見方は、-45.5 というのは3時間のDeepSleep指定で45.5秒早く起きたということです。
誤差は、3時間のDeepSleep指定で平均-0.58%の誤差があったということです。

|  | 1回目 | 2回目 | 3回目 | 4回目 | 5回目 | 6回目 | 平均 | 誤差% |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 秋月電子通商  |-45.5|-67.0|-55.1|-85.7|-53.4|-66.7|-62.2|-0.58|
| HiLetgo  |-71.1|-73.6|-60.3|-89.0|-51.8|-68.6|-69.1|-0.64|
| スイッチサイエンス  |-108.5|-56.8|-77.5|-55.8|-58.2|-|-71.3|-0.66|

#まとめ
上記の結果を踏まえると、３時間のDeepSleepで約1～2分早く目覚めるということが分かりました。
なので、例えば12時間のDeepSleepさせたいときは、誤差-0.6%発生することを加味して、

```
    set_sleep_sec = 12 * 60 * 60;   // sec
    esp_sleep_enable_timer_wakeup(set_sleep_sec * 1000000LL * 1.006);
    esp_deep_sleep_start();
```

のようにしておけば大体よろしいかと。まぁそれでも12時間だと1,2分の差は覚悟が必要ですね。
svn更新中にエラーが発生して途中で止まるので『更新→クリーンアップ』を自動化する

## 実現したいこと

どんなに大きなデータでもエラーで止まることなく、svn更新を成功させたい！

## エラー内容

TortoiseSVNで行う更新の途中で「**～is already locked lease execute the 'Cleanup' command**」とエラーメッセージが表示され、クリーンアップを行ってから再び更新を行うも、同じエラーが発生してしまう。

##更新〜クリーンアップの自動化手順

1. 普段はTortoiseSVNを使ってGUIで直感的に操作してる君も、svnのコマンドをコマンドラインで利用できるようにするために以下のリンクで「Apache Subversion command line tools」をダウンロードしましょう。
[Apache Subversion command line tools](https://www.visualsvn.com/downloads/)

2. 環境変数のPathにダウンロードした「command line tools」の中にあるbinフォルダのパスを通しましょう(語尾にでも追加しよう）
【例】〜〜〜〜;C:\Apache-Subversion-1.10.0\bin

3. cmdで以下のコマンドを実行し、SVNコマンドを利用できるか確認しよう。
```svn --version```
実行後、コマンドは利用できませんみたいな文が返ってこなければ成功です。

4. ○○.bat（ファイル名はテキトー）を作成しましょう。

5. batファイルの中に以下のコードを入力して適当な場所に保存しましょう。

```
@ECHO OFF

set SVN_DIR=＜SVNのローカルリポジトリパス＞
set /A CNT=0

:LOOP

call svn update --accept p %SVN_DIR%
IF "%ERRORLEVEL%"=="0" GOTO END

call svn cleanup %SVN_DIR%
GOTO LOOP

:END 
```

**エラーメッセージが返ってこなくなるまで、更新コマンド(update)とクリーンアップコマンド(cleanup)を繰り返して行う！** という中身になっています。

最後に、cmdでSVN更新対象のファイルへ移動し、batをそこにドラッグ&ドロップ！
すると更新が終わるまで、更新→クリーンアップを自動で繰り返してくれます。
個人メモ：GRPC

# protobufとrpc勉強後の、gRPCを勉強～

# GRPCとは

HTTPより良いモノ

（HTTP/2を標準でサポートしたRPCフレームワーク
　HTTP/2による通信
　ProtocolBufferデフォルト対応
　...
　）



# GRPCで、protocol buffers使用
gRPCは、デフォルトでprotoBufを使っている

![grpc-protocolBuffers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378181/6c9c0558-adae-fe55-77cd-c7f0347149a7.png)


上記、
サーバは、c++
クライアントは、Rubyとかjavaなどの、で構築
これを、Protoで通信することで、cross platform、実現。

# gRPCのインストール

```
go get -u google.golang.org/grpc
```


# rpcでの例をgrpcで作ってみる
RPC例：円の半径を計算する関数を、別の端末での呼び出しを想定

## フォルダ構成
grpc_CircleArea
|-- 0_myproto\
|　　-- circle.proto
|　　-- circle.pb.go
|-- 1_server\
|　　-- main.go
|-- 2_client\
|　　-- main.go


## proto作成：0_myproto/circle.proto
```protobuf
syntax = "proto3";

package myproto;

// サービスを定義
service CircleArea {
    // 円の面積取得サービス
   rpc CalculateCircleArea (CircleAreaReq) returns (CircleAreaRes) {
    }
}

// クライアント→サーバ
message CircleAreaReq {
    float round = 1;
}
// サーバ→クライアント
message CircleAreaRes {
    float area = 1;
}
```

コンパイルし、circle.pb.goを作成

```
protoc --go_out=plugins=grpc:. circle.proto
```

ちなみに、前で学んだrpc用のコンパイルは、サービスなど作成しない
`protoc --go_out=./ circle.proto`

## サーバ側：1_server/main.go
```golang
package main

import (
	"grpc_CircleArea/0_myproto"
	"context"
	"google.golang.org/grpc"
	"math"
	"net"
)

type CalculateCircleArea struct{}

// 円面積計算method
func (c *CalculateCircleArea) CalculateCircleArea(ctx context.Context, in *myproto.CircleAreaReq) (out *myproto.CircleAreaRes, err error) {
	area := in.Round * in.Round * math.Pi
	return &myproto.CircleAreaRes{Area: area}, nil
}

func main() {
	// 1 grpcサービス作成
	srv := grpc.NewServer()
	// 2 円面積計算サービス登録
	myproto.RegisterCircleAreaServer(srv, &CalculateCircleArea{})
	// 3 サービスを、ポート8001で監視(err判断省略)
	litsen, _ := net.Listen("tcp", ":8001")
	srv.Serve(litsen)
}
```

## クライアント側：2_client/main.go
```golang
package main

import (
	"grpc_CircleArea/0_myproto"
	"context"
	"fmt"
	"google.golang.org/grpc"
)

func main() {
	// 1 クライアントが接続先サーバ定義(err判断省略)
	conn, _ := grpc.Dial("127.0.0.1:8001", grpc.WithInsecure())
	defer conn.Close()

	// 2 grpcクライアント定義
	client := myproto.NewCircleAreaClient(conn)

	// 3 半径の値を入力
	var round float32
	fmt.Printf("円の半径入力 --> ")
	fmt.Scanln(&round)
	
	res, _ := client.CalculateCircleArea(context.Background(), &myproto.CircleAreaReq{Round: round})
	fmt.Println("円の面積：",  res.GetArea())
}
```

## 起動&実行結果

- サーバ起動：

```
1_server>go run main.go
```

- クライアント起動：

```
2_client>go run main.go
円の半径入力 --> 3
円の面積： 28.274334
```
Firebase for iOSの機能を記憶用に配置して色分けした

# はじめに

試行錯誤中なんでWIP感あります。

調べ物をしたときに、文字だけ読んでもなかなか記憶に定着しないので、普段ものを覚えるときに情報を絵に切り取って記憶するので、習って実際に一枚作って記憶させてみようという、試み１。
とりあえずfirebaseの機能をさらう機会があったので、それを人柱に。

# Firebase for iOS
商標プロダクトでも、個人アプリでも、無料で使えるツールが多いFirebase。
クラッシュ、アクセル、トラッキングなどの情報を収集できたり、そのデータを元に機能改善を行える。
Firebase Consoleから登録したプロパティを変更したりプリリリースを特定ユーザに配信したり、いろんなテストも操作できる。

#　機能イメージ

![firebase.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274090/a6c6a7ae-3941-3850-88ec-b3a19e87bf9a.png)

# おわりに
ちょっとまだ記憶に置くイメージとしての印象が甘い。
サブコンテンツごとにアイコンつけたほうがイメージはっきりしそうだけど、コスト考えると悩みどころ。
Unity2Dで使えるアニメーション画像素材を動画から生成してみる

![momo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366532/675f0fe9-db5f-4d76-faaf-14f200cdf534.gif)


#キャラのアニメーションつくるのめっちゃ大変じゃない……?
Unityでの2Dゲーム作成につきもの(?)な、アニメーション的連続性のある画像の準備。
~~ぶっちゃけミニマムなら3Dモデルを2Dに表示したらいいのでは~~
ミニマムなゲームであんまり労力をかけられない……。これをちょっとでも楽にしたい……。
そんな気持ちからたどり着いた苦肉の策を共有がてら記事にする。
なお、Mac。

自分みたいな初学者でも運用できる感じに簡単のための表記をしているので、最適化はまだできます。
また、キャラ透過の部分に関しては未了(imagemagickでやれそうですがまだやってない(Winのソフトでやってしまった))なので、でき次第更新します。
追記:まさかの透過もFFMPEGで完結できそうなので、でき次第更新か、別記事で紹介します。

##目次
- 動画を準備
- FFMPEGを入れてみる
- 動画を切り刻んで画像にしてみる
- 画像でけぇ……キャラの範囲に切り取りたい……
- (未了)背景を透過したい
- Unityで動いた……!

##動画を準備
もちろん、動画から生成なのでお好きな動画を準備、デスクトップに配置しましょう。キャラ以外、背景が一色のほうがやりやすいです。
<img width="230" alt="スクリーンショット 2019-10-06 14.32.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366532/99e448fb-777f-6b6a-feda-6d720459ee46.png">

##FFMPEGを入れてみる
有害じゃないと思うのでご安心ください。
動画に対して、様々な操作ができます。

これのインストールにHomebrewというのを使うので、まずこれを入れましょう。入ってる場合は無視で大丈夫です。

``` 
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
```


こんなみための
<img width="50" alt="スクリーンショット 2019-10-06 14.36.00.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366532/9cfe7190-8c8c-c863-5533-cab39e61c8ed.png">
Consoleを起動して、これをコピペしてエンターです。
もしくは
https://brew.sh/index_ja
ここに記載のある最近のコマンドをコピペしてください。
~~ところで、なんでMacのConsoleにコピペする前提のコマンドの先頭に$が含まれていることが多いんですかね。僕の環境構築がおかしいのか。~~

ちょっとまって、終わった感あったら次にこれをコピペしてください。

```
brew install ffmpeg
```

以上です。変なことはしてないです。
もしうまくいなかなったら、パーミッションとかそこらへんかもですが、遭遇してないのでまだわからないです。お気軽に聞いてください。


##動画を切り刻んで画像にしてみる
デスクトップに動画を配置している前提です。また、切り刻んでたくさんの画像を書き出すので、フォルダを作っておきましょう。

```
ffmpeg -i /Users/ここはユーザー名/Desktop/動画の名前.動画の拡張子 -r 8 /Users/ここはユーザー名/Desktop/ここにフォルダ名/
```

Consoleに、これを、ユーザー名とファイル名とフォルダ名だけ書き換えてエンターです。
前半が対象動画(かなりの形式いける)、後半が書き出す先です。デスクトップを指定すると大変なことになるので、デスクトップにフォルダを作ってそこに書き出しましょう。

```
-r 8
```
の部分は、切り刻むフレーム数、大雑把に書くと、1秒あたりの枚数です。おおきくするほど細かくなります。

##画像でけぇ……キャラの範囲に切り取りたい……
このままだと、画像の無駄な部分が多くあります。
もちろん、1枚の大きな画像に全部を突っ込んで、UnityでSpriteを分割、アニメーションにする、という手段もある~~しなんならそれのほうがいい~~んですが、今回は分割した画像を突っ込んでD&Dでアニメーションにします。

https://apps.apple.com/jp/app/xnconvert/id436203431?mt=12
私はこれを使いました。
複数の画像に同じ処理を適用できます。
このアプリに画像を全部突っ込みます。

動画の写り方によって変わるので色々設定をいじって探ってほしいのですが、仮にこんな感じに設定します。
<img width="428" alt="スクリーンショット 2019-10-06 14.50.55.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366532/0ff21d43-a338-998d-70b6-1f431a829393.png">

これで、いい感じにキャラがいるところだけのサイズにトリミング、切り取ってくれます。便利。
この設定の上、出力したらいいです。

##(未了)背景を透過したい
これなんですが、Macだとimagemagickでできそうなのです。ですが、現状やっていないので、未了とします。
Winで、複数画像を同じように透過してくれるソフトがたくさんあるので、一旦それを使いました。
上記アプリでできるんじゃないかと思うんですが、できないです。2色とかグレイスケールで制限つけたりでできなくはないですが、きついです。

##Unityで動いた……!
そう、ここまでで生成された画像を全部D&D、そのあとHierarchyにD&Dでアニメーションができます!![kore.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/366532/a7cd8ca0-b6c9-2542-68f8-4897a1ab8013.gif)

##感想
もっと楽にできると思いますし、なんならこれにおいても、Macなら標準でAutomatorの自動化を使えばワンクリックで動画をアニメーションに使える画像に出力できると思います。
ですが、苦労したので出力せねば損だろう、という考えで出力しました。
もしもこの世界の誰かの役に立ったらきっと彼も成仏できるとおもいます。
【FactoryBot】投稿を持ったユーザーを生成するファクトリ

## はじめに

EverydayRailsの4章の「**ファクトリで関連を扱う**」という項では、belongs_to 関連付けを扱ったファクトリが紹介されています。

例えば、あなたのRailsアプリに`Userモデル`と`Postモデル`が用意されており、「*1つの投稿は、1つのユーザーを持つ*」というPost側から見た**一対一(belongs_to)の関係**が定義されているとします。

```ruby:spec/factories/posts.rb
FactoryBot.define do
  factory :post do
    title { "Hello." }
    association :user # <=これを記述しておく
  end
end
```
その場合、上のファクトリを用意することで

`FactoryBot.create(:post)`を実行する際に、裏でユーザーを作成し、生成されるPostインスタンスに自動で関連付けてくれます。

```ruby
post = FactoryBot.create(:post)
puts post.user #=> <User:0x00007f91213a3ce8>
```
人の手でいちいちユーザーを作って`FactoryBot.create(:post, user: user)`とする必要がなくなるわけですから、単に適当なPostインスタンスが欲しいってときには便利ですよね。

## 本題

では逆に「*1つのユーザーは、複数の投稿を持つ*」という、User側から見た**一対多(has_many)の関係**を取り扱うファクトリはどう書くのでしょうか？
要は、**最初から投稿を持つユーザーを生成してくれるファクトリ**が欲しいんです。

残念ながらEverydayRailsにはその方法が載っていません。そこで、FactoryBotの[公式ドキュメント](https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md)を確認したところ、ありました。
というわけで、以下にドキュメントで紹介されているそのサンプルコードを抜粋します（コメントは私が日本語に訳しました。だいぶ意訳してます。）

```ruby:公式ドキュメントより抜粋（一部改変）
FactoryBot.define do

  # 投稿ファクトリ（ユーザーへの"belongs_to"関連付けを持つ）
  factory :post do
    title { "Through the Looking Glass" }
    user
  end

  # 投稿なしのユーザーファクトリ（投稿を持たない）
  factory :user do
    name { "John Doe" }

    # 投稿ありのユーザーファクトリ（ユーザーのあとに投稿データを生成する）
    factory :user_with_posts do

      # 一時的な属性(transient attribute)として posts_count を定義しています。
      # これは、オブジェクトを生成するときやファクトリのコールバックで利用できます。
      transient do
        posts_count { 5 }
      end

      # after(:create)コールバックのブロック引数(|user, evaluator|)は、
      # 生成されるユーザーと"evaluator"というオブジェクトを表します。
      # "evaluator"はファクトリで定義された全ての値を保持するオブジェクトであり、
      # その中には一時的な属性も含まれます。"create_list"メソッドの
      # 第二引数には、生成したい投稿の数を指定しています。
      after(:create) do |user, evaluator|
        create_list(:post, evaluator.posts_count, user: user)
      end
    end
  end
end
```
このコードを参考にファクトリを定義することで、以下のように複数の投稿を持ったユーザーをたった1行で生成することができるようになります。

```ruby:公式ドキュメントより抜粋（一部改変）
create(:user).posts.length #=> 0
create(:user_with_posts).posts.length #=> 5
create(:user_with_posts, posts_count: 15).posts.length #=> 15
```
引数に投稿の数を指定することも可能。これは便利ですね！

## 補足

サンプルコードを見てわかる通り、一対多(has_many)の関係を扱うファクトリは一対一(belongs_to)のものに比べると、作りが少々複雑になっています。また、`transient`なる謎のブロックもありますね。これは**一時的な属性(transient attribute)**というものを定義しています。わからない方もいるかもしれないので最後に解説しておきます。

### 一時的な属性(transient attribute)
あるファクトリ内で追加的に定義することができる属性のことです。一時変数とも呼ばれます（確かに変数を定義しているみたいですよね。）尚、この属性が実際のモデルの属性として反映されることはありません。
この属性値は、オブジェクト作成時の挙動を変更するためのフラグや追加データとして利用されます。定義した一時的な属性をファクトリのコールバックで使用する場合には、"evaluator"（これについては上のサンプルコードのコメントで説明されています）から呼び出します。

```ruby
transient do
  posts_count { 5 } # 追加したい属性名 { 値 } の形で記述します
end
```
【Office 365】PowerShellでのリスト処理に役立った私的コマンド集（随時更新）

# はじめに

PowerShellでのリスト処理に役立った私的コマンド集。
随時更新の雑多なコマンド集なので、ある程度記載が増えたら記事分割するかも。

# コマンド

## 以下記事で紹介されているコマンド（`fl`,`ft`,`Select-Object`,`Out-GridView`）

http://www.vwnet.jp/windows/PowerShell/2018060501/GettingStartedWithPowerShell-03.htm

`Out-GridView`を初めて知ったときの衝撃といったら。

## パブリックフォルダーのパーミッション情報から`User`ごとの`AccessRights`属性内の各権限を`;`区切りで取得する

```powershell
Get-PublicFolderClientPermission -Identity "\Folder001" |
    Select-Object Identity, User, @{L="AccessRights"; E={$_.AccessRights -join ";"}}
```

## `Get-Mailbox`の取得結果から`EmailAddresses`属性内の各アドレスを`;`区切りで取得する

```powershell
Get-Mailbox | Select-Object DisplayName, @{L="EmailAddresses"; E={$_.EmailAddresses -join ";"}}
```

## リストを`ForEach-Object`したときのループカウントをコンソール画面に出力

### コマンド

```powershell
$counter = 0
Get-MsolUser | ForEach-Object {

    #ForEachさせたい処理

    $counter ++
    Write-Host ($counter) ($_.UserPrincipalName)
}
```

### 画面出力

```
1 liam@contoso.com
2 noah@contoso.com
3 emma@contoso.com
4 olivia@contoso.com
5 ava@contoso.com
6 …
7 …
8 …
9 …
10 …
11 …
… …
```

## 取得した現在時刻を文字列と結合させる

作成したリストをCSV出力するときのファイル名定義のときなどに。

```powershell
$fileName = [String](Get-Date -Format "yyyyMMddTHHmm") + "_export.csv"
```

## CSVからインポートしたリストが必須列を持っているか確認する

```powershell
#CSVからデータインポート
$ImportedData = Import-Csv import.csv -Encoding Default

#インポートしたデータの列を取得
$ImportedColumnAry = ($ImportedData | Get-Member -MemberType Properties).Name

#必須列を定義
$RequiredColumnAry = @("Verb", "Noun", "Identity", "Property", "Value")

#インポートしたデータが持っていない必須列を抽出
$NotInColumnAry = $RequiredColumnAry | Where-Object {$_ -notin $ImportedColumnAry}

#持っていない必須列が一部ない(すべてある)場合は処理
If($NotInColumnAry.Count){

    Write-Host "インポートしたデータに右記の必須列がありません。: " ($NotInColumnAry -join ", ")
    #　//一部ない場合の処理//

}else{

    Write-Host "インポートしたデータはすべての必須列を持っています。"
    #　//すべてある場合の処理//

}
```

## リストの列・行を変換する

### コマンド

Get-OrganizationConfigの場合。

```powershell
$Result = Get-OrganizationConfig
($Result | Get-Member -MemberType Properties).Name |
    Select-Object @{L="Property"; E={$_}}, @{L="Value"; E={$Result.$_}}
```

### 結果

```
Property                                                  Value
--------                                                  -----
PSComputerName                                            outlook.office365.com
PSShowComputerName                                        False
RunspaceId                                                xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
ACLableSyncedObjectEnabled                                False
ActivityBasedAuthenticationTimeoutEnabled                 True
ActivityBasedAuthenticationTimeoutInterval                06:00:00
ActivityBasedAuthenticationTimeoutWithSingleSignOnEnabled True
AdfsAudienceUris
AdfsAuthenticationConfiguration
AdfsEncryptCertificateThumbprint
(中略)
```

以上
KubernetesでHostPathを使う

# Hostpath
- KubernetesNode上のボリュームをコンテナにマッピングするプラグイン
- `Directory`はディレクトリが存在しない場合に作成しない
- `DirectoryOrCreate`はディレクトリが存在しない場合には作成して起動する
- 利用できないようにしているKubernetesも多いみたい
- あまり推奨の構成ではないようで、検証環境とかは手っ取り早くHostpathというのはありなのかもしれない

## Sampleをデプロイ

```sample-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
  name: sample-hostpath
spec:
  containers:
  - image: nginx:1.12
    name: nginx-container
    volumeMounts:
    - mountPath: /srv
      name: hostpath-sample
  volumes:
  - name: hostpath-sample
    hostPath:
      path: /etc
      type: DirectoryOrCreate
```

```
kubectl apply -f sample-hostpath.yaml
```

## Podからマウントされているか確認

```
kubectl exec -it sample-hostpath cat /srv/hostname
```

出力結果

```
k3d-k3s-default-worker-1
```

dfコマンドで見ると

```
df | grep /srv
```

overlayとでる。出ていればマウントされいているに違いない。

```
overlay         61255492 13356212  44757956  23% /srv
/dev/sda1       61255492 13356212  44757956  23% /srv/hosts
```

## ホスト上のファイルを確認

```
docker exec -it k3d-k3s-default-worker-1 cat /etc/hostname
```

出力結果

```
k3d-k3s-default-worker-1
```
個人メモ：RPC？

# (grpc見る前にまず)RPCとは？
RPC　( Remote Procedure Call )
別プロセスの関数起動するため～～の規約

# golandでRPC例を作ってみる
RPC例：円の半径を計算する関数を、別の端末での呼び出しを想定

## フォルダ構成
1_rpc_CircleArea
|-- 1_server_pkg_rpc\
|　　-- main.go
|-- 2_client\
|　　-- main.go

### サーバ側：1_server_pkg_rpc/main.go
```golang
package main

import (
	"math"
	"net"
	"net/http"
	"net/rpc"
)

type CircleArea struct {}

// (対象)関数名(clientからのリクエスト, clientへのレスポンス) エラー
func (c *CircleArea) CalculateCircleArea(r float32,area *float32)error  {
	*area = math.Pi * r * r // 圆形的面积：π * r * r
	return nil
}

func main() {
	// 1　初期化
	circleArea := new(CircleArea)
	// 2 rpcサービス登録
	_ = rpc.Register(circleArea)
	// 3 関数を　httpに登録。httpを通じて、データ転送を実現
	rpc.HandleHTTP()
	// 4 特定のポートで、監視
	listen, _:=net.Listen("tcp", ":8001")
	http.Serve(listen,nil)
}
```

### クライアント側：2_client/main.go
```golang
package main

import (
	"fmt"
	"net/rpc"
)

func main() {

	var round float32      // リクエスト用
	var area float32   // レスポンス用
	fmt.Printf("円の半径入力 --> ")
	fmt.Scanln(&round)

	//　1 サーバへ接続
	clent, _ := rpc.DialHTTP("tcp", "localhost:8001")
	//  2 サービスる呼び出し
	//      CircleArea.CalculateCircleArea：サーバ名 (golandで教えてくれないので、間違わないようにする→コピーしよう)
	//      r：計算用の円の半径
	//      &area:　計算後の円の面積
	_ =clent.Call("CircleArea.CalculateCircleArea", round, &area)
	fmt.Println("円の面積：",  area)
}
```


## 起動&実行結果

- サーバ起動：

```
1_server_pkg_rpc>go run main.go
```


- クライアント起動し、結果出力：

```
2_client>go run main.go

円の半径入力 --> 2
円の面積： 12.566371

```
SQLまとめ(分類まで)

#前回までの流れ

前回、「データベースとはなんぞや？？」といった部分をまとめました。
→　[データベース基礎まとめ](https://qiita.com/matsukei/items/9dfae2df9e7e3aa4ecd2)

今回は、データベースを操作する「**SQL**」について書いていきます。

#1.　SQLとは？

**データベース言語**(の１つ)。

###1.1　プログラミング言語とデータベース言語
　　
**データベース言語**は**プログラミング言語**ではないのでシステム開発はできない。
この２つがどう違うのか先にざっくり理解しておきましょう。

■**データベース言語**・・・データベース(正確には、DBMS)とやりとりをするための言語。

■**プログラミング言語**・・・プログラム本体を作る言語。

#2.　SQLの分類
###■ 大きく３つに分類
SQLはデータを扱う上で分類が分かれている。

「SQLをつかって、DBにする命令」は大きく３つに分類できる。ということ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396284/d01ca5b3-2897-68d6-e31c-a0c9dcf44e76.png)




すごく簡単に言えば、
>１．DML・・・データをあれこれするときに使う命令
２．DDL・・・データの格納場所をあれこれするときに使う命令
３．DCL・・・データベースに対する権限周りをあれこれするときに使う命令

引用元:[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word15638.html)

↑↑こちらのサイトの説明がイメージしやすいと思います。

###2.1 DML　（Data Manipulation Language）
DMLは、テーブルに対し、格納されているデータの
「取得」「登録」「修正」「削除」などを行う命令。

4つの文は非常によく使い、「**SQLの四大命令文**」と呼ばれるほど特に重要なSQL文です。

■**SELECT**　(取得)　・・・　テーブル内のデータを**取得**する
■**INSERT**　(登録)　・・・　テーブル内にデータを**登録**する
■**UPDATE**　(修正)　・・・　テーブル内のデータを**修正**する
■**DELETE**　(削除)　・・・　テーブル内のデータを**削除**する

###2.2 DDL　（Data Definition Language）
DMLは、テーブルに格納されているデータをあれこれしますが、
DDLは、テーブルを「作成」「修正」「削除」したりする命令。

■**CREATE**　（作成）　・・・　新しくテーブルを作成する
■**ALTER**　　（修正）　・・・　既存のテーブルなどを修正する(変更を加える)
■**DROP**　　（削除）　・・・　既存のテーブルなどを削除する

#まとめ

以上、SQLの分類についてまとめました。
それぞれの文の書き方などは別途作成します。
→[DMLの文法](https://qiita.com/matsukei/items/5281ae5c45b059fb54fc)

間違っている箇所があればご指摘いただけると幸いです。
jQueryのargumentsの振る舞い

# はじめに

今更ではありますが、諸事情があってjQueryを使うことになったので自分なりのメモの
意味も兼ねて

##非同期処理と順番

jQueryを使用する理由の一つにajaxによる非同期処理が可能になると言う点があります。
しかし、今まで基本的に科学計算しかしてこなかった人間からすると、
プログラムが上から順番に流れずに実行されることに違和感を感じてしまっていました。

どういうことかと言うと、Cなんかで数値計算を書いた場合基本的に先に書いてある文が実行されてから次の文に処理が移動します。

しかし、ajaxを使用するとajx通信を行なっている部分は完了していようがいなかろうが、関係なしに次の文に移ってしまうことになります（それが良いところでもあるのですが…）。

ajax通信をしてサーバー側から値を受け取ったものを表示したい場合などには、
ajax通信が完了してから値の表示を実行する必要があります。

そこで登場するのがコールバック関数になります。

##コールバック地獄とその対策

コールバック関数とは以下のようなものを指し、ある関数Aに関数Bを引数として与えて、関数Bを関数A内で実行するものになります。

```javascript

test(call);

function test(callback_function) {
    console.log("Hi!");
    callback();
}

function call(){
    console.log("I'm called")
}


//実行結果
//Hi!
//I'm called
```

次に非同期処理についてです。下のプログラムはsetTimeoutを使用して、非同期処理を作っています。

``` javascript
var a = 1;

console.log("first",a);
setTimeout(function(a){a = 100},2000);//2秒待ってからaの値を書き換える
console.log("second",a);

//実行結果
//first 1
//second 1
```

setTimeoutはプログラムの流れとは関係なしにとりあえず2秒間待つので
当然secondで表示したaは書き換えが終わっていないので元の値(つまり1)のままです。
これの解説案として一番単純なのは下のように書いてしまうことです。

``` javascript
var a = 1;

console.log("first",a);
setTimeout(function(a){
           a = 100;
           console.log("second",a},2000);//2秒待ってからaの値を書き換えて出力する

//実行結果
//first 1
//second 100
```

このようにsetTimeout配下にconsole.logを配置してしまえば、
setTimeout配下では同期処理ですので通常通り先に書いたプログラムが先に実行されます。
なんだか科学計算の並列計算と似てるなぁと私は思いました。


コールバック関数使ってなくね？と思われる方もいるかもしれませんが、setTimeout内に書かれている
無名関数が今回のコールバック関数ということになります。

これで問題解決のように思えるかもしれませんが、今回のaの書き換えの処理のさらに1秒後にaを1000に更新したいとします。そうするとコードは以下のようになります。

``` javascript
var a = 1;

console.log("first",a);
setTimeout(function(a){
           a = 100;
           console.log("second",a}
           setTimeout(function(a){
                      a = 1000;
                      console.log("3rd",a}
                      ,1000)
           ,2000);//2秒待ってからaの値を書き換えて出力する

//実行結果
//first 1
//second 100
//3rd 1000
```

段々とコールバック地獄の片鱗が見えてきました。
このように非同期処理内でさらに非同期の処理を行おうとすると
延々とネストが深くなる上に正直なにをやっているのか分からなくなります。

これの解消策として次に紹介するpromiseになります。

##promiseとarguments

コールバック地獄を解消するための仕組みがpromiseです。
以下のように書きます

``` javascript
//jQUeryを使います
var a = 1;

console.log("first",a);
$.when(change_value(a))
    .done(console.log("second",arguments[0])



function change_value(x){
    var dfd = new $.Deferred();//defferedオブジェクトのインスタンス化
    setTimeout(function(x){x = 200;
                           dfd.resolve(x);
                           },2000);//2秒待ってからaの値を書き換える
    return dfd.promise()
}
//実行結果
//first 1
//second 200
```

promiseは非同期の処理が終わったタイミングで信号を送ってくれるような仕組みです。
そのため、非同期処理が完了した後に処理を行うことができます。

さてここからが本題となります。
promiseで信号を受け取り、非同期処理によって更新もしくは得た値を使いたいとします。

その値はarguments(MDNを参照: https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/arguments)
に入っているのですが、
このリファレンスが少々曲者です。というのも上記のリファレンスによると

-----引用-------
arguments は、関数へ渡された引数を含む、関数内のみアクセス可能な 配列様 (Array-like) オブジェクトです。
----引用終了----

これだけを見るとargumentsには関数内のみアクセス可能な配列オブジェクトである可能性があります。

つまり
arguments = 関数へ渡された引数

なのか
argumentsには関数へ渡された引数の他にも何か入っている

のかが分かりません。

これについて原文の英語の方を当たるとすんなり答えが見つかりました。
日本語で「含む」と訳されている部分がincludeではなくcontainでしたので
この場合は
arguments = 関数へ渡された引数
という認識が正しいはずです。
バックアップファイルがいつ、どのDBを取得したかを知る方法

# はじめに
データベースのバックアップを取得する際、
ファイル名に「端末名、データベース名、日時」等をいれておけば
復元する際に困らないかと思います。

とはいえ、あくまで文字情報になるので、
バックアップしたファイルから上記の情報が取得できないか調べてみました。

（そもそもSSMSで復元する際に上記の情報は参照できるのでt-sqlで取得できないか調べた結果です）

# RESTORE Statements - HEADERONLY (Transact-SQL)

[RESTORE Statements - HEADERONLY (Transact-SQL)](https://docs.microsoft.com/ja-jp/sql/t-sql/statements/restore-statements-headeronly-transact-sql?view=sql-server-2017)

公式サイトに全て書いてあるのですが、
以下の構文で取得できます。

```sql:restore_headeronly.sql
RESTORE HEADERONLY FROM DISK = N'hoge.bak'
```

実行すると、SELECTを投げた際と同じようにレコードとして結果の取得ができます。
そのため、プログラムから実行した場合もDataReaderやDataTable等で受け取ることが可能です。

どのような情報が取得できるかは公式サイトに記載されていますが、
取得日、データベース名、取得ユーザ、端末名等です。
Linuxのtarコマンドの使い方のメモ

Linuxで良く使うtarコマンドの使い方のメモです。

# 1. tarファイルで固める（無圧縮「.tar」）

```
tar cvf ＜名前＞.tar ＜ファイル及びディレクトリ＞ […]
```

```bash:使用例
tar cvf dir1_arc.tar dir1
```

# 2. tarで固めgzipで圧縮する（gzip圧縮「.tar.gz」）

```
tar zcvf ＜名前＞.tar.gz ＜ファイル及びディレクトリ＞ […]
tar acvf ＜名前＞.tar.gz ＜ファイル及びディレクトリ＞ […]
```

```bash:使用例
tar zcvf dir1_arc.tar.gz dir1
tar acvf dir1_arc.tar.gz dir1
```

# 3. tarで固めbzip2で圧縮する（bzip2圧縮「.tar.bz2」）

```
tar jcvf ＜名前＞.tar.bz2 ＜ファイルやディレクトリ＞ […]
tar acvf ＜名前＞.tar.bz2 ＜ファイルやディレクトリ＞ […]
```

```bash:使用例
tar jcvf dir1_arc.tar.bz2 dir1
tar acvf dir1_arc.tar.bz2 dir1
```

# 4. tarで固めzzで圧縮する（xz圧縮「.tar.xz」）

```
tar Jcvf ＜名前＞.tar.xz ＜ファイルやディレクトリ＞ […]
tar acvf ＜名前＞.tar.xz ＜ファイルやディレクトリ＞ […]
```

```bash:使用例
tar Jcvf dir1_arc.tar.xz dir1
tar acvf dir1_arc.tar.xz dir1
```

# 5. tarアーカイブファイルを解凍・展開する

```
tar xvf ＜tarアーカイブファイル名＞ [-C ＜展開先パス＞]
``` 

```bash:使用例
tar xvf dir1_arc.tar
tar xvf dir1_arc.tar.gz
tar xvf dir1_arc.tar.bz2
tar xvf dir1_arc.tar.xz
```

# 6. tarアーカイブファイルの内容を参照する

```
tar tvf ＜tarアーカイブファイル名＞
``` 

```bash:使用例
tar tvf dir1_arc.tar
tar tvf dir1_arc.tar.gz
tar tvf dir1_arc.tar.bz2
tar tvf dir1_arc.tar.xz
```

以上
Docker mysql8 へ接続するときにUser権限を変更する方法

最近、mysqlはmysql8以上で使っているのですが、ローカル環境で、dockerから起動すると、nodeサーバーから接続できないことがあって、mysqlのuser権限を変更しないと接続できないことに気づきましたので、忘れないのようにメモしておきます。

```mysql
ALTER USER 'username'@'%' IDENTIFIED WITH mysql_native_password BY 'userpassword'
FLUSH PRIVILEGES;
```
VBEの設定

# 概要
ちょこちょこVBA触る機会が出てきた割には
VBEの設定を触ってなかったので設定する。


環境はいまだに2007。

# 設定
ツール⇒オプションから設定

- 編集タブ
    - 自動構文　　　　　　　⇒　チェック無し
    - 変数の宣言を強制する　⇒　チェック有

- エディタの設定
    - インジケータバー　⇒　チェック有
- 文字
    - フォント　　メイリオ　12pt
    - 標準コード　文字色：緑　背景：黒
    - コメント　　文字色：灰　背景：黒
    - キーワード　文字色：青　背景：黒
    - 識別子　　　文字色：白　背景：黒


VBEは文字色の設定をもう少し柔軟にさせてほしい。
最新だともう少し細かく設定できるのだろうか。
【小ネタ】Kotlinでnullableな関数型を定義するときの '?.invoke()' について

高階関数やラムダ式でnullableの関数型を渡したい場合があります。

..と文章にすると複雑ですが、Buttonで `onClick()`コールバックを渡すようないつもの処理の場合です。
nonnullで `onClick` 定義する場合は以下のように `onClick()`を呼ぶと実行できます。

```
fun nonnullFunction(onClick: () -> Unit) {
    onClick()
}
```

nullableの式を実行する場合、 `onClick()` とするとコンパイルエラーとなります。
エラー時のKotlin Playgroundのリンクを以下に貼ります。
https://pl.kotl.in/b3Y5BDPzs?theme=darcula

```
fun nullableFunction(onClick: (() -> Unit)?) {
    onClick() //コンパイルエラー
}
```

エラー内容は以下の通りです。`?.invoke()` を使用するように指示されます。

> Reference has a nullable type '(() -> Unit)?', use explicit '?.invoke()' to make a function-like call instead.

指定通り以下のようにすると正しく実行できます。

```
fun nullableFunction(onClick: (() -> Unit)?) {
    onClick?.invoke()
}
```

# invoke()とは

nullableの際に突然出てきた `invoke()` が気になり調べました。

下記のページから、
最初の`onClick()` はシンタックスシュガーで `onClick.invoke()` をオーバーロードしていることがわかります。

> Higher-Order Functions and Lambdas
> https://kotlinlang.org/docs/reference/lambdas.html

> Operator overloading > Invoke operator
> https://kotlinlang.org/docs/reference/operator-overloading.html#invoke

すなわち以下は ` onClick()` を呼んだときの処理と同じ挙動です。

```
fun nonnullFunction(onClick: () -> Unit) {
    onClick.invoke() // equals onClick()
}
```

kotlin.jvm.functionsのソースコードを見ると `invoke()` のインターフェイス定義を見ることができます。
Kotlin1.3では引数定義は0から22まで可能なことがわかります。

```
package kotlin.jvm.functions

/** A function that takes 0 arguments. */
public interface Function0<out R> : Function<R> {
    /** Invokes the function. */
    public operator fun invoke(): R
}

:

/** A function that takes 22 arguments. */
public interface Function22<in P1, in P2, in P3, in P4, in P5, in P6, in P7, in P8, in P9, in P10, in P11, in P12, in P13, in P14, in P15, in P16, in P17, in P18, in P19, in P20, in P21, in P22, out R> : Function<R> {
    /** Invokes the function with the specified arguments. */
    public operator fun invoke(p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9, p10: P10, p11: P11, p12: P12, p13: P13, p14: P14, p15: P15, p16: P16, p17: P17, p18: P18, p19: P19, p20: P20, p21: P21, p22: P22): R
}

```

# invoke() の処理を変更

`invoke()` をオーバーロードすることにより、関数型を実行するときの処理を変更可能です。

https://stackoverflow.com/questions/45173677/invoke-operator-operator-overloading-in-kotlin

上記Stackoverflowの例がわかりやすかったので参考にしました。
サンプルコードは以下となります。
関数型と `invoke()` との関係を知った後だと理解しやすいと思います。

```
class Greeter(val greeting: String) {
    operator fun invoke(target: String) = println("$greeting $target!")
}

fun main() {
    val hello = Greeter("Hello")
    hello("world")  // Prints "Hello world!"
}
```

Kotlin Playgroundのリンクを以下に貼ります。
https://pl.kotl.in/Q0pi-t1Am?theme=darcula


# 感想

nullableな関数型の実行には `?.invoke()` を使用します。
invoke()を調べることによってすこしKotlinの理解を深めた気がします。
ブラウザで手軽に試せるPlayground便利です。

# 関連

https://try.kotlinlang.org/#/Kotlin%20Koans/Conventions/Invoke/Task.kt
nginx関連の参考URL

個人用のメモです。
僕が初学者なので、初学者の人が読んでわかるリンクを載せています。
日々更新します。
世の中に発信してくれている人達のおかげで僕もコツコツ作品作れます。
ありがとうございます。

- *Docker Composeを使ってサクッとNginxコンテナを起動する*

[https://qiita.com/NagaokaKenichi/items/c03366f0b84b12c0a30d](https://qiita.com/NagaokaKenichi/items/c03366f0b84b12c0a30d)

- *docker+Node.js(Express)+nginxの最小構成プロジェクトを作成する*

[https://qiita.com/ryo-ohnishi/items/3653f7583c8591eef333](https://qiita.com/ryo-ohnishi/items/3653f7583c8591eef333)

- *ExpressフレームワークでCSSやJQueryのアクセスでHTTP500が発生する時の対策法*

[https://qiita.com/MahoTakara/items/cbd97794828b30d9a4b3](https://qiita.com/MahoTakara/items/cbd97794828b30d9a4b3)

nginx+Node.js(Express)を作ろうとした時にCSSが反映されていないことに気づいたため参照。
ビット演算とシフトによる加算関数

ビット演算とシフトのみによる加算ルーチンです。
2進数加算結果は、A⊕B⊕carryになります。
加算のキャリーは、（A&B)|(A&carry)|(B&carry)になります。
正確に知りたい方はベン図と真理表を書いて求めて下さい。
対称性があるので、ベン図はきれいな三つ葉模様になります。
int addbit()が本体です。
C言語で書かれています。

```addbit.c
int addbit(int a,int b) {
    int cy=0,t=1,s=0;
    while(t) {
        s|=(a&t)^(b&t)^cy;
        cy=(t&(a&b|cy&b|cy&a))<<1;
        t<<=1;
    }
    return(s);
}
```
Djangoでwebサービスを作る1

使うコマンドを覚えるのが面倒なのでコピペ用にまとめました。

##まずプロジェクトを作る
```
django-admin startproject project2
```
『project2』というプロジェクトを作りました。

##次にアプリケーションを作る
まずディレクトリ移動

```
cd project2
```

アプリケーション作成

```
python manage.py startapp hello
```
これで『hello』というアプリケーションを作成。

##ある程度ファイルを編集したらブラウザで確認
開発用サーバ起動

```
python manage.py runserver
```
ブラウザで下記にアクセスし実行状態を確認する

```
http://localhost:8000/hello<アプリケーション名>
```
React初心者向け「state,props使い方」（div背景の色をランダムに変えるボタン）

# 今回の目標
画面に簡単なボタンを一つ追加して、ページの背景の色をランダムに変える簡単なReactを作ってみましょう〜
ボタンを押すとボタンを持っているDIVの背景の色がランダムに変わる。

### 学ぶこと
コンポーネントを作れる。
stateを使ってみる。
イベント処理をしてみる。
propsを使ってみる。

# Stateとは
コンポーネント内で使用できる状態を管理します。
値が変更されるとrenderが走って画面を更新してくれます。
HashでKey,Valueのデータを管理
更新する時は直接更新した場合、renderは走らないので画面が更新されないので使わないでください〜
`this.state.key='test'`

```
constructor(props) {
  super(props);
  this.state={
      key: 'value',
      ....
  };
}
```

# Propsとは
コンポーネントの属性
親コンポーネントでPropsに設定した情報を子コンポーネントで使う

親コンポーネントでタイトルを入力

```react:App.js
<ColorControl title="色を変えます！クリックしてください。"/>
```

子コンポーネントからタイトル取得

```react:ColorControl.js
this.props.title
```


#プロジェクト生成
### `create-react-app`を使って
```
$ create-react-app backgroud-button
$ cd background-button
```

### `components`フォルダと作ってColorControl生成してボタン追加


```react:ColorControl.js
import React,{ Component } from 'react';

class ColorControl extends Component {
    constructor(props) {
        super(props);
        // reactではデータの保存にstateを使います。
        // App.jsで設定したtitleをこのように取得できます。(this.props.title)
        this.state = {
            title: this.props.title,
            color: [0,0,0]
        }
        // イベントハンドラーでthisを使いたい場合はBindする必要があるのでConstructorに定義する
        this.handleClickButton = this.handleClickButton.bind(this);
    }

    handleClickButton() {
        const new_color = [
            Math.floor((Math.random()*55) + 200),
            Math.floor((Math.random()*55) + 200),
            Math.floor((Math.random()*55) + 200)
        ];
        //stateを変更するときは必ずsetStateで変更、stateが変更されるとViewはレンダリングされる
        this.setState(
            {
                color: new_color
            }
        );
    }

    render() {
        const title = this.state.title; 
        const color = this.state.color;
        const style = {
            background: `rgb(${color[0]},${color[1]},${color[2]}`
        };

        return (
            <div style={style}>
                <button onClick={this.handleClickButton}>{title}</button>
            </div>
        )
    }
}

export default ColorControl;

```

### `App.js`にColorControlコンポーネント追加

コンポーネントを別のフォルダに作ったのでimportする時はフォルダパスを追加
`title`が`props`です。`ColorControl`で`this.props.title`でデータ取得できます。
ボタンのタイトルをこちらから設定しました。

```react:App.js

import React from 'react';
import ColorControl from './components/ColorControl';

function App() {
  return (
    <div>
      <ColorControl title="色を変えます！クリックしてください。"/>
    </div>
  );
}

export default App;

```

### 完成！

<img width="500" alt="スクリーンショット 2019-10-06 13.11.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/108475/caec4e3f-3f69-a05c-ce23-86188bab25be.png">


次は子コンポネートのイベントを親のリスナーから受け取って処理してみます〜
Docker上でSeleniumを利用し、遠隔操作の様子をVNCViewerで視覚的に確認する

Docker上でSeleniumを利用することで、ブラウザ自体やそれに対応するドライバをインストールする必要がなくなり、簡単に導入・廃棄をすることができる
しかし、そのままだとブラウザが動く様子が見えないので、VNCViewerで様子を確認する方法を以下に示す

# 前提
- macOS Mojave 10.14.6
- Docker Desktop 2.1.0.3
- Node.js 10.15.0

# 手順
## SeleniumのChromeノード準備
以下ファイルにて、Selenium-HubとChromeノードのコンテナを定義する
ChromeノードはChromeブラウザ1プロセスに対応し、Selenium-Hubは複数のノードを制御するものである
今回はChrome1プロセスのみを用いるが、複数プロセスによる並列実行が可能である

```yaml:docker-compose.yml
version: '3'

services:
  hub:
    image: selenium/hub
    ports:
      - 4444:4444
  chrome:
    image: selenium/node-chrome-debug
    environment:
      - HUB_PORT_4444_TCP_ADDR=hub
      - HUB_PORT_4444_TCP_PORT=4444
    ports:
      - 5900:5900
    depends_on:
      - hub
```

以下コマンドにて、コンテナを起動しておく

```shell
docker-compose up -d
```

VNCViewerを起動し、Chromeノードにホスト`localhost`、パスワード`secret`で接続する
VNCViewerは各種存在するが、ここでは[RealVNCViewer](https://www.realvnc.com/en/connect/download/viewer/)を用いている

## Node.jsのテストコード作成
次に、Node.jsを用いてYahooのポータルサイトを自動操作するサンプルを作成する
まず、依存関係や実行コマンドの定義のために以下ファイルを作成する

```json:package.json
{
  "main": "index.js",
  "scripts": {
    "test": "mocha index.js --timeout 10000"
  },
  "dependencies": {
    "mocha": "^6.2.0",
    "selenium-webdriver": "^4.0.0-alpha.4"
  }
}
```

実際のテストコードを以下のように作成する

```javascript:index.js
const webdriver = require("selenium-webdriver");
const { Builder, By, until } = webdriver;

const TIMEOUT_MILLISEC = 10000;

let driver;

describe("Yahooポータルサイト", () => {
  before(() => {
    driver = new Builder()
      .forBrowser("chrome")
      .usingServer("http://localhost:4444/wd/hub")
      .build();
  });

  after(() => {
    return driver.quit();
  });

  it("検索ボックスに入力する", async () => {
    await driver.get("https://www.yahoo.co.jp/");

    INPUT_XPATH =
      '//*[@id="wrapper"]/header/section[1]/div/form/fieldset/span/input';
    await driver.wait(
      until.elementLocated(By.xpath(INPUT_XPATH)),
      TIMEOUT_MILLISEC
    );
    await driver
      .findElement(By.xpath(INPUT_XPATH))
      .sendKeys("DockerでSeleniumを使う");
  });
});
```

以下コマンドにて依存関係をインストールする

```shell
npm install
```

## テスト実行
以下コマンドにてテストを実行する

```shell
npm run test
```

以下のように、ブラウザが自動で操作される様子を見ることができる
![VNCViewer.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125334/e7cba2e8-8e7b-860e-ce06-829f4fbd95a3.gif)

## 後処理
終了時は、コンテナ群を削除しておく

```shell
docker-compose down
```