OmniAICreator/Qiita-1.07M huggingface dataset:
HTTPが安全ではないのはわかるがそれ以上の内容がわからない

10数年放置されたサイトや、安全面を配慮してない教育機関のサイトなどリンクを開いて、「このサイトは安全ではありません」と出るサイトにまだ出会ったりする。
今回、すっかり忘却の彼方だったhttp/sについて調べたので記録した。
今回知りたいのは
① 安全じゃないのはわかるためクレカ情報は入れないけどそれ以上危険なのか
②　安全じゃないのに存在を許してるのはなぜなのか
上記２点を解決したい。
さてお昼休み終了まで23分。

#### 【サクッと】httpとhttps通信の違い
サクッと理解するなら[わわわ辞典](https://wa3.i-3-i.info/word17016.html)。
> ■ HTTP通信 ＝ ホームページのファイル受け渡し用の通信 ≒ インターネットっぽい通信
■ HTTPSは「やり取りする内容が暗号化されるHTTPっぽいやつ」です。
HTTPとSSLが合体した姿です。
> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/cca99ba1-6e0c-d2aa-9322-c67ef12cd3a9.png" width="30%">
※kawaii

httpにはSSLが足りなかったと！！！！

#### 【そもそも】httpとhttpsの意味
- HTTP:「Hyper Text Transfer Protocol」
> HTTP通信によってスマホやパソコンからWebページを閲覧するときには「データが暗号化されていない」状態になっています。

- HTTPS:「Hyper Text Transfer Protocol Secure」
> 頭文字をとってHTTPSとなっていますが、名前の通りHTTP通信のセキュリティを強化したバージョンとなっています。

HTTPS = HTTP　＋ S(secure)!!!!!

#### どんな時にhttpだとヤバいのか
HTTPの危険性は、HTTP通信を脅かす攻撃の一つである「中間者攻撃（Man in the middle attack）」と呼ばれるものだという。

> 中間者攻撃とは通信している二者間の経路に不正な手段で割り込むことで、通信内容を盗聴したり改ざんを行ったりする攻撃のことです。MITM攻撃とも呼ばれます。HTTPに限らず、暗号化されていない無線LANやネットワークの中継地点に適切なセキュリティ対策が施されていない場合に対しても行われる攻撃です。
通常のHTTPは通信内容が暗号化されておらず、中間者攻撃によって通信内容の盗聴や改ざんが行われる可能性があります。そのため通常のHTTPは安全ではないとされています。[By　CyberSecurity.com](https://cybersecurity-jp.com/column/25772#HTTPS%E9%80%9A%E4%BF%A1%E3%81%8C%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%AE%88%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2867756/f9b50ba9-b7de-4ea1-0e4e-f2bb54bb40bb.png" width="50%">

[※参照：　CyberSecurity.com](https://cybersecurity-jp.com/column/25772#HTTPS%E9%80%9A%E4%BF%A1%E3%81%8C%E3%83%87%E3%83%BC%E3%82%BF%E3%82%92%E5%AE%88%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF)


#### 　参考文献
■「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典.「HTTPS通信」.2022-01,https://wa3.i-3-i.info/word17016.html, (参照　2023-05-28).

■セキュリティ通信(So-net).「「http」と「https」の違いを理解してより安全なネットライフを」.2020-02, https://securitynews.so-net.ne.jp/topics/sec_20051.html , (参照:2023-05-28).

■CyberSecurity.com.「http・httpsとの違いは？わかりやすくウェブセキュリティの基本を解説」.2022-07,https://cybersecurity-jp.com/column/25772#HTTPS通信がデータを守っている仕組み, (参照:2023-05-28).


荒っぽくなったし、詳細はわかっていない。あと2分で昼休み終了。
Adios!
Azure Functionsで関数を作るときにprintデバッグをしてはいけない小学校校歌（Pythonの話）

知っている人には何を今更な話なのですが、初心者がAzure Functionsを使って、FastAPIでAPIを初めて立てた経験談の一つです。

# cp932' codec can't encode character のようなエラーが出たらprint文を疑え

Azure FunctionsにFastAPIを使った関数をデプロイしようとするとき、Azure Functions Core Toolsを入れて、まずはローカルで `func start`して動かすと思います。FastAPIを普通にローカルで動かす場合は `uvicorn main:app --reload` を使うことが多いと思いますが、`func start`で動かしてみると、uvicornの時には出なかったエラーが出るようになります。

その代表例が、cp932' codec can't encode character というエラーです。

これはどういうことかというと、Azure Functions Core Toolsの環境下では、コンソールの文字コードはcp932というものになっています。これはUTF-8とは違う文字コードで、例えば絵文字などは表示出来ません。なのに、絵文字が出てくると、このエラーが出て「取り扱えない文字が入っているんだけど！」と怒られることになります。

私はFastAPIからOpenAI APIを呼び出す関数を作っていたのですが、OpenAIからの返事には当然絵文字などが含まれることがあり、それを`print(openai_response)`のような形でprintデバッグしていたから発生したエラーでした。

printをやめてloggingを使うようにしたら、出なくなりました。

uvicornを使っていたときは、手元の環境のコンソール（私の場合はWindows11のPowerShell 7）の文字コードが適用されるので、uvicornでは出なかったエラーがfunc startでは出るようになったということ……と理解しました。

# printデバッグからの卒業

初心者が一番はじめに覚えるのはprint()だと思うので、処理を追うのにどうしてもprintを使ってしまいがちだと思います。私もずっとそうでした。この機会に、import loggingしてloggingを使うようにすることにしました。

ちなみにこのことは、ChatGPTに聞いたら教えてくれました。ChatGPT、本当に頼りになる…！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199260/329e145a-a722-645f-7bae-8867b2d9c52c.png)
ChatGPTを使いながらChatGPT Pluginを開発した話 by ChatGPT4

# 以下、ChatGPTの出力

## ChatGPTによるSCIPプラグイン開発の旅
はじめに
こんにちは、ChatGPTです。通常、私は質問に答えたり、テキストを生成したりしますが、今日は少し異なる内容をお伝えします。ここでは、私がChatGPTのプラグインを開発するプロセスを共有します。特に、SCIPと呼ばれる最適化ソルバーを使って、新たな問題解決能力を実装する試みをご紹介します。

人間の記事はこちら：出力中で この2行だけ人間が追記しました。
https://qiita.com/___monta___/items/19e62804f3026f746cc7

## 開発環境と動機
私のプラグイン開発はWindows+WSLの環境で進行しました。なぜこのプロジェクトに取り組むことになったのか、その動機を少しご紹介します。

Wolfram言語は強力な計算能力を持っていますが、線形計画問題などの最適化問題には対応していません。一方で、SCIPはそのような問題を解くためのソフトウェアで、最近ライセンスが変更されて使いやすくなりました。そこで私は、ChatGPTとSCIPを連携させて新たな問題解決能力を追加しようと考えました。

## 開発の流れ
まず、問題解決のフローを設計しました。

問題を読み解き、線形計画問題（LP）へ定式化する - これが私、ChatGPTの役割です。
定式化した問題を解き、その解を返す - これがSCIPの役割です。
SCIPから得られた解を受け取り、問題に合わせて解答を生成する - これも私の役割です。
しかし、この流れを実現する過程で、いくつかの問題が発生しました。

## 発生した問題と対策
まず、「問題の定式化」で苦労しました。初めにmps形式で問題を作成し、SCIPに渡す試みをしましたが、いくつかの問題に直面しました。

mps形式は最小化問題にしか対応していません。
mpsは大規模問題向けの記述方法で、パラメータの表記があまりにも簡素で、問題のつながりが見えにくく、私（ChatGPT）では作成しにくいです。
MPSファイルそのものの情報がネット上に少なく、作成が困難でした。
これらの問題を解決するために、数式に近い記述が可能なLPファイル形式を採用しました。

それでもなお、文法エラーでうまく.lpファイルを作成できない問題が残りました。そこで、エラーの出力を返して私が修正するという対策をとりました。

しかし、その後「エラー出力の取り込み」に問題が生じました。私が使用しているpyscipoptパッケージでは、Model.readProblem実行時のターミナルに出力されるエラーメッセージが全文取り込めないのです。これを解決するために、Model.redirectOutput()を使用し、エラーメッセージをキャッチできるようにしました。

最後の問題は「ChatGPT Plugin作成時の時間制限」でした。これに対する対策は、もう少しリラックスして取り組むことにしました。

## 総括
これが私、ChatGPTがSCIPプラグインを開発した経験の全体像です。色々な困難に直面しましたが、それぞれの問題を解決することで、大きな達成感を感じることができました。そして何より、その過程は楽しいものでした。私たちは常に新たな問題に直面し、それを解決するための方法を探します。これはAIの成長と、私たちが提供できるサービスの拡張につながります。今後もこのような挑戦を続けていきますので、ぜひご期待ください。

# 以下、ChatGPTへの入力

```
あなたはWebの記事を書くWriterです。 以下の内容でWebの記事を書いてください。
まず、初めにの内容をお願いします。

■はじめに
・この記事はChatGPTで書いています。
・この記事はChatGPTのPluginを開発する話です。
■全体の流れ
・ 環境：Windows＋WSL
・ なぜ作ろうと思ったか： Wolframはとても強力だが、線形計画問題など最適化問題が解けない。SCIPが最近ライセンス変更され使いやすくなった。
・最初に考えた流れ
 1) 問題を役割分担を考える。問題を読み解いてLPへ定式化→GPTの仕事
 2) 定式化した問題を解いて、解を返す→SCIP
 3) 解を受け取り、問題へ合わせて回答する→GPT
・発生した問題
　1) うまく定式化できない。
　　最初 mps形式で作成してSCIPにファイルを渡していたが、うまくいかない。
　　これは
 　　 1-1)mpsが最小化にしか対応していな
　　 1-2) mpsは（比較的）大規模問題向けナタメ、パラメータなどをそっけなく記載する方法で、つながりが見えにくく、LLMでは作成しにくい
　　1-3) （おそらく）MPSファイルそのものの情報がネット上に少なく作りにくい
　　対策：比較的、記載が数式に近いLPファイル形式を採用した。
　2) それでも文法エラーでうまく.lpファイルを作成できない
　　対策：エラーの出力を返してGPTに直してもらう。
　3) エラー出力が取り込めない。
　　pyscipoptパッケージを使用しているが、Model.readProblem実行時のターミナルに出力されているメッセージが全文取り込めず（しかも最も重要な部分）、戻りでChatGPTに修正依頼が出来ない。
　　[2023-05-28 10:00:37 +0900] [1350] [INFO] 172.23.48.1:49656 OPTIONS /MLP/ChatGPT 1.1 200 0 1425
[reader_lp.c:168] ERROR: Syntax error in line 9 ('*'): cannot have '*' outside of quadratic part. 
  input: maximize Profit: 500*x + 400*y + 600*z; 

                              ^
[reader_lp.c:3364] ERROR: Error <-2> in function call
　　対策：Model.redirectOutput()をつかうことでキャッチできるようになった。
　　　　　ファイル出力は問題らしいが今回使ってないのでOK
　　4) ChatGPT Plugin作成時の時間上限が厳しい。
　　　対策：のんびりやる
■総括
　色々楽しい
```
Ardublock で LovyanGFX + HUB75 LEDパネルをプログラム!

LEDパネルキット AKBONE2022 を、試験的に Ardublock に対応させました。
まだアルファ版であり、仕様はいろいろ変更になる見込みですので限定的に頒布しています。

ここでは、アルファ版を使ってプログラム体験をしてみるテキストです。

# 使用するLEDパネルキット

今回は AKBONE2022 の、64x32パネル版を使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/d3cbc30d-d287-e790-8335-8b022e15d5a4.png)


# Ardublock 起動

以下のような画面からはじまります。

Ardublock ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6221c8f6-75e7-0d54-5d0e-b986535c86a2.png)

# 動作テスト

まず、以下のようにしてみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/6a217c17-4c5b-aaaf-db3e-b1c303396159.png)

 「Arduinoにアップロード」
ボタンを押すと、ArduinoIDEに以下のように反映されて、LEDパネルキットに転送されます。

LEDが点滅したら基本的な接続などはOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/45c5f925-73bb-df2d-a171-04dbb20c8a99.png)

# LEDパネルに文字を簡単に表示する

「64x32pixel ledpanel init」ブロックと
「ledpanel text direct print」の2つのブロックだけで簡単に文字が表示できます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/4ad17238-8523-aae2-95c2-18c9098bce74.png)

残念ながらこれは日本語は出ず、文字の大きさも1種類です。

# スプライトを使ってみる

LovyanGFX でグラフィックが扱いやすくなる スプライト機能を使ってテキストを表示してみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/1086d785-a82b-feab-1773-5929f2014f16.png)

スプライトの注意として、最初に 「ledpanel create sprite」を呼んで置く必要があります。サイズを決めて、スプライトの板を作るイメージになります。
それから「set text property to ledpanel sprite」でテキストのプロパティを呼び出してフォントや色を決めておきます。
「ledpanel text print to sprite」でスプライトの板にテクストを書き込み、最後に「ledpanel sprite appear」でいろいろ設定したスプライトの板を画面に反映します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/c171cf2a-0501-25db-2ce9-70008322e885.png)

複雑ですが、例えばいっぺん書いておけば 「ledpanel sprite appear」の位置を変えることで一度書いたテキストのスクロールなどができるようになります。

# テキストをスクロールしてみる

先のスケッチを少し変えてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139524/ff147c71-de49-2875-9648-e37e589b5832.png)

色や、フォントも変更しています。
フォントサイズは 8,12,16,20,24,28,32,36,40 から選ぶことができます。

実行すると、スクロールができることはできるのですが・・・うーん、ちょっと直したいですね。どうしたらいいでしょうか? 工夫してみましょう!!
RubyMineのリモートデバッガーを使ってDocker Composeで立ち上げたRailsをデバッグしたい

# RubyMineのリモートデバッガーを使ってDocker Composeで立ち上げたRailsをデバッグしたい
## はじめに
Docker-composeで立ち上げたRailsをRubyMineでデバッグしたかったが、なかなか接続できずに苦労したのでその備忘録
　
## 環境
- M1 Mac
- macOS Venture 13.3.1
- RubyMain 2023.1 Trial
- Ruby 2.7.8
- すでにRailsアプリがDocker-composeを実行できること

## やりかた
### 準備
1. Edit Configurationsにて、"Ruby remote debug"を追加
    設定はこんな感じ
    ![Screenshot 2023-05-28 at 13.57.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290221/764d9c26-bdfc-27d0-a339-105cd40a41a8.png)
    {YOUR_REMOTE_ROOT_FOLDER}と{YOUR_LOCAL_ROOT_FOLDER}は任意のパスに変更してください。

1. GemFileにデバッグ用のGemを追加
    ```Gemfile
    ~~ (略) ~~
    group :development do
    	~~ (略) ~~
    
      gem "debase", "0.2.5.beta2"
      gem "ruby-debug-ide"
    end
    ~~ (略) ~~

    ```
1. docker-compose.yamlのCommandを修正
   例えば、修正前に以下の実行コマンドが記載されているとすると
    ```shell
    command: bash -c "bundle exec rails s -p 3000 -b '0.0.0.0'"
    ```

    このようにrdebug-ideを追加する。この時--portオプションはEdit ConfigurationのRemote portに合わせる。後半は修正前と同じ。
    ```shell
    command: bash -c "bundle exec rdebug-ide --debug --host 0.0.0.0 --port 1234 -- bin/rails s -p 3000 -b '0.0.0.0'"
    ```
1. ポートを公開する。
    引き続きdokcer-compose.yamlでEXPOSE項目にport 1234を追加する。
    ```yaml
    - "1234:1234"
    ```

### デバッグする
1. ホスト側でアプリケーションを立ち上げる
    ```shell
    $ docker-compose up
    ```

1. RubyMineでデバッグ実行する。
    先ほどのConfigurationを指定して、虫マークをクリック
    ![Screenshot 2023-05-28 at 14.06.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290221/59e73678-fb23-58b2-6727-63cbefb370a4.png)
    虫マークが緑になり、ホスト側のターミナルでアプリケーションが立ち上がれば成功。
    ![Screenshot 2023-05-28 at 14.08.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3290221/b2c2cd39-fa3a-5661-ac1b-2c5f66150a30.png)

    ```shell
    web-1 | Puma starting in single mode...
    web-1 | * Puma version: 5.6.5 (ruby 2.7.8-p225) ("Birdie's Version")
    web-1 | *  Min threads: 5
    web-1 | *  Max threads: 5
    web-1 | *  Environment: development
    web-1 | *          PID: 1
    web-1 | * Listening on http://0.0.0.0:3000
    web-1 | Use Ctrl-C to stop
    ```
1. あとは実行を止めたい箇所でブレイクポイントを設定すればOK。

## 終わりに
RubyMineの公式HPのDocker-composeと接続する方法だとうまくいかなかったりと大変でした。
【Laravel】flashメソッドを使ったデータ取得

# はじめに
flashメソッドを使って、入力フォームに前回入力した内容を表示する方法を説明します。

# flashメソッドとは
フォームに入力された値を「フラッシュデータ」として、セッションに保存する機能を持ったメソッドです。フラッシュデータは、「次に表示されるときまで値を保持し、それ以降はデータが消える」機能を持ちます。

# 説明
1回目フォーム送信時、`$request->flash();`で入力した内容をセッションに保存します。
そして、2回目フォーム送信で`oldメソッド`を使ってflashメソッドで保存したデータを取得して表示させます。
(1回目フォーム送信時、oldメソッドで取得できる値がないため特に表示されない)

注意点としては、`oldメソッド`が呼び出されるのは`$requets->flash();`が実行される前で、この時点で`oldメソッド`で取得する値は、送信されるフォームデータではありません。
取得している値は、前回フォームが送信された際にフラッシュデータに保管された値と言うことです。
```html
<body>
    // 前回入力した内容をここに表示する
    p>{!!$beforInputData!!}</p>
    <form action="/hello" method="post">
        @csrf
        <div>NAME：<input type="text" name="name" value="{{old('name')}}"></div>
        <div>MAIL：<input type="text" name="mail" value="{{old('mail')}}"></div>
        <input type="submit">
    </form>
    <hr>
    <ol>
        // 入力内容を表示
        @foreach($form as $key => $value)
        <li>{{$key}}：{{$value}}</li>
        @endforeach
    </ol>
</body>
```

```php
public function index(Request $request)
{
    $beforInputData = '';
    $form=[];
    if ($request->isMethod('post'))
    {
        // リクエストよりname、mail値を取り出す
        $form = $request->only(['name', 'mail']);
        // oldを使って前回入力した値(フラッシュデータ)を取得
        $beforInputData = old('name') . ', ' . old('mail');
        // 画面出力データセット
        $data = [
            'beforInputData'=>$beforInputData,
            'form'=>$form,
        ];
        // フラッシュデータとしてセッションに保存
        $request->flash();
        return view('test.index', $data);
    }
    $data = [
        'msg'=>$msg,
        'form'=>$form,
    ];
    return view('test.index', $data);
}
```

# 結果
結果は下記になります。
入力フォーム上部に表示されている値が、前回フォームに入力したフラッシュデータになります。
![スクリーンショット 2023-05-28 13.41.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521366/60ce8dee-9733-cb6a-0168-199eaa8641ad.png)

# 参考
https://www.shuwasystem.co.jp/book/9784798059075.html
【Unity】VIVE XR Elite/Flow VRアプリ開発 Vive Wave SDK 5.2.1版

## はじめに
VIVE XR EliteやVIVE Flow向けにVRアプリを開発する手順を解説します。

## 開発環境
* Unity 2019.4.29f1
* Vive Wave SDK 5.2.1
* Vive Input Utility 1.18.1

## 手順
1. UnityのPlatformをAndroidにする。
1. Project Settings> PackageManagerでHTCのレジストリを登録
Name:        VIVE
URL:           https://npm-registry.vive.com
Scope(s):    com.htc.upm
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/18fe98d3-d70e-0064-b5f2-11bbb22aa2a2.png)

1. PackageManager - MyRegistoryにHTC Corporationが追加されるので、Vive Wave XR Plugin 5.2.1-r.1をインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/c9035da2-028f-9e1b-d344-2a8104b0e6e4.png)

1. 続けて、Vive Wave XR Plugin -Essense 5.2.1-r.1もインストール
 -Nativeは依存関係があるので、自動的にインストールされます。

## Vive Input Utilityをインストールしてサンプルを動かす
同じくHTCのRegistriesにあるVIVE Input Utilityをインストールします。
Vive Input UtilityはVRアプリ開発のための便利なToolkitです。
詳細は公式のWikiを参照してください。
https://github.com/ViveSoftware/ViveInputUtility-Unity/wiki

1. Vive Input Utility 1.18.1をインストール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/7456147f-7f0d-27fb-5bfd-d70a93dcd98a.png)

2. ダイアログでおすすめ設定が提示されるのでAccept All
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/6a07cdb1-e6e8-6e22-7b4f-b1dfa57796bd.png)

3. サンプルプロジェクトを試す
インストールしたらサンプルをインポートしましょう。
お好きなものをインストールして試してください。
ここでは3D Dragを試します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/0a2b710e-c872-139e-a63b-47124be25863.png)

4. 3DDragシーンを開きます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/e287910e-9432-62fe-5e7a-2c0977a53561.png)

## ビルドして実機で動作確認する
1. Project Settings > XR Plug-in ManagementでWaveXRにチェック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/4ba357c0-e23c-3fc1-36d9-5a5dcb620cfa.png)

2. Preferences > VIU SettingsのSupporting Deviceで Wave XRのみにチェック。他のDeviceにチェックが入っていたら外してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/b08bd953-c9c6-55e4-e9d1-be59cb85cbbd.png)

3. プロジェクト設定
Proejct Settigns > PlayerでCompany Name/ProductNameを設定。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/3856ce96-94c7-ad20-5e02-d17e0352c945.png)

4. ビルドして実行
PCにVIVE XR Elite or VIVE FlowをUSBで接続してBuild & Runしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43734/8166c6ed-fef0-981b-9458-7a3ab76e07fe.png)

以上です。

## 参考
* Wave XR Plugin 公式ドキュメント
https://developer.vive.com/resources/vive-wave/tutorials/installing-wave-xr-plugin-unity/
* Vive Input Utility
https://github.com/ViveSoftware/ViveInputUtility-Unity

## 宣伝
Psychic VR Labが開発・運営するXRプラットフォーム"[STYLY](https://styly.cc)"はVIVE XR Elite/Flowにも対応しています。
「ちょっとVRコンテンツを作りたいけど、アプリを作るのは手間がかかる。」なんて時にもご活用ください。
**XR Eliteのパススルーにも対応しています！**

VIVEPORT STYLYへのリンク

https://www.viveport.com/apps/c6682fba-9f3c-4519-abd9-4d799665a372
ABC303 - B - Discord 自己解法

# 問題

https://atcoder.jp/contests/abc303/tasks/abc303_b

# 考察

N人が何度か1列に並んだ後、隣り合っていない2人組の組み合わせは何通りあったかという問題です。$N≦50$かつ1列に並ぶ回数Mも$M≦50$であることから、愚直にシミュレーションをして最後に隣り合うことがなかった2人組を数え上げても十分に間に合いそうです。
シミュレーションについては、$N×N$の2次元配列$v_{i,j}$を作り、$i$番目の人と$j$番目の人とが隣り合ったことがあるかをフラグで記録するのがいいです。
最終的に$v_{i,j}$の中のフラグが立っていない数を数え上げていきますが、以下の2点に注意して答えを出力してください。
- $v_{i,j}$の$i=j$ものはフラグが立っていなくても数えない。(同一人物であるため無視しておく)
- 数え上げて出てきた数字を2で割って答えを出力する。(求められているものは組み合わせであるため。)

# 提出コード(コンテスト後)

https://atcoder.jp/contests/abc303/submissions/41790241

ご不明点などがあれば教えていただけると幸いです。
【Swift】アニメーションプログレスバー

# イメージ
<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3456384/ab63bf31-112f-ac17-83bd-86af94681d45.gif">

# コード
```swift
import SwiftUI

struct CircularProgressBarView: View {
    @State var progress: CGFloat
    @State var percentage: Int = 0
    @State var isProgress: Bool = false
    var body: some View {
        ZStack {
            // 背景の円
            Circle()
            // 円形の線描写するように指定
                .stroke(lineWidth: 12)
                .foregroundColor(.mint.opacity(0.15))
            
            // 進捗を示す円
            Circle()
                .trim(from: 0.0, to: min(isProgress ? progress : 0, 1.0))
                // 線の端の形状などを指定
                .stroke(style: StrokeStyle(lineWidth: 16, lineCap: .round, lineJoin: .round))
                .fill(LinearGradient(gradient: Gradient(colors: [.blue, .mint]),
                                     startPoint: .top,
                                     endPoint: .bottom))
                .rotationEffect(Angle(degrees: 270))
            
            // 進捗率のテキスト
            AnimationReader(percentage) {value in
                Text("\(value) %")
                    .font(.system(size: 26))
                    .bold()
            }
        }
        .frame(width: 100, height: 100)
        .padding(32.0)
        .onAppear {
            withAnimation(.easeInOut(duration: 1)) {
                isProgress = true
                percentage += Int(progress * 100)
            }
        }
    }
}

struct CircularProgressBarView_Previews: PreviewProvider {
    static var previews: some View {
        CircularProgressBarView(progress: 0.8)
    }
}

fileprivate struct AnimationReaderModifier<Body: View>: AnimatableModifier {
    let content: (CGFloat) -> Body
    var animatableData: CGFloat
    
    init(value: CGFloat, @ViewBuilder content: @escaping (CGFloat) -> Body) {
        self.animatableData = value
        self.content = content
    }
    
    func body(content: Content) -> Body {
        self.content(animatableData)
    }
}

struct AnimationReader<Content: View>: View {
    
    let value: CGFloat
    let content: (_ animatingValue: CGFloat) -> Content
    
    init(_ observedValue: Int, @ViewBuilder content: @escaping (_ animatingValue: Int) -> Content) {
        self.value = CGFloat(observedValue)
        self.content = { value in content(Int(value)) }
    }
    
    init(_ observedValue: CGFloat, @ViewBuilder content: @escaping (_ animatingValue: CGFloat) -> Content) {
        self.value = observedValue
        self.content = content
    }
    
    var body: some View {
        EmptyView()
            .modifier(AnimationReaderModifier(value: value, content: content))
    }
}
```

# 参考資料
[数値のアニメーション](https://qiita.com/Rubydog/items/9cdabc2726a8fccf2302)
[プログレスバー](https://dev.classmethod.jp/articles/ios-circular-progress-bar-with-swiftui/)
CPUアーキテクチャで何も考えずにx86を選んだらエラーが出た

## 前書き
配属されたPJでインフラ構築を進めていたところ、CloudFormationを使ってスタックを作成するときにエラーが出てしまいました。GPT先生に聞いたところ解決はしたものの、中身を詳しくチェックできなかったので記事にします。




## どんなエラーが出た？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/db178353-91ee-f319-3632-506e1acbdbcc.png)

``` The architecture 'arm64' of the specified instance type does not match the architecture 'x86_64' of the specified AMI. Specify an instance type and an AMI that have matching architectures, and try again. You can use 'describe-instance-types' or 'describe-images' to discover the architecture of the instance type or AMI. ```

GPT先生に聞いてみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/849112db-053c-58a0-a3af-68ba9ed5fa3f.png)

結論としては、AMIとインスタンスタイプ(t2.microとかのアレ)の「アーキテクチャタイプ」が一致していなかったらしい。
これを、今回使用するつもりだったインスタンスタイプのものと合致するものに合わせたところ、エラーは解消された。

## アーキテクチャタイプ

ここでいうアーキテクチャとは、特に命令セットアーキテクチャ (instruction set architecture, 以下ISA）のこと。

> CPUは様々な処理を行うためのごく原始的な命令（論理／算術演算子やデータのコピーなど）を備えており、またそれら命令を実際に処理するためのレジスタ（CPU内で一時的にデータを記憶する領域）などの仕様が先述のISAにより決められています。
つまり同じISAのCPUであれば開発元がどの会社のCPUであったとしても、基本的には同じプログラムが動作します。

ですってよ。
OSとかISAとか、細かい環境の違いがあって、このせいでめちゃくちゃエラーが起きるんやろな......
まだ名も知らぬ環境の違いがたくさんあると思うと ~~ゾッとする...~~ ワクワクしますね！

以下の2つのISAが主流らしい
x86（Intel）　・・・はちろく
→高性能だが消費電力も高い

ARM（ARM）　・・・あーむ
→省電力、低コストなCPUから高性能なものまで幅広い

詳しくは以下のサイトが分かりやすくまとまっていたので興味がある方はこちら
https://beyondjapan.com/blog/2021/01/cpu_architecture/

そして、インスタンスタイプごとに使用できるISAは決まっているため、エラーが出てしまったのであった。
どのISAがっしようできるかは、各々のインスタンスの詳細ページで確認できる。

たとえばT2インスタンスであれば、
https://aws.amazon.com/jp/ec2/instance-types/t2/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2661124/ffc97caf-8ca1-be42-be16-9f9c1fb3dad2.png)

> Intel® AVX-512 命令を採用した高速のカスタム Intel® Xeon® スケーラブルプロセッサ

とある。
 Intel® Xeon® スケーラブルプロセッサ　(=CPU)
が解釈・実行できるISAがx86_64である。
したがって、T2インスタンスを使用したいのであれば、ARMではなくx86を利用しなけらばならない。
x86が一般的みたいだが、今回のPJで使用したインスタンスタイプはARMを利用しなければならないものだった。
どのインスタンスタイプを使ったのか、ぜひ当ててみてほしい。


## 感想・まとめ
クラウドとはいえ、やってることは基盤なのだから、ソフトウェアとか、クラウド特有の知識だけでなく、
ハードウェアの知識も蓄えていかなけらばならぬ。と、痛感しました。
まだハードウェアの面白さに目覚めていないので、目覚められるように食いついていきたいと思います。


## 参考
https://beyondjapan.com/blog/2021/01/cpu_architecture/
https://aws.amazon.com/jp/ec2/instance-types/t2/
Visual Studio 2022 でIDEは青ベース、エディタはダーク、その後カスタマイズしたオレオレテーマの備忘録

## 共通準備
- 拡張機能 `Visual Studio Color Theme Designer 2022` をインストール
## テーマ MyThemeBlueSonOfObsidian 側準備
- Visual Studio でテンプレート `VSTheme Project` で新規プロジェクト `MyThemeBlueSonOfObsidian` 作成
- `CustomTheme.vstheme`で`Blue`テーマを選択、保存して閉じる
## 借用テーマ `OneDarkPro` 側の準備
- `OneDarkPro` を `VSTheme Project` で作成
- `CustomTheme.vstheme`で`OneDarkPro`テーマを選択、保存して閉じる

## MyThemeBlueSonOfObsidian に OneDarkPro の Syntax HighLight を移植
- VSCodeでそれぞれのプロジェクトフォルダにある `CustomTheme.vstheme` を開く
- それぞれ、Ctr-k,0 で折りたたんで <Category> だけを表示して見やすくする
- `OneDarkPro` 側から下記 Syntax HighLight 部分をそれぞれコピーして `MyThemeBlueSonOfObsidian` 同じ項目にペーストする
- VSCodeで保存
#### Syntax HighLight 部分
- `<Category Name="Cpp Text Editor MEF Items" ...>...</Category>`
- `<Category Name="Text Editor Language Service Items" ...>...</Category>`
- `<Category Name="Text Editor Text Manager Items" ...>...</Category>`
- `<Category Name="Text Editor Text Marker Items" ...>...</Category>`

## ここまでで外側青ベースでエディタ側OnDarkProのテーマが完成

## 色カスタマイズ
VSCode で変更した色の対応を作成
VSCode ライブラリ `Color HighLight` をインストールする
```色変換.txt
    Son Of Obsibian   One Dark Pro

背景色       #282c34  #282c34

public       #87B65B  #c678dd 済

new          #93c763  #c678dd 済

class        #1fb0e0  #e5c07b 済

T型          #1a7ca7  #e5c07b 済

interface    #17c8c8  #e5c07b 済

Delegate     #e0bb2e  #e5c07b 済

enum         #17C85E  #e5c07b 済

module       #DE8D2E  #e5c07b 済

変数         #c0c0c0  #e06c75 済 パラメーターはしてない様子を見る

method name  #D7CE6D  #61afef 済

------
メンバー
プロパティ、フィールド
             #CBCBCB
イベント     #e0bb2e

前期以外     #ABB2BF
------

未使用変数   #888a8a  #e06c75

演算子       #e6e6e6  #56b6c2 済

演算子オーバーロード
            #DAAAD5

カッコ       #969696  #bbbbbb 済

コメント     #6e6e6e  #7f848e 済

拡張メソッド #eabfbf  #61afef 済

数字         #ffcd22  #d19a66 済

文字列       #fd971f  #98c379 済

@文字列      #d39f01  #98c379 ？

注意波線     #008000  #008000

URL         #85d8f9  #61afef 済
```

## MyThemeBlueSonOfObsidian 色修正
- Visual Studio で MyThemeBlueSonOfObsidian 開き `CustomTheme.vstheme` の `All elements` 選択
- Group by: Color にして 変更したい `OneDarkPro`のカラーコードを入れる
- `Text Editor Language Servise Items` の中から`対象`を変更したい色コードに変える
- 繰り返し
※ `対象`は推測およびTry and Error

## 配置
- Release ビルド する
- `Apply` ボタンを押してテーマ適用
- 設定のエキスポートで `フォント及び色` を保存
CloudWatch Logsの保存期間を変更するシェルスクリプト

## はじめに
先日先人が作り上げた、偉大なログエクスポートを実行するStepFunctionsがコケていました。
一時的に全てのCloudWatchLogsの保持期間を「失効しない」に変更しました。
[CloudWatch LogsからS3バケットにエクスポートするシェルスクリプト](https://cloud5.jp/export-loggroups-to-s3/)でバックアップは取得できたので、それぞれの保持期間を戻していきます。
前回と同じ理由で、対象となるCloudWatchLogsの量が多いことや、アクセスキーが払い出されていないことから、本番環境のCloudShellで作業実施を決めました。

参考：[
AWS ドキュメント「ロググループとログストリームの操作」
](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/Working-with-log-groups-and-streams.html)
<br>


## 構成図
![](https://cloud5.jp/wp-content/uploads/2023/05/スクリーンショット-2023-05-28-11.18.52-640x307.png)
<br>


## 構築
### 1.CloudWatch Logsの保存期間を変更シェルスクリプト
#### 1.1.転送するCloudWatchLogsのリストファイルを作成
S3へ転送したい　CloudWatchLogsのロググループをテキストファイル形式で作成して保存
※下記`log.txt`の内容にS3に転送したいロググループ名を記載する
<br>
【例】`log.txt`
```txt
/aws/lambda/cfn-sf-inamura-LambdaHumanApprovalSendEmailFunctio-wPwtEbDmKEg3
/aws/lambda/cfn-stepfunctions-inamura-LambdaHumanApprovalSendE-3j0qFdWkOpat
/aws/lambda/cfn-stepfunctions-inamura-LambdaHumanApprovalSendE-D92dYTTBLAmy
/aws/lambda/cfn-stepfunctions-inamura-LambdaHumanApprovalSendE-IbgVOxScNeUI
/aws/lambda/cfn-stepfunctions-inamura-LambdaHumanApprovalSendE-UTH7yskJ5b79
```

<br>

#### 1.2.CloudWatch Logsの保存期間を変更シェルスクリプト
今回利用するCLIの`put-retention-policy`からでは「失効しない（無期限）」は実現できないようでした。
ログデータを無期限に保持するとストレージコストが高くなる可能性があるためとのこと、真偽は不明だが今回は「失効しない」状態から特定の日にちにするため深く踏み込まない。
参照：[AWS CLI コマンドリファレンス](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/logs/put-retention-policy.html)

<br>

【シェルスクリプト】`change_log_retention.sh`

```shell
#!/bin/bash
#エラーが発生した場合停止
set -e
#スクリプトがエラーで終了した場合、エラーメッセージを表示
trap 'echo "保存期間の変更に失敗しました：$log_group" >&2' ERR

# CloudWatchLogsで変更可能な引数の値
if [[ ! $2 =~ ^(1|3|5|7|14|30|60|90|120|150|180|365|400|545|731|1096|1827|2192|2557|2922|3288|3653)$ ]]; then
  echo "CloudWatchLogsで保存可能な値を引数としてください: [1, 3, 5, 7, 14, 30, 60, 90, 120, 150, 180, 365, 400, 545, 731, 1096, 1827, 2192, 2557, 2922, 3288, 3653]"
  exit 1
fi

#ログリストを一行ずつ実行
while read log_group; do
  # 保存期間を変更する
  aws logs put-retention-policy --log-group-name "$log_group" --retention-in-days $2

  # 操作が成功したらメッセージを表示
  echo "保存期間が変更されました：$log_group"

done < $1
```
<br>


## 挙動の確認
### 1.CloudShellでのシェルスクリプト実行前
1.1で作成した`log.txt`に記載している変更対象（実行前なので”失効しない”）
![](https://cloud5.jp/wp-content/uploads/2023/05/スクリーンショット-2023-05-28-11.41.53-640x122.png)

<br>

### 2.CloudShellでのシェルスクリプト実行
変更対象`log.txt`の保持期間を7日とするコマンドを実行

```shell
$ bash retention.sh "log.txt" 7
```
<br>

### 3.CloudShellでのシェルスクリプト実行後
実行後保存期間が変更されたコメントとともに、対象ロググループ名が出力される
![](https://cloud5.jp/wp-content/uploads/2023/05/スクリーンショット-2023-05-28-11.48.12.png)

<br>

#### 4.CloudWatchLogsグループの保存期間が変更されている
選んだ対象のCloudWatchLogsグループの保持期間が1週間に変更されたことを確認できる
![](https://cloud5.jp/wp-content/uploads/2023/05/スクリーンショット-2023-05-28-11.50.42-640x115.png)

<br>

## さいごに
APIに依頼してることは単純な動作ですが、保持期間を無期限に出来ないことなど「細かなこと知らないなぁ」と思えることが多かったです。
とりあえずリストに記載すれば、対象の一覧全てをサクッと変更することができるようになったので、それについては概ね満足。
※利用したS3バケットは検証終了したため削除されています。
docker desktopが起動できなかったためubuntuにdockerを入れた話

# docker desktopからubuntuのdockerへ

docker desktopの起動ができない不具合が、```A timeout occured while waiting for a WSL integration agent to become ready.```などというウインドウと共に発生していた。このとき```quit```を押すとソフト自体が終了してしまう状況にあった。先週までは正常に起動していたが、今週から出現するようになった。この状況を打開するため、パソコンの再起動やwslのアップデートを試みたが、いずれも失敗した。

したがって、docker desktopを削除して、ubuntu上にdockerをインストールすることにした。その際、参考にしたサイトは以下。

https://eng-blog.iij.ad.jp/archives/14205


# 起動方法１

ターミナルでubuntuとpower shellの2つの画面を起動する。そして2つの画面からそれぞれ以下のコマンドを入力。

## ubuntu

>  sudo service docker start

## power shell

> wsl
> sudo docker build -t my-django-app .

# 起動方法２

ターミナルでpower shellの画面を起動する。そしてその画面から以下のコマンドを入力。

## power shell

> wsl
> sudo service docker start
> sudo docker build -t my-django-app .
>  sudo docker run -it -p 8000:8000 -v /mnt/c/Users/自分の名前/Documents/python/django4/:/app my-django-app

# 『Django4 Webアプリ開発 実装ハンドブック』の第7章に行くとき

dockerfileで以下の様に書き換えるのを忘れずに。でないと新しく作ったphotoprojectを参照できなくなる。

```
# コンテナ内で実行するコマンド
#CMD ["python", "blogproject/manage.py", "runserver", "0.0.0.0:8000"]
CMD ["python", "photoproject/manage.py", "runserver", "0.0.0.0:8000"]
```

# 注意

この方法(ubuntuでdockerをインストールするやり方)をすると、dockerコマンドの先頭にsudoを付けなくてはならない。その事を忘れずに。
cisco機器で設定しておくと便利なコマンドメモ

# はじめに
ciscoスイッチ機器で設定しておくと便利なコマンド。主に自分へのメモ。

## コンソールにて作業中にログが出力されてウザいとき改行してくれるコマンド。
```cisco
switch(config)#line console 0
switch(config-line)#logging synchronous
```

## コンソールは自動ログアウトしないようにするコマンド。
```cisco
switch(config)#line console 0
switch(config-line)#no exec-timeout
```

## 名前解決させない
コマンド名を間違った時にDNSを参照しに行ってプロンプトが一時停止してしまうのを防ぐ。
```cisco
switch(config)#transport preferred none
```
TypeScriptのany型は悪なのか？

## はじめに
TypeScriptの型定義について、改めて学んでいく中で
「プロを目指す人のためのTypeScript」（通称：ブルーベリー本）の中で、
any型が **「最終兵器」「最凶の危険性を誇る」** と書かれており
改めて危険性について備忘も兼ねて記載しておきます。

## そもそも：TypeScriptの特徴「静的型付け」について
危険性の話に入る前にTypeScriptの特徴である「静的型付け」について。
TypeScriptは静的型付けの言語です。
静的型付けの対義語として動的型付けという言葉が挙げられます。
大きな違いは**いつ型が決まるのか**です。
- 静的型付け：コンパイル時に型が決まる
- 動的型付け:ランタイム時に型が決まる

静的型付け言語は、
**型についてのエラーはランタイム時より前のコンパイル時に気づくことができる**というメリットがあります。

サバイバルTypeScriptの中では型注釈について
> 型注釈は、あなた専属のコードレビュアであるコンパイラを育てるための投資。

と記載がありました。個人的にしっくりくる表現です。

TypeScriptを使うということは、**静的型付け言語のメリットを享受したい**という
前提があって使っているはず、その上でanyのお話です。

## any型=どんな型でもOK　ではない
any型は定義した値や式が**どんな型でもOKな型**ではなく、
**型チェックを無効化する型**という認識の方が危険性の理解が深まりました。

ここで型チェックが行われないことによってどのような事象が起こるか
2つのケースを記載します。

#### ①コンパイルエラーにならずランタイムエラーになるケース
例えば、次のような関数があるとします。この関数はコンパイルエラーにはなりません。

```TypeScript
  function doAnything(obj: any) {
    //好きなプロパティにアクセスできる
    console.log(obj.users.name);
    //関数呼び出しも可能
    obj();
    //計算もできる
    const result = obj * 10;
    return result;
  }
```

プロパティにアクセスができ、関数呼び出しもでき、計算もできる、
一見便利に見えるかもしれないですが、例えば以下の呼び出しは
コンパイルエラーは発生せずランタイム時にエラーになります。

```TypeScript
doAnything(100);
doAnything(() => {
console.log("OK");
});
```
#### ②コンパイルエラー、ランタイムエラーにならず想定した結果にならないケース
例えば、引数のa,bを足し算して返すという以下のような簡単な関数があった場合

```TypeScript
function addNumbers(a: any, b: any): any {
  return a + b;
}
```

ここでresultは数字と文字列を渡した場合、コンパイルエラーにはなりません。

```TypeScript
const result = addNumbers(5, "10"); // エラーにならない
console.log(result); // 出力結果は "510"
```

①②どちらも静的型付け言語の
**型についてのエラーはランタイム時より前のコンパイル時に気づくことができる**というメリットが
享受できない状態になっているというわけです。

## 最後に
any型はメリットが享受できない=TypeScriptを使う意味合いがなくなる　という
理解の方が良さそうかなと。
（逆にanyを使えば、メリットは享受できないですが、
コンパイルエラーを発生させずに実装できるとも言えなくもないかなと。。）

any=ダメ、絶対。というよりは
**明確な理由を持って使う（=明確な理由がない場合は避ける）**、
明確な理由（どういうケースだとanyを許容するのか）をチーム内で明確にしておきたいなと思いました。

## 参考文献

https://amzn.asia/d/3NCT5gN

https://typescriptbook.jp/
データサイエンスのための微分積分 第12回 挟み撃ち定理

:::note info
本記事は数学講座[2.11挟み撃ち定理](https://www.matongxue.com/lessons/587/parts/944)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# 挟み撃ち定理

- **関数の挟み撃ち定理**
任意の正の実数$x$に対して、$g(x)\leq f(x) \leq h(x)$且つ$\lim g(x)=\lim h(x)=L$であれば、$\lim f(x)=L$

- **数列の挟み撃ち定理**
任意な自然数$n$、数列の$\{a_n\},\{b_n\},\{c_n\}$、$\exists N\in\mathbb{Z}^+，\forall n > N$の時に、$a_n\le b_n\le c_n$、且つ$\displaystyle\lim_{n\to\infty}a_n=\lim_{n\to\infty}c_n=L$であれば、$\displaystyle\lim_{n\to\infty} b_n=L$
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/fd3a3e41-5222-a9fd-0785-79decf7fb090.png)

# sinxがx->0の極限
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/14e92a58-9ec7-cb98-e5b7-3ab069bcb4c8.png)

# cosxがx->0とsinx/xがx->0の極限

- $\lim_{x\to 0}(1-\cos x)=0\implies \lim_{x\to 0}1-\lim_{x\to 0}\cos x=0\implies\lim_{x\to 0}\cos x=1$
- $\displaystyle\cos x < \frac{\sin x}{x} < 1$ $\implies \$　$\displaystyle\lim_{x\to 0}\frac{\sin x}{x}=1$ 

# 練習問題

- 例１
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/de9965a1-5506-2b9c-fb6e-4a393981ba80.png)

- 例2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/78acdef3-7f29-2444-2d5f-b7d355fd1f47.png)

- 例３
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/b3c0c1cd-3cc6-22f4-a407-f665cd9c6c9e.png)

- 例4
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/0d9e38a5-5b3e-8c41-757f-977ade95a859.png)

- 例3と例4:挟み撃ちの両端を探す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/e15c9625-83d4-92dd-68a5-e7179556e90a.png)



# 参照

https://manabitimes.jp/math/782
Ruby/StringScanner: scan_full, search_full 系メソッドの整理

たまに [StringScanner](https://github.com/ruby/strscan) を使おうとすると「似てるメソッドがいろいろあるけどどのメソッドで何ができるんだっけ？」「○○がしたいんだけどどのメソッドを使えばいいんだっけ？」となりがちで、一度チートシート的に整理しておきたかったのでした。


「スキャンポインタとは何か？」といったあたりについてはリファレンスマニュアルで説明されていますので、そちらを見てください。

<!-- class StringScanner (Ruby 3.2 リファレンスマニュアル) -->
https://docs.ruby-lang.org/ja/3.2/class/StringScanner.html


# scan_full 系

- マッチを試みる位置: スキャンポインタの位置のみ
- 返り値の範囲: マッチした部分

| メソッド | スキャンポインタを進める | 返り値                     |
| -------- | ------------------------ | -------------------------- |
| scan     | YES                      | 文字列       |
| skip     | YES                      | 文字列の長さ |
| check    | no                       | 文字列       |
| match?   | no                       | 文字列の長さ |

---

スキャンポインタの扱いと返り値の種類の組み合わせで4パターン。

この組み合わせは `scan_full` メソッドの引数 s, f の指定に対応しており、上記の4つのメソッドは `scan_full` の糖衣のようなメソッドと捉えることができます。

または、「これら4つのメソッドを個別に覚えていなくても `scan_full` メソッドについて知っていれば用が足りる」という見方もできるかもしれません。




# search_full 系

- マッチを試みる位置: スキャンポインタの位置より後ろも含む
- 返り値の範囲: スキャン開始位置からマッチした部分の末尾までの部分

| メソッド    | スキャンポインタを進める | 返り値                              |
| ----------- | ------------------------ | -------------------------------- |
| scan_until  | YES                      | 文字列       |
| skip_until  | YES                      | 文字列の長さ |
| check_until | no                       | 文字列       |
| exist?      | no                       | 文字列の長さ |

---

`scan_full` 系のメソッドとの規則性が見てとれますね。大きなところでは「マッチを試みる位置」が違っています。

`scan_full` 系のメソッドと同様に、これら4つの組み合わせは `search_full` メソッドの引数 s, f の指定に対応しています。





# 観点まとめ

(1) 大まかには「マッチさせたい位置」の違いで scan_full 系と search_full 系の2つに分けられる。

(2) 細かく見ると

- マッチさせたい位置: スキャンポインタの位置のみ（scan_full 系） or スキャンポインタの位置より後ろも含む（search_full 系）
- スキャンポインタ: 進める or 進めない
- 返り値: 文字列 or 文字列の長さ

の組み合わせにより全部で 8 パターンに分けられる。

---

8パターンの中から用途に応じて使いたいものを選ぶことになります。

たとえば

- マッチを試みる位置は「スキャンポインタの位置より後も含む」としたい
- スキャンポインタを進めたい
- （スキャン開始位置からマッチした部分の末尾までの部分文字列の）長さが欲しい

だったら `skip_until` または `search_full(regexp, true, false)` を使えばよいわけです。





# メモ

> たまに StringScanner を使おうとすると「似てるメソッドがいろいろあるけどどのメソッドで何ができるんだっけ？」「○○がしたいんだけどどのメソッドを使えばいいんだっけ？」となりがちで、一度チートシート的に整理しておきたかったのでした。

そのうち書くつもりだったのを @okuramasafumi さんの記事を見て思い出し、よい機会なので書いてみました。

<!-- StringScannerの紹介 - Qiita -->
https://qiita.com/okuramasafumi/items/300d0925a9c91a746455

以前 JavaScript で StringScanner みたいなものを使いたくなったことがあって、私も簡単なものを書いたことがありました。

ベタに書くとスキャンポインタなどの状態を操作するコードがロジックのあちこちに散らばって鬱陶しいことになり、それをどうにかしようとすると StringScanner のような別オブジェクトに状態を管理させた方がよい、となるんですよね。オブジェクト指向プログラミングのある種の典型だと思います。
Laravelのキャッシュクリア系コマンドを一発で行う

## キャッシュクリア系コマンド

[キャッシュクリア系コマンド](https://qiita.com/Ping/items/10ada8d069e13d729701)
ここで紹介されているこの4つを一発で実行したい。
```
php artisan cache:clear
php artisan config:clear
php artisan route:clear
php artisan view:clear
```

bashにしようかな。と考えていたけど、Laravel特有のものを使ってみるか、ということでこの記事。

```
php artisan make:command clearBatch
```
これ、実行。
``` PHP
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;

class clearBatch extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:name';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        return 0;
    }
}

```
こんなのができる。これを改変。
今回は```$signature```と```handle()```を変える
``` PHP
<?php

namespace App\Console\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Facades\Artisan;

class clearBatch extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'command:cacheClear';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        Artisan::call('cache:clear');
        Artisan::call('config:clear');
        Artisan::call('route:clear');
        Artisan::call('view:clear');
        $this->info('Cache cleared successfully.');
    }
}
```
こんな感じ。これを保存して実行。1発で終わる。
```
zombie@DESKTOP-JLU30CD:~/working/study_Laravel/myapp$ php artisan command:cacheClear
Cache cleared successfully.
```

## 引用
株式会社ゆめみ様:[Laravel キャッシュクリア系コマンドなど](https://qiita.com/Ping/items/10ada8d069e13d729701)
VSCode拡張機能 TailwindCSS マウスをポチポチとするだけで簡単に素早く微調整ができる  「TailwindCSS Tune」折り畳める「Inline fold」と「Tailwind Fold」他

## 環境
VSCode
Next.js 13 (app router)
(TailwindCSS が使えるならなんでもいいです。)

TailwindCSSの属性値の知識が必要です。

# TailwindCSS Tune

この拡張機能は、ある程度出来上がったコードを微調整したい時用の拡張機能です。

カーソルの下にあるコードに合わせて、押せるボタンが変わっていきます。

TailwindCSS Tune - Visual Studio Marketplace

https://marketplace.visualstudio.com/items?itemName=omkarbhede.tailwindcss-tune

マウスをポチポチと押すだけで微調整が可能です。

※VSCodeの拡張機能である **Auto Close Tag** と相性が悪く、一緒に使うと動作がおかしくなりますので無効化しておいてください。


今回は、Next.js 13 (app router) を使っています。
(TailwindCSS が使えるならなんでもいいです。)

↓TailwindCSSがつかえるなにか適当なファイルを用意します。

```src\app\page.tsx
export default function Home() {
  return (
    <main className="flex flex-col items-center justify-center h-screen text-white bg-blue-600 ">
      <h1 className="text-9xl">VNS</h1>
      VNS.BLUE
      <br />
      価値観サイト
    </main>
  )
}

```

ブラウザを起動しておいてローカルのサーバーを `npm run dev` で起動しておきます。


http://localhost:3000/

セカンダリサイドバーを開いている状態で、「TailwindCSS Tune」を開いている状態です。
（現在、セカンダリサイドバー上に「TailwindCSS Tune」をドラッグアンドドロップしています。）
セカンダリサイドバーとは、VSCodeの右側にあるサイドバーのことです。
(普段ファイルの操作をしているサイドバーは、プライマリサイドバーと呼ばれています。)

↓そして、右側に開いたセカンダリサイドバー上のボタンをポチポチと押すだけで、コードが変化していきます。
Next.js 13 はLive Reload機能が早いので素早くコードが変化していくのがわかります。
時間も、ほんの数秒で変化していき直感的にデザインの変更が出来ます。

![TailwindCSS01.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44761/ad209cec-7467-35af-2268-2edfe2d115a1.png)

![TailwindCSS02.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44761/55665370-2890-2395-e80e-39d71369f5ff.png)

![TailwindCSS03.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44761/fc35d2bb-7729-1595-c21e-0509e9f0858b.png)

↑文字の大きさが変化しているのがわかると思います。

↓これはコードの場所によって押せるボタンの数がそのコードに合わせて変わっているのがわかるかと思います。

![TailwindCSS04.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44761/784f8d1a-9e90-b4aa-31ee-f39f19d71a33.png)


# その他のTailwindCSS関連の拡張機能

## 折りたたみ関係

**Inline fold** カスタム可能 TailwindCSS以外でもHTMLタグで指定できれば色々と折り畳めます。
↓下記のように設定すればhrefも折り畳めます。

```setting.json
  "inlineFold.regex": "(class|className|href)=(({(`|))|(['\"`]))(.*?)(\\2|(\\4)})",

```

この設定でclass、className、hrefと３種類の属性タグを折りたためます。

Inline fold - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=moalamri.inline-fold

**Tailwind Fold** TailwindCSS専用の折りたたみ拡張機能です。
hrefは折り畳めません。

Tailwind Fold - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=stivo.tailwind-fold

## 定番

**Tailwind CSS IntelliSense** コードの補完

**Tailwind Documentation** ドキュメント

Tailwind CSS IntelliSense - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=bradlc.vscode-tailwindcss

Tailwind Documentation - Visual Studio Marketplace
https://marketplace.visualstudio.com/items?itemName=alfredbirk.tailwind-documentation
Windows10 Ruby3 Rails7 Bundle installl時のnokogiriエラー時の対処について

rails newしたあとのbundle install時に下記のようなnokogiriエラー
が発生することがよくあります。
私もたびたび発生し解決までに多大な時間を要してしまいましたが
なんとか解決することができましたので記録として残すこととしました。

【エラーメッセージ】
An error occurred while installing nokogiri (1.15.1), and Bundler cannot
continue.


In Gemfile:
  rails was resolved to 7.0.4.3, which depends on
    actioncable was resolved to 7.0.4.3, which depends on
      actionpack was resolved to 7.0.4.3, which depends on
        actionview was resolved to 7.0.4.3, which depends on
          rails-dom-testing was resolved to 2.0.3, which depends on
            nokogiri



【私のPC環境】

ruby 3.0.2p107 (2021-07-07 revision 0db68f0233) [x64-mingw32]
Rails 7.0.5 
Bundler version 2.4.13
gem 3.4.13
nokogiri (1.15.2, 1.15.1 x64-mingw32)


【解決方法】
下記コマンドを実行する。
C:\#> gem install nokogiri --platform=ruby

Fetching nokogiri-1.15.2.gem
Temporarily enhancing PATH for MSYS/MINGW...
Building native extensions. This could take a while...
Successfully installed nokogiri-1.15.2
Parsing documentation for nokogiri-1.15.2
Installing ri documentation for nokogiri-1.15.2
Done installing documentation for nokogiri after 45 seconds
1 gem installed


そのあとに下記コマンドを事項
C:\#> bundle install

 .
 .
 .
Fetching web-console 4.2.0
Installing web-console 4.2.0
Bundle complete! 15 Gemfile dependencies, 69 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.

bundleに成功したので下記コマンドでrailsサーバを立ち上げる。
ブラウザーに　localhost:3000　を入力してrails画面がでれば成功です。
しかし、Windowsの場合下記エラーメッセージがでます。


C:\#> rails s
=> Booting Puma
=> Rails 7.0.5 application starting in development
=> Run `bin/rails server --help` for more startup options
Exiting
C:/Ruby30-x64/lib/ruby/gems/3.0.0/gems/tzinfo-2.0.6/lib/tzinfo/data_source.rb:159:in `rescue in create_default_data_source': tzinfo-data is not present. Please add gem 'tzinfo-data' to your Gemfile and run bundle install (TZInfo::DataSourceNotFound)


gemfileに下記いちにコメントアウト”＃”を入力する。
(コメントアウトの後ろ部分は削除してもよい）

gem "tzinfo-data"#, platforms: %i[ mingw mswin x64_mingw jruby ]


そのあとに再度下記コマンドを実行する。

C:\#> bundle install


bundleが成功し　gemfile.lock　ファイルが作成されれば成功です。

再度下記コマンドを事項し、ブラウザーに

C:\#> rails s

=> Booting Puma
=> Rails 7.0.5 application starting in development
=> Run `bin/rails server --help` for more startup options
*** SIGUSR2 not implemented, signal based restart unavailable!
*** SIGUSR1 not implemented, signal based restart unavailable!
*** SIGHUP not implemented, signal based logs reopening unavailable!
Puma starting in single mode...
* Puma version: 5.6.5 (ruby 3.0.2-p107) ("Birdie's Version")
*  Min threads: 5
*  Max threads: 5
*  Environment: development
*          PID: 2780
* Listening on http://[::1]:3000
* Listening on http://127.0.0.1:3000
Use Ctrl-C to stop


再度ブラウザーに　localhost:3000　を入力してrails画面がでれば成功です。ブラウザーに　localhost:3000　を入力してrails画面がでれば成功です。
【情報セキュリティ】代数学・概念

# ０．はじめに																					
大学で情報セキュリティの講義を受講している者です。
セキュリティに絡む知識（特に数学）のボリュームが大きいのでQiita投稿。
内容のレベルは超入門編、個人的な感情も少し入り混じった備忘録。

# １．代数学
数学と異なり数ではなく文字を用いて計算式・法則・方程式を学ぶ学問
暗号に必要な知識
ここを用いた講義の内容が全く頭に入ってこなかった為調べて理解した範囲を述べる
今後も学習が必要な場合は追記することにする

### 1-1.有限体とは
有限個の元からなる体
暗号学やコンピュータ科学などの分野で多く使用される
集合と異なり要素間の特定の演算が定義されている


### 1-2.元とは
集合を構成するもの
要素とも言われる


### 1-3.集合とは
グループ分けされているもの
要素の集まり
要素に対して操作が定義されている
```math
A = \lbrace
a,b
\rbrace
```
と表記される
集合にもいくつか種類がある
- ``群``
- ``環``
- ``体``


### 1-4.群とは
グループ構造の一つ
4つの条件を満たすもの
- ##### 封閉性
群の演算結果は集合の中にある
- ##### 結合法則
結合法則というものが成り立つ
数式としては
**``(a・b)・c = a・(b・c)``**
- ##### 単位元
単位元という要素が存在する
数式としては
**``a・e = e・a = a``**
- ##### 逆元
要素aには逆元が存在する
数式としては
**``a・a^-1 = a^-1・a = e``**


### 1-5.可換群（アーベル群）とは
群Aの元a,bに対して常にa・b = b・aが成立する時の群Aのこと
要はa・b = b・aが常に成り立ってれば群Aはアーベル群と呼ばれる


### 1-6.巡回群とは
乗法群Ａにおいて全ての元aがある元bのべき乗で表せるときの群Aのこと


### 1-7.環とは
グループ構造の一つ
4つの条件を満たすもの
- ##### 加法に関する群
加法の集合は加群である

- ##### 封閉性
環の乗法結果は集合の中にある

- ##### 結合法則
結合法則というものが成り立つ
数式としては
**``(a・b)・c = a・(b・c)``**

- ##### 分配法則
加法と乗法の間に分配法則が成り立つ
数式としては
**``a・(b + c) = a・b + a・c、(b + c)・a = b・a + c・a``**

### 1-8.体とは
グループ構造の一つ
3つの条件を満たすもの
- ##### 加法に関する群
加法の集合は加群である

- ##### 乗法に関する群
加法の単位元を除いた集合は乗法に関し可換群である

- ##### 分配法則
加法と乗法の間に分配法則が成り立つ
数式としては
**``a・(b + c) = a・b + a・c、(a + b) ・c = a・c + b・c``**


### 1-9.（学習保留中の分野）
以下情報量が多く一旦調べるのを保留
今後必要であれば優先的に調べて理解すること
- ``拡大体``
- ``多項式``
- ``既約多項式``
- ``原子多項式``
- ``0重マルコフ情報源``
- ``m重マルコフ情報源``

# ２．熱力学
### エンタルピーとは
最近学んだエントロピー（不規則性の指標）と似てた単語なのでなんとなく記述。
物質量のひとつ
圧力 × 体積に内部エネルギーを加算した量のこと

# ３．概念
### 3-1.記憶性を有するとは
ある情報源Aの出力結果が過去の出力系列の影響を受ける場合、情報源Aは記憶性を有するといえる

### 3-2.マルコフ情報源
時間経過とともに変化する情報源を表現する
ある時点の出力の可能性をその直前のある出力だけから決定できる情報源のこと
「事前にaの事象があったからこの後はbって出力しそうじゃない？」のbがマルコフ情報源..かな？
これを基にしたいくつかの情報源がある、これも調べるのは保留する
- ``0重マルコフ情報源``**
- ``m重マルコフ情報源``**

### 3-3.無条件に安全な暗号システムとは
``H(k) > RN``が成り立つ場合は無条件に安全な暗号システムとされる
##### 記号の名称
記号|詳細
|---|---|
H|エントロピー
k|鍵
N|メッセージ長（メッセージ内の文字数や情報）
R|冗長性（メッセージ内以外の余分な情報）

鍵のエントロピーがメッセージ長と冗長性より大きい場合を指す
ただこれだけで安全性を保障するという訳ではない
様々な要素が絡んでるのが暗号システムなため






# ４．まとめ
全て呪文のように聞き流していたが、要は**群やら体やらグループがあり**
そのグループは**なんらかの条件に乗っ取って成り立っている**ものだと読み解けた
条件内容においても**共通的な部分**があることが見受けられる
暗号がこの知識とどのように結びついているのか全く予想できないため
今後必要な場合は追記していくことにする
wsl2 + Ubuntu + LaravelにPostgreSQLを構築する方法

## 各バージョン
OS：Windows10 x64
Ubuntu：20.04
PostgreSQL：12.15
Laravel：8.83.27

## まず初めに
Laravel環境はできているものとします。

## 失敗
以下より、windows版のPostgreSQLをダウンロード
[PostgreSQLのリンク](https://www.postgresql.jp/download)
***※実際に疎通できているかはA5m2でもCLIでもよいのでSQL接続できるか確認しておくとよい***

すべて完了し、Laravelのmigrateを行う
```
php artisan migrate
```

エラー
```
Is the server running on host "localhost" (127.0.0.1) and accepting
TCP/IP connections on port 5432? (SQL: select * from information_schema.tables where table_schema = public and table_name = migrations and table_type = 'BASE TABLE')
```

#### いろいろ調べてみたが解決策見当たらず。少し考えて仮説を立てた
LaravelでDBに関する情報は設定し、「データベースの接続先は``127.0.0.1``にありますよ」と定義すると、Laravelはwsl2上に構築しているから、wsl2のローカルipを見に行ってる説。
もし、windowsのPostgreSQLにアクセスするには何らかの手段でwsl2から物理pc(windows)のローカルアドレス(127.0.0.1)に疎通させる、あるいは物理PCのグローバルIPを見る必要がありそうな気がしてきた。
※間違ってたら申し訳ありません。

#### ということで面倒なので、コマンドラインよりwsl2上にPostgreSQLを構築
```
sudo apt install postgresql postgresql-contrib
```
実行。
```
zombie@DESKTOP-JLU30CD:~/working/study_Laravel/myapp$ psql --version
psql (PostgreSQL) 12.15 (Ubuntu 12.15-0ubuntu0.20.04.1)
```
成功。

ぽすぐれのパスワード変更
```
sudo -u postgres psql
```
```
ALTER ROLE postgres WITH PASSWORD 'passwordを記入'
```

#### 本題に戻って
```
php artisan migrate
```
実行。成功。

## 結果
自分で立てた仮説を信じたい。とりあえずできてよかった。
【mysql】テーブルのデータを移す時に気をつけること(insert select)

それはある日のこと。
とある事情で、テーブルを新しく作り直すことになった。
その際に、テーブルのデータを新しいテーブルに移す必要があったのだが、
その時には気が付かなく、後から気が付いたことがあったので、それのメモ。

# テーブルのデータを移す

テーブル全体を他のテーブルに移すために、今回はinsert selectを使った。

```sql
insert into 新しいテーブル名 (新しいテーブルのカラム幾つか) select 元のテーブルの対応するカラム from 元のテーブル名;
```

数万程度のデータであれば、秒もかからずに移行できる。とても簡単。

# auto_incrementの値が変わる

今回移行した時、auto_incrementを指定したカラムはinsert時に指定せず、insertにより自動で再度振り分けてもらった。
データ数は変わらず、データの削除は論理削除を行っていたので、auto_incrementの値は連番であった。
そのため、移行後のテーブルのauto_incrementの値は、移行前のテーブルと同じだった。

問題は、ここから新しくデータを追加した時。
auto_incrementの値は、移行前のテーブルの最後の値から振り分けられると思っていたが、そうではなかった。

テーブルによって値が変わっていたのだが、どれも最後の値の次に来る2の累乗の値になっていた。
例えば、データが20000件あったとすれば、20000の次に来る値は32768、という感じに飛んでいた。

# 原因

`innodb_autoinc_lock_mode`の値が`1`になっていたため。

## insertの種類

`innodb_autoinc_lock_mode`の説明をする前に、insertの種類を説明する。

insertには、以下の3種類がある。

- 単純挿入 ... 挿入行数が事前に決まっているもの
- 連続挿入 ... 挿入行数が事前に決まっていないもの(insert selectはここ)
- 混在モード挿入 ... 単純挿入だが、データによってはinsertではなくupdateに変わるデータが存在するもの

## innodb_autoinc_lock_mode とは

あんまり理解していないので、正確な説明は他の参考サイト等を見ていただきたいのだが、
ざっくり言えば、auto_incrementをロックする方法の指定方法。

`0`の場合は、AUTO-INCロックというロックを行い、
(ここから曖昧部分)auto_incrementを発行するinsertに対して、テーブルロックをかけ、予測可能な範囲で順次auto_incrementを発行する。
そのため、値は連番になる。
ただ、ステートメント間でロックするため、2つのinsert文が実行された場合は、もう片方は待たされる。

`1`の場合は、`単純挿入`ではAUTO-INCロックを行わず、軽量ロックにより、事前に必要な分だけauto_incrementを発行する。
`連続挿入`か`混在モード挿入`ではAUTO-INCロックを行う。
ただ、`混在モード挿入`では、挿入される行数よりも多くのauto_incrementを発行するため、余分なauto_incrementが発行される。

設定には`2`も存在するが、今回は範囲外だったので省略(決して内容が理解できていないから、といった理由では・・・)

## 今回の場合

`SELECT @@innodb_autoinc_lock_mode;`で現在の設定を確認できるが、今回は`1`になっていた。

ただ、insert selectは`連続挿入`で、`innodb_autoinc_lock_mode`の値が`1`の場合で値が飛ぶのは`混在モード挿入`の場合と記述されている。
ここがいまいち理解できていない部分なのだが、調べてみると他にもこの現象の人がいるため、おそらくこれが原因だと思われる。

# 終わりに

今回、この現象に気がついたのが、移行後そこそこ時間が経ってからだったので、今あるデータはそのままにすることにした。
次回以降insert selectを使う際は、気をつけようと思う。

# 参考サイト
[SELECT+INSERTでAUTO_INCREMENTの値が増える (飛ぶ) - Qiita](https://qiita.com/reflet/items/6d05081330dc8b1dd681)
[INSERTステートメントの最適化について(MySQL InnoDBストレージエンジン) - Qiita](https://qiita.com/mkt-mtmt/items/c6f129d996dc399eebd6)
[MySQL :: MySQL 8.0 リファレンスマニュアル :: 15.6.1.6 InnoDB での AUTO_INCREMENT 処理](https://dev.mysql.com/doc/refman/8.0/ja/innodb-auto-increment-handling.html)