OmniAICreator/Qiita-1.07M huggingface dataset:
Excelで重複削除 (重複列を削除する)

Excelの基本的な機能で、重複する行を削除することができますが、重複する列を削除することはできないようです。

## やりたいこと
下記のように、A行の重複を削除したり、B行の重複を削除したりする
![列重複削除.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/ea52c201-f377-995e-9719-fba4e71b4bfb.jpeg)

## 1行に対して重複列を削除

選択範囲 (1行) の重複列を削除します。

1. 重複列を削除したい範囲を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/b756c075-2d22-43b1-74c0-aba1de3feb54.png)

2. マクロ (下記のVBAコードを実行) の処理結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/357feea4-790f-e01f-8c27-8a48356310cc.png)



```vb:module1.bas
'水平方向に重複削除 (先頭行基準)
Public Sub removeDeplicatesHorizontal()
    Dim rng As Range, rngNotUsed As Range
    Set rng = Selection '選択範囲をrngオブジェクトに格納
    Set rng = rng.Rows(1)
    rng.Select
    
    With ActiveSheet.UsedRange
        Set rngNotUsed = Range(Cells(.Rows(.Rows.Count).Row + 1, 1), _
        Cells(.Rows(.Rows.Count).Row + rng.Columns.Count, 1)) '使用していない領域をrngNotUsedオブジェクトに設定
    End With
    rngNotUsed = WorksheetFunction.Transpose(rng) 'rngオブジェクトの行/列を入れ替えてrngNotUsedオブジェクトに貼り付け    
    rngNotUsed.RemoveDuplicates Columns:=1　'Excel標準機能で、重複行を削除

    rng.Clear 
    rng = WorksheetFunction.Transpose(rngNotUsed) 'rngNotUsedオブジェクトの行/列を入れ替えてrngオブジェクトに貼り付け
    rngNotUsed.Clear

End Sub
```

## 複数行に対して重複列を削除

複数行に対して一括で処理を行う場合は、重複削除の基準とする行を一つ選ぶ仕様になります。

1. 重複列を削除したい範囲を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/55c0141d-6d20-6399-061d-83609dcb44fa.png)

2. 重複を判断する基準の行を1つ選択
例として、2行目を基準にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/009908ae-daf6-0ddf-baf0-ea1e66d3bc29.png)

3. 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/99d551b1-c5ce-53e3-c379-0746e88f8018.png)

```vb:module2.bas
'水平方向に重複削除 (n行目基準)
Public Sub removeDeplicatesHorizontalMultiple()
    
    Dim rng As Range, rngNotUsed As Range, c As Long, i As Long, n As Long, s As String
    Set rng = Selection

    c = rng.Rows.Count
    If c > 1 Then
        s = InputBox("重複削除の基準を何行目にしますか?", , 1)
        If IsNumeric(s) Then
            n = WorksheetFunction.Min(CLng(s), c)
        Else
            n = 1
            Set rng = rng.Rows(1)
            rng.Select
        End If
    Else
        n = 1
        Set rng = rng.Rows(1)
        rng.Select
    End If
    
    With ActiveSheet.UsedRange
        Set rngNotUsed = Range(Cells(.Rows(.Rows.Count).Row + 1, 1), _
        Cells(.Rows(.Rows.Count).Row + rng.Columns.Count, c))
    End With
    rngNotUsed = WorksheetFunction.Transpose(rng)
    rngNotUsed.RemoveDuplicates Columns:=n
    
    rng.Clear
    rng = WorksheetFunction.Transpose(rngNotUsed)
    rngNotUsed.Clear

End Sub
```

## 注意点

* 書式などは消えてしまう → rng.Clear を rng.ClearContentsと書き換えれば、書式は消えないが、古い書式が残ることで別の問題が起きる可能性に注意する必要あり
* Activesheetに、使用していない行が、十分に存在しないとエラーになってしまう (実行時エラー'1004')
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80231/0597116b-9d28-b65f-87ca-f1dc8b5db8a9.png)

 → このエラーを生じさせないためには、使用していない行が十分にない場合、処理を行わないなどのエラー処理が必要。

## 参考
https://tonari-it.com/excel-remove-duplicate-vba/
呪術廻戦で俺が学ぶMySQL②【PHP】

こんにちは！
先日、呪術廻戦で俺が学ぶ[MySQL①【PHP】](https://qiita.com/hayatoganbaru/items/f9ae47370cce8b8ec4a6)をアップしましたが、
今日はその続きです。

さらに新しいことをアウトプット、前回の記事より理解度が上がった箇所は
もう一度ディグってみます。
そもそもデータベースとは？SQLとは？とか突かれると
答えられなくて泣きながら走って逃走する自信しかないので
ちゃんと言語化できるように今度記事にしてまとめます（絶対やる）

# カラムを追加

![スクリーンショット 2021-09-05 11.13.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/cbce6125-c5ae-80d2-7fe0-56bbccd7e575.png)

前回よりデータ増やしました。
ちなみに僕の好きな術式は投射呪法です。
ちょっと領域展開がなさそうなのが不安ですが、
僕なら投射呪法を会得したいなあ。

例えば上図のmagiciansテーブルに
どこに所属しているのかを表すカラムbelong,
階級を表すカラムrankを増やしたとしましょう。

![スクリーンショット 2021-09-05 11.31.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/7808cfd7-6c26-7d9a-f32f-d22a9b1f4691.png)
こんな感じで。（悠仁って２級やったっけ？）

一見ちゃんと管理できてるように見えますが、
今後データが増えたときにすごくごちゃっとして
わかりにくくなります。
実際五条先生を追加するのを忘れてた。
また、rankは悠仁は2級呪術師（？？？？？）ですが、
階級が変わった時に一々書き換えなければいけません。

# リレーション

データベースを使用する最大の利点はリレーションらしい。
テーブルを分けることで管理しやすくします。
リレーションを利用することであたかも2つ以上のテーブルが
1つであるかの如く振る舞うことが可能です。
テーブルが複数存在しているのにデータが簡単に
管理できるって素敵やん（紳助さん）
リレーションってRuby on Railsの
アソシエーションみたいなものと考えればええんかな？

ということでrankテーブルとbelongテーブルを作成しました。

belongテーブル

![スクリーンショット 2021-09-05 11.56.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/af32c91b-d29e-41a3-0967-aafb27033edc.png)

rankテーブル

![スクリーンショット 2021-09-05 12.00.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/6e88a62b-cacd-cfaf-b4fb-63a10dea0133.png)



じゃあこの呪術師（呪詛師と呪霊いるけどごめんね）の情報とどこに所属しているか、階級はどうなのかというデータを紐付けるにはどうすればいいのか。

magicianテーブルにbelong_id、　rank_idというカラムを追加し、
それぞれのテーブルの該当するidを記述します。

![スクリーンショット 2021-09-05 12.08.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/a44c700c-4e31-9710-538f-e2097e97f26e.png)

何でこんなデータ作ったんやろか…
めんどくさかった…
しかし、これで出来上がりと思っちゃあいけねえいけねえ。
真人がナナミンのことを知りたくて「キミ何級？」とデータを調べようとしたときに、
magicianテーブルのrank_idの番号を確認してからrankテーブルに
情報を見に行かなければなりません。
この確認方法は非常に効率が悪いです。
宿儺もびっくりです。

そこでリレーションです。

ナナミンの階級を調べたい時は

```sql
SELECT * FROM `magicians`, `rank`  WHERE magicians.id=4 AND rank.id = magicians.rank_id;
```

WHERE句に続けて```magicians.id=4```と記述するとmagiciansテーブルの
idの４番目、つまりナナミンを指定できます。
真人はナナミンが何級か知りたいのでANDで```rank.id = magicians.rank_id;```
とリレーションを利用することで1級呪術師なのだとわかりました。
これで真人も宿儺から斬撃を受けることもなくなるでしょう

このsql文を入力すると

![スクリーンショット 2021-09-05 12.23.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1435543/36d51e7b-c442-960a-f747-565e06972a5f.png)

リレーションを利用することで複数のテーブルに値を入れてデータを管理し、
必要な時だけ合体させて取り出し閲覧することが可能なので
データベースがより便利なものとなりますねえ。
【Python】あるある？ChromeDriverのバージョン不一致をLineに通知する方法

#はじめに
私はPythonのSeleniumでwebサイトへのログインやサイト情報の確認を自動化しています。
その際にChromeDriverを使っています。
ところが、Chromeブラウザが定期的に自動アップデートされるので、ChromeDriverとのバージョン不一致でプログラムが止まっていることがよくあります。（ありますよね！？）

エラー処理を入れないと、数日間動いていなかったなんてことも・・・。

そこで今回はChromeDriverのバージョン不一致をLineに通知する方法を紹介したいと思います。

#環境
・python3.7
・windows10
・Chromeブラウザ

#エラー内容
日本語訳：
selenium.common.exceptions.SessionNotCreatedException: 
メッセージ：セッションが作成されていません：このバージョンのChromeDriverはChromeバージョン89のみをサポートしています。
現在のブラウザバージョンは93.0.4577.63でパスは・・・なんとかかんとか。

```
selenium.common.exceptions.SessionNotCreatedException: 
Message: session not created: This version of ChromeDriver only supports Chrome version 89 Current browser version is 93.0.4577.63 with binary path C:\Program Files (x86)\Google\Chrome\Application\chrome.exe
```

ChromeDriverのバージョンとChromeブラウザバージョンが不一致ってことですね。
Chromeブラウザのバージョンは自動で上がっちゃうので。確かにブラウザは最新版の方がセキュリティ的に安心。

ちなみにChromeブラウザの自動更新を停止するためには、「GoogleUpdate.exe」というファイルを削除するか、名前を変えてしまうと、その後自動更新は行われなくなるそうです。バージョン不一致はこちらでも解決できます。
私はブラウザの更新をお勧めします。

#バージョン不一致通知プログラム
```chromedriver_error.py
import requests                 #←Line通知用
import sys                      #←強制終了用
from selenium import webdriver#←selenium

#↓try節でChromeを起動して、webスクレイピングを開始します。
try:
    driver = webdriver.Chrome("c:/driver/chromedriver.exe") #←chromedriver.exeの保管場所。最新版を置くところです。
    driver.get("https://www.google.co.jp")#←webスクレイピングしたいサイトのURL。サイトは例なので好きなところに書きかえてください。


#↓except節はエラーがあった場合のみ、通過します。今回はここにLine通知用のプログラムを記載しています。
    
except:
    addmessage="ドライバエラーが発生しています"                                #←変更不要
    line_notify_token = '*******************************************'          #line_notify_tokenを発行して記載してください。
    line_notify_api = 'https://notify-api.line.me/api/notify'                  #←変更不要
    message = addmessage                                                       #←変更不要
    payload = {'message':"\r\n"+ message}                                      #←変更不要
    headers = {'Authorization': 'Bearer ' + line_notify_token}                 #←変更不要
    line_notify = requests.post(line_notify_api, data=payload, headers=headers)#←変更不要
    sys.exit()                                                                 #←強制終了。変更不要
       
#↓ドライバーエラーが発生しない場合はこの行以下を実行するので好きなコードを書いてください。
```
line_notify_tokenを発行方法はGoogleで検索して頂ければすぐ見つかると思います。

###ちなみにバージョン不一致のエラーを解消したい場合
まずChromeブラウザのバージョンを確認します。
1.Chromeを開く　＞　右上の「・・・」(設定)　＞　[ヘルプ]　＞ [Google Chromeについて]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/1b5763d5-47eb-961e-724b-e221962ecc4e.png)
今は「93.0.4577.63」ですね。

