OmniAICreator/Qiita-1.07M huggingface dataset:
クラシックマウス　作ってみた　その3 ToF

# はじめに
* 作成したクラシックマウスの各パーツの解説。
* 今回は「距離センサー　VL53L0X」。

# 距離センサー　VL53L0X
距離センサーは、光の反射光量を利用するのが一般的なようだが、調整が面倒なイメージがあって、手間の少なそうなToFセンサーを選んでみた。
Amazonで購入したもの（青色）を使っているが、他に秋月で購入したもの、Amazonで紫色のものも試してみた。どれも同じように使えるが、精度や性能に関しては個体差があるように思う。
* 利用方法
    * 正面と左右に計3個取り付けている。壁との距離計測に使っているが、壁判定に用いる場合には、現在いる区画の壁だけでなく、 **1つ先の壁も見る** ようにしている。このため40CM程度までは計測する必要がある。
    * 探索を早めるために一つ先の壁を見るようにしているが、どの程度の効果があるのか良くわからない。現区画の壁だけ見るようにするかも。
* 取付高さ
    * 高い位置（4～5cm)に取り付けたほうが良い気がする。低い位置に取り付けると、床からの反射の影響のせいか、計測できる距離が短くなる（一定の距離以上が全て同じ数字で計測されてしまう）。一つ先の壁を見るには、これでは困るので、高い位置に取り付けている。
* 誤差
    * 個体差があるが、総じて少し大きめに計測される傾向があるように思う。5mmから10mm程度。会場の照明や、壁の材質にも影響されるのかもしれません。データシートにはOFFSET調整方法が記載されているようですが、ここでは計測結果を適宜調整して対応しています。
    * 計測数字そのものにも振れがある。5～10mm程度のイメージ。平均値をとる対応策が考えられるが、その分時間がかかる。
    * 最短距離は1～2CM程度。これ以下は数字があまり変わらない。個体差があって、1cm以下でもそれなりの数字を返すものもある。
    * 以上を考慮すると、計測数字に全面的に依存するのは危険。ある程度の誤差を前提として機体をコントロールする必要がある。
* 計測頻度/精度
    * いくつか選択肢があるが、以下の2つを検討した。
        * Normal：　 計測頻度　30ms
        * Accuracy：　  計測頻度　200ms
    * 200msは長すぎると判断して、Normalを選択。計測結果も平均値は取らず、１回目の数字をそのまま使っている。
* 計測モード
    * 連続計測モード：開始命令を与えると、センサーが連続的に計測を開始する。計測頻度は指定できるが、ここでは最短(30ms)を指定している。必要な時にすぐ結果が取り出せるが、最悪30ms前の数字の可能性がある。マウスが高速で動いている場合は留意する必要があるが、この機体ではあまり影響はなさそう。
    * シングル計測モード：計測したいときに都度命令を発行して結果を取得する。１回の計測に30msかかるので、計測回数が多いと速度に差が出てくる。今回は連続計測モードで利用している。
* 複数アドレス
    * 本モジュールは、I2Cアドレスが固定されている（0X29)。ハード的に変更する手段がなさそうなので、複数使用する場合はXSHUTピンを使ってソフト的に変更する必要がある。
        * 全てのモジュールのXSHUTピンをLOWにする。
        * 一つ目のモジュールのXSHUTを開放する（pinMode(10,INPUT)）。
        * 初期化　.INIT()
        * 変更後I2Cアドレス設定　.setAddress()
        * 連続計測開始　.startContinuous(0)
        * 2つ目のモジュールのXSHUT開放　以下同じ
* ライブラリ
    * 皆と同じようにPololu Arduino Library for VL53L0X を使いました。
    * Sampleプログラムを適宜利用しています。以下ご参照。
    * sensorの宣言は配列が使えます。

```
#include <VL53L0X.h>
VL53L0X sensor[3];

/////  以下SETUP内  ////////////
//VL53:初期化,I2Cアドレス変更　開始
pinMode(10,OUTPUT);
digitalWrite(10,LOW);
pinMode(11,OUTPUT);
digitalWrite(11,LOW);
pinMode(12,OUTPUT);
digitalWrite(12,LOW);

pinMode(10,INPUT);
sensor[0].setTimeout(250);
if (!sensor[0].init())
  {
    oled.println("sensor[0] Failed to detect and initialize sensor!");
    while (1) {}
  }
sensor[0].setAddress(0X20);
sensor[0].startContinuous(0);  // 連続計測モード
oled.print(" I2C");
oled.print(sensor[0].getAddress(),HEX);

pinMode(11,INPUT);
sensor[1].setTimeout(250);
if (!sensor[1].init())
  {
    oled.println("sensor[1] Failed to detect and initialize sensor!");
    while (1) {}
  }
sensor[1].setAddress(0X21);
sensor[1].startContinuous(0);  // 連続計測モード
oled.print(" I2C ");
oled.print(sensor[1].getAddress(),HEX);

pinMode(12,INPUT);
sensor[2].setTimeout(250);
if (!sensor[2].init())
  {
    oled.println("sensor[2] Failed to detect and initialize sensor!");
    while (1) {}
  }
sensor[2].setAddress(0X22);
sensor[2].startContinuous(0);  // 連続計測モード
oled.print(" I2C");
oled.print(sensor[2].getAddress(),HEX);
//VL53:初期化,I2Cアドレス変更 終了

/////  以下必要な時に取得  ////////////
float d_cm;
d_cm = sensor[　].readRangeContinuousMillimeters()*0.1;
```
以上
【Vim】ステータスラインの表示／非表示

# はじめに
スマホ（Android）で開発するのでVimの環境構築は必須です。

# 動作環境
* Sony Xperia 10 IV
* Android OS 12
* UserLAnd 3.1.4
* Ubuntu 20.04.5 LTS
* Vim 8.1.3741

# 一時的に切り替えたい場合
* 常に表示
```vim
:set laststatus=2
```

* 分割時のみ表示
```vim
:set laststatus=1
```

* 常に非表示
```vim
:set laststatus=0
```

# デフォルト設定にしたい場合
* 常に表示
```~/.vimrc
set laststatus=2
```

* 分割時のみ表示
```~/.vimrc
set laststatus=1
```

* 常に非表示
```~/.vimrc
set laststatus=0
```

# スクリーンショット
* 常に表示（右は分割時）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/0ed934ab-f5cd-fbff-f10b-22cefc5c9673.png" width=42%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/729ad298-be8e-c78c-9e00-0b1627930b1a.png" width=42%>

* 分割時のみ表示（右は分割時）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/19d0249c-2591-fe9c-d1f1-18daedbffd4e.png" width=42%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/05034ab4-b94a-2b78-f348-dc2181792c65.png" width=42%>

* 常に非表示（右は分割時）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/11380742-f9fc-bdc2-9d21-b07106911412.png" width=42%> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118198/19445f1a-e898-8031-9e79-a9de0fe0c956.png" width=42%>
macamいじり

ハードオフでNTSCのキャプチャモジュールを330円で手に入れました。

UVCなモジュールかと思ったのですが、MacにつないでPhoto Boothで認識されず、はずれでした。

とりあえず分解せずに製品情報で検索したところEM2860+SAA7113のモジュールのようです。

しかたないのでmacamのEM2820のサポートに追加してみました。

https://github.com/yamori813/macam

EM2820+TVP5150

![Untitled 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/72744cd7-c674-47b9-d408-88e27159b3dd.jpeg)

EM2860+SAA7113

![Untitled.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/62707fe6-de9c-b750-14a5-60644ceea022.jpeg)

ちょっとカラーバランスが悪いみたいです。

両方ともLinux方面の初期化コードが使えなかったので、WireShrakでUSBをキャプチャして初期化データを作りました。

NTSCとはいえ、Macに負荷かけるとUSB転送がとまります。
Spring Batch メモ

# Spring Batch メモ
## 導入
Spring Batch を勉強したので、まとめがてらメモ

## 環境
OS: mac OS Ventura (ver. 13.1)
IDE: IntelliJ CE

## Step モデル
### Chunk
以下IFが用意されており、それに従い作成
* ItemReader
* ItemProcessor
* ItemWriter

### Tasklet
Chunkにはまらないものを作成する際に使用

### Listner
主にログ出力で使用
それぞれの実行前後、エラー発生時に起動可能

## Job/Step間の値渡し
### ExecutionContext(実行結果などを保持するクラス)
JobExecutionContext - Step間渡し可能
StepExecutionContext - Step間渡し不可
* メリット: パラメータ等がDBに保存される(後追い可能)
* デメリット: 実装が煩雑

### Scope
@JobScope、@StepScopeを付与したクラスで受け渡し可能
* メリット: 実装が容易
* デメリット: パラメータ等がDBに保存されない

## 実行時パラメータの設定
実行の構成を編集

### バリデーション
DefaultJobParametersValidator クラスを使用
* setRequiredKeys(必須チェック)
RunIdIncrementer を使用している場合は、run.idを指定する必要がある
* setOptionalKeys(オプションチェック)
* afterPropertiesSet(パラメータ名重複チェック)
Configファイルに設定

#### 任意チェック
JobParametersValidator を継承したクラスを作成

## 参考
[Spring解体新書(バッチ編): 基礎から学べるSpring Batch](https://www.amazon.co.jp/%E6%82%B2%E6%83%A8%E3%81%AA%E3%83%9F%E3%82%B9%E3%82%92%E3%81%AA%E3%81%8F%E3%81%99SpringBatch%E5%85%A5%E9%96%80%E6%9B%B8-Spring%E8%A7%A3%E4%BD%93%E6%96%B0%E6%9B%B8-%E3%83%90%E3%83%83%E3%83%81%E7%B7%A8-%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B9%E3%82%8BSpring-Batch-ebook/dp/B09D3ZTJTB)
HTMLはどのように構成されるか

# head要素
・ウェブサイトの基本上などを記載する
・ブラウザ上では表示されない

# body要素
・ブラウザ上に表示する情報を記載する

# DOCTYPE
・ドキュメントタイプの略で、この文章がHTML文章であることを宣言する要素
・実際に記述する場合は<!DOCTYPE HYML>と記載する

# html要素
・HTML文章の始まりと終わりを表す要素
・<html></html>と記載

# meta要素
・HTML文章に関する情報を指定する時に使用
・終了タグはなし
・<meta charset="UTF-8">などと記載
└charsetはmate要素の属性
└"UTF-8"は属性値

# 属性
・要素に情報を付け加える役割を持っている
・属性のあとに属性値がつく

# charaset(キャラセット)属性
・メタ要素にて、どのような文字コードを用いることが示すことできる属性

# title要素
・ウェブサイトのタイトルを指定する要素
・Googleでの検索結果や、ブラウザのタブに表示するタイトルとして使用される
・<title></title>と記載

# h1〜h6要素(見出し要素)
・文章の見出しを作る要素
・hはheadingの略
・h1から順に文字の太さと大きさが小さくなる

# p要素
・文章の段落を表す要素
・pはparagraphの略
・Webページ内では、見出しを除くテキストのほとんどが、p要素が使われている

# br要素
・テキストを改行するための要素
・brはLine Breakの略
・br要素は終了タグが不要

# b要素
・文字を太くする要素
・bはboldの略

# a要素
・<a></a>で囲ったテキストをリンクにすることができる要素
・aはAnchorの略
・aタグのhref属性に移動させたいページのURLを指定する

# href属性(エイチレフ)
・リンクの移動先を指定する
・Hyper Referenceの略

# コメントアウト
・プログラムの中のコードを、無いものとして扱うことができるテクニック
・HTMLだけでなく他のプログラミング言語にも同じ機能がある
・<!- と　-->で囲む
・メリット：コード上にメモを残せるので、他人がコードを見た時に何を意図して書いてあるのか分かりやすく、複数人で開発をする際に便利
・コメントアウトするためには、コメントアウトしたい部分を選択して「コマンドを押しながら/」でできる

# 見本のコードと差分の確認方法
①見本のコードをコピー
②自分のコードがあるファイルを開く
③コマンド　＋　シフト　＋　P でコマンドパレットを開く
④>に続けて　compare と入力し、　compare active file with clipboard を選択
⑤赤字でハイライトされている見本と異なる部分を確認
⑥編集したいファイルを選択して、誤字や抜けているコードを修正
バージョン管理ソフト：pyenvのインストール


https://github.com/pyenv/pyenv#installation
参考記事


```
 curl https://pyenv.run | bash
```
を実行すると、オートインスト―ラーが実行される。

~/.bashrcに以下を追記
```
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
```

そして
```
source ~/.bashrcを実行
```

ここまでで、セットアップ完了。

次にHOMEで
```
pyenv install 3.10.1
```

プロジェクト作成中のディレクトリに移動し、
```
pyenv local 3.10.1
```
を実行。
```
pyenv version
```
でプロジェクト内で、pythonの指定が出来ているか、最終確認が
出来る。
mswでmockするときにデータが取得できなかった話(parse-error)

## 結論

テスト用の`node`環境では、
`msw`のエンドポイント定義は、**フルパス**で設定しないと取得できない。

:::note info
よい例：
:::

```js
const server = setupServer(
  rest.get('http://localhost:3000/users', (req, res, ctx) => {
    return res(ctx.json({ firstName: 'John' }))
  }),
)
```
:::note alert
ダメな例：
:::

```js
const server = setupServer(
  // "/users"だけではハンドリングされません！
  rest.get('/users', (req, res, ctx) => {
    return res(ctx.json({ firstName: 'John' }))
  }),
)
```

## 経緯
ローカルでフロントのテスト用に`msw`でAPIレスポンスをモック化したら、データが取得できず、なんで？？ってなった。

### モック化方法：

[mswの公式手順](https://mswjs.io/docs/getting-started/integrate/node)に従い、`src/mocks/server.js`と`src/setupTests.js`(CRA使用プロジェクト)を作成・更新した。

```js
// src/mocks/server.js
const server = setupServer(
  rest.get('/users', (req, res, ctx) => {
    return res(ctx.json({ firstName: 'John' }))
  }),
```
```js
// src/setupTests.js
import { server } from './mocks/server.js'
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
```

テスト対象コンポーネント(React、データ取得は[rtk-Query](https://redux-toolkit.js.org/rtk-query/overview)使用)
```tsx
const { users, isSuccess, isLoading, isError, error } = useUsers();

const getContent = () => {
    if (isLoading) {
      return <Skeleton animation="wave" />;
    } else if (isSuccess) {
      return (
        <Container maxWidth="xl">
          {users.ids.map((id) => (
            <StyledUserPreview userId={id} key={id} />
          ))}
        </Container>
      );
    } else if (isError && error) {
      if ('status' in error) {
        return (
          <Alert variant="filled" severity="error">
            An error has occurred:
            {error.status}
          </Alert>
        );
      } else {
        // you can access all properties of `SerializedError` here
        return <div>{error.message}</div>;
      }
    }
  };
  return (
    <div>
      ・・・省略
      {getContent()}
      ・・・省略
    </div>
  );
```
この時点で出てきたエラー：
```terminal
 console.warn
    [MSW] Warning: captured a request without a matching request handler:
    
      • GET http://localhost:3000/users
    
    If you still wish to intercept this unhandled request, please create a request handler for it.
    Read more: https://mswjs.io/docs/getting-started/mocks
```
```terminal
  console.error
    Error: Error: connect ECONNREFUSED 127.0.0.1:3000
```
`http://localhost:3000/users`で取得しようとして、結局コネクト(ハンドリング)できないやーっていう感じ。

なので、吐いてくれたパス`http://localhost:3000/users`をそのまま`server.js`のやつに書き換えたら、うまくいった～
```diff_javascript
// src/mocks/server.js
const server = setupServer(
-  rest.get('/users', (req, res, ctx) => {
+  rest.get('http://localhost:3000/users', (req, res, ctx) => {
    return res(ctx.json({ firstName: 'John' }))
  }),
```

## さいごに
[公式ドキュメント](https://mswjs.io/docs/getting-started/integrate/node#direct-usage)にも、ちゃんと注意書きとして記載されていることを後から気づいた。
公式ドキュメントをちゃんと読むべし。:laughing:
No3_ググったこと投稿(5分)_DB関連


## 目次
 [1.JOINのアルゴリズム](#1-JOINのアルゴリズム)

 [2.NestedLoopJoinの高速化](#2-NestedLoopJoinの高速化)

# 1. JOINのアルゴリズム
- アルゴリズムが3種類存在する(sort/merge, hashは触れない)
    - Nested Loop
        - 駆動表のレコードを1行ずつ取り出す
        - 取り出されたレコードと結合可能なレコードを内部表から検索する
    - Sort/Merge
    - Hash

SQL例)
``` 
SELECT * FROM tableA 
INNER JOIN tableB 
ON tableA.id = tableB.id; 
```

- 駆動表（外部表）
    - JOIN時のベースになる表 tableA
- 内部表
    - 結合対象のテーブル （駆動表（外部表）に合わせる表）tableB



# 2. Nestedloopjoinの高速化
- 駆動表から結合対象のレコードを検索するとき
    - 駆動表にインデックスを作成することで、結合対象を検索する際に振るテーブルスキャンが不要になり早くなる
- 結合条件を満たす内部表のレコードを検索するとき
    - 内部表にインデックスを作成することで、結合に時に駆動表1レコードごとで行っていた内部表のフルテーブルスキャンが不要になる

参考）
https://nishinatoshiharu.com/overview-nested-loopjoin/#:~:text=1%E8%A1%8C%E3%81%9A%E3%81%A4%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%8C,%E8%A1%A8%EF%BC%89%E3%80%8F%E3%81%A8%E5%91%BC%E3%81%B3%E3%81%BE%E3%81%99%E3%80%82
Windows11でSSH keyを作成する

# SSH keyを作ってみたい
GitHubで使用するために

下記サイト様がとても分かりやすかったです。
【参考サイト様】
https://sc.ddbj.nig.ac.jp/application/ssh_keys_windows/

#### pwsh で躓く
なんぞや？？

```PowerShell```のこと。
```コマンドプロンプト```と何が違うのか。。。

**PowerShellのほうが高機能**らしい。
じゃあもうこっち使おうと思う。
【参考サイト様】
https://qiita.com/opengl-8080/items/bb0f5e4f1c7ce045cc57

#### 最新のPowerShellをインストール
どうせならコマンドでやりたい。
【公式サイト様より】
https://learn.microsoft.com/ja-jp/powershell/scripting/install/installing-powershell-on-windows?view=powershell-7.3#winget

```PowerShell:PowerShell
winget search Microsoft.PowerShell
winget install --id Microsoft.Powershell --source winget
winget install --id Microsoft.Powershell.Preview --source winget
```

### OpenSSHクライアントソフトウェアのインストール
**SSHプロトコルを利用するために最も使用されてるソフトウェア**らしい。

SSH keyってこういうソフトウェアで作成するんだと学習。。。

以下のコマンドでインストールされているか確認できるそうです。
```PowerShell:PowerShell
Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124182/9daba62e-9529-06c9-ed50-26359d9c56e1.png)
されていました。なぜだろう？？

### SSH keyの作成
```PowerShell:PowerShell
ssh-keygen -t rsa -b 3072
```
これで作成できたみたいです。

```PowerShell:PowerShell
Get-ChildItem -Directory C:\Users\<ユーザー名>
Set-Location C:\Users\<ユーザー名>\.ssh
Get-ChildItem
```
上記コマンドで鍵が作られてるのか確認できるみたいです。
```PowerShell:PowerShell
cat .\id_rsa.pub
```
上記コマンドで鍵の内容を確認。
ここからコピペでSSHkeyを登録できる！！

# SSH keyって簡単に作れる！！
これだけでいろんなサイトとセキュアな通信できるなんて、すごい。
Ubuntu on WSL2でのDocker Engineの最短インストール手順

# 概要
WSL2のUbuntu環境にDocker Engineをインストールする手順を端的に紹介します。

# WSL2のインストール
こちらページの手順でWSL2をインストールします。

https://learn.microsoft.com/ja-jp/windows/wsl/install

実際のコマンドとしては以下の通りで、WSLやUbuntuのインストール等の一通りの処理が実行されます。

```powershell:PowerShell
wsl --install -d Ubuntu
```

# Docker Engineのインストール
インストールしたWSLを起動し、以下の手順でDocker Engineをインストールします。

## Docker Engineのインストールスクリプトの実行
下記の "Install using the convenience script" に記載されているインストール用スクリプトを用いてインストールします。

https://docs.docker.com/engine/install/ubuntu/#install-using-the-convenience-script

実際のコマンドとしては以下の2つです。

```bash:Bash
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
```

WSL環境で上記のコマンドを実行した場合、以下のようにDocker Desktop for Windowsの利用を推奨するメッセージが表示されますが、そのまま待機するとインストールが進められます。

```
WSL DETECTED: We recommend using Docker Desktop for Windows.
Please get Docker Desktop from https://www.docker.com/products/docker-desktop
```

## ルート以外のユーザーでdockerコマンドを利用する設定を加える
上記でDocker Engineのインストールは完了ですが、ルートユーザー以外から実行できるように以下の設定を加えます。

https://docs.docker.com/engine/install/linux-postinstall/

実際のコマンドとしては以下のコマンドだけです。

```bash:Bash
sudo usermod -aG docker $USER
```

## systemdの有効化

:::note
2023/09/23 追記
下記のドキュメントにも記載の通り、現在ではUbuntuを含めた多くのディストリビューションにおいて既定でsystemdが有効化されているようです。 `/etc/wsl.conf` に既にオプションが記載されていればOKです。
:::

こちらのページの記載の通り、systemdを有効化するオプションを追加します。

https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config#systemd-support

具体的には、vim等を使って`/etc/wsl.conf` にsystemdを有効化するオプションを以下の通り記述します。

```bash:Bash
sudo vi /etc/wsl.conf
```

```/etc/wsl.conf
[boot]
systemd=true
```

## WSLの再起動
ここまでの設定を反映させるため、WSLを再起動します。WSLを閉じ、PowerShellで以下のコマンドを実行します。

```powershell:PowerShell
wsl --shutdown
```

# Dockerの実行確認
再度WSLを起動し、以下のコマンドでdockerが実行できるかどうか確認します。

```bash:Bash
docker run hello-world
```

以下のようなメッセージが表示されればインストールは完了です。

```
Hello from Docker!
This message shows that your installation appears to be working correctly.
```

# 関連文献
筆者のブログにもWSL2でのDocker Engineのインストール方法や関連情報、DockerでのPyTorch環境の構築方法を掲載しています。

https://nujust.hatenablog.com/entry/2022/12/28/185044
ServiceNowでブラウザだけでページ全体のスクリーンショットを撮る力業

Version: Tokyo
Browser: Firefox, Edge
# 困りごと
## ページ全体でスクリーンショットが撮れない
ServiceNowでCtrl+Shift+Sでスクリーンショットを取ると「ページ全体」で保存しても
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/b6979236-d7fd-646c-b1d1-63029cbd1b1f.png)
見えている範囲だけ撮られて画面の一部が欠けてしまいます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/5261aa54-1c9a-9e4e-5a60-7496b78ae9a3.png)
ドキュメントにServiceNowの縦長の画面全体を載せたいときにはスクリーンショットを複数枚撮ってペイントなどで加工…は面倒なので何とか頑張ってみます
# 解決
## リスト、ナレッジ
リスト、ナレッジであればアプリケーションメニューなどのリンクをCtrl+左クリックやマウスホイールのクリックなどで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/3fab1905-6851-0637-2e76-13f84449835b.png)
別タブで開いて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/3faf24f8-02b0-7f13-9390-b6e87570b141.png)
Ctrl＋Shit＋Sを押下後「ページ全体」で保存するとページ全体のスクリーンショットを撮ることが出来ます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/5dd92ea8-2397-7d4d-416f-e2e171abb20a.png)
## フォーム
ですがフォームは別タブで開いても
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/d55afe0d-7013-1834-004a-f3168c284fad.png)
画面の一部が欠けてしまうのであれこれ試して分かったことが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/fd9d249d-2f13-4875-8e79-7ba4a296fc50.png)
Ctrl+Shift+Iで開発ツールを起動して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/6768bab9-4232-51e1-8a5b-4326065ee457.png)
&lt;body&gt;タグのclass=""の値を
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/f9e8edfb-bfec-84fe-40ae-e3ab279fdae6.png)
削除して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/eac76006-1dba-7301-c808-c3c5b1fe8a35.png)
&lt;body&gt;タグ内で2つめに出現する&lt;div&gt;タグのclass=""の値を
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/d9cc320a-5c0b-b854-4f9b-793b823ba984.png)
削除して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/fe786922-c855-527d-6ed2-f1c4f8a53f75.png)
Ctrl+Shift+Sで「ページ全体」で保存すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/09ed2b7d-1c69-dd24-908e-dcca1702967a.png)
ページ全体のスクリーンショットを撮ることが出来ました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193272/2a252fe1-eff7-ca4d-2809-7e6aee21e825.png)
なんでこうなるのかは理解していません…何とな～く勘でやりました
ダッシュボードはこの方法でも撮れなかったのですが今時点で自分は必要ないので考えないことにします
ローカルにVue CLIで作成したプロジェクトをGitのリモートリポジトリにプッシュする手順

# はじめに
いつもはGitHubでリポジトリを作成して、
クローンした後に、ローカルで初期のセットアップをして開発を進めていましたが
ローカルで作成したプロジェクトをGitHubにプッシュすることに挑戦してみました。

# プロジェクトを作成
1.下記のnpmコマンドを実行してVue CLIをインストールします
```
npm install -g @vue/cli
```
yarn派の方はこちら
```
yarn global add @vue/cli
```
下記より引用

https://cli.vuejs.org/guide/installation.html

インストールが終われば、Vue CLIがインストールされていることを確認します
```
vue --version
>@vue/cli 5.0.8
```

2.プロジェクトを作成します
```
vue create sample-vue
```
vue create (プロジェクト名）で雛形を作成してくれます

3.プリセットを選択するよう求められます。今回は「Default ([Vue 3] babel, eslint)」を選択しました
```
? Please pick a preset: (Use arrow keys)
❯ Default ([Vue 3] babel, eslint) 
  Default ([Vue 2] babel, eslint) 
  Manually select features 
```

Successfully createdが表示されればOK
```
🗃  Initializing git repository...
⚙️  Installing CLI plugins. This might take a while...

yarn install v1.22.18
info No lockfile found.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...

success Saved lockfile.
✨  Done in 29.89s.
🚀  Invoking generators...
📦  Installing additional dependencies...

yarn install v1.22.18
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...
success Saved lockfile.
✨  Done in 7.82s.
⚓  Running completion hooks...

📄  Generating README.md...

🎉  Successfully created project sample-vue.
👉  Get started with the following commands:

 $ cd sample-vue
 $ yarn serve
```

# Gitのリモートリポジトリへプッシュ
1.プロジェクトの階層へ移動します
```
cd sample-vue
```
プロジェクト名に適宜変えて実行してください

vue CLIを使わない場合には以下のコマンドを実行しますが
vue createコマンドの際に、コミットまで済ませてあるのでスキップします
```
git init
git add .
git commit -m 'first commit'
```

2.GitHubを開き、作成したプロジェクト名で(リモート)リポジトリを作成します
（GitHubの画面は省略）

(リモート)リポジトリを作成すると、コマンドがたくさん書かれてプッシュの案内があると思います

3.ブランチを選択します
```
git branch -M main
```

4.リモートリポジトリにaddします
```
git remote add origin https://github.com/(アカウントID）/sample-vue.git
```

5.リモートリポジトリにプッシュします
```
git push -u origin main
```

GitHubの画面を開き、履歴を確認すると
ローカルで作成したVueのプロジェクトがプッシュされていると思います

# 補足
ue uiというコマンドでGUI上でプロジェクトの管理ができるようです
```
vue ui
```

「#プロジェクトを作成-手順3」のプリセットを選択する箇所で
「Manually select features」を選択すると、機能を選択する案内があります
```
? Please pick a preset: Manually select features
? Check the features needed for your project: (Press <space> to select, <a> to toggle all, <i> to 
invert selection, and <enter> to proceed)
❯◉ Babel
 ◯ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◯ Router
 ◯ Vuex
 ◯ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing
```

先ほど選択した機能を次回に再利用するように保存されるか聞かれるので、再利用したい場合は"y"を入力しましょう
```
Save this as a preset for future projects? 
```
想定外のメール大量送信によるSNSサブスクリプションの非アクティブ化に対処する

# はじめに

Amazon SNSには、Eメッセージの配信レート（1秒あたり10件）の上限を超過した場合に、SNSサブスクリプションを非アクティブ化させる仕様があります。
参考URL： [Amazon SNS サブスクリプションを手動で無効にしたことを示す E メールが AWS から届いたのはなぜですか?](https://aws.amazon.com/jp/premiumsupport/knowledge-center/sns-email-subscription-disabled/ "AWS公式ドキュメント")

つい先日この問題を対処したことがあったため、投稿しました。

# 発生ケース
![SNS_AWS構成図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046178/e622da65-f3d9-5901-52d6-b39189ccdc72.png "SNS_AWS構成図.png")

1. CloudWatch Logsのロググループにサブスクリプションフィルターを設定
1. サブスクリプションフィルターのフィルターパターンに一致したログがロググループに出力
1. サブスクリプションフィルターをトリガーにLambdaが起動し、SNSへ配信
1. SNSからメール配信

上記ケースにおいて、
フィルターパターンに一致するログが大量出力され、
結果的にメール大量送信、
SNSサブスクリプションの非アクティブ化に繋がりました。

# 起きてしまったら…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046178/b4b865d6-f175-598b-3d18-c730b764089d.png)
引用： [https://dev.classmethod.jp/articles/intor-subscribe-sns-with-email/](https://dev.classmethod.jp/articles/intor-subscribe-sns-with-email/)

対象のSNSサブスクリプションのコンソール画面を確認すると、
｢保留中の確認｣となっているため、｢リクエストの確認｣から確認メールを送信し、
サブスクリプションの有効化を実施することで解消させることができます。

# 対策 - Lambda同時実行数の調整

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1046178/2b690e4e-c802-e74a-bd1b-6c1bae830e11.png)
引用： [https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/](https://aws.amazon.com/jp/blogs/news/new-provisioned-concurrency-for-lambda-functions/)

Lambdaは、デフォルトで同時実行数が1,000に設定されております。 
この同時実行数は、複数のリクエストを同時に処理するインスタンスの数を指し、現状では大量のログイベントを処理できる状態となっております。
参考URL： [Lambda 関数のスケーリング](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/invocation-scaling.html "AWS公式ドキュメント")

この同時実行数を下げることで配信レートを減少させることが可能です。
実施するコマンドは下記です。
```shell:CLI
aws lambda put-function-concurrency \
    --function-name <対象のLambda> \
    --reserved-concurrent-executions 1
```

# プラスα
上記方法の場合、SNSサブスクリプションの非アクティブ化回避策として有効ですが、
メール配信の一部が欠損する可能性がございます。

Lambdaのイベント最大時間（最大6時間）までは再試行による処理が可能となりますが、
最大時間以降はメッセージが破棄されてしまいます。[1]
Lambdaの内部キューにSQSを使用されているため、[2]
キューとして保持されるメッセージ数は無制限、
デッドレターキューの活用により破棄されるメッセージを退避させることが可能です。
[1] [最大イベント経過時間](https://aws.amazon.com/jp/about-aws/whats-new/2019/11/aws-lambda-supports-max-retry-attempts-event-age-asynchronous-invocations/#:~:text=%E9%96%A2%E6%95%B0%E3%81%8C%E5%AE%9F%E8%A1%8C%E5%89%8D%E3%81%AB,%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%82%92%E5%89%8A%E9%99%A4%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82 "AWS最新情報")
[2] [Security Overview of AWS Lambda - Invoke Data Path](https://pages.awscloud.com/rs/112-TZM-766/images/Overview-AWS-Lambda-Security.pdf#page=12 "whitepaper")

# 終わりに
あくまで要件の都合で対象ログのイベントを全量メール送信はやむを得ない場合や、
緊急の場合の対処法として検討いただきたい内容のため、
大原則対象ログのイベントを全量メール送信する運用を回避する方法も並行して検討いただくと良いかもしれません。（メトリクスフィルターによるメトリクス監視のみ実施するとか）
他に良い方法がございましたらぜひコメントいただけますと幸いです。

調査不足かもしれませんが、SNSサブスクリプションの非アクティブ化の対処に関するナレッジが見つからなかったため、どなたかの役に立てば嬉しいです。
Apex バッチでのエラー


# System unexpectedexception Error processing messages

+ [System unexpectedexception Error processing messages](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000NFNoj)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b9109b03-b587-68e4-cc4c-0c580d43fc46.png)

原因はStartメソッドの中のSOQL文
List<Contentdocument> ContentDocumentList = [SELECT id from Contentdocument];
がガバナ制限に引っかかっているみたいでしたので、こちらをDatabase.getQueryLocator
で取得することで無事解決いたしました。

# その他

+ [バッチ同期実行:Apex バッチを実行していますが、Salesforce では非同期で実行されるため、Visualforce でメソッドを呼び出すと、バッチが完了するまで待機しません。呼び出しが完了するようにバッチが完了するまで待機する方法はありますか?](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000KhOv3)

:::note
バッチは非同期で実行されます。これは、VF ページから呼び出したメソッドと同じトランザクションの一部ではありません。私が考えられる唯一の方法は、ユーザーがそのページで待機している場合、バッチ ステータスを照会し、ユーザーが確認できるようにページを更新し続けることです。このオブジェクトを使用できます - https://developer.salesforce.com/docs/atlas.en-us.object_reference.meta/object_reference/sforce_api_objects_asyncapexjob.htm
:::
【AWS】EC2+dockerで外部からアクセスできるWebサイトを構築する手順

# 概要
* ローカル環境から踏み台サーバー→EC2インスタンス「sample」へSSHトンネル接続し、git cloneやdocker composeインストール後に外部からアクセスできるWebサイトを公開しました。その際のAWSリソースの設定を記します。

## 環境
* Mac
    * 機種ID：MacBookPro18,3
    * macOS：Monterey
    * チップ：Apple M1 Pro
    * メモリ：16GB

## 作成したAWSシステム構成図

![Sample_システム構成図_20230204.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/bd444c5a-a135-fd5d-2904-12451729f138.png)


* AWSのネットワーク環境の構築手順をバラバラ書くより、上記のように視覚的に図で示した方がわかりやすいと自分の場合は感じましたので、今回は上記のようにまとめました。自身の理解や整理のためにも非常に良いと感じています。
* ぜひネットワーク環境を構築する際は、先にシステム構成図を作成することをお勧めします！

## 前提（補足）
* ELB/SSHによるGIP制限の対象IPは「133.233.333.444」としています。
    * どこからでもアクセスできるようにしたい場合は、ELB/SSHのインバウンドルールを編集してください。
* 踏み台サーバーのパブリック IPv4 アドレスは「11.222.3.444」としています。
* 接続先のEC2インスタンス「sample」のプライベート IPv4 アドレスは「555.666.77.888」としています。
* ロードバランサーの接続先の切り替えがある場合、ターゲットグループは「ブルーグリーンデプロイメント」の考えのもと、本来であればブルーとグリーンを作成することが望ましいです。
* システム構成図を参考にそれぞれのリソースの作成手順を書こうと思いましたが、上記の図だけで何をどのような設定で作成すべきかわかるので、実行手順の記載は省略しました。

## 注意点
* ELB(パブリックサブネット)のセキュリティグループのインバウンドルールのリスナーで登録するポート番号をdockerで立ち上げる予定のアプリのポート番号と合わせておくこと
    * もちろん、ELBで登録するターゲットグループ、セキュリティグループも同様
* 踏み台サーバー(パブリックサブネット)のセキュリティグループのインバウンドルールにSSHを登録しておくこと
* 接続先のEC2インスタンス「sample」(プライベートサブネット)のセキュリティグループのインバウンドルールにELBとSSHを登録しておくこと
* 接続先のEC2インスタンス「sample」(プライベートサブネット)のターゲットグループに「sample」を登録しておくこと

## 後続作業について
* AWSリソース設定後のSSH接続方法やGitCloneなどの流れは以下の記事にまとめているので、ぜひご参照ください
    * [【まとめ】踏み台サーバーを経由したSSH接続後にgit clone & docker composeで外部からのアクセスできるWebサイトを構築する手順](https://qiita.com/Ryo-0131/items/76cbd86c72ddbc754a0a)

## 参考記事
[`[AWS]EC2内でDockerコンテナを起動して、ブラウザからアクセスする`](https://weseek.co.jp/tech/2196/)
ログインの失敗回数の設定

指定の回数ログインに失敗した場合にロックがかかる設定を入れたかったのですが、
プロファイルを作成し、`password-auth`と`system-auth`ファイルを編集しただけでは上手くロックがかからなかったので、調べてみたところ[こちら](https://www.server-world.info/query?os=CentOS_8&p=pam&f=2)のサイトを見つけ、同じように設定したところ上手くいきました！

### 現在の設定確認
```
# authselect current
Profile ID: sssd
Enabled features:
- with-silent-lastlog
```

### Faillock を有効にする
```
# authselect enable-feature with-faillock
Make sure that SSSD service is configured and enabled. See SSSD documentation for more information.
```
設定が追加された事が分かります。
```
# authselect current
Profile ID: sssd
Enabled features:
- with-silent-lastlog
- with-faillock
```


次に、以下の設定ファイルを書き換えて保存します。
今回は、5回失敗するとロックをかけ、自動ロック解除はしないように設定します。（管理者が手動でロックを解除）
```
# vi /etc/security/faillock.conf

★ロックする連続失敗回数を設定
# deny = 3
deny = 5

★自動ロック解除される時間 (秒)
※自動ロック解除しない場合は0秒を指定
# unlock_time = 600
unlock_time = 0
```

わざと5回パスワードを間違え、正しいパスワードを入力してもログインできないことを確認します。

以下のコマンドで、現在のログイン失敗回数を確認できます。
```
# faillock --user <ユーザ名>
```
そして、以下のコマンドでロックを解除します。
```
# faillock --user <ユーザ名> --reset
```
これで再度ログインできるようになっていると思います！

ここまで、設定を追加する方法を紹介しましたが、まだプロファイルを作成していない場合は作成時に指定することも可能です。

```
★プロファイルの作成
authselect create-profile <プロファイル名> -b sssd

★作成したプロファイルの選択(ここでwith-faillockを指定)
authselect select custom/<プロファイル名> with-silent-lastlog with-faillock
```

上手くロックがかからない！という場合はこちらを試してみてください！

ではまた:wave:
代表的な高階関数を図解してみた

高階関数を使えば配列に対する要素に対しての少し複雑な処理やforループを使って書くような処理もシンプルに書けるようになります。
だけど、代表的な高階関数である`map`や`reduce`がどのような処理ができるか混乱してしまう人も多いと思います。
一目でどの関数で何ができるか図解してみたので、気休めに覗いてみてください！

---

## map
配列のすべての要素に対して関数を適用し、その結果からなる新しい配列を生成します
```JavaScript
const people = ['Sad guy', 'Normal guy', 'Exciting guy'];
const mastedPeople = people.map(function(person) {
  return person + ' is wearing the mask';
});
console.log(mastedPeople); // ["Sad guy is wearing the mask", "Normal guy is wearing the mask", "Exciting guy is wearing the mask"]
```
![Screen Shot 2023-02-05 at 14.25.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486680/b363d0b7-fb84-d6bf-0322-97cd18dc9aba.png)


## reduce
配列のすべての要素を畳み込んで、1つの値にまとめることができます
```JavaScript
const testScores = [40, 70, 90]; // 国語・数学・英語の順番として

const totalScore = testScores.reduce((acc, score) => {
  return acc + score;
}, 0);

console.log(totalScore); // 200
```
![Screen Shot 2023-02-05 at 14.26.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486680/14896173-8efa-bdbc-9f64-ee4494159a8a.png)


## filter
配列から特定の条件に合った要素を抽出するために使用します
```JavaScript
const movies = [
  { title: "Star Wars", rating: 9.0 },
  { title: "The Avengers", rating: 8.0 },
  { title: "Jurassic Park", rating: 7.5 },
];

const highlyRatedMovies = movies.filter(movie => movie.rating >= 8.5);
console.log(highlyRatedMovies); 
/*
 output
	[{
    rating: 9,
    title: "Star Wars"
	}] 
  */
```
![Screen Shot 2023-02-05 at 14.38.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/486680/b517cc00-1855-a20e-0082-6a3224d55698.png)




## おわりに
よりシンプルにわかりやすいコードを書けるように技術的な勉強をしていきましょう！

## 参考
[# JavaScript Map, Reduce, and Filter - JS Array Functions Explained with Code Examples](https://www.freecodecamp.org/news/javascript-map-reduce-and-filter-explained-with-examples/)
Litで構造化データを属性としてコンポーネントに渡す

# はじめに

Litを使ってWebコンポーネントを開発している中で、Reactのように構造化データをタグに渡して使いたいと思ったのですが、公式のドキュメントをみても簡単に解決できなかったのでまとめていきます

# 方法1 : 文字列として渡す

文字列として属性に渡して、オブジェクトとして受け取る方法です
属性は文字列でいれないといけないようで、受け取りは`object`にすることでJsonParseなどをしていい感じにしてくれています

```ts
  render() {
    return html`
      <user-card
        user='{
          "username": "watanabe",
          "age": "25",
          "prefecture": "埼玉県",
          "topImage": "https://source.unsplash.com/random?human",
          "subImages": "https://source.unsplash.com/random?fruit, https://source.unsplash.com/random?sweets, https://source.unsplash.com/random?cat, https://source.unsplash.com/random?school",
          "selfIntroduction": "こんにちは。"
        }'
      ></user-card>
    `;
  }
```

```ts
export class UserCard extends LitElement {
  static properties = {
    user: {
      type: Object,
      attribute: "user",
    },
  };
```

# 方法2 データとして渡す

これがやりたかったことになります

```ts
  @property({ type: Object })
  user = {
    username: "じん!!",
    age: "25",
    prefecture: "埼玉県",
    topImage: "https://source.unsplash.com/random?human",
    subImages: [
      "https://source.unsplash.com/random?fruit",
      "https://source.unsplash.com/random?sweets",
      "https://source.unsplash.com/random?cat",
      "https://source.unsplash.com/random?school",
    ],
    selfIntroduction: "test",
  };


    return html`
      <user-card .user="${this.user}"></user-card>
    `
```

ポイントは属性に`.`をつけることです。`.user`とすることで構造化データとして認識してくれるようでした

```ts
export class UserCard extends LitElement {
  static properties = {
    user: {
      type: Object,
      attribute: "user",
    },
  };
```

受け取りは1と変わらないです。

# おまけ

ユーザーはsubImageという配列を持っていますが、これは更新があっても子コンポーネントには伝わりません (Reactと同じく)

なのでUserのsubImagesが変わったときに更新が入るようにUserに対して`updated`を定義すると他の更新をキャッチして`subImages`の更新ができました

```ts
  static properties = {
    user: {
      type: Object,
      attribute: "user",
    },
  };

  updated(changedProperties: any) {
    changedProperties.forEach((oldValue: any, propName: any) => {
      if (propName === "user") {
        this.topImage = this.user.topImage;
        this.subImage = this.user.subImages;
      }
    });
  }
```

# おわりに

ここまでの内容がわかってやっと最低限使えるようになった感じがしました
とにかくドキュメント以外に参考になるものがすくなく大変でした

# 参考

https://stackoverflow.com/questions/68645830/how-to-pass-nested-data-structures-as-properties-in-litelement
Kerasライブラリの各種モデルによる鉄鋼材料の金属組織画像の学習と検証

# はじめに
[前回](https://qiita.com/_Moony/items/0f6635b2e47a941c1696)はKerasライブラリのMobilenetV2というモデルを使って金属組織画像の学習・検証を行いましたが、今回はMobilenetV2、VGG16、Xception、InceptionResNetV2、ResNet50V2、DenseNet121、NASNetMobile、EfficientNetV2B1というモデルを使って、前回と同じ金属組織画像を学習して結果を比較します。

# 学習と検証の方法
[前回の記事](https://qiita.com/_Moony/items/621fe59932d688c913fe)で解説したプログラムをKerasの各種モデルに適用して、学習・検証を行います。いずれのモデルについても、学習用と検証用の画像の比率は8：2とし、いずれのモデルについても学習と検証には同じ画像を用いました。また、[Keras Apprications](https://keras.io/api/applications/)を参考にして、表1のように入力画像のサイズを設定するとともに、preprocess_inputを用いて各モデルに適した画像データの正規化を行いました。
プログラムについては、画像データをGoogleDriveに置いた状態で、GoogleColab上でGPUを用いて実行しました。
なお、作成したプログラムとその実行結果、学習後のモデルのうちMobileNetV2とNASNetMobileモデル、各種モデルをテストするためのPythonプログラム、テスト用のサンプル画像は以下に格納しております。

https://github.com/repositoryfiles/TrainValidationMetallograpyUsingVariousKerasModels

表1　各モデルの入力画像サイズ
|モデル  |入力画像サイズ  |
|---|---|
|MobileNetV2  |224x224  |
|VGG16  |224x224  |
|Xception  |299x299  |
|InceptionResNetV2  |299x299  |
|ResNet50V2  |224x224  |
|DenseNet121  |224x224  |
|NASNetMobile  |224x224  |
|EfficientNetV2B1  |224x224  |

# 学習と検証の結果

各モデルにおける検証データの正解率の最大値、その値が得られた学習回における学習データの正解率、モデルのファイルサイズを表2に示します。表2よりファイルサイズが大きいInceptionResNetV2モデルにおいて、正解率が高いことが分かります。その一方で、ファイルサイズが小さいMobileNetV2やNASNetMobileモデルでは正解率がやや低くなっています。

表2　各モデルの検証データの正解率の最大値、その値が得られたときの学習データの正解率、モデルのファイルサイズ
|モデル  |検証データの正解率の最大値  |検証データの正解率の最大値が得られたときの学習データの正解率 | モデルのファイルサイズ(kB) |
|---|---|---|---|
|MobileNetV2  |0.90  |0.95  |2126|
|VGG16  |0.92  |0.97  |57578|
|Xception  |0.91  |0.97  |82007|
|InceptionResNetV2  |0.96  |1.00  |214361|
|ResNet50V2  |0.97 |0.97  |92468|
|DenseNet121  |0.98  |0.90  |28689|
|NASNetMobile  |0.97  |0.93  |18823|
|EfficientNetV2B1  |0.96  |0.97  |28030|

# 終わりに

何かのお役に立てれば幸いです。
【SwiftUI】欠けた円の作り方


SwiftUIで欠けた円の作り方を紹介しようと思います。

Xcode Version 14.2



まずは通常の円です。
```ContentView.swift
Circle()
    .trim(from: 0, to: 1) // 線のトリム
    .stroke(
        Color.blue,
        style: StrokeStyle(lineWidth: 20)
    )
    .frame(width: 205, height: 205)
```


![スクリーンショット 2023-02-05 13.19.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/272346c3-5835-0334-b195-662cee370927.png)

`.trim(from: 0, to: 1)`trimの値を変えてみると、欠けた円になります。


```ContentView.swift
Circle()
    .trim(from: 0, to: 0.5) // 線のトリム
    .stroke(
        Color.blue,
        style: StrokeStyle(lineWidth: 20)
    )
    .frame(width: 205, height: 205)
```

![スクリーンショット 2023-02-05 13.25.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/db93bc41-542a-6622-5d78-6908184315cd.png)

このように`to: 0.5`に変更すると下だけの半円になります。

あとは、欠けさせたいお好きな数値を入れてみて下さい。
メンバ変数に配列を持つ時のサイズの定義

# TL;DR
メンバ変数に配列を持つ時、サイズの指定は`static constexpr`を使えばいい。

```c++
class Manager
{
public:
    Manager()
        : m_item{0}
        {};
private:
    static constexpr int ITEM_NUM = 10;
    int m_item[ITEM_NUM];
};
```

# ダメな方法
## メンバ変数を使う
- コンパイルエラーになる
```c++
class Manager
{
public:
    Manager()
        : m_item{0}
        {};
private:
    int ITEM_NUM = 10;
    int m_item[ITEM_NUM];
};
```

## `const`のメンバ変数を使う
- これもコンパイルエラー
```c++
class Manager
{
public:
    Manager()
        : m_item{0}
        {};
private:
    const int ITEM_NUM = 10;
    int m_item[ITEM_NUM];
};
```

## `static const`のメンバ変数を使う
- これはコンパイラによってはリンクエラーになるので、あまり良いとは言えない
    - VisualStudioなどではエラーにならない
```c++
class Manager
{
public:
    Manager()
        : m_item{0}
        {};
private:
    static const int ITEM_NUM = 10;
    int m_item[ITEM_NUM];
};
```

## `static constexpr`のメンバ変数を使う
- ということで、冒頭のとおり`static constexpr`を使えばいい
```c++
class Manager
{
public:
    Manager()
        : m_item{0}
        {};
private:
    static constexpr int ITEM_NUM = 10;
    int m_item[ITEM_NUM];
};
```
piyopiyo.ex #14：Elixirでデータ分析をしてみよう！開催メモ

本記事は、2023/2/4開催「piyopiyo.ex #14：Elixirでデータ分析をしてみよう！」を開催したメモです。

https://piyopiyoex.connpass.com/event/271474/

LivebookでExplorerを使ったデータ分析を行いました。

ExplorerはPythonだとpandasにあたる機能があります。
このExplorerを使いながら、データ分析でよく使う関数を使ってきました。

## Livebookとは？

別の勉強会で作ったLivebookの紹介スライドを再利用しました。

https://speakerdeck.com/nako_sleep_9h/livebookwole-simutamenoqian-shuo

## デスクトップアプリ版Livebookを使おう！

@t-yamanashi さんの書いた記事を紹介しました。

https://qiita.com/t-yamanashi/items/737bf63ce7e4980e0269

## Explorerを使ったデータ分析をしてみよう！

@RyoWakabayashi さんの下記記事を読みながら、Livebookでコードを実行していきました。
https://qiita.com/RyoWakabayashi/items/dfb5495b9c25eff710a2#comment-9fc58ad4ce4359709dce

### CSVダウンロード

勉強会では、アプリ版やDokcer環境などLivebook環境が混在していたので、
CSVダウンロードのコードを会の中では追加しています。
@t-yamanashi さんありがとうございます！

```elixir
Mix.install([
  {:explorer, "~> 0.5"},
  {:kino, "~> 0.8"},
  {:download, "~> 0.0.4"} # <-追加
])
```

```elixir
Download.from(
  "https://raw.githubusercontent.com/RyoWakabayashi/elixir-learning/main/livebooks/explorer/population_20211001.csv"
)
Download.from(
  "https://raw.githubusercontent.com/RyoWakabayashi/elixir-learning/main/livebooks/explorer/assets_20151216.csv"
)
```

## 感想

Explorerを使った四則演算から、CSVを使ったデータ変換まで出来たので
自分がどこまでついていけて、どこから難しく感じるのか分かったのが良かったです。

今回、2時間弱で、Livebookの説明、アプリインストール、Explorerのコードを実行を
駆け足でも進められたのは、 @RyoWakabayashi さんの記事の構成がすばらしかったのと、
@t-yamanashi さんの準備の丁寧さのおかげです。大感謝！
parted コマンド メモ

## 6TB の外付けHDDを almalinux で利用した時のメモ

### fdisk ではディスクを認識できなかった

```
# fdisk /dev/sdd

fdisk (util-linux 2.32.1) へようこそ。
ここで設定した内容は、書き込みコマンドを実行するまでメモリのみに保持されます。
書き込みコマンドを使用する際は、注意して実行してください。

古い ext4 署名は write (書き込み)コマンドを実行すると消えてしまいます。

デバイスには認識可能なパーティション情報が含まれていません。
このディスクのサイズは 5.5 TiB (6001175126016 バイト) です。DOS パーティションテーブル形式では 2199023255040 バイト以上のドライブには セクタサイズ 512 バイトを使用することができません。GUID パーティションテーブル (GPT) 形式を使用してください。
```

## parted コマンドで実行

```
# parted /dev/sdd
GNU Parted 3.2
/dev/sdd を使用
GNU Parted へようこそ！ コマンド一覧を見るには ‘help’ と入力してください。

```

#### 現在の状態を確認
print コマンド

```
(parted) print
モデル: BUFFALO HD-NRLD-A (scsi)
ディスク /dev/sdd: 6001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: loop
ディスクフラグ:

番号 開始 終了 サイズ ファイルシステム フラグ
1 0.00B 6001GB 6001GB ext3
```

#### GTP でラベル
fdisk で怒られたので・・・GTPを利用する
GPTとは最大サイズ 8.5ZB のパーティションを管理する方式

mklabel コマンド

```
(parted) mklabel gpt
警告: /dev/sdd のパーティションが使用中です。
無視(I)/Ignore/取消(C)/Cancel? I
警告: いま存在している /dev/sdd のディスクラベルは破壊され、このディスクの全データが失われます。続行しますか？
はい(Y)/Yes/いいえ(N)/No? Y
(parted) mkpart
パーティションの名前? []? primary
ファイルシステムの種類? [ext2]? ext4
開始? 0%
終了? 100%
```

#### 確認

```
(parted) print
モデル: BUFFALO HD-NRLD-A (scsi)
ディスク /dev/sdd: 6001GB
セクタサイズ (論理/物理): 512B/4096B
パーティションテーブル: gpt
ディスクフラグ:

番号 開始 終了 サイズ ファイルシステム 名前 フラグ
1 1049kB 6001GB 6001GB ext4 primary
```

#### フォーマット

```
# mkfs -t ext4 /dev/sdd　
```

フォーマットした後にマウントして利用する
外部ライブラリを使わず値の絞り込み

## 参考

* https://kuroeveryday.blogspot.com/2016/03/incremental-search.html

## ソース

* http://localhost/?k=lemon

のようにkの値で絞り込む


```js
<h2>過去配信の動画ページ</h2>

配信第 <input id="keyword" type="text" /> 回
<ul id="list"></ul>

<script>
	var keyupStack = [];
	var keyword = document.getElementById('keyword');
	keyword.addEventListener('keyup', function () {
	  keyupStack.push(1);

	  setTimeout(function () {
	    keyupStack.pop();
	    // 最後にkeyupされてから一定時間次の入力がなかったら実行
	    if (keyupStack.length === 0) {
	      // 部分一致を可能にする(例: .*a.*b.*c.*)
	      var buf = '.*' + this.value.replace(/(.)/g, "$1.*");
	      var reg = new RegExp(buf);
	      
	      var filteredLists = data.filter(function (d) {
	       return reg.test(d);
	      });
	      createRow(filteredLists);
	    }
	  }.bind(this), 300);
	});

	var createRow = function (lists) {
	  var list = document.getElementById('list');
	  list.textContent = null;
	  lists.forEach(function (l) {
	    var li = document.createElement('li');
	    li.appendChild(document.createTextNode(l));
	    list.appendChild(li);
	  });
	};

  
  
window.addEventListener("load", function() {
	// 初期表示
	createRow(data);
  
	// URLを取得
	let url = new URL(window.location.href);
	// URLSearchParamsオブジェクトを取得
	let params = url.searchParams;
	// getメソッド
	if (params.get('k') != null) {
		document.getElementById('keyword').value = params.get('k');
      	  // 部分一致を可能にする(例: .*a.*b.*c.*)
	      var buf = '.*' + params.get('k').replace(/(.)/g, "$1.*");
	      var reg = new RegExp(buf);
	      
	      var filteredLists = data.filter(function (d) {
	       return reg.test(d);
	      });
	      createRow(filteredLists);
	}
    document.getElementById("keyword").focus();
});
  
  
	var data = ['apple','apricot','avocado','banana','bilberry','blackberry','blackcurrant','blueberry','boysenberry','cantaloupe','currant','cherry','cherimoya','cloudberry','coconut','cranberry','damson','date','dragonfruit','durian','elderberry','feijoa','fig','goji berry','gooseberry','grape','raisin','grapefruit','guava','huckleberry','jabuticaba','jackfruit','jambul','jujube','juniper berry','kiwi fruit','kumquat','lemon','lime','loquat','lychee','mango','marion berry','melon','cantaloupe','honeydew','watermelon','miracle fruit','mulberry','nectarine','olive','orange','blood orange','clementine','mandarine','tangerine','papaya','passionfruit','peach','pear','persimmon','physalis','plum/prune','pineapple','pomegranate','pomelo','purple mangosteen','quince','raspberry','salmonberry','rambutan','redcurrant','salal berry','salak','satsuma','star fruit','strawberry','tamarillo','tamarind','ugli fruit'];
  
</script>
```
Markdwon / reStructuredText / Sphinx でよく使う記法

この記事は、執筆者自身が使っているがすぐに忘れてしまうMarkdownなどの記法をメモしておくものです。(執筆中)
ここに書かれている記法が全ての環境で動作するものではなく、特定の環境でのみ動作する場合があります。


# Markdown

主に、[Jupyter Book](https://jupyterbook.org/en/stable/intro.html) で使用する [MyST Markdown](https://jupyterbook.org/en/stable/content/myst.html) について書いています。

## リンク

```
[リンクタイトル](URL)
```

## キャプションとリファレンス

```
```{code-block}
---
name: sample_table
caption: XXXが持つ機能
---

図: XXXが持つ機能
```

```
上記{numref}`sample_table`
```

## ページ間

```
(content:references:SECTION_NAME)=
# タイトル
```

```
[このタイトル](content:references:SECTION_NAME)
```

## 注釈

```
文章内に[^ref_NOTE1] 

^ref_NOTE1]: URLなどの注釈
```

## 定義リスト

```
Term 1
: Definition

Term 2
: Definition
```

## 備考

```
```{note}
本文
```

## 画像

```
![ALTテキスト](画像PATH)
```

タイトル付きは以下

```
![ALTテキスト](画像PATH　"タイトル文字列")
```
成果物レビューへの臨み方

最近現場で成果物のレビューをする機会があるので、私が意識していることを書いてみました。

## 意識していること
[ルールを決め、セルフチェックを徹底させる](#ルールを決め、セルフチェックを徹底させる)
[レビュー観点を明確にする](#レビュー観点を明確にする)
[順序を決める](#順序を決める)
[指摘点を伝える際は具体的に](#指摘点を伝える際は具体的に)
[横展開を徹底させる](#横展開を徹底させる)
[レビューのタイミングを意識する](#レビューのタイミングを意識する)

## ルールを決め、セルフチェックを徹底させる
レビューは面倒な作業で、出来るだけ指摘をしたく無いのでメンバーにはセルフチェックをしてもらいます。
例えばドキュメント類であれば、

- 誤字、脱字
- フォントや罫線等のレイアウトの統一
- 粒度を合わせる

ソースコードであれば、

- 警告は潰す 
- 変数名の命名
- 適切な量でメソッド分割する 
- 動作確認

などです。

チーム内でルールを決め、メンバーにはこれらを依頼前にチェックしてもらうことで指摘を出来るだけ減らします。
誤字、脱字などの指摘は出来るだけしたくないし、大量の行数のメソッドが来ると気が遠くなります。

## レビュー観点を明確にする
自分の好みで指摘をするのはよくないと思います。現場にあった観点を見極めます。
既存の指摘表等があれば参考にして、今までどんな指摘が上がっているのかを確認するのも良いです。
ソースコードであれば、基本的にはコーディング規約に従います。
動作はするが明らかに非効率だったり可読性が悪い場合は指摘します。
こっちの方が効率良いとかはメンバーの成長の為にアドバイスしても良いと思います。

## 順序を決める
システム開発には要件定義→設計→実装→試験という風に順序がありますが、レビューもある程度順序を決めておかないと途中でよくわからなくなって戻って確認し直したりと、無駄な工数が発生しかねません。

私の場合は、レビュー対象機能の仕様を大まかに確認した後にレビューを始めます。
機能要件と合っているか、網羅出来ているか（漏れがないか）を確認し、その後に可読性等の品質周りを確認します。
仕上げに誤字脱字等をザーッと確認。

## 指摘点を伝える際は具体的に
レビューイに伝わらないと、指摘の再指摘が発生してしまいます。
極力は一往復で終わらせたいので、出来るだけ具体的に伝えます。

私は
- 指摘箇所
- 指摘理由
- 修正方法

を伝えるように意識しています。

## 横展開を徹底させる

同じ指摘が出ないように、メンバーには依頼前に横展開をしてもらうようにしています。
指摘数がそのまま品質の指標となるので、減らせるところは減らしておきたいですね。

## レビューのタイミングを意識する

レビューイの手が止まらないように、優先してレビューを実施するのが理想です。
ですが、自分の作業もあると思うので優先度を考えて判断します。
また、自分の作業が中途半端な時は切りの良いところでレビュー作業に切り替えます。無理に切り替えると戻った時に整理しなおす無駄な工数が発生するためです。

## 最後に

レビューはとても面倒な作業で、責任も感じてしまい漏れなく完璧にしようと思いがちです。
その結果時間がかかってしまう事もありました。
ですが、完璧なレビューは無いと思うので漏れなく指摘するという意識ではなく、成果物を良くするという意識で今後もレビューに臨みたいです。
safariでwebkit-line-clampによる行数制限が効かない

# はじめに

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/557d8bcf-0b00-563c-52fc-eef4a6f23373.png" width="300px" />

👆画像のようなQiitaの記事をカードで表示するようなものを実装したところ、
`Safari`で👇のように潰れて表示されてしまった。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/3064d4f5-ee56-ad5e-e148-1d59571154a7.png" width="300px" />

これを解消した時のメモ

# 環境

* Safari
    * 16.1（18614.2.9.1.12）

# 実装

```css
.content {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
}
```

この実装で`GoogleChrome`では3行制限ができたが、`Safari`では画像のように潰れてしまった

# 原因(おそらく)

`Chrome`では上記の実装をするといい感じに指定行数の高さで、`min-height`を設定してくれるが、
`Safari`ではそれがないため、潰れてしまう。

# 解決

明示的に`min-height`を示すことで`Safari`でも潰れることなく表示されました

```css
.content {
  overflow: hidden;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  min-height: 5em;
}
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/0e7ee2f8-af83-d01e-abf4-363abe2cbad5.png" width="300px" />
Splunk: Appの作成


###### 実施環境： Splunk Free 8.2.2

 Splunk には機能拡張として、様々な App が存在します。
多くの場合 App は外部からインストールする形で追加しますが、実は自分で作成することも可能です。
なお、本記事で紹介する手順は単一のサーバからなる環境で実施しており、クラスタ環境ではこの通りでないことに注意してください。

まず、ホーム画面の左にある App 列の右上の歯車マークをクリックして、 App の一覧を開きます。

![WS000493.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/5bf723a0-f9f5-3077-38fd-8a0237e4c623.jpeg "App")

次に、右上の「 App の作成」をクリックします。

![WS000494.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/89d7c417-3d8c-bd99-dd0d-27171060c9f3.jpeg "Appの一覧")

すると、 App の作成画面が開きます。

![WS000496.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/6a8cb4a1-2485-97a6-458d-4f30a5aa6536.jpeg "App作成")

今回は名前を「 TEST_APP 」、フォルダー名を「 test 」にし、その他はデフォルトのままにして作成してみます。
一覧で検索すると、以下のように作成できていることがわかります。

![WS000498.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/10a8446a-8ed5-c301-28dc-f8a3371fd8d1.jpeg "App作成確認")

もちろん、ホーム画面の App 列にも表示されています。

![WS000499.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/215442d9-a9a3-626b-4b8b-1ca4879d432d.jpeg "App作成済み")

 App を作成することで、ダッシュボードやアプリケーション等の範囲を App 内に制限して管理したりすることが可能です。
個人で使用する分にはあまり関係ないかもしれませんが、複数人で使用する場合は利用場面や利用グループで App を作成し分割することで利用しやすくなることがあります。
IntelliJ IDEAが真っ赤になったので直した

# はじめに

Ktorのプロジェクトを、IntelliJ IDEAで久しぶりに開きました。そして、**build.gradle.kts**を開いてみると次のような真っ赤な画面になっていました。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/261df66e-98f6-d4e1-62a3-388468071ff2.png)

エラーの内容を確認してみると、次のように表示されていました。

```shell
Expression 'application' cannot be invoked as a function. The function 'invoke()' is not found
```

# Gradleのすべてのプロジェクトをリロードする

この問題を解決するために、IntelliJ IDEAの右側にある**Gradle**タブを開きます。

そして、**Reload All Gradle Projects**アイコンをクリックします。

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/d8385fd9-37c4-9977-1c92-46dea3830033.png)

この操作で、Gradleプロジェクトの再読み込みが行われます。
進捗状況は、ビルドツールウィンドウで確認することができます。

再読み込み終了後、`BUILD SUCCESSFUL in m s`とウィンドウに表示されれば完了です。

![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/1b0940e9-0c6d-79e1-1249-bec26cf39b67.png)

もう一度、**build.gradle.kts**を確認しましょう。
今まで真っ赤だった画面が解消されています。

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577119/ef7bbcbb-e2d9-0727-1960-451144dd7252.png)

# まとめ

**build.gradle.kts**が真っ赤なときは、一旦冷静になり、とりあえずGradleプロジェクトの再読み込みを行いましょう（未来の自分へ）。

# 参考にした記事

https://pleiades.io/help/idea/build-sync-tool-window.html#354afc92
Error: Member not found: 'FirebaseAppPlatform.verifyExtends'.  FirebaseAppPlatform.verifyExtends(_delegate);への対応

① pubspec.yamlに

```pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

dependency_overrides:
  firebase_core_platform_interface: 4.5.1

dev_dependencies:
  flutter_test:
    sdk: flutter
```

を追記。

② flutter clean

③ Podfile.lockファイルを削除

④ Podsフォルダを削除

⑤ pubspec.lockを削除

```
Error (Xcode): Undefined symbol: __swift_FORCE_LOAD_$_swiftCompatibilityConcurrency
```

というエラーに変わる。

⑥ 以下の記事を参考にXcodeのバージョンを変更
（自分は最新のバージョンにしました。Xcode13.0 → Xcode14.2）

https://qiita.com/bakatsuyuki/items/52d8959d45f20ef16419


⑦ flutter run


上記でエラーが解消でき、ビルドが通るようになりました☺︎

同じ現象で詰まった方の参考になれば幸いです！

※Xcode14.2にしたことで他の開発環境で下記のエラー対応が必要になってしまったので、他の開発を並行している場合は、前のXcodeも保存しておき、プロジェクトごとに切り替える注意が必要かもしれません。


**参考サイト**

https://stackoverflow.com/questions/74226250/error-member-not-found-firebaseappplatform-verifyextends

https://qiita.com/mogmet/items/4bd48bce39ad8f265c72
vcpkgでインストールしたQtで「qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""」のエラーが出る場合の対処法

vcpkgでインストールしたQtを呼び出そうとしたところ、コンパイルは通ったのですが、実行時に以下のようなエラーが出ました。

```
qt.qpa.plugin: Could not find the Qt platform plugin "windows" in ""  
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem. 
```

実行時に必要なプラグインが欠けているのが原因のようなので、vcpkgでQtをインストールしたときに一緒に追加されるwindeployqtをCMakeの`POST_BUILD`イベントで実行するようにしたところ、動くようになりました。

具体的には、`CMakeLists.txt`に以下のようなカスタムコマンドを追加して、ビルドタイプが`Debug`なら`windeployqt.debug.bat`、`Debug`以外なら`windeployqt.exe`が実行されるようにします（ターゲット名の`main`の部分は各自のターゲット名で置き換える必要があります）。
`find_program`はデフォルトでは値をキャッシュするようなので、`NO_CACHE`を付けないとビルドタイプが変わったときにうまく動かなくなります。

```cmake:CMakeLists.txt
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
	find_program(WINDEPLOYQT NAMES windeployqt.debug.bat NO_CACHE)
else()
	find_program(WINDEPLOYQT NAMES windeployqt.exe NO_CACHE)
endif()

add_custom_command(
  TARGET main POST_BUILD
  COMMAND ${WINDEPLOYQT} $<TARGET_FILE:main>
)
```

リポジトリ例はGitHubにも上げてあるので、併せて参照してください。
https://github.com/ishioka0222/qt-vscode-vcpkg