2.ChromeDriverをダウンロードする。以下のサイトにあります。
https://chromedriver.chromium.org/downloads

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/299c96fd-cb6e-d415-9216-cb9a8b387818.png)
Topページにさっそく「Supports Chrome version 93」と記載のあるChromeDriverがありました。今回はChromeブラウザのバージョンが93なので、これでOKです。
自分が利用しているブラウザバージョンをサポートしているバージョンをダウンロードしてください。

#最後に
いかがでしたでしょうか。経験上バージョン不一致のエラーは1か月～3か月くらいの周期で発生します。今はLine通知が来たらChromeDriverを手動で入れ替えていますが、これも自動化できたらいいですね。ご参考になれば幸いです。
【Linux】rmdirとrmの違い

コマンドで消すときは、「ゴミ箱」には行かずに、本当に消されるので気をつけよう！

## ディレクトリを消したい
（安全であるがあまり使わない）

```terminal
$rmdir ディレクトリ名
```
- ファイルが入っているものは`rm -r`コマンドでないと消えないよ
- 空のディレクトリじゃないと消せないよ

<br>

## ファイルを消したい

```terminal
$rm ファイル名
```
- スペース名で区切れば、複数ファイル消せるよ

<br>

## ディレクトリもファイルも消したい
（よく使う）

```terminal
$rm -r ディレクトリ名（ディレクトリの中にあるファイルも消す）
```
【Swift UI】iOS 15からAsyncImageでURL先の画像を読み込む

# はじめに

WWDC2021にリリースされたSwiftUIには、**`AsyncImage`**と呼ばれる新しいビルトインビューが導入されており、非同期で簡単にURLからリモート画像をダウンロードできるようになった。

`環境：　xcode13 beta5, iOS15`


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/a06c2d81-8bba-4295-18f9-b06dfc709137.gif" width=25%>


# 目次
<!-- タイトルとアンカー名を編集 -->
1. [基本的な書き方](#基本的な書き方)
2. [画像読み込み中の時](#画像読み込み中の時)


<!-- 各チャプター -->
<a id="#基本的な書き方"></a>
# 基本的な書き方


```swift:ContentView.swift
struct ContentView: View {
    var logo: Logo

    var body: some View {
        VStack {
            AsyncImage(url: URL(string: logo.imageURL))
                .frame(maxWidth: 300, maxHeight: 100)
        }
    }
}
```
<br>

・**`AsyncImage`**の書き方はとてもシンプルで、URLをつめれば非同期で画像を読み込みできる。
・ただ、リサイズしなければ画像はデフォルトのままになっちゃうので、Swift UIではよく**`frame`**を使って画像の加工をする。




<a id="#画像読み込み中の時"></a>
# 画像読み込み中の時

・非同期処理のため、画像を読み込みの間に余白が出てしまい、なので画像が完全に読み込んだ前にインジゲーターなどのアイコンを用意する。
・今回のアイコンはアップルさんが用意した**`"photo"`**という[SF Symbols](https://qiita.com/anchor_/items/4ad5b1705589ce0e4e4d)を使う。


```swift:ContentView.swift
@ViewBuilder
func placeholderImage() -> some View {
   Image(systemName: "photo")
       .renderingMode(.template)
       .resizable()
       .aspectRatio(contentMode: .fit)
       .frame(width: 200, height: 200)
       .foregroundColor(.gray)
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/1a8ca25f-217b-7a19-73fb-ecbce510c8c0.png" width=40%>

<br><br>

・画面が読み込まれる時に、先に`placeholder`にある**`placeholderImage()`**が読み込まれ、非同期処理が終わった後にlogoが表示される。

```swift:ContentView.swift
struct ContentView: View {
    var logo: Logo

    var body: some View {
        VStack {
            AsyncImage(url: URL(string: logo.imageURL)) { image in
                image
                  .frame(maxWidth: 300, maxHeight: 100)
            } placeholder: {
                  placeholderImage()
            }
        }
    }
}
```


<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1065841/94b03677-d87a-53ec-dbdb-8ed84252af01.png" width=25%>


<a id="#reference"></a>
# 参考文献
- https://wwdcbysundell.com/2021/using-swiftui-async-image/
Tinyproxyでさくっとリバースプロキシを立ててみる

# はじめに

ポートを1つにまとめたいけど、Apacheやnginxを使ってちゃんと作りこむほどでもないし...と思っていたら、Tinyproxyを見つけました。

http://tinyproxy.github.io/

最低限の設定をしたらすぐに使えて、メモリ消費量も少ないようです。

> The memory footprint tends to be around 2 MB with glibc

というわけで、試しにリバースプロキシとしてwebアプリを動かしてみました。

# 環境

```bash
$ tinyproxy -v
tinyproxy 1.10.0
```

# サンプルアプリ

https://github.com/Syuparn/tinyproxy-sample

docker-composeでリバースプロキシ(Tinyproxy)とwebアプリを動かします。

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

services:
  # リバースプロキシ
  tinyproxy:
    image: vimagick/tinyproxy
    ports:
      - "8080:8080"
    volumes:
      - ./tinyproxy:/etc/tinyproxy
    restart: unless-stopped
    # -dでフォアグラウンド起動（デフォルトはバックグラウンド）
    entrypoint: tinyproxy -d -c /etc/tinyproxy/reverseproxy.conf
  # webアプリ（何でもいいけどここではワンライナーREST API）
  web:
    image: ghcr.io/syuparn/webawk:0.3.0
    entrypoint: ./webawk.sh 'GET("/names") { b["names"][1]="Taro"; res(200, b) }'
```

パス `/example/` 配下は `example.com`、`/web/` 配下はwebコンテナへプロキシしています。

![tinyproxy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239887/c4c7c9df-69c0-1068-2446-c770ab2d4bdd.png)

```:tinyproxy/reverseproxy.conf
# Tinyproxyの設定

User nobody
Group nobody

# 1024以下の場合はrootユーザー必要
Port 8080
Listen 0.0.0.0

# 60秒でタイムアウト
Timeout 60

# yesの場合普通のプロキシが使えなくなる。リバースプロキシの場合はyes推奨（公式）
ReverseOnly Yes

# example.com
ReversePath "/example/" "http://www.example.com/"

# webコンテナ
# NOTE: docker-composeはコンテナ名をホストとして名前解決可能
ReversePath "/web/" "http://web:8080/"
```

参考

https://isabelcmdcosta.medium.com/how-i-set-up-tinyproxy-as-a-forward-proxy-and-reverse-proxy-2a5dc1ed64e4

# 結果

```bash
# localhost:8080/example/ -> example.com
$ curl localhost:8080/example/
<!doctype html>
<html>
<head>
    <title>Example Domain</title>
...
# localhost:8080/web/ -> web:8080/ (webコンテナへコンテナ間通信)
$ curl localhost:8080/web/names
{"names":["Taro"]}
```

レスポンスヘッダには `Via` が追加されています。

```bash
$ curl -i localhost:8080/web/names
HTTP/1.1 200 OK
Via: 1.1 e8667db7b85d (tinyproxy/1.11.0)
Content-Length: 18
Content-Type: application/json
Date: Sat, 04 Sep 2021 12:57:38 GMT

{"names":["Taro"]}
```

また、`X-Tinyproxy`オプションを有効にすると、サーバー側にリクエスト元のIPアドレスを伝えることができます。

```:tinyproxy/reverseproxy.conf
# リクエストに "X-Tinyproxy" ヘッダ追加
XTinyproxy Yes
```

```yaml:docker-compose.yml
    # webアプリ: リクエストヘッダ X-Tinyproxy をログだし
    entrypoint: ./webawk.sh 'GET("/names") { print("X-Tinyproxy ", REQUEST_HEADERS["X-Tinyproxy"]); b["names"][1]="Taro"; res(200, b) }'
```

```bash
$ docker-compose logs web
Attaching to tinyproxy-sample_web_1
web_1        | X-Tinyproxy  172.21.0.1
```

# おわりに

ほぼパスの設定だけで使えるので、デモアプリ作成に重宝しそうです。（フォワード）プロキシの機能もあるので、機会があったらそちらも使ってみたいと思います。
M5Paper での USB通電時の DeepSleep と M5.getBatteryVoltage() について

## 書きたいこと
M5Paperで時計を作ろうとして電圧の取得でハマったので、覚書。

### 症状
USB通電時に起動時のみ電圧が取得できて、DeepSleep復帰時は電圧が取得できない

### 結論
USB通電時とバッテリーモードでは、DeepSleepを行うときの準備が違う。

バッテリーモードでDeepSleepを実行するために必要なコードを、USB通電時に記述すると、
M5.getBatteryVoltage() を M5.RTC.begin() より前で実行するしないと、電圧が取得できない症状が出る。

### 対策
USB給電時の為のみに、DeepSleepを用いるなら、バッテリーモード時に必要なESP32への電力供給の為の以下のコードは不要（というか書いてはだめ！）

```c:DeepSleep時にもESP32への電力供給を維持
    gpio_hold_en((gpio_num_t) M5EPD_MAIN_PWR_PIN);
    gpio_deep_sleep_hold_en();
```

### 経緯

* バッテリーモードでUSB給電の時期を知るために M5.getBatteryVoltage() で電圧を取得していた。

* 取得位置は、画面表示の直前、温度や湿度などと同じタイミング。

* バッテリーモード（シャットダウン動作）時には、普通に取得できた。
* USB通電時では、起動直後は正しく取得できるが、DeepSleep復帰後には全く取得できなかった。

* 何かが安定していないのかと思い delay(1000) を入れてみたが結果は変わらなかった。

通電時のことなので、取得できなくとも問題がなく、放置していたのだが、どうにも気になり、調べてみた。

```c:調査ソース
#include <M5EPD.h>

void setup() {
    uint32_t vol1, vol2;


    M5.begin(
        false, // bool touchEnable
        false, // bool SDEnable
        true, // bool SerialEnable
        true, // bool BatteryADCEnable
        false// bool I2CEnable
    );

    vol1 = M5.getBatteryVoltage();

    M5.RTC.begin();  // <-- これの前後で結果が変わる!!!

    vol2 = M5.getBatteryVoltage();

    Serial.printf("vol1=%4dmV, vol2=%4dmV\n", vol1, vol2);

    int32_t dt = 10;

    // 周辺への電力供給を停止
    M5.disableEXTPower();
    M5.disableEPDPower();

    // USB切断時には、ESP32への電力供給を停止して待機
    M5.shutdown(dt);

    // USB通電時には、こちらを実行
    // ESP32への通電を維持
    // USB通電時に使用するなら、以下の2行は書いちゃだめ!!!
    gpio_hold_en((gpio_num_t) M5EPD_MAIN_PWR_PIN);
    gpio_deep_sleep_hold_en();

    // 休眠時間を指定
    esp_sleep_enable_timer_wakeup(dt * 1000 * 1000);  // wakeup every 5secs

    // DeepSleep開始
    esp_deep_sleep_start();  
}

void loop() {
}
```

#### プログラムについて
* M5.begin()で引数を明記しているのは、引数なしだと、M5.begin()内部で余分な出力がされているのを抑止するためです。
* M5.begin()直後の、vo1, vol2 M5.RTC.begin()が本体。
* コメント、`// 周辺への電力供給を停止` 以降は、一定時間停止するコード。
* USB通電時には、`M5.shutdown()`が素通りすることを利用して、DeepSleepの処理を記述

実行すると

```
M5EPD initializing...OK
vol1=4298mV, vol2=4298mV
M5EPD initializing...OK
vol1=4298mV, vol2=   0mV
M5EPD initializing...OK
vol1=4300mV, vol2=   0mV
.......
```

みたいな感じで、リセット直後のみ取得できて、DeepSleep後は`M5.RTC.begin()`の前でないと電圧は取得できていないことがわかる。

次に、バッテリーモードでESPに電力供給を行うためのコードをコメントアウトして実行

```
M5EPD initializing...OK
vol1=4294mV, vol2=4294mV
M5EPD initializing...OK
vol1=4294mV, vol2=4294mV
M5EPD initializing...OK
vol1=4294mV, vol2=4294mV
```
正しく取得できている

## まとめ
バッテリーモードでDeepSleepを実行するための対策がUSB通電時に悪影響を及ぼしているとは思いませんでした。

今回は、

* USB通電時には、DeepSleep
* バッテリーモードでは、シャットダウン

と切り分けましたが、

もし、バッテリー給電時にも、DeepSleepしたい場合には、注意が必要です。

> M5Paperでは、USB通電とバッテリー供給を正確に切り分ける事ができないので、
> 電圧を見て判別するなどして、
> ESP32への電力供給のためのコードの実行の是非を判断する必要があります。
>
> もしくは、正しいかどうかわかりませんが、M5.RTC.begin()より前で電圧を取得するとか。
【トラブルシューティング】ipconfigなどコマンドが認識されないときの対処法【Windows10】

#OSと環境変数(Path)の関係
##Pathの設定をしないとOSがソフトウェアを認識しない。なのでPathの設定・確認は非常に重要。
開発環境の設定でPCにソフトウェアのディレクトリ(例：C:\Program Files\〇〇.exe)を認識させるためにPathの設定を行う必要があります。

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/44bd327c-1087-b2e9-596f-cd6ae011472c.png)


PCのデフォルトのパス情報は[環境変数]⇒[システム環境変数（S）]の中の変数Pathに格納されています。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/d0844bdc-3f6f-2546-50f1-65a143eea927.png)
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/296efdd7-08a5-ea2e-9934-c7e64a1a612a.png)

#インストールしたいソフトウェアとOSのPathの変数名が被る場合がたまにある

通常は、この変数Pathを変更することはあまりないと思いますが、ソフトウェアの種類によっては変数名のPathの名称が被る場合があります(表１)。
この場合、システム環境変数には同じ変数名を登録することはできません。

（表１）OSとソフトウェアのPathの変数が同じ場合

|OSまたはソフトウェア  |Pathの変数名  |値  |
|---|---|---|
|Windows10  |Path  |C:\WINDOWS\SYSTEM32;  |
|ソフトウェア A  |Path  |C:\Program Files\〇〇.exe  |

その場合は、ソフトウェアのパスの変数を別の変数名に変更する必要があります（表２）。

（表２）ソフトウェアのPathの変数名を変更した場合

|OSまたはソフトウェア  |Pathの変数名  |値  |
|---|---|---|
|Windows10  |Path  |C:\WINDOWS\SYSTEM32;  |
|ソフトウェア A  |Software_Path  |C:\Program Files\〇〇.exe  |


#間違ってOSのPathの変数の値をソフトウェアの値に変更してしまった場合
OSのPathが認識されていないためipconfigやwhereコマンドが認識されません。

#OSのPathの値に再度、置き換えることで解決できます(⇓)。

![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1169664/b3f7aa1d-c3a4-8d52-5bff-4965f82ac8c5.png)

#参考にさせていただいたサイト
■電脳産物：Windows10：Path設定を確認する
URL:https://dianxnao.com/windows10%EF%BC%9Apath%E8%A8%AD%E5%AE%9A%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B/

■ProEngineer：Windows10でTempやPathなどの環境変数を設定する方法
URL:https://proengineer.internous.co.jp/content/columnfeature/5205#section300
macOS + emacsで PlantUML

## Homebrewで PlantUMLをインストール

```
brew install plantuml
```

## emacsの設定

```C-x package-list-package``` で plantuml-modeをインストール
![スクリーンショット 2021-09-05 11.05.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847/18abb57f-d223-601d-bfea-86866e95f0f5.png)

### .emacsの設定

```elisp
(add-to-list 'auto-mode-alist '("\\.plantuml$'" . plantuml-mode))
(setq plantuml-executable-path "/usr/local/bin/plantuml")
(setq plantuml-default-exec-mode 'executable)
(setq plantuml-output-type "png")

(defun plantuml-preview-frame (prefix)
  (interactive "p")  
  (plantuml-preview 16)
  )
(add-hook 'plantuml-mode-hook
          (lambda ()
            (setq plantuml-executable-args
                  (append plantuml-executable-args '("-charset" "UTF-8"))
                  )
            )
          )

```

## 動作確認

![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847/20e8eb77-d208-2918-d733-83c4649bd62e.gif)

## 感想

コード補完の性能は vscodeのほうがいいかなという感じではあるが、emacsのほうが慣れているのでまあ気分で使い分けていくと思う。

## 参考

* [PlantUMLをMac OS Xで使う](https://qiita.com/kohashi/items/1d2c6e859eeac72ed926)
* [PlantUML + Emacs](https://skoji.jp/blog/2020/01/plantuml.html)
【3枚目】おっさんが入門CakePHP　(動画第４回:ControllerとViewで画面表示)

今回の動画ではControllerとViewを使って文字を画面に表示するらしい。

<b>【CakePHP3】ControllerとViewで画面表示【入門】</B>
https://www.youtube.com/watch?v=ANFACTySK20&t=248s

最初はMVCモデルについて説明。
分かり易く図示してくれてる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/694662fd-7765-650b-024a-42510850aacd.png)


今回はエディタとしてATOMを使用するとの事だが、ATOMのインストールについては説明がないので一応貼っておく。　　※他のエディタを使っても何も問題は無い。
ココからDownload　→　https://atom.io/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/841a6699-a0ee-2d8f-dc1b-7d1e16d679c8.png)
インストールしたら
Add Project Folder
で
cake-project
を追加。
その後はコントローラとビューを作るのだけど コードはコピペでOK　　※後半で説明してくれる
スースは↓
https://github.com/asterisk-lab/CakePHP/tree/main/code-001

コントローラは↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/7ca608f2-a341-ad6b-fa1d-34a93b552814.png)

ビューは↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/385d4858-cd8b-9c7a-acb7-052753ac3a42.png)

ソースの準備が出来たら　XAMPPでアパッチをスタート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/f043a04e-f909-0333-0489-b98d25b47717.png)

ブラウザで動作確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/f11e4e34-93c4-32d5-e048-3f235bf92668.png)


とりあえず、動かしてからのソースの説明
行毎に説明してるソースから読み取れないルールなどの注意点も解説してくれる。
過保護すぎでは？？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102625/5b27a335-687c-493e-7716-523c7b8025ca.png)


受講者的な本日のまとめ
・細かく説明してくれるのでcakephpの動きについては分かり易い。
・cakephpと関係のない個人の趣味が出る使うツール等は特定で押し付けないので解説無し。
Lootで話題の「コントラクトmint」を一緒にやってみよう

![](https://firebasestorage.googleapis.com/v0/b/hideaki-97c59.appspot.com/o/images%2FKg8fOSQeQSXraUWzyRlub9tFNoF2%2FwccX-aBzb.png?alt=media)

※2021年11月追記

いつも記事を読んでくださる皆様、ありがとうございます。

このたび本ブログは、[イーサリアムnavi](https://ethereumnavi.com/)へお引越しいたしました。

お手数おかけいたしますが、[こちらのリンク](https://ethereumnavi.com/2021/11/08/etherscan-contract-mint-nft/)からアクセスして記事を読んでいただけますと幸いです。

ご不便をおかけしてしまい誠に申し訳ございませんが、ご理解のほど何卒よろしくお願いいたします。

でりおてんちょー
AWS VPC でIPアドレスを10.0.1.0/16 を設定しようとするとmust be a valid ipv4 cidrのエラー

VPCやサブネットのIPアドレスは、EC2のような固有のIPアドレスではなく、ネットワークアドレスである必要があります。

ですので、IPアドレス設定時にネットワークアドレスを指定する必要があり、ネットワークアドレスのホスト部はすべて0になります。

10.0.1.0/16の場合だと、ホスト部がすべて0になっていない為、must be a valid ipv4 cidrのエラーになっていました。
10.1.0.0/16 とすることで正しく設定ができました。
テスト45

```vb

Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long

'Word
'Private Sub testopen(ByVal str_path As String, ByVal PW As String)
Private Sub testopen()
'⊂(`･ω･´)⊃ﾊﾞｯ
Dim strPassword As String
Dim hWnd As Long
Dim wd As Variant
Dim FSO As Variant
Dim w As Variant

Set FSO = CreateObject("Scripting.FileSystemObject")
strPassword = "111111"

wd = Shell("winword.exe C:\Users\User\Desktop\VBA練習\PDF\test3.pdf")

'ハンドル取得(ハンドルが取得できたということはポップアップが完全に表示されたということ)
Do Until hWnd <> 0

    hWnd = FindWindow("NUIDialog", "パスワード")
    
    DoEvents

Loop

SendKeys strPassword, True
SendKeys "{Enter}", True

Set wd = GetObject("C:\Users\User\Desktop\VBA練習\PDF\test3.pdf")

wd.SaveAs FileName:=FSO.BuildPath(wd.Path, "word_test.htm"), _
                    FileFormat:=wdFormatHTML

Set FSO = Nothing

End Sub
pmdarimaでARIMAモデルの次数を自動選択する

# はじめに

https://www.amazon.co.jp/dp/4903814874/ref=cm_sw_r_tw_dp_FVCFFJ8BE602B8574WAW?_encoding=UTF8&psc=1

時系列分析を学習するために「時系列分析と状態空間モデルの基礎」を購入したが、普段業務では専らPythonを使うので、できれば全編通してPythonで学習したい。

【RでやるべきことをPythonでやるシリーズ】と題して、上記本の実装例をPythonで実装し直すのに詰まった部分を備忘録に残す。

# 目的

 - 第2部7章「RによるARIMAモデル」より、Rのパッケージ`forcast`にはARIMAモデルの次数p,q,rの次数を最適化するための関数`auto.arima`が存在する。
 - Pythonの時系列分析パッケージとしては`statsmodels`が有名だが、上記関数に相当する機能はない。
 - 前例を探すと次数をGridsearchするFor文を書いて実行するコードが散見される。何とかして楽な書き方をしたいので、この処理をラップしたパッケージを探したい。

**参考**

For文でARIMAモデルの次数決定を行う例が記載

https://qiita.com/hcpmiyuki/items/b1783956dee20c6d4700

# 解決方法

 - `statsmodels`をラップしたパッケージ`pmdarima`を採用する。auto.arima関数に相当する関数が提供されている。

https://pypi.org/project/pmdarima/

**実装例**

```python
# インストール
# !pip install pmdarima

# パッケージダウンロード
import datetime
import pandas as pd
import pmdarima as pm
import statsmodels.tsa.api as tsa
import statsmodels.api as sm

# trainデータの準備
# ~~省略~~

# モデルの定義
auto_arima = pm.auto_arima(
                    y=train['front'], 
                    X=train[['PetrolPrice', 'law']], 
#                   stepwise=False, 
                    seasonal=True,
                    max_order = 5,
                    m = 12,
                    approximation = False,
                    information_criterion='aic')

# 実行
auto_arima.summary()

```

**結果**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591481/1d2048ed-3a62-af30-72af-d93a4c371293.png)

**補足**
 
 - trainデータセットは下記のようなデータを保持する
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/591481/56cb75e1-24d0-0c49-0842-2f382cedd555.png)
 - 季節性(Seasonal)及び外生変数(eXogenous)を定義しているため、正確にはSARIMAXモデルの次数決定をしている。
 - パラメータ`m`は季節性の周期、ここでは12（月）を指定している。
 - パラメータ`max_order`は$SARIMA(p,d,q)(P, D, Q)$における$p+q+P+Q$の最大値を指定する。大きくするとより複雑なモデルを候補にモデル選択を行う。
 - その他のパラメータは公式リファレンスを参照されたい。

# おわりに

今後はRDatasetのPythonでの参照方法や、pystanの実行方法などを整理する予定。

# 参考資料

https://alkaline-ml.com/pmdarima/modules/generated/pmdarima.arima.auto_arima.html

https://alkaline-ml.com/pmdarima/tips_and_tricks.html
Continuous DeliveryするためにGitLab RunnerからSSH接続

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

GitLab CI/CDパイプラインで外部のサーバーにSSH接続してCD(Continuous Delivery)したかった。

以下を参考にしました。

Using SSH keys with GitLab CI/CD | GitLab
https://docs.gitlab.com/ee/ci/ssh_keys/

GitLab Runnerで任意のSSH接続を行いたい - Qiita
https://qiita.com/fukasawah/items/9c257f0bc2dfe1d6823f

OpenSSHの警告メッセージを黙らせる – Siguniang's Blog
https://siguniang.wordpress.com/2014/02/28/get-rid-of-openssh-warning-message/

# 1. .gitlab-ci.yaml

以下の様な.gitlab-ci.yamlになりました。

```yaml:.gitlab-ci.yaml
default:
  image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/ubuntu:20.04

variables:
  USER: user
  SERVER_IP: "192.0.2.129"

.ssh_before_script:
  before_script:
    - 'which ssh-agent || ( apt-get update -y && apt-get install openssh-client -y )'
    - eval $(ssh-agent -s) && echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
    - mkdir -p ~/.ssh && chmod 700 ~/.ssh
    - echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config

connect:
  stage: test
  extend: .ssh_before_script
  script:
    - ssh $USER@$SERVER_IP 'ls -la'
```

# 2. 解説

Dependency Proxyを使っていない場合は、imageの`${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/`を削除してください。
GitLab.comでも使えるはずです。

SSH接続の前処理を再利用しやすいようにYAMLアンカーを使ってステージの外に出しました(.ssh_before_script)。
SSHを利用するジョブでextendを使って追加します。

SSH鍵秘密鍵は、「GitLabのプロジェクト」＞「設定」＞「CI/CD」＞「変数」で`SSH_PRIVATE_KEY`変数に入れてください。
ssh-agentがインストールされていない場合は、aptでインストールします。
SSH Fingerprintのチェック回避の為に`StrictHostKeyChecking no`を`~/.ssh/config`に書きました。ssh-keyscanが不要になります。

# 3. まとめ

 .gitlab-ci.yamlでextendを使ったことがありませんでしたが、やってみるとすっきり書けて良さそうです。
活用していきたいです。
これで完全に理解SwiftUI frame minWidth maxWidth

理解が曖昧だったminWidth maxWidthについて調査してみました。
この場合この法則が崩れるorこの場合はどの法則にも当てはまらないみたいなことがあったら教えてください!
idealWidth&idealHeightはわかりません!!!


## minWidthのみ
- 親Viewか子ViewどっちかよりminWidthが大きければminWidthになる
- 親Viewと子Viewの両方よりminWidthが小さいとき親Viewと子Viewの小さい方に合わせる

## maxWidthのみ
- 親Viewと子Viewの大きい方に指定した値まで大きくなる

## minWidth & maxWidth
- minWidthが親Viewより大きい場合minWidthに指定した値になる
- minWidthが親Viewより小さい場合maxWidthまで親Viewに合わせる
- minWidthが親Viewと子Viewの両方より小さいときmaxWidthまで親Viewに合わせる

## 参考
- https://medium.com/fantageek/how-to-use-flexible-frame-in-swiftui-f17c1e0d4c5f
Oracle Cloud Infrastructure での 2FA の設定

Oracle Identity Cloud Service のユーザーかどうかによって設定方法が異なるので、備忘録としてメモ

# 非 Oracle Identity Cloud Service ユーザー
こちらが最初にサインアップしたときに作られるユーザー
設定方法は、Oracle のドキュメントに従う
https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/usingmfa.htm?Highlight=two%20factor

# Oracle Identity Cloud Service ユーザー
何か色々やってると存在に気付くユーザー
知らないうちにこちらでログインしていることもある
設定方法は、以下の StackOverflow を参照
https://stackoverflow.com/questions/68097557/i-cant-enable-mfa-for-oracle-identity-cloud-service-user
arduinoでインスツルメント クラスター その2

#概要

arduino unoでcanからインスツルメント　クラスターを操作した。
シリアルから、コマンドで操作してみた。

#写真

![CIMG2968.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/0d989bfa-e608-4da2-3225-f786d87e85cb.jpeg)



#サンプルコード

|コマンド|rpm|speed
|:--|:--|:--|
|a|1000|20
|b|3000|
|c|5000|
|d||40
|e||100


```
#include <SPI.h>
#include "mcp_can.h"

MCP_CAN CAN(10);
unsigned char stmp[8] = {
	0,
	0,
	0,
	0,
	0,
	0,
	0,
	0
};

void setup() {
	Serial.begin(115200);
START_INIT:
	if (CAN_OK == CAN.begin(CAN_1000KBPS))
	{
		Serial.println("CAN BUS Shield init ok!");
	}
	else
	{
		Serial.println("CAN BUS Shield init fail");
		Serial.println("Init CAN BUS Shield again");
		delay(100);
		goto START_INIT;
	}
	Serial.print("\n>");
}
int rpm = 3000;
int speed = 40;
void loop() {
	if (Serial.available() > 0) 
	{
		char c = Serial.read();
		if (c == 13) 
			return;
		Serial.print(c);
		switch (c) 
		{
		case 'a':
			rpm = 1000;
			speed = 20;
		break;
		case 'b':
			rpm = 3000;
		break;
		case 'c':
			rpm = 5000;
		break;
		case 'd':
			speed = 40;
		break;
		case 'e':
			speed = 100;
		break;
		default:
			rpm = 7000;
			speed = 180;
		break;
		}
		Serial.print("\n>");
	}
	stmp[0] = (rpm * 4) / 256;
	stmp[1] = (rpm * 4) % 256;
	stmp[4] = (speed * 100 + 10000) / 256;
	stmp[5] = (speed * 100 + 10000) % 256;
	CAN.sendMsgBuf(0x201, 0, 8, stmp);
	delay(100);
}





```

以上。
Windows11で画面キャプチャをする方法と、クリップボードのデータを保存する ClipbdSv

以下で説明している ClipbdSv は、[**GitHub**](https://github.com/fukuyori/clipbdsv/releases)に公開されています。

Vectorにも登録されています。[**clipbdsv(Clipboard Data Saver)**](https://www.vector.co.jp/soft/winnt/util/se523454.html)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/e06ca7ad-d1e5-4396-9b79-50aaccdf6e28.png)


# 画面キャプチャのショートカット
　Windows11で画面キャプチャーをするとき、以下の操作ができます。

- 「PrintScreen」
    - デスクトップ画面の全体がキャプチャされ、クリップボードに入れる
- 「Alt」 + 「PrintScreen」
    - 選択したウィンドだけをキャプチャしてクリップボードに入れる
- 「Win」 + 「Shift」 + 「S」
    - 画面の一部をトリミングしてクリップボードに入れる
    - 画面上部に出てくるアイコンで、キャプチャ方法の選択も可能
    - 通知の表示から「切り取り＆スケッチ」で編集、保存も可能
- 「Win」 + 「PrintScreen」
    - デスクトップ画面全体がキャプチャされ、「ピクチャ」フォルダの「スクリーンショット」フォルダにPNG形式で保存される
- 「Win」 + 「Alt」 + 「PrintScreen」
    - 選択したウインドウをキャプチャし、「ビデオ」フォルダの「キャプチャ」フォルダにPNG形式で保存される

　この中では **「Win」 + 「Shift」 + 「S」** が最強なのですが、この機能を「PrintScreen」キー一発で行う設定があります。

　「設定」の「アクセシビリティ」にある「キーボード」から、「プリントスクリーンボタンを使用して画面切り取りを開く」をオンにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/b6786b55-009f-ddb4-a21f-df4ad5a83a3a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/51a3b222-e8db-551e-26a7-3b1bfa7874de.png)

　これで、「PrintScreen」ボタンを押すと、「Win」 + 「Shift」 + 「S」と同じ動作をするようになります。

# クリップボードの内容を保存する
　選択範囲を指定して保存するには、一旦クリップボードに入れてどこかに貼り付けを行って保存するのが一般的です。でも、張り付けるためのアプリを起動して保存操作を行う作業は、地味に面倒です。もっと操作を簡単にしたいとき、ClipbdSvは、アプリを起動するだけでデスクトップの「ClipbdSv」フォルダに保存されます。
　保存形式は、通常のテキストの場合はテキストファイル（拡張子.txt）、エクセルからコピーした内容はＣＳＶ（拡張子.csv）、ワードからコピーした内容はリッチテキスト（拡張子.rtf）、画面キャプチャや画像のコピーはJpeg(拡張子.jpg）として保存されます。
　また、画像ファイルがQRコードの場合、エンコードした内容をテキストファイルに書き出します。

　clipbdsv.exe をPCに保存し、アプリを右クリックで「その他のオプションを表示」から「タスクバーにピン留め」しておけば、いつでも呼び出せます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864075/d49b3476-89d6-0426-74c9-f3bc88c01cf5.png)

# コマンドラインオプション
　ClipbdSvには、いくつかのコマンドライン・オプションがあります。

-d 出力先のディレクトリを指定します。指定しない場合は、デスクトップの「ClipbdSv」フォルダになります。

-f ファイル名を指定します。拡張子は、自動で付与されますので、拡張子なしで指定します。指定しない場合は、日時に基づくファイル名を自動で作成します。

-t 出力形式を指定します。テキスト形式はtxt、CSVはcsv、チッチテキストはrtf、画像はimgを指定します。クリップボードの内容が指定された形式のものでなかった場合は、無視されます。エクセルデータは、txt、csv、imgいずれの形式でも出力できます。指しない場合は、クリップボード内のデータから自動で作成します。

-e 出力ファイルのエンコード方法をしてします。出力形式がテキスト、ＣＳＶの場合に有効です。

# コマンドラインオプションの例

```
clipbdsv

clipbdsv -d C:\temp -f clipimg -t img

clipbdsv -t txt -e Shift_JIS
```
AWS WEBサーバーからDBサーバーのMySQLにアクセスする

*[DBサーバー用のEC2の起動からMySQLのインストール](https://qiita.com/ebtiag/items/4449825d2542bc961259)の続き

##構成
*パブリックEC2
Linux 2
LANPサーバー

*プライベートEC2
MySQL8.0


##DBアクセスに使用するユーザーの状況を確認する

ローカル環境で作った場合、データベース接続に使用するユーザーがローカルホストからのみになっていることがあります
下記コマンドで表示内容のhostを確認します
```mysql> select user, host from mysql.user;```


ユーザーの権限変更ができるユーザーを作成します
```mysql> create user '[ユーザー名]'@'%' identified by '[パスワード]';```

特定IPから、もしくはどこからでもアクセス可能に変更します
（%はどこからでもアクセス）
```mysql> grant all on *.* to '[変更したいユーザー名]'@'%';```
[MySQL｜外部のホストから接続できるようにする方法 - わくわくBank](https://www.wakuwakubank.com/posts/322-mysql-access-host/)


##ユーザーの認証方式を変更する
MySQL8.0以降の場合、認証形式の変更が必要です

作成したユーザーの認証方式を確認
```mysql> SELECT user, host, plugin FROM mysql.user;```

pluginが caching_sha2_password になっている場合、　mysql_native_password　に変更
```ALTER USER '[ユーザー名]'@'%' IDENTIFIED WITH mysql_native_password BY '[パスワード]';```

##WEBサーバーからDBサーバーのMySQLにアクセスできることを確認する
```mysql -h [DBサーバープライベートIP] -D [データベース名] -u [ユーザー名] -p```

##参考
*[【MySQL】PHPで接続できないとき SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client](https://motomotosukiyaki.com/mysql-from-php-server-requested-authentication-method-unknown-to-the-client)
*デフォルトの認証方式変更をする場合
[phpからMySQL 8.0へPDOで接続時「SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client](https://symfoware.blog.fc2.com/blog-entry-2160.html)
RailsでWebP出し分けをimage_tagと同じ使い勝手で実装する

## TL;DR

1. ApplicationHelperにimaget_tagと同じ使い勝手のpicture_tagメソッドを作成
2. `従来フォーマットの画像 + .webp` という形式で画像を保存
3. Viewからpicture_tagを呼び出す

## 前提

一般的にRailsでpicture要素によるWebPの出し分けを行おうとすると以下のように、
view内において4行のコードに2つの画像パスを書くことになります。

```sample.html.erb
<picture>
  <source srcset="<%= image_path("WebP画像のパス") %>" type="image/webp">
  <%= image_tag('従来フォーマット画像のパス') %>
</picture>
```

参考：[railsでpictureタグによるwebp出し分けをする](https://qiita.com/you8/items/79deca47928495a2db7a)

WebP化したい箇所が少ないのであればこの方法は直感的かつシンプルです。
しかし、対応したい箇所が増えると途端に見通しが悪くなりますし、何よりDRYではありません。

## 調査

image_tagの実装を確認してみましょう。

```asset_tag_helper.rb
# 引数は画像のソースとclass, styleなどを取る(なければ空ハッシュ)
def image_tag(source, options = {})
  options = options.symbolize_keys
  check_for_image_tag_errors(options)
  # Rails 5.1で追加されたconfig項目
  # 詳細は以下を確認
  # https://y-yagi.tumblr.com/post/160114728555/rails-51%E3%81%A7%E8%BF%BD%E5%8A%A0%E3%81%95%E3%82%8C%E3%81%9Fconfig%E3%81%BE%E3%81%A8%E3%82%81
  skip_pipeline = options.delete(:skip_pipeline)

  # ここが肝心で、ソース名からasset_pipeline通過後の画像パスを取得している
  options[:src] = resolve_image_source(source, skip_pipeline)

  if options[:srcset] && !options[:srcset].is_a?(String)
    options[:srcset] = options[:srcset].map do |src_path, size|
      src_path = path_to_image(src_path, skip_pipeline: skip_pipeline)
      "#{src_path} #{size}"
    end.join(", ")
  end

  options[:width], options[:height] = extract_dimensions(options.delete(:size)) if options[:size]
  tag("img", options)
end
```

参考[rails / rails - actionview](https://github.com/rails/rails/blob/f33d52c95217212cbacc8d5e44b5a8e3cdc6f5b3/actionview/lib/action_view/helpers/asset_tag_helper.rb#L340)

## 解決策

image_tagを元にpicture_tagを実装してみましょう

```application_helper.rb
def picture_tag(image_source, options = {})
  # image_tag同様にskip_pipelineを確認する
  skip_pipeline = options.delete(:skip_pipeline)
  # WebPのパスを探す
  src_path = path_to_image("#{image_source}.webp", skip_pipeline: skip_pipeline)

  tag.picture {
    tag.source(srcset: src_path, type: 'image/webp') << image_tag(image_source, options)
  }
end
```

```
# 画像の保存先
app
┗ assets
  ┗ images
    ┣ test.png
    ┗ test.png.webp
```

```sample.html.erb
<!-- viewからの呼び出しはimage_tagと同じ -->
<%= picture_tag "test.png", loading: "lazy" %>
```

```sample.html
<picture>
    <!-- webpもちゃんとパスの解決できてます -->
    <source srcset="/assets/test.png-8fca8f7a0351d6cc6203f79b4d18da0d1f32d823db5294726104ee587d9eb47f.webp" type="image/webp">
    <img loading="lazy" src="/assets/test-49833f6482d22ae5aa5141294877224cf7907cb1de22e321c451666a380f11fe.png" alt="New business consultant">
</picture>
```

複数個所に入れるならpicture_tagを作っちゃうというのも手だと思います。
Fastify で decorate plugin を nested register で書く場合の注意点

# Fastify で Decorators を使う

fastify の decorators は非常に便利。

ただ、nest された register で decorators を登録しようとする場合、全てを [`'fastify-plugin'`](https://github.com/fastify/fastify-plugin) で囲む必要があるので注意。

きちんとドキュメントを読めばわかるが、軽く内容をメモしておく。
https://www.fastify.io/docs/latest/Plugins-Guide/#decorators

## decorators は子の register でしか使えない

まず大前提の知識として、FastifyInstance に生やした decorator はその配下の FastifyInstance でしか使えない。

```javascript
fastify.register((instance, opts, done) => {
  instance.decorate('util', (a, b) => a + b)
  console.log(instance.util('that is ', 'awesome'))

  fastify.register((instance, opts, done) => {
    console.log(instance.util('that is ', 'awesome')) // これは上手く動く
    done()
  })

  done()
})

fastify.register((instance, opts, done) => {
  console.log(instance.util('that is ', 'awesome')) // これはエラーになる

  done()
})
```

## `'fastify-plugin'` で囲めば、同じ階層でも使えるようになる。

```javascript
import fp from 'fastify-plugin';

// register する中身を 'fastify-plugin' でラップしている
fastify.register(fp((instance, opts, done) => {
  instance.decorate('util', (a, b) => a + b)
  console.log(instance.util('that is ', 'awesome'))

  fastify.register((instance, opts, done) => {
    console.log(instance.util('that is ', 'awesome')) // これは上手く動く
    done()
  })

  done()
}))

fastify.register((instance, opts, done) => {
  console.log(instance.util('that is ', 'awesome')) // これも上手く動く

  done()
})
```

## `.register` をネストさせる場合は、その全ての階層で `'fastify-plugin'` で囲む必要がある

当たり前といえば当たり前だが...

簡略化のために１ファイルに全て書いていますが、本来は `registerPlugins` 以降は別ファイルに定義することを想定しています。そのため、定義の順番とかは適当なので悪しからず

```typescript
import fastify, { FastifyPluginCallback } from 'fastify';
import fp from 'fastify-plugin';

const app = fastify();
app.register(fp(registerPlugins));

app.MAIN_PROPERTY // アクセスできる。（どこか1つでも fp が外れると、読めなくなる）

const registerPlugins: FastifyPluginCallback = (app, _ops, done) => {
  app.register(fp(registerMainPlugins));
  app.register(fp(registerSubPlugins));
  done();
};

const registerMainPlugins: FastifyPluginCallback = (app, _ops, done) => {
  app.register(fp(xxxPluginCallback));
  done();
};

const xxxPluginCallback: FastifyPluginCallback = (app, _opts, done) => {
  app.decorate(MAIN_PROPERTY, MAIN_VALUE);
  done();
};

const registerSubPlugins: FastifyPluginCallback = (app, _ops, done) => {
  app.register(fp(yyyPluginCallback));
  done();
};

const yyyPluginCallback: FastifyPluginCallback = (app, _opts, done) => {
  app.decorate(SUB_PROPERTY, SUB_VALUE);
  done();
};
```
Pythonで強力なパスワードを作る

Pythonで強力なパスワードを作る方法を簡単に解説した。
パスワードの文字数を入力すれば複雑な文字列を生成できる関数を作って実装する。

自力でランダムに文字を組み合わせてパスワードを生成することもできるが、機会で無作為に作成したほうがはるかに効率的だろう。

# 半角英数字だけのパスワードを生成

Pythonなら次の10行近くのコードだけで複雑なパスワードを簡単に生成できる。

```python
import secrets
import string

def get_random_password_string(length):
    pass_chars = string.ascii_letters + string.digits
    password = ''.join(secrets.choice(pass_chars) for x in range(length))
    return password

print(get_random_password_string(10))
print(get_random_password_string(13))
print(get_random_password_string(8))
```

上記のコードを実行すると、以下のように複雑な文字列が表示される。たったの10行で強力なパスワードを作れるのが凄い。

```
z8tzplZQ5e
EF2BfRm9A0cwF
QbfhSiln
```

やり方は以下に示す。

①パスワードの長さを第一引数としてパスワードを生成する関数<code>get_random_password_string</code>を定義する
▼
②パスワードを生成するための文字列<code>pass_chars</code>を<code>string</code>モジュールを用いて表現する
▼
③空の文字列に組み込み関数の<code>join</code>を用いて、第一引数として渡した整数の回数だけ<code>pass_chars</code>の中の文字列を取り出して<code>password</code>を作る。
▼
④戻り値として<code>password</code>を返す。

プログラムの中にある<code>string</code>モジュールと<code>secret</code>モジュールについて解説する。

<code>string</code>モジュールとは、文字列を操作するためのモジュールである。

<code>string.ascii_letters</code>は、アルファベットの大文字小文字全ての文字列を扱う。<code>string.digits</code>は、0から9までの半角数字を扱う。

<code>secret</code>モジュールは、パスワードやアカウント認証、セキュリティトークンなどの機密情報を扱うのに適した非常に強いランダムな文字列を生成できるモジュールである。このモジュールを使ってパスワードに適した文字列を表示できる。

これでPythonを使って簡単に複雑な文字列のパスワードを簡単に生成できるようになる。

# 半角英数字＋記号のパスワード生成

前述で取り上げたPythonプログラムの中にある式

```python
pass_chars = string.ascii_letters + string.digits
```

この式を、

```python
pass_chars = string.ascii_letters + string.digits + string.punctuation
```

このように変更するだけでより複雑なパスワードを生成できる。

<code>string.punctuation</code>を<code>print</code>関数で実行すると、

```
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
```

このように実行されるので、手入力で記号を入力する必要がない。つまり、アルファベットや数字ではない記号を扱うのに使われる。

▼プログラムの完成形はコチラ

```python
import secrets
import string

def get_random_password_string(length):
    pass_chars = string.ascii_letters + string.digits + string.punctuation
    password = ''.join(secrets.choice(pass_chars) for x in range(length))
    return password

print(get_random_password_string(10))
print(get_random_password_string(13))
print(get_random_password_string(8))
```

これを実行すると、以下のように表示され、前のプログラムよりも複雑なパスワードを生成できる。

```
$YpE{x/VKe
Bm]hn`#1Skr/[
ko3I;q!z
```

# おわりに

今回の記事では、Pythonで強力なパスワードを生成するための方法を解説した。
今回の記事をきっかけに、複雑で強力なパスワードを生成するプログラムの実装について理解を深めていただければ幸いである。


【参考サイト】

https://docs.python.org/ja/3/library/string.html

https://docs.python.org/ja/3/library/secret.html

https://gammasoft.jp/blog/generate-password-by-python/
[AWS基礎①]仮想ネットワーク構築用語 VPC サブネット ルートテーブル インターネットゲートウェイ

<h2>初めに</h2>
クラウド学習開始数日目です。
プログラミングスクールのカリキュラムで、仮想環境を構築しましたが、
正直何をやってるのか分からなかったので、Youtube動画を見て理解し直しました。

今回、構築時に出てきた用語の解説だけです。
現状理解がおかしい点はご指摘いただきたいです。

<h2>勉強させていただいたYoutube動画</h2>

https://www.youtube.com/watch?v=7J_crzU5KP8

<h2>AWSでサービスを使うには「仮想ネットワーク」を構築する必要がある</h2>

そこで構築するのがVPCです。
バーチャル　プライベート　クラウド　の略です。
図にすると以下のような感じになります。

![スクリーンショット 2021-09-05 9.21.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/c9d54158-5e68-a6c4-4a99-c1414588711f.png)

<h2>VPCが持つIPアドレスの範囲を定義する</h2>
VPC構築時に、IPアドレスを定義する必要があります。

<h2>VPCを作ったらサブネットが必要になる</h2>
VPCを構築したらその中にサブネットが１つ以上必要になります。
以下のようなイメージです。

![スクリーンショット 2021-09-05 9.27.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/29691a23-e284-6c26-df02-75de70a01bb0.png)

<h3>サブネットとは</h3>

サブネットは、仮想環境の中にさらに小さな仮想ネットワークを構築します。
上記の図のように「公開」「非公開」を設定できます。

:point_up:```「パブリックサブネット」```
インターネットから出れるし、入れます。
誰でもアクセスできます。
デフォルトのゲートウェイをインターネットゲートウェイに設定したルートテーブルを持った
サブネットがパブリックサブネットになります。（これについては後述）

:point_up:```「プライベートサブネット」```
インターネットに出れますが、外からは入れません。
データベースなんかはこちらに配置します。


<h3>サブネットのIPアドレスの範囲</h3>
サブネットはVPC内部に構築されますので、その中の範囲のIPアドレスを持つことになります。
また、サブネットも、IPアドレスの範囲を指定する必要がありますが、
範囲は重複して作成はできません。

<h2>ルートテーブル</h2>
ルートテーブルはサブネット毎に作ります。
Public用のサブネットのルートテーブルと、
Privateサブネット用のルートテーブルです。

<h2>インターネットゲートウェイ</h2>
Public用のサブネットのルートテーブルのデフォルトのゲートウェイを
インターネットゲートウェイに設定します。

以下のような感じ。
オレンジ色のものが、インターネットゲートウェイです。
ここを通じてパブリックサブネットは、インターネットから出たり、
アクセスされたりします。

![スクリーンショット 2021-09-05 9.36.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1633266/25fe6b07-bc37-c725-d837-1770f2210655.png)

<h2>終わり</h2>
プログラミングスクールのカリキュラムで、仮想環境を構築しましたが、
正直何をやってるのか分からなかったので、Youtube動画を見て理解し直しました。
まだまだ、理解できてないところは多いので、順次学習していきます。
【Venv】仮想環境の使用ライブラリをfreezeしたら思ってた10倍はパッケージが書き込まれた話【Anaconda】【備忘録】

#背景
ハッカソンにチームで参加するにあたって，Githubでコード管理をしようと思った．
いざ作った仮想環境のライブラリをfreezeしたら，インストールしてないライブラリまでめっちゃ書き込まれてて焦った．
前回に引き続き備忘録として投稿します．

#環境
OS：MacOS BigSur
ターミナル：zsh
PYTHONPATH：Anacondaに繋げました（[前回記事](https://qiita.com/Hana-mizu-wood/items/1cb320487fa1988d311e)はそれに伴う問題の解決）
↑今回はこいつが悪さしてます


#アプローチ
##とりあえずfreeze
Djangoのパッケージだけをpip installした環境を作成．
runserverまで確認できたので，ライブラリをfreeze

```
(venv)(base)$ python -m pip freeze > requirments.txt
```

##requiments.txtの確認
```
Django==3.2.7
その他numpyなど想定外に記述されたライブラリたち
```

あれ...?

##venv環境を作り直してみる
venvの環境構築は[Python Japan](https://www.python.jp/install/macos/virtualenv.html)を参照

##freeze, requimentsの確認
```
Django==3.2.7
その他numpyなど想定外に記述されたライブラリたち
```

やっぱりインストールしてないパッケージも記載される．　\ｺﾝﾆﾁﾊ/

##そういえば...
この前PYTHONPATHをAnacondaに繋げたことを思い出した．
Anaconda-Navigatorのenvironmentで確認すると，自分がどうやらAnacondaの仮想環境「base」上に存在することが判明．

![スクリーンショット 2021-09-05 9.18.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1494601/1e8fe48c-7616-06ea-45b6-8628876a5fc4.png)

確かにzshでも(base)って表示されてた...

```
(venv)(base)$ 
```

##Anacondaに別仮想環境を作成，切り替え
[【初心者向け】AnacondaでPythonの仮想環境を作成・切り替える(多分)最も簡単な方法](https://qiita.com/ell/items/fb60d2fd765650417c7a)
ということで上記記事を参考に，Anacondaで別環境を作成し，環境を切り替えました．
環境名はDjangoとしました．

Djangoの環境の方を起動させると...

```
(venv)(base)$ conda activate Django
(venv)(Django)$ 
```

無事に起動しました！

##ライブラリのインストール，freeze
再度Djangoをpip installし，freezeを行う．

```
(venv)(Django)$ pip install django
(venv)(Django)$ python -m pip freeze > requirments.txt
```

requirements.txtの確認

```
asgiref==3.4.1
Django==3.2.7
pytz==2021.1
sqlparse==0.4.
```
しっかり必要なパッケージのみが書き込まれてる！

#今回のオチ
PYTHOHPATHがAnacondaに繋がっていたため，デフォルトで使用する環境がAnacondaのbase環境になっていました．そのため，その上で仮想環境を構築しても，base環境のライブラリが利用できる状態になっていたことが原因でした．
学生エンジニアとかは結構陥りやすいイベントかもしれないので，こうなってしまった時は落ち着いてAnacondaの仮想環境を切り替えて対処してみてください．
（そもそもAnacondaにPYTHONPATHを繋げる人は少ないか...？）

本日の記事は以上です．
ハッカソン頑張ってきます！

--追記--
残念ながらハッカソンは入賞できず...
でもその過程でこの問題をはじめとして色々学ぶことができたのでヨシ！

#参考にさせていただいた記事
[【初心者向け】AnacondaでPythonの仮想環境を作成・切り替える(多分)最も簡単な方法](https://qiita.com/ell/items/fb60d2fd765650417c7a)
classNamesでReactのスタイリング

# はじめに

現在Reactについて勉強中なのですが、classNameを複数個宣言する方法がわからず調べたことを残しておきます(記録用)。classnamesというモジュールはとりあえずインストールしてていい気がしますね。

# classNameとは

Reactではjsx形式を扱いますが、classNameはそこでスタイリングを担当します。htmlで言うところのclassです。

# classNameの使い方

divタグにclassName={color_red}を与え、文字を赤色に装飾することができます。htmlを触ったことがある人は理解しやすいと思います。

```
export default Hello world!(() => {
  return (
    <div className={color_red}>
      <h1>Hello world!</>
    </div>
  );
});
```

# classNamesの宣言方法

では、classNamesと複数形で宣言する場合はどうなるのでしょうか？
* まず、`npm install --save classnames`でインストールが必要です(これを知らず困った)。
* インストール完了後、ファイルにインポートします。
* 以下のように、classNamesを使うと、複数のクラス名を定義して使うことができます。useStateなどと合わせて、複数の状態を変化させたい場合などに便利です。

```
import React, { useState } from "react";
import classNames from "classnames";

export default Hello world!　()　=> {
  return (
    <div className={classNames("signUp", "open")}>
      <h1>Hello world!</h1>
    </div>
  )
}
```

# 複数のクラス名を付けたい

classNamesを使うことで複数のクラス名を扱うことができます。

```
import React, { useState } from "react";
import classnames from "classnames";

export default App() => {
  return (
    <>
      <div className={classnames("signIn", "isOpen")}>
        <h1>Hello world!</h1>
      </div>
    </>
  );
}
```

# 動的切り替え

useStateを使い、ハンバーガーを食べている状態のスタイリングを変えたいとします。
このとき、statusをsetStatusで切り替えることによって、statusClassNamesが変化させられます。
classNameを、"eating"なのか"finished"なのかに切り替えられるというわけです。
※classNameは別途自分で設定する必要がある(ex. eating時のスタイリング、finished時のスタイリング)。

```
import React, { useState } from "react";
import classnames from "classnames";

export default function App() {
  const [status, setStatus] = useState("eating");
  const statusClassNames = {
    hamburger: true,
    eating: status === "eating",
    finished: status === "finished"
  };

  return (
    <>
      <div className={classnames(statusClassNames)}>
        <h1>A man who likes hamburger in a restaurant</h1>
      </div>
    </>
  );
}
```

classNamesを使うことで、簡単に動的なスタイリングができます。useStateによる状態管理ができれば、スタイリングの変更も自由自在ですね。

# 参考にした資料

・Reactのスタイリング(classNameやclassNamesの使い方)
https://qiita.com/terry_6518/items/de53123253cf67e048b3

・React公式ドキュメント(CSS とスタイルの使用)
https://ja.reactjs.org/docs/faq-styling.html

・classnamesパッケージドキュメント
https://www.npmjs.com/package/classnames
【Git】GitHubとssh接続する ~公開鍵・秘密鍵の生成~

##リモートへpushする際に、エラー発生
```
$ git push origin master
```
このようにリモートリポジトリへpushを試みたところ、エラーが出た。

```
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
公開鍵の認証ができませんでしたということらしい。

GitHubにssh接続するためには鍵の登録が必要とのことなので、その手順をまとめておく。

##公開鍵・秘密鍵を作成する
ターミナルを立ち上げ、以下のコマンドで鍵を生成する。

```
$　ssh-keygen -t rsa

//結果
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/＊＊＊＊＊/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/＊＊＊＊＊/.ssh/id_rsa.
Your public key has been saved in /Users/＊＊＊＊＊/.ssh/id_rsa.pub.
```
途中Enterキーの入力を3回求められる。
2・3回目はpassphraseの設定（パスワード設定のようなもの）ですが、ここでは何も入力せずEnterキーを押す。

##公開鍵をGitHubに登録する
###公開鍵の内容をクリップボードにコピーする
念のため、公開鍵が生成できているか確認する。

```
$ ls ~/.ssh

id_rsa      id_rsa.pub
//この２つのファイルが存在していれば、鍵が生成できている。
//id_rdaが秘密鍵で、id_rsa.pubが公開鍵
```
鍵が生成できていると確認できたので、公開鍵の内容を以下のコマンドでコピーする。

```
//Macの場合
$ pbcopy < ~/.ssh/id_rsa.pub

//Windowsの場合
$ clip < ~/.ssh/id_rsa.pub
```

###GitHubに登録する
以下のページで登録をする。
https://github.com/settings/keys

画面右上の**「New SSH Key」**をクリック。
1. Titleには任意の名前を入力。
2. Keyの欄に、クリップボードの内容を貼り付ける。
3. Add Key ボタンをクリック。



##参考記事

https://qiita.com/shizuma/items/2b2f873a0034839e47ce

https://monsat.hatenablog.com/entry/generating-ssh-keys-for-github
List内の指定した要素のインデックスを取得する【Kotlin】


## はじめに
Listから要素を検索しインデックスを取得します。
Kotlinでは、上記の処理をする関数がいくつかあるため紹介します。

紹介する関数は[公式](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/-list/)を参照しています。
バージョンは、Kotlin1.5です。

## indexOf,lastIndexOf
一致する一番最初の要素のインデックスを取得します。
該当するものがない場合は -1 を返します。
lastIndexOfは最後の方から探索します。

```kotlin
val list = mutableListOf('a', 'b', 'c', 'd', 'e', 'd')
println(list.indexOf('d')) // 3
println(list.lastIndexOf('d')) // ５
list.remove('d')
println(list.indexOf('d')) // -1
println(list.lastIndexOf('d')) // -1


```


## binarySearch,binarySearchBy
バイナリサーチで指定した要素のインデックスを取得します。
指定した要素が存在しない場合は　負の値　を返します。
ソートがされている前提なので、ソートがされていないと正しく動作しません。
引数でオプション（始点・終点・比較方法など）を設定できます。
binarySearchByは要素を変換したうえで探索することができます。

```kotlin
val list = mutableListOf('a', 'b', 'c', 'd', 'e')
println(list.binarySearch('d')) // 3
println(numberList.binarySearch(element = 2, fromIndex = 0, toIndex = 3))
println(numberList.binarySearch(element = 2, comparator = Comparator { a, b -> a - b }))
println(numberList.binarySearchBy(2, selector = { it }))

```