OmniAICreator/Qiita-1.07M huggingface dataset:
EtherscanでERC1967のProxyを認識させる方法の備忘録

## ERC1967とは
アップグレード可能なコントラクトを実装する際に使用する規格です。

[こちらの記事](https://qiita.com/taijusanagi/items/59d4692393532c8c87e6)に詳細を記載しています。

## EtherscanでのERC1967コントラクト

実際にRopstenで設定した[Proxyコントラクト](https://ropsten.etherscan.io/address/0xb381521b8bf778ba47cfb1d7c204a9565124bdff#code)です。

Etherscan上でProxyとして認識させることによって、下記のようにProxyコントラクトからImplementaionのロジックを呼び出せる状態にします。
![Screen Shot 2022-02-01 at 20.51.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/d036acbe-1436-83d2-a72f-a90af6658942.png)

## 前提条件

事前に下記のように[Implementationコントラクト](https://ropsten.etherscan.io/address/0x57e36355942b043d92c42f69bbc4d42a7bf06f0f#code)の検証を行っておく必要があります。

![Screen Shot 2022-02-01 at 20.43.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/bb4971f3-c703-fe71-cb6f-df527b0018d5.png)

## Proxyの検証手順

ProxyコントラクトのEtherscanのページで、"More Options"の"Is this a proxy?"をクリックします。
![Screen Shot 2022-02-01 at 20.38.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/8dd6895f-0bcb-670b-c160-710f7a665bc7.png)

Proxy登録用のページに遷移するので、自動的に入力されているアドレスがProxyのアドレスかを確認し、Verifyをクリックします。
![Screen Shot 2022-02-01 at 20.39.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/07f4cb24-3df4-3e08-9ebd-557638355991.png)

検証に成功すると、下記のようなモーダルが出てきます。
![Screen Shot 2022-02-01 at 20.45.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/c48253ff-176d-bfd7-139f-52e49d38615b.png)

EtherscanでProxy先のImplementationの関数を利用できるようになります。
![Screen Shot 2022-02-01 at 20.46.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/cb8911ce-c24f-d053-95c4-421efb5a7a8e.png)
Ubuntu 20.04 LTSでnode.jsのバージョンを上げる

**環境**
Ubuntu Server 20.04 LTS

Ubuntu 20.04 LTSだと`apt install`ではバージョン10.19.0が当たるらしい。

```
# sudo apt install nodejs
# node -v
v10.19.0
```

* `apt install nodejs`からの導入では、難ありなので、`npm`のインストールからやった方が良かった。

```
# sudo apt install npm
# npm -v
6.14.4
```

* `npm`で`n`パッケージをインストールします。

```
# sudo npm install n -g
```

* `n`コマンドで任意のバージョンをインストールします。

```
# sudo n 16
   installed : v16.14.0 (with npm 8.3.1)
```

* `n`コマンドで任意のバージョンを選択します。

```
# sudo n
  ο node/16.14.0

Use up/down arrow keys to select a version, return key to install, d to delete, q to quit
```

* `npm`を`purge`します。

```
# sudo apt purge npm
# npm
bash: /usr/bin/npm: そのようなファイルやディレクトリはありません
```

* 設定を反映します。

```
# sudo ln -sf /usr/local/bin/node /usr/bin/node
# sudo ln -sf /usr/local/bin/npm /usr/bin/npm
```

* 反映を確認します。

```
# node -v 
v16.14.0
# npm -v
8.3.1
```

先に指定したバージョンになっていれば完了。
AWSパラメータストアのSecureStringを取得して、起動テンプレートのユーザデータに入れる方法

AWSパラメータストアのSecureStringを取得するには下記のコマンドを実施する。パラメータの意味は次の通り。`--name "MyParameterName"`でパラメータ名を指定。`--query 'Parameter.Value'`でパラメータの値を指定。`--with-decryption`で暗号化された文字列を復号。

```bash
$ aws ssm get-parameter --name "MyParameterName" --query 'Parameter.Value' --with-decryption --output text
```

EC2起動テンプレートのユーザデータにパラメータストアの値を入れるには下記のようにすればいい。これで`${PARAMETER}`に値がセットされる。

```bash
$ set $(aws ssm get-parameter --name "MyParameterName" --query 'Parameter.Value' --with-decryption --output text)
$ PARAMETER=${1}
$ echo ${PARAMETER}
＜パラメータの値が表示される＞
```
個人開発のアイデア帳（随時更新）

# 作った目的
個人でアプリを作成していますが、その他にも作りたいアプリがあるのでまとめようと思います。
**「なんか作りたいけど、これといって作りたいものはないな」という方**の一助となれば嬉しいです。  

# Twitter
・自分のいいね！のリストを「自己啓発用」「好きな漫画」のようにカテゴリ分けができ、ざっと見れるアプリ
（自然言語処理を使用して自動カテゴリ出来ればなお良し)
・ツイッターのやべーアカウント一覧を出すアプリ
・業務効率方法に特化したSNSアプリ
・Twitter転職用に社長、採用者アカウントがザっとだすアプリ
# 学習サイト
・GitHubのプルリクみたいに、自分の書いたコードのフィードバックがもらえるアプリ
・[このサイト](http://www.databaseanswers.org/data_models/index.htm)のようなNoSQLの設計リストがザっと出るサイト
・マテリアルデザイン、ヒューマンインターフェースを手軽に学べるアプリ。
#ビジネス
・IT流行り言葉、バズワードを検索できるアプリ
・IT流行り言葉、バズワードのリストがザっと見れて、Wikiを遷移できるアプリ
・リファラル採用の敷居を下げるために、採用担当・社長に気軽にいろんなことを聞けるチャットアプリ
・技術書を個人間で貸し借りできるアプリ（他の人から聞いた）
・個人開発のWebアプリを集めたアプリ
　主に、ベンチャーキャピタル等の投資側と開発側の橋渡しになれるような形
　GitHubとリンクさせて継続的に開発しているか見れるようにする
・10分ほど愚痴を聞いてくれる。聞き手、話して間で継続的に参加する仕組みを作る。
・サービスのユーザーペルソナが自動生成できるアプリ

#その他
・自分がやっているゲームの集計データを集めるプラットフォームアプリ
　ガチャ確立などのデータを他のユーザーから集めるプラットフォームを作るなど
　例：[アークナイツのペンギン急便データ統計処理部門](https://penguin-stats.io/)

# アイデアのヒントメモ
・**Web APIを探してみる**
>・Twitter、hotpepperなどの既存のアプリと組み合わせてアプリを作りたい。
その場合、そのデータをWebAPIとして公開している場合があるので探してみましょう。
役立つWebAPIがあるかもしれません。
お勧め検索サイト
・[API LIST 100+](https://api.app-rox.com/)
　-面白そうなAPIを集めたサイト
 -ザっと見るとアイデアが思いつくかも
 -ただし、ぐるなびAPIのような有料化などの補足はないので代替を探すなども必要　
・[Rakuten RapidAPI](https://api.rakuten.net/marketplace)
　-楽天が提供するAPI管理を1元化するサービスです。
　-無料プランもありますが、基本的に有料として使うものなので。API検索のみとして使うのもありかもしれないです。
・[programmableweb API search](https://www.programmableweb.com/api-research)
 -主に世界のAPIを探すためのサービスです。
 -APIの統合、廃止などを補足してくれるので使えるかどうか？というのもこのサイトで完結する場合もあります。
 -英語が読める人向け  
※APIのエンドポイント変更、打ち切りなどがある可能性があります。もし、アプリを育てていきたいならば継続的な運用が必要であることも考慮しましょう。
※スクレイピングという方法もありますが、著作権法上の問題がありますので必ず各サイト様の利用規約とお問い合わせを行いましょう。

・**オフラインコミュニティに参加しましょう**
>・継続的に参加したら色々な人と話して「このアプリを使えば解決できるかも」「これがしたいけど一緒にやろうよ！」という話ができてモチベーションが上がるかもしれません。
・個人開発アプリのフィードバックができる良い機会に出会えるかもしれません。
・ちなみに僕が行っているお勧めのコミュニティはこちらです。（ダイマ）

https://mht-code.connpass.com/

#おわりに
もし「こういうアイデアがあるよ！」「こういうものってどういう形で作ればいいの？」「似ているけどこんなアプリあるよ！」などがありますたら、[Twitter](https://twitter.com/API_daisuki)のDMかリプライかコメントで書いていただけたらと思います。
こちらの記事で反映するかもです。
40 代おっさん EC2にmariadbをダウンロードをしてlaravelで使用してみる

## 本記事について

本記事は AWS 初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 構築環境

・EC2:Amazon Linux2
・PHP7.3
・Laravel 5.8
・mariadb

mariadb以外の構築環境は
https://qiita.com/kou1121/items/638c7052f44b8d1b1766
参照してください


## mariadb

### mariadbのダウンロード

``` sh
sudo yum install -y mariadb-server
```

### mariadbの起動

``` sh
sudo systemctl start mariadb
```

### mariadbのパスワードを設定

``` sh
sudo mysql_secure_installation
```

Enter current password for root (enter for none):
このように聞いてくるがEnterでおｋ！

ついぎに
Set root password?
と聞いてくるので y を

自分のパスワードを入れてください。
再度パスワード入れてと来るので再度入れる。

次は色々聞かれますがすべて y で対応！！

Thanks for using MariaDB!
とでたら大丈夫です。

### mariadbの自動起動を有効化

``` sh
sudo systemctl enable mariadb
```

Created symlink from /etc/systemd/system/multi-user.target.wants/mariadb.service to /usr/lib/systemd/system/mariadb.service.
と出ました。

起動してるか確かめる

``` sh
sudo systemctl is-enabled mariadb
```
enabled
となっていれば大丈夫です。

## laravelの.eneでデータベースの設定をする。

``` sh
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=自分のUSERNAME
DB_PASSWORD=自分のPASSWORD
```

## mariadbに入ってデータベースを作る。

``` sh
mysql -u root -p
```

Enter password: 
と聞かれますので自分のパスワードを

mariadbに入りましたら

``` sh
create database laravel;
```

出来たか確認

``` sh
show databases;
```

``` sh
+--------------------+
| Database           |
+--------------------+
| information_schema |
| laravel            |
| mysql              |
| performance_schema |
+--------------------+
```

laravelのデータベースが出来ています。
exit
出てください。

## phpMyAdminをブラウザ上で見れるように設定する。

### laravel の public に必要なファイルを入れる

publicに移動

``` sh
cd public
```
移動したら

``` sh
wget https://files.phpmyadmin.net/phpMyAdmin/4.8.3/phpMyAdmin-4.8.3-all-languages.zip
```
ファイルをダウンロードしたら解凍

``` sh
unzip phpMyAdmin-4.8.3-all-languages.zip 
```

ファルダ名が長いのでphpMyAdminにする。
出来ましたら
phpMyAdmin/index.php
をURLの後ろにつけるとphpMyAdminの画面が出てくる。

できました～～
久しぶりに頑張って見ました。
ゆっくりながらも勉強頑張ります。

## 参考資料

https://www.youtube.com/watch?v=XXXQOYnsCBk&t=195s
MAUIをチュートリアルにしたがって動かしたいのにAndroid Emulatorが動かないときの解決策

# MAUIをチュートリアルにしたがって動かしたいのにAndroid Emulatorが動かないときの解決策

自分の環境で起きたことなので、他の人の参考になるかわかりませんが残しておきます。
結論から話しておきますと、PCを再起動・VisualStudioを再起動してみると良いかもしれません。
それでも詰まった場合は、自分のやったことがもしかしたら有効に働いたかもしれませんので読み進めてみてください。

## 自分の環境で発生した現象

以下のページのリンク先の直前まで実行する。

<https://docs.microsoft.com/ja-jp/dotnet/maui/get-started/first-app#:~:text=%5B%20Android%20Device%20Manager%20%5D%20%E3%82%A6%E3%82%A3%E3%83%B3%E3%83%89%E3%82%A6%E3%82%92%E9%96%89%E3%81%98%E3%81%BE%E3%81%99%E3%80%82>

上記のページではウインドウを閉じると、次のステップである
> 12.Visual Studio ツールバーで、ピクセル 5-api 30 (Android 11.0-api 30)ボタンを押して、アプリをビルドして実行します。

というように指示されるが、そもそもウインドウを閉じただけではピクセル 5-api 30 (Android 11.0-api 30)ボタンが表示されない。
しょうがなく[Android デバイス マネージャー]ウインドウから対象のエミュレータを実行するものの、以下のようなエラーが発生する。
>デバイス エラー: Could not get emulator name after starting AVD pixel_5_-_api_30
![2022-02-01_19h16_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452291/8ae288f7-5476-5356-1e73-f4741eacfc0a.png)

## トラブルシューティング

手順になかったこととして、以下のダイアログが表示されていた。
>"Hyper-V" 機能をオンにして、ネイティブ ハイパーバイザーに切り替え、エミュレーターを加速させてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452291/1238ec11-6712-c8a9-d97f-506dba5f84e9.png)

もしかしたら上記の原因があるかもしれないため、一旦[ドキュメント]ボタンを押下してHyper-V機能のOnを試みる。

<https://docs.microsoft.com/ja-jp/xamarin/android/get-started/installation/android-emulator/hardware-acceleration?tabs=vswin&pivots=windows#hyper-v>

以下のリンクでは、ファームウェアで仮想化を有効化する方法が書かれています。

<https://nj-clucker.com/virtualization-support-disabled/>

その後の手順で、プログラムの有効化のところでHome EditionではHyper-Vが起動できないことに気づいたのですが、とりあえずそれっぽいフォルダのところにチェックを入れました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452291/e583bf43-aa1a-fb12-595a-2f1e119f925b.png)

すると、再起動が求められたため、PCを再起動してもう一回 VisualStudio2022 を起動しなおすと、ピクセル 5-api 30 (Android 11.0-api 30)ボタンが表示されているため実行してみると…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/452291/5924fd6a-cc09-3160-71cc-e2cb5da21d23.png)

**なぜか、動いてる。**（本当になんで？）

## まとめ

結局、何が有効に効いたかわかりませんでした。
プレビュー版ですので、色々とバグがひそんでいるかもしれません。
何か詰まったりしたら、参考にしてみてください。
[PHP]入力値がSJISで表現できるか調べる

# 概要
ある文字列がSJISで表現できるかどうかを調べます。

# 手順
デフォルトの文字コードで表現された文字列を、SJISに変換して再度元の文字コードに変換。
その結果が同一であればSJISで表現できる文字列。(表現できない場合は変換時に?などで置き換えられる為)

[結果](https://3v4l.org/Q7WKA)

```php
<?php
// デフォルト文字コードをUTF-8とする
// SJISで表現できない文字
$a = '𠮟';
var_dump($a);
#=> string(4) "𠮟"　//問題なく出力される

// UTF-8からSJISに変換
$converted = mb_convert_encoding($a, 'SJIS', 'UTF-8');
var_dump($converted);
#=> string(1) "?"　//表現されない

// SJISからUTF-8に変換 
$new_a = mb_convert_encoding($converted, 'UTF-8', 'SJIS');
var_dump($new_a);
#=> string(1) "?"　//表現されない

// $a !== $new_a なので"𠮟"はSJISで表現できない
```

# まとめ
この辺の関数を使用してもうまくチェックできなかったので、今回のような方法を取りました。

https://www.php.net/manual/ja/function.mb-detect-encoding.php

https://www.php.net/manual/ja/function.mb-check-encoding.php

何か他に良い方法があったりしたら教えていただけるとありがたいです。
8.2 基本構文（変数とは、if文, switch文, for文, while文について）補足

# 基本構文を使用して表示を制御してみよう

## if文、for文

if文やfor文を使用して、ボタンを押下することで表示、非表示の切り替わる文字列を実装していきます。

<details><summary>index.html</summary>
<div>

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>8.3</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <p>visibilityプロパティを使用して表示を切り替える</p>
    <p id="test1">あいうえお</p>
    <button onClick="hide()">非表示にする</button>
    <button onClick="show()">表示する</button>
    <button onClick="showHide()">表示／非表示</button>

    <p>displayプロパティを使用して表示を切り替える</p>
    <p id="test2">かきくけこ</p>
    <button onClick="displayHide()">非表示にする</button>
    <button onClick="displayShow()">表示する</button>
    <button onClick="displayShowHide()">表示／非表示</button>

    <p>渡された引数の数分の数値を表示</p>
    <p id="test3"></p>
    <button onClick="repetitionShowNum(5)">数値を表示</button>
  </body>
  <script src="script.js"></script>
</html>
```
</div>
</details>


<details><summary>script.js</summary>
<div>

```js
/** visibilityを使用して非表示 */
const hide = () => {
  let element = document.getElementById("test1");
  element.style.visibility = "hidden";
};

/** visibilityを使用して表示 */
const show = () => {
  let element = document.getElementById("test1");
  element.style.visibility = "visible";
};

/** visibilityを使用して表示／非表示 */
const showHide = () => {
  let element = document.getElementById("test1");
  if (element.style.visibility === "hidden") {
    element.style.visibility = "visible";
  } else {
    element.style.visibility = "hidden";
  }
};

/** displayを使用して非表示 */
const displayHide = () => {
  let element = document.getElementById("test2");
  element.style.display = "none";
};
/** displayを使用して表示 */
const displayShow = () => {
  let element = document.getElementById("test2");
  element.style.display = "block";
};

/** displayを使用して表示／非表示 */
const displayShowHide = () => {
  let element = document.getElementById("test2");
  if (element.style.display === "none") {
    element.style.display = "block";
  } else {
    element.style.display = "none";
  }
};

/** 渡された引数の数分の数値を表示 */
const repetitionShowNum = (num) => {
  let element = document.getElementById("test3");
  for (let i = 1; i <= num; i++) {
    element.textContent += i;
  }
};
```
</div>
</details>


# 参考

https://allabout.co.jp/gm/gc/23973/
ExcelVBA使いが、ClosedXMLを利用してみた

# はじめに
ExcelVBAはよく使っていたんですが、いかんせんレガシーだろうということで、ClosedXML＋C#でいろいろやってみたので、そのメモ。

# 前提など
ClosedXMLは[[こちら]](https://www.nuget.org/packages/ClosedXML/)より取得。

# ClosedXML操作サンプル

#### ブックの読み込み・作成・保存
``` C#
//新たなブックを作成
var workBook = new XLWorkbook();

//既存のブックを開く
var workBook2 = new XLWorkbook("C:\\work\\text.xlsx");

//ブックを保存する
workBook.SaveAs("C:\\work\\text3.xlsx");
```
注意点として、保存するときは、「new XLWorkbook()」するだけではだめで、シートがひとつでもないとエラーになるようです。

#### ワークシートの読み込み・作成
``` C#
var workBook = new XLWorkbook();

//既存ワークシートを取得
var workSheet = workBook.Worksheet("sheet1");

//新たなワークシートを追加
var workSheet2 = workBook.Worksheets.Add("sheet2");
```

#### セルの参照など

``` C#
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");

//sheet1のセルA1から値を取得します
var cellItem = workSheet.Cell(1, 1).Value;

//同様に”A1”形式指定で取得します
var cellItem2 = workSheet.Cell("A1").Value;

//値の取得には種々のメソッドが用意されているようです
var cellStr = workSheet.Cell(1, 1).GetString();
var cellInt = workSheet.Cell(1, 1).GetValue<int>();
```
Cell、Rangeの扱いはVBAなんかと同じですね。Range(Cell(1,1),Cell(2,2)) みたいな使い方もできるようです。
ちなみに、Valueで取得すると、object形式となるようで、対象のセルに設定される値が決まっている場合は、型指定して取得したほうが安全で扱いやすいかもしれません。

#### 文字列検索、セルのアドレス・行列番号取得

``` C#
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");

//シート内を文字列検索します
var resultCells = workSheet.Search("hoge");
foreach (var resultCell in resultCells)
{
    //該当セルのアドレスを返却
    Console.WriteLine(resultCell.Address);
    //該当セルの行番号を返却
    Console.WriteLine(resultCell.Address.RowNumber);
    //該当セルの列番号を返却
    Console.WriteLine(resultCell.Address.ColumnNumber);
}
```
Searchメソッドで文字列を検索し、結果が配列で帰ってきます。Linqも使えるので以下のような方法も可能。AddressメソッドでCell番地情報を取得します。

``` C#
var resultCell = workSheet.Search("hoge").LastOrDefault().Address.RowNumber
```

#### シート内で入力されているセルから最終行・列を取得

``` C#
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");

//最終行を取得
var lastRow = workSheet.LastRowUsed().RowNumber();
//最終列を取得
var lastCol = workSheet.LastColumnUsed().ColumnNumber();
```
VBAだと、「.End(xlDown)」とかで取得してたやつに近いかもしれないです。ループ処理で制御するために使うことになりそうです。

#### シート内から範囲をテーブル形式で取得
``` C#
var workBook = new XLWorkbook();
var workSheet = workBook.Worksheet("sheet1");

//値が入力されている範囲をテーブル形式で取得
var tbl = workSheet.RangeUsed().AsTable();

//取得結果を行単位でループ
foreach(var rowData in tbl.Rows())
{
    //列単位でループ
    foreach(var cellData in rowData.Cells())
    {
        Console.WriteLine(cellData.Address);
        Console.WriteLine(cellData.Value);
    }
}
```
AsTableメソッドでテーブルイメージで一気に値を取得できます。そのあとは行列をループ制御したり、直接セルにアクセスしたりもできるようです。一回でまとめて情報を取得できるので、処理スピードが速くなるかもしれないです。

ちなみに、以下のように範囲を指定して取得することもできます。

``` C#  
var tbl = workSheet2.Range("A1:B3").AsTable();
```
使いこなすとかなり便利かもしれないです。

おわり
PHP 「===」 と 「==」の違い

基本的なことですがわかっていなかったので調べてみました。

先に結論を書きますと
####"==="は値と<font color="red">データの型</font>が完全に一致している場合
####"=="は値のみ一致している場合
ということでした。

###例

```
    $array = ["15", 15];

    var_dump($array);//出力：array(2){[0] => string(2) "15", [1] => int(15)}
    
    // 例１
    foreach ($array as $v) {
        if($v === 15){
            echo "YES" . " ";
        }else{
            echo "NO" . " ";
        }
    }
//出力:NO YES
    
    // 例２
    foreach ($array as $v) {
        if($v == 15){
            echo "YES" . " ";
        }else{
            echo "NO" . " ";
        }
    }
//出力:YES YES
```
データの型はstring=文字列, int=整数のことを表しています。
例１の条件式は$v <font color="red">===</font> 15 なので<font color="red">int(整数)の15の場合</font>のみ"YES"、それ以外は"NO"を表示するので
出力：NO YES　となります

例２の条件式は$v <font color="red">==</font> 15 なので<font color="red">int(整数)、string(文字列)関係なく15の場合</font>に"YES"を表示するので
出力：YES YES　となります

こちらの記事でさらに詳しくわかりやすい説明をされていたので、深堀したい方はこちらをご覧になってみてください。
参考：https://qiita.com/atsushi586/items/adca2368d9a760ad862d
AWS SAA合格体験記

<h1>【2022年1月】AWS SAA合格体験記
<p>先日、AWS SAAを取得しましたので、合格までの学習方法について記載します。
これから学習する方にとって、少しでもお役に立てれば幸いです。
※2021年8月にAWS CLF　合格済<p/>

<h3>学習教材＆学習時間
<p>・[AWS認定資格試験テキスト（12時間）](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9A%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-%E6%94%B9%E8%A8%82%E7%AC%AC2%E7%89%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/4815607389/ref=asc_df_4815607389/?tag=jpgo-22&linkCode=df0&hvadid=342397001181&hvpos=&hvnetw=g&hvrand=1139345574279359912&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009717&hvtargid=pla-1016930256377&psc=1&th=1&psc=1&tag=&ref=&adgrpid=72867581430&hvpone=&hvptwo=&hvadid=342397001181&hvpos=&hvnetw=g&hvrand=1139345574279359912&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009717&hvtargid=pla-1016930256377)
・[Web問題集（28時間）](https://aws.koiwaclub.com/)
・社内勉強会（3時間）<p/>

<h3>勉強方法
<p>1. AWS認定資格試験テキストを一周する（7時間）
2. 復習しながらNotionに纏める（5時間）
　※試験後も定期的に確認できるように纏めました↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/4c10f743-1653-c01f-83a1-c3a9bac53243.png)
中身↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/63c5adda-9890-790e-ca44-7433bfe5d94a.png)
3.AWS Web問題集（28時間）
80~150を3周解きました。
こちらのサイトでは、本番と似た形式の問題や同難易度の問題を解くことができます。
問題数がとても多いので、初回で正答率80%を超えた回は2回目を解かない、などルールを決めてどんどん先に進みました。

4.社内勉強会（3時間）
社内研修でAWSのSAA対策を受講しました。
VPC、セキュリティ周辺の知識をハンズオン形式で学びました。

<h3>試験結果
<p>試験本番は初めて見る問題や語句もありましたが、可能な限り選択肢を二択に絞りました。
それでも結構ギリギリでしたが、なんとか合格することができました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1520342/3d2cb139-aef8-d5fa-532d-8b913c784d51.png)
勉強会を主催してみました

---
 
この記事は[リンク情報システム](https://www.lis.co.jp/)の「TechConnect！2022年2月」のリレー記事です。
engineer.hanzomon のグループメンバによってリレーされます。
（リンク情報システムのFacebookは[こちら](https://ja-jp.facebook.com/lis.co.jp/)から）

 

TechConnect！2022年2月のインデックスは[こちら](https://qiita.com/hs-lis/items/69eee14fd7bec92a854f)
 
---
#はじめに

社内で技術関連の勉強会を主催したので、
それの運営についてや、得られた教訓や感想等をつらつら書いていきたいと思います。

#勉強会の形式

まず、前提知識として勉強会の形式のお話。
だいたい大きく分けて3つあると思います(細かいものはもっとあると思いますが)

1.　フリー形式
　発表者は居たり居なかったり、自由に質問したり、雑談したり。
　テーマで集まって自由に喋ったり（所謂もくもく会）
2.　セミナー形式
　発表者が居て、テーマについて能動的にしゃべる。その後質疑応答など。
　発表者が複数人でテーマを絞らない場合はLightningTalk(LT)とも言います。
3.　ハンズオン形式
　何かテーマに関して実演しながら発表するタイプ。
　参加者も一緒にやってみたりする。ワークショップ形式ともいえる。

#勉強会のメリットとは？
それぞれ大体3つ。
参加する側としては、
　1. 対象のテーマに関する見識が広がる
　　　知らない言葉について知ることが出来る（これがデカイ）
　2. 同様の成長意欲・問題意識を持った人と知り合える
　3. 人脈の形成、能動的な人、色んな人とコミュニケーションができる

開催する側としては、
　1. 対象のテーマに関する能動的な理解が得られる
　　　フィードバックやコメント、指摘を通じてより正しい・深い理解が得られる
　2. 社内コミュニケーションの促進や全体的なスキルアップに繋がる
　3. 人脈の形成、能動的人、色んな人コミュニケーションができる

あんまりデメリットがない。
めっちゃ旨味が強い。やらないほかないのでは....?

#実施した勉強会の形式

前半がセミナー形式、後半がフリー形式。
発表を行って後は自由に語り合う・話し合う、みたいな形式です。
所要時間はだいたい、発表に30分、雑談や質問等に30分、合計1時間。

主催する時点で上記の形式を考えていて、
既に何回か実施しましたが、実際これはまぁまぁ上手くいきました。
雑談や質問等で沈黙になることはなく、
色々な質問や話が出てきて盛り上がることもしばしばです。
ただ、指摘や語るポイントのようなものがないので、
中々一つのことで会話が続かず、話題が断続的になりがちでした。
深い理解を誘うような形式で行われている、とは言いづらいです。
なので、フリーっぽい形にするならば、
発表者側としても、
**事前に、ここは語ろう、というポイントを作ったり、
参加者への理解の問いかけなど意図の明確化、より工夫する必要がある**
というのを強く感じています。

参加者より**ハンズオン形式も取り込むとより盛り上がるのでは？**
みたいな意見も途中で頂いていたりしました。
一方的に発表していると参加者が受動的になってしまう（すぐには喋ってくれない）ので、
そういったことを防ぐ面では、
確かにいいかもしれない！と思ったりもしました。**発表中でもやり取り大事！**

#実施した勉強会の目的
そもそもなんで勉強会主催したんです？って話なんですが、
技術的なキャッチアップの重要性が増してきている、という認識がありました。
近年流行っているアジャイル開発が特にそれを押し上げていると思います。、
様々な技術の過渡期で新しい設計手法や概念の登場などが多発しているのもあります。
そこで**知らないよりは少しでも知っている方がいい**。
それは例えよく知らない単語でも、単語やその概念を少しでも知っていれば先んじて学べる。
ということで、決してITのベテランとは言えませんが、勉強会を主催することにしました。
また、自身としても勉強会を実施することで、より色んな分野の理解を深めたいという気持ちもありました。

#実施した勉強会のテーマ

テーマはとりあえず幅広く自由に語れるように、WEB技術について、としました。
現時点でブラウザ等の歴史から、フロントエンド、バックエンド、インフラまで話したりしました。
何回かに分けて実施しています(実はまだ続いている)

・テーマ（予定）
　1回目 : Web技術の変遷と現在の状況（済）
　2 回目 : Webフロントエンドについて（済）
　3 回目 : Webバックエンドについて（済）
　4 回目 : 仮想環境・自動化について（済）
　5 回目 : DB・検索システム（今ここ！！）
　6 回目 : クラウドサービス
　7 回目 : 近年の技術思想について


#その他感想

発表者として私は全部に立っているのですが、なかなか範囲が広く、
この技術はちょっと自信ない、とかいうところも多々あったりしました。
そこは雑談や質問で参加者のフォローや指摘も頂きながらやることでカバーして頂いたりもしたり...
4回目にもなってくると、自身の知識量を超えていて一部御高説気味といいますか、
少しテーマが広すぎたかもなぁ...という反省もありました。
もちろん、そういった反省の中で色々と知ることもあるので自分自身は全然マイナスではないのですが、
参加者にはマイナスにはなっている部分もあるかもしれないだろうな、とは思っています。

**参加者にマイナスになってしまうかもしれない、というのは注意しないといけない**ですね。
勉強会は参加者と発表者と互いに深い理解を得られるようにしないといけないです。
せっかく参加してくれているのですから。そういう思慮は必要かな、と思います。
これは教育など、そういったテーマには付きまといがちな問題でもあります。
まぁ自信を持って御高説しないと教えられない、という面ももちろんありますので考えすぎも良くないですが。

#さいごに
ほぼ中身のない感じの記事ですが、もし勉強会をやってみたい方の参考になれば幸い。
意外と楽しく運営できていて学び強いので、みんなも勉強会やろう！！！
laravel sendgrid メール送信 ファイル添付、テンプレートも

#インスコ

```
composer require "sendgrid/sendgrid"
```

#apikey取得

① sendgrid にログイン
② 左側メニュー Settings > API Keys > Create API Key
③ .env に記載

```env
SENDGRID_API_KEY=SG.youryour
```


# ① 送信するだけ

```HogesController.php
use SendGrid;
use SendGrid\Mail\Mail;
use \Symfony\Component\HttpFoundation\Response;

class HogesController extends Controller
{
    public static function test(request $request)
    {
        $email = new Mail();
        $email->setFrom('from@from.com', '送信元名');
        $email->setSubject("メールのタイトル");
        $email->addTo("to@to.com");
        $email->addContent("text/plain", "これがコンテンツです");
        
        $sendgrid = new SendGrid(env('SENDGRID_API_KEY'));
        $response = $sendgrid->send($email);
        if ($response->statusCode() == Response::HTTP_ACCEPTED) {
            print_r("送信 できました");
        } else {
            print_r("送信 NG");
        }
    }

}
```

`OK`

# ② ファイルを添付

```HogesController.php
    $path = public_path("img/gal.jpg");
    $file_encoded = base64_encode(file_get_contents($path));
    $email->addAttachment(
        $file_encoded,
        mime_content_type($path),//image/jpeg
        "gal.jpg",//送信されるファイル名
        "attachment"//固定
    );
```

`OK`

# ③ テンプレートを利用

```HogesController.php
    $data = [
        "hoge" => 'ほげ',
        "name" => 'たろう'
    ];

    $email->addContent(
        "text/plain",// "text/html"//plain にしないとblade.phpの改行が有効ならない
        strval(
            view(
                'emails/test',//view/emails/test.blade.php
                compact('data')
            )
        )
    );
```

```/view/emails/test.blade.php
テストメールテンプレート
変数{{ $data['hoge'] }}も{{ $data['name'] }}も渡せます
```

`OK`

以上
JavaScriptでは「時間のかかる処理」は後回しになる？


「javascriptは非同期言語なので、時間のかかる処理は後回しになる」といった書き方をしている記事をいくつか目にしたことが有ります。僕も以前は「たぶん後回しになるんだろうな～」くらいに思っていました。

しかし、「時間のかかる処理は後回しになる」は、正しくない認識です。
非同期関数等を除けば、基本的には時間のかかる処理であっても同期処理（上から順に処理）されます。

以下のコードはそのー例です。

```javascript
console.log("while前")
start = Date.now()
while(true){
  if( Date.now() - start > 3000){
    console.log("3秒経過");
    break;
  }
}
console.log("while後")

//"while前"
//"3秒経過"
//"while後"
```
上記コードを実際に実行するとコンソールには以下の順で表示されます。

・while前
・3秒経過
・while後

3秒もかかるwhileの処理を待ってから、`console.log("while終了後")`が実行されていることがわかります。
もうひとつ似たような例を用意してみました。

```javascript
console.log("for前")
for(let i = 0;i <= 10000; i++){
  if(i == 10000){console.log("10000")};
}
console.log("for後")

//"for前"
//"10000"
//"for後"
```
こちらも同様で、コンソールに表示される順番は「for前」→「10000」→「for後」となります。
つまり、時間のかかる処理でも後回しにせずに同期的に（上から順に）処理していることがわかります。

## setTimeout等が特殊なだけ

setTimeoutを使用して上記２つのコードと似たようなことを行ってみます。

```javascript
console.log("setTimeout前")

setTimeout(function(){
  console.log("3秒経過")
},3000)
           
console.log("setTimeout後")

//"setTimeout前"
//"setTimeout後"
//"3秒経過"
```

この場合、コンソールに表示される順番は「setTimeout前」→「setTimeout後」→「3秒経過」となり
setiTimeoutの処理を待たずに`console.log("setTimeout後")`が実行されていることがわかります。

そして、こうなる理由は「時間のかかる処理を後回しにしているから」ではなく「setTimeoutのような非同期処理をする関数を使用しているから」です。
その裏付けとなるのが以下のコードとなります。

```javascript
setTimeout(function(){
  console.log("setTimeout終了")
},0)

start = Date.now()
while(true){
  if( Date.now() - start > 3000){
    console.log("while終了");
    break;
  }
}
//"while終了"
//"setTimeout終了"
```
コードを見てもわかるとおり、whileの処理には3秒かかるのに対し、setTimeoutは0秒に設定してあります。
もし「時間のかかる処理が後回しになる」のであればコンソールの表示順は`setTimeout終了`→`while終了`となるはずですが、
実際に実行すると`while終了`→`setTimeout終了`となります。

これは、非同期関数に渡されたコールバック関数は同期処理の後に実行される、という処理順序があるからです。
↓そのあたりわかりやすく解説してくださっている記事
https://qiita.com/UTDoi/items/d49ea919818d9b519f93

## まとめ
「時間のかかる処理」が後回しになるのではなく、非同期関数に渡されたコールバック関数の処理が後回しになる。


## JavaScriptは非同期言語？

これに関しては、非同期言語の定義がはっきりしないので何とも言えません。
ただ、JavaScript自体はシングルスレッドの言語であり、上に書かせて頂いる内容なども含めて考えると
非同期言語と断定できるものではないような気がします。
Spark SQLでCSVを読み込む

# CSVファイルを読み込む時に
外部や違うシステムから送られてきたCSVファイルをSparkやDatabricksで読み込む際、いくつかの方法があるが、最も便利だと思う方法がUSING CSV。pysparkでspark.read.csvするのと同じようにエンコーディングやクオートの指定などが細かくできる。

## 例えば以下のようなファイル
エンコーディングは`utf-8`だけど、クオートの中に改行が混ざっていたりすると、手間がかかる。なんとか一発でテーブルにしたい。

```text
"aaa","あああ",","
"bbb","いいい","
"
"ccc","ううう"," "
```

# 手順
1. ファイルをhdfsやdbfsに置く
ファイルをアップロードしたり、ストレージをマウントしたりして、Sparkのクラスタからアクセスできる状態に。

2. CREATE TABLEでテーブルを作る
この時に、`USING CSV`句をつかって、`OPTIONS`に設定を追加する。この例では、エンコーディング、クオート、マルチライン（クオート内が複数行であっても一つのカラムとして読み込む）を設定している。

```sql
CREATE TABLE test_quotation (
  col1 STRING, 
  col2 STRING, 
  col3 STRING
)
USING CSV
OPTIONS (
  'encoding'='utf-8', --エンコーディングをutf-8に設定。sjisも可。
  'quote'='"', --クオートとして"を設定
  'multiLine'='True' --マルチラインを有効に
)
LOCATION '/mnt/test/utf-8' --ここには先ほどファイルを置いた場所を指定
```

# 確認
SELECT文を実行すると`LOCATION`で設定したディレクトリのファイルに対して、`OPTIONS`で設定した内容にしたがって、ファイアが読み込まれてテーブルに。

```sql
SELECT * FROM test_quotation
```

![csv.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1680893/8c79fa1f-b4ca-9ccf-8165-844ce1b004e5.png)


# 参考
- CREATE TABLE文の文法について。`PARTITION`などの設定も併用可能。

https://spark.apache.org/docs/latest/sql-ref-syntax-ddl-create-table-datasource.html

- `USING CSV`で設定可能な`OPTIONS`はこちらに。ヘッダーの扱いなども可能。

https://spark.apache.org/docs/latest/sql-data-sources-csv.html#data-source-option
Yolov5で乳首を物体検出 Object Detectionしたいんだ！

# 利用規約

まずは、Qiitaでこの記事を書いて良いか確認する。

```
第11条(遵守すべき事項・禁止事項)
登録ユーザーは、本サービスを利用するに際し、以下の要素を遵守するものとします。

~~
公序良俗に反する内容の情報を開示する行為
```

つまり、本記事では「公序良俗に反する内容」は開示しません。
技術的な話にとどめます。

もっと詳細はここで
（いつかここにリンクを張るかも）

# 目的

乳首 = Nipple を 機械学習で物体検出したい
乳首 = Nipple を 機械学習で物体検出したい
乳首 = Nipple を 機械学習で物体検出したい
乳首 = Nipple を 機械学習で物体検出したい

# 手法

Yolov5 を使う

https://github.com/ultralytics/yolov5

# データセット

ここらへんから拾ってこよう

https://github.com/EBazarov/nsfw_data_source_urls

# ラベリング

ひたすら 「YoloLabel」を用いてラベリング

https://github.com/developer0hye/Yolo_Label

# 学習

Google Colaboratory でひたすら学習
（間違いなくデータセット間の重複あるけどとりあえず気にしない）


学習データ数
・train数 : 2200個ぐらい
・val数 : 350個ぐらい

# 結果

まぁまぁな精度で乳首検出できた。

結果を載せたい。でも規約が。。

これで!
結果を示します。

引用：https://blog.goo.ne.jp/hama6655/e/d81b3ce36d3c47a47340e2d75170996a

<img width="400" alt="result" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520322/aa3542d1-f9e1-6238-5e54-6724d21e2bae.jpeg">

# 使いたい？

期間限定でデモサイト用意しました。（たまにメンテナンス）

http://whereisnipple.com/

# デモサイト参考

こちらのレポジトリを参考にさせてもらいました。

https://github.com/WelkinU/yolov5-fastapi-demo
wordle風ロゴ？ジェネレータを作ってみた

(タグが必須なので「React」タグを付けていますが、本文はReactと関係ありません。ジェネレータでReactを使用しています)

[wordle](https://www.powerlanguage.co.uk/wordle/)が人気ですね。
そんな中、The New York Timesがwordleを買収したという報道がありました。
筆者が見た記事の一つでは「The New York Times」をwordle風にしてアイキャッチ画像に使っていました。（どのネットメディアだったか思い出せず＆見つけられませんでした...）

↓こんな感じの画像です
![wordle_image_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25588/4917af69-f65f-29a3-d65a-62d83ebd01ae.png)

それで何となく面白そうだったので、勢いでジェネレータを作ってみました。

https://y-takey.github.io/wordle_logo_generator/
(repo: https://github.com/y-takey/wordle_logo_generator )

テキストエリアに適当な単語を改行区切りで入力するとwordle風にします。

![wordle_image_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25588/f1ffc9b3-4ec9-aaf0-66ca-beb2912846d9.png)

* アルファベットだけでなく、何でも入力可能です。
* 単語の文字数や単語数に制限はありません。
* 最終行の単語を正解として扱います。
* 正解の単語より文字数が長い場合は切り捨てます。
* ダウンロードボタンで画像をダウンロードできます。
[2022年] AWS ソリューションアーキテクト - アソシエイトに本2冊で合格した話

# はじめに
10年以上セキュリティエンジニアとして働いていましたが、訳あって最近インフラのリーダーになりました。会社では主にAWSを利用しているため、勉強がてらAWSの資格を取得したという話です。

ちなみにセキュリティエンジニアの時はAWSを使うことはなくGCPで色々なことをやっていました。AWSを使わなかった理由は、数年前にAmazonアソシエイトを意味不明な理由で垢バンされたからです。。

# 前提知識
クラウドプラクティショナーの資格を取得したくらいで、AWSはほぼ触ったことがないです。

https://qiita.com/hanzawak/items/8bb13b20f07bdb3fe875

# 勉強方法
以下2冊の本を読み込みました。どちらも1年以上前の本ですが特に問題なかったです。
Amazonアソシエイトを垢バンされているためアフィリエイトリンクにはなっておりません。安心してクリックしてください。

以下の本は項目ごとに必要な情報がまとまっていたので暗記するのに使いやすかったです。
3日くらいかけて内容を暗記しました。

https://www.amazon.co.jp/dp/4865941991

上の本1冊だけでは不安だったので以下の本も買いました。
上の本に記載していない内容が多々ありましたので買ってよかったです。
こちらも3日くらいかけて内容を暗記しました。

https://www.amazon.co.jp/dp/4815607389

# 受験
ピアソンVUEで自宅から受験しました。
楽勝だと思って受験しましたが、見たことない単語がでてきたりいまいち内容が理解できない問題が出てきたりしてもしかして落ちたかも・・と思いながら解いていました。
結果は無事合格できたのですが、運が良かった気もします。

# 感想
AWS全体を広く浅く把握するためにはちょうどよい勉強ができたと思います。
HAYST法に関する情報の整理

# はじめに
自分のプロジェクトにHAYST法を取り入れようかと考えている。
HAYST法に関する情報を集めておく。
集めた情報から、知見が得られたら、それも記録していく。

# 私のプロジェクトに適用するためのポイント
特に、HAYST法プロセスの「テスト設計」が、今のプロジェクトにぴったりマッチしそうであると考えている。
「有則因子テスト設計」「無則因子テスト設計」「状態遷移テスト設計」をどのような考え方で選択するとよいかを明らかにしたい。
まずは、参考情報として挙げた書籍・資料・記事等から、参考になる点がないかを確認する。

# 参考情報
https://bookmeter.com/books/128129

https://bookmeter.com/books/8206222

http://jasst.jp/symposium/jasst13tokyo/pdf/A2-2.pdf

http://jasst.jp/symposium/jasst18tohoku/pdf/S1.pdf

https://toshimana.hatenablog.com/entry/2018/01/29/003413

https://www.slideshare.net/mhlyc/hayst-ver-78921254

https://note.com/kataruyube/n/n135b3ebc57f9

https://togetter.com/li/1223175
ros json c++

# はじめに

ros c++ パッケージでjsonを扱うためのメモ

※追記(2022/12/25): こっちのライブラリのほうが使いやすい

https://qiita.com/hoshianaaa/items/108ae9edab791fe5e77d

# install

```
sudo apt install rapidjson-dev
```

# プログラム

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.0.2)
project(json_samples)

include_directories(include/rapidjson/include) ## add

find_package(catkin REQUIRED)

catkin_package(
)

## add
add_executable(main src/main.cpp) 
target_link_libraries(main 
)
```

```cpp:src/main.cpp
#include <fstream>
#include <iostream>

#include "rapidjson/document.h"
#include "rapidjson/istreamwrapper.h"
#include "rapidjson/ostreamwrapper.h"
#include "rapidjson/writer.h"

using namespace rapidjson;

int main(int, char **)
{

    // read file
    std::ifstream ifs("sample.json");
    IStreamWrapper isw(ifs);

    Document doc;
    doc.ParseStream(isw);

    std::cout << "a: " << doc["a"].GetInt() << std::endl;
    std::cout << "b: " << doc["b"].GetInt() << std::endl;
    std::cout << "c: " << doc["c"].GetInt() << std::endl;
    std::cout << " ---- " << std::endl;

    // change value
    doc["a"].SetInt(7); 

    std::cout << "a: " << doc["a"].GetInt() << std::endl;
    std::cout << "b: " << doc["b"].GetInt() << std::endl;
    std::cout << "c: " << doc["c"].GetInt() << std::endl;

    // write file
    std::ofstream ofs("output.json");
    OStreamWrapper osw(ofs);

    Writer<OStreamWrapper> writer(osw);
    doc.Accept(writer);    
}
```

# 実行

実行ディレクトリに以下のような,jsonファイルを用意します

```sample.json
{
  "a":1,
  "b":2,
  "c":3
}
```

実行すると```sample.json```を読み込んで```output.json```というファイルに値変更したjsonデータが保存されます.

```
$ rosrun json_samples main
a: 1
b: 2
c: 3
 ---- 
a: 7
b: 2
c: 3
```

```
$ cat output.json
{"a":7,"b":2,"c":3}
```

# 参考

https://pystyle.info/cpp-rapidjson-basic-usage/

# リポジトリ

https://github.com/hoshianaaa/json_samples_cpp
MASM32でdllを作る その2

#MASM32でdllを作る

```dlltest.asm
comment *
ml /c /coff dlltest.asm
link /dll dlltest.obj
*

.386
.model flat

.code

DllEntry proc stdcall hinstDLL:DWORD, fdwReason:DWORD, lpReserved:DWORD
	mov eax, 1
	ret
DllEntry endp

myadd proc stdcall export a:DWORD, b:DWORD
	mov eax, a
	add eax, b
	ret
myadd endp

mysub proc stdcall export a:DWORD, b:DWORD
	mov eax, a
	sub eax, b
	ret
mysub endp

end DllEntry
```

```dev.bat
@echo off
path %path%;C:\masm32\bin
path %path%;C:\Windows\Microsoft.NET\Framework\v4.0.30319
cmd
```

#C#でテスト
環境：Windows 10 Pro (64bit)
x86版のcsc.exeにpathを通す。

```dlltest.cs
// csc /platform:x86 dlltest.cs

using System;
using System.Runtime.InteropServices;

class Program {
	[DllImport("dlltest.dll")]
	static extern int myadd(int a, int b);
	[DllImport("dlltest.dll")]
	static extern int mysub(int a, int b);

	static void Main() {
		Console.WriteLine("add = {0}", myadd(1, 2));
		Console.WriteLine("sub = {0}", mysub(1, 2));
	}
}
```

##実行例
![m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/0f1ab8cd-21c2-f0b3-4a35-9c04cc74665a.png)

#MASM32でテスト
dlltest.dll、dlltest.libをカレントディレクトリに用意する。

```dllclt.asm
comment *
ml /c /coff dllclt.asm
link /subsystem:console dllclt
*

includelib kernel32.lib
includelib user32.lib
includelib dlltest.lib

.386
.model flat, stdcall
option casemap:none

include windows.inc
include kernel32.inc
include user32.inc

mysub proto stdcall :DWORD, :DWORD

.const
fmt	db	'sub = %d', 0dh, 0ah, 0

.data?
hStdOut	dd	?
written	dd	?
len	dd	?
buf	db	1024 dup (?)

.code
start:
	invoke	GetStdHandle, STD_OUTPUT_HANDLE
	mov	hStdOut, eax
	invoke	mysub, 1, 2
	invoke	wsprintf, addr buf, addr fmt, eax
	mov	len, eax
	cld
	invoke	WriteConsole, hStdOut, addr buf, len, addr written, NULL
	invoke	ExitProcess, 0

end start
```

```dev.bat
@echo off
path %path%;C:\masm32\bin
set INCLUDE=C:\masm32\include
set LIB=C:\masm32\lib
cmd
```

##実行例
![m.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/257554/d0982a77-502e-3366-4893-61790f07cbc4.png)


#参考
http://www.interq.or.jp/chubu/r6/masm32/tute/tute017_Jp.html

https://qiita.com/Stosstruppe/items/177043d7b5f840a8fb7a
情報処理安全確保支援士に合格するためのアウトプット（4/n）

#Webアプリケーションファイアウォール（WAF）
IDS、IPSでNWを流れる不正なものを検知・防御できるようになったけれど、
アプリケーションの脆弱性を狙ったものは防御できない。
ただ、世の中にあるものはアプリケーションであり、そこも同様に防御する必要がある。
そんな時に近年利用されるものが、WAF（Webアプリケーションファイアウォールで、ワフと言われる）である。

##WAFの種類
いくつか種類があるが代表的なものは3つほど

- リバースプロキシ型
    - いわゆるプロキシ（PCからWANに行く時に代理でアクセスする）の逆（リバース）
    - なので、WANから来る通信をPCに代理で中に渡すもの
    - これにより、どこの誰かも分からないアクセスを、知った人からの通信に変更できる
- ブリッジ型
    - IPSなどと同様インラインで接続するが、通信は代行しない
    - 橋のように単に架け橋となるだけ
- ソフトウェア型
    - Webサーバーのプラグインとして利用されるもの
    - サーバーには通信が届いてしまうので、防げないことも多いよ

##WAFが検知・防御する内容
- XSS
- インジェクション系の攻撃
    - OS、SQL
- 不正アクセス
    - ディレクトリ、ファイル
- セッションハイジャック
    - アプリ独自の仕様について検出・防御するのは困難
    - 複雑にするほどWAFの処理効率は落ち、システム全体の可用性が落ちることも有り得る

##WAFのチェック内容
- 接続元ホスト
- HTTPリクエスト（コマンド）
- クエリストリング（URLパラメータ）
- HTTPヘッダ情報
- POSTデータ
- クッキーの内容

```
チェック条件やパラメタについては、サイト管理者が設定する必要があるよ
```

##チェック後のアクションについて
- リクエストの排除、エラーコードの返却
    - 安全ではあるが、誤って遮断した場合には不都合となることもある
- 特定URLへのリダイレクト
    - 決まったページ（例えばセキュリティチームへの案内ページ）があるなら飛ばすもよし
- アラートの通知
- 特定プログラムの実行
- ログへの記録
    - 少なくとも最低限これがないと今後の改善ができないので、ログは必須

##付加機能
- SSLアクセラレータ
    - ロードバランサ（LB）やIPS/IDSに機能が備わっていれば、そちらに任せることも可能
- 負荷分散
- Passiveモード
    - リバプロ型のWAFを経由した際に、通信元アドレスをそのまま引き継いで渡す機能

##構成例
- DMZに接続して公開Webサーバへの攻撃を防御する
    - IDS/IPSと同じ一般的な構成
- クラスタ環境に接続
    - LB併設型
        - WAFはLB（＋アクセラレータ）からの通信についてのみチェックを行う
        - それぞれ機能が分離するため負荷は高くなく、利用しやすい
        - 但し、機器は増えるので管理工数は増える
    - LB兼用型
        - 全てを担うことになるので、WAFの負荷が高くなってしまうことには注意
        - 機器は1つ2つで済むため、構成としてはシンプル
        - 全て統合されるのでどこかに問題があった場合、全体を停止する必要性が考えられる

#総じて言うと
- WAFを入れればいいってもんではなく、アプリ側でもセキュリティ対策は必要である
- NW・FW・IPS（IDS）・WAF・アプリなど全体を見てどこをより守るのかなど検討が必要
    - 可用性とセキュリティは表裏一体
        - 家のセキュリティを高めるために鍵を10個も20個もつけてたら、出入りができない
        - とは言え鍵をかけないと、泥棒に入られてしまうので、最低限1－2個の鍵は必要だよね
- どんな製品を入れればいいか
    - 環境や費用次第であるため、現状に合ったものを入れるのがよい
        - [参考リンク](https://kn.itmedia.co.jp/nwsec/waf/product/)
第4回 株価予測_アプリ化編

# 初めに
全部で4本の記事に分けて書いています！

+ 第1回 株価予測_可視化編
+ 第2回 株価予測_LSTM ver.1
+ 第3回 株価予測_LSTM ver.2
+ 第4回 株価予測_アプリ化編

今回は株価予測のアプリ化を行なっていきます。Flaskの特徴は、1つのファイルでアプリケーションを作成できることです。これはmicroframeworkと呼ばれています。それに加えて、大きなアプリケーションを作るための拡張機能も備えている優れものです。
**このシリーズで行っている株価のチャート分析は意思決定のためのテクニカル指標に過ぎません。なので、予測に絶対は無いことと、株やFXで損する・得することの判断は自己責任でお願いします。ちなみに私は過去にFX(レバレッジ20倍)でテクニカル指標を過信し過ぎて。。。。なので皆さんも実際に取引する時はファンダメンタルズ分析もしっかり取り入れつつ、楽しく取引しましょう！！**

**今回の章立て**

+ 今回のファイル構成
+ ngrok
+ 最後に
+ 参考文献


# 今回のファイル構成

```
flask（ファイル）
  ┣ main.py
  ┣ predict.py
  ┣ static
  ┃   ┣ images ━ xxx.png
  ┃   ┣ predict_file ━ xxx.png
  ┃   ┗ train_files ━ xxx.pth
  ┃                 ┗ xxx.pkl
  ┗ templates
        ┣ get.html # 株価入力
        ┗ post.html # 株価予測結果
```

`main.py`でwebアプリを起動します。
`predict.py`は前回の株価予測を少し変えた内容が入っているファイルです。
`static`にはWebページに表示するための画像ファイルや予測のためのpklファイルが入っています。
`templates`にはwebページに記載するためのhtmlファイルが入っています。

今回もcolab上でモジュールのインポートします。

```
!pip3 install torch==1.6.0+cu101
!pip3 install torchvision==0.7.0+cu101
!pip3 install numpy==1.18.5
!pip3 install matplotlib==3.2.2
!pip3 install scikit-learn==0.23.1
!pip3 install seaborn==0.11.0
!pip3 install flask==1.1.2
!pip install flask-ngrok
```

次にflask.zipとしたFlaskをWeb上で起動するためのフォルダへ移動し、ファイルを確認します。

```
from google.colab import files
uploaded = files.upload()

!unzip flask.zip
%cd flask
!ls
```

次にngrokをインストールします。

```
!pip install pyngrok
!ngrok authtoken xxxxx #Your Authtoken
```

最後に`main.py`を起動します。

```
!python3 main.py 
```
実行すると以下のようなものがRunningとして表示されるので、~~~~ngrok.ioをクリックしてwebアプリを起動します。

```
Running on http://xxx.x.x.x:xxxx/ (Press CTRL+C to quit)
Running on http://xxxx-xx-xxx-xx-xxx.ngrok.io
Traffic stats available on http://xxx.x.x.x:xxxx
```

# ngrokについて

まず、webアプリをGoogle colab上で立ち上げるためには、tokenの取得とコードの追記が必要です。まずtokenの取得をしましょう。

https://ngrok.com

ngrokにアクセスします。

Sign upします。

メールが届いているので、承認します。

Your Authtokenからトークン確認します。

以下のコマンドで実行します。

```
!pip install pyngrok
!ngrok authtoken xxxxx #Your Authtoken
```

# 最後に
Flaskに関しては入門書をやってみた感じですが、先駆者の皆様のサイトをみながら、書籍を参考にさせていただきながら、一応完成はしました！

# 参考文献

> [Flask Tutorial](https://flask.palletsprojects.com/en/2.0.x/tutorial/)
> [ゼロからFlaskがよくわかる本: Pythonで作るWebアプリケーション開発入門](https://www.amazon.co.jp/ゼロからFlaskがよくわかる本-本田崇智-ebook/dp/B07F2X9GRQ)
>[動かしながら学ぶ PyTorchプログラミング入門](https://www.amazon.co.jp/dp/B08PBH4YNT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

ngrok：詳しくは以下を参照
>[GoogleColabでFlaskアプリを実行する方法(ngrok token必要になった模様)](https://qiita.com/k_koba619/items/32ec04a04d1e37b86465)
>[Quickly share ML WebApps from Google Colab using ngrok for Free](https://towardsdatascience.com/quickly-share-ml-webapps-from-google-colab-using-ngrok-for-free-ae899ca2661a)
>[ローカルで実行したい場合はこちら➡︎【Macユーザー向け】ngrokでローカル環境のサイトを外部へ公開](https://kakechimaru.com/ngrok/)
PostgreSQLの権限まわり簡易メモ

# PostgreSQLの権限まわり
権限まわりは触る機会少ないし、ドキュメントが読みづらい。勉強してもすぐ忘れる。
久しぶりにこの辺り触れたのでサクッと重要な点のみメモしておく。



* PostgreSQL用語で、データベース、テーブル、カラム、ビュー、シーケンス、スキーマ、関数等全てを `データベースオブジェクト`と呼ぶ。
* `データベースオブジェクト`のownerはその対象に全権限を持つ。また、作成者はデフォルトでownerとなる。例えば、`CREATE TABLE`したユーザにそのtableの全権限がデフォルトで付与される。
* 対象の`データベースオブジェクト`のGRANT/REVOKEできるのは、ownerかスーパーユーザ権限ロールのみ。
* 権限の種類と`データベースオブジェクトの種類の対応表は`[表](https://www.postgresql.org/docs/13/ddl-priv.html#PRIVILEGE-ABBREVS-TABLE)にある。
   * データベースのownerにはロクな権限はないことに注意。temporary tableを作成したり、schema作成したり。**tableに対する権限はゼロ** であることに注意。
* `GRANT admins TO joe;` のように権限を継承することができる。
* `\du` にて権限を確認することが多いと思うが、明示的に`grant`していない権限は表示されない。スーパーユーザ権限ロール、ownerのロール、継承されたロールは表示されない。
* ^を表示させるには、[has_table_privilege関数を使って頑張る](https://qiita.com/nuko_yokohama/items/085b75ee4c0938936ab9#%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%A8%A9%E9%99%90%E7%85%A7%E4%BC%9A%E9%96%A2%E6%95%B0)必要がある。
* 今後作成されるテーブル等にも権限が付与されるようにしたければ、[ALTER DEFAULT PRIVILEGES](https://qiita.com/yteraoka/items/d526e4c4c869b8592667)を使う。
[IntelliJ IDEA] 静的セキュリティーチェックツール

# 概要
ここ記事は下記のgithubを参考し、作成しました。
[immomoのgithub](https://github.com/momosecurity/momo-code-sec-inspector-java)

### immomoとは

静的javaコード、sqlコードをチェックし、セキュリティー上の問題が発見すると、エラーを表示し、改修案を提示してくれるIntelliJ IDEAのプラグインです。



# requirement
下記によって、IntelliJ IDEAのバージョンは` >= 2018.3`

>https://github.com/momosecurity/momo-code-sec-inspector-java#%E7%89%88%E6%9C%AC%E6%94%AF%E6%8C%81

# インストール

プラグインマーケットで`immomo`を検索すれば良い。

> https://github.com/momosecurity/momo-code-sec-inspector-java#%E5%AE%89%E8%A3%85%E4%BD%BF%E7%94%A8


# 試して、使ってみる

- sqlインジェクション問題が発生しそうなSQL文を書いた。

![スクリーンショット 2022-02-01 16.56.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/19d30f61-2ecd-36ec-e66f-5c24edce1dda.png)


- 表示したproblem
![スクリーンショット 2022-02-01 16.58.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/889e9d33-c556-3e13-efa3-e9ded7bde8a3.png)

- fix案を採用する。
![スクリーンショット 2022-02-01 16.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1184340/8251124a-7f65-2b3f-2d3e-cddbd0a3b0a3.png)


- 下記の観点で、セキュリティー問題をチェックしている
 -  参考↓

>https://github.com/momosecurity/momo-code-sec-inspector-java#%E6%8F%92%E4%BB%B6%E8%A7%84%E5%88%99


↑翻訳してみました。


|エラーコード|規則|
|--|--|
|	1001|sqlの文字列の結合によって、インジェクションする|
|	1002|SQLプレースホルダーインジェクション|
|	1003|MybatisアノテーションSQLインジェクション|
|	1004|MybatisのxmlのSQLインジェクション|
|	1005|RegexDos攻撃|
|	1006|Jacksonによるjson文字列パース脆弱性|
|	1007|Fastjsonによるjson文字列パース脆弱性|
|	1008|Netty HTTPレスポンスSplitting(CRLFインジェクション)|
|	1009|固定的な乱数seed脆弱性|
|	1010|XXE脆弱性|
|	1011|XStreamパース脆弱性|
|	1014|簡単なメッセージダイジェストアルゴリズム脆弱性|
|	1015|古い暗号化技術を使うことによって、起きる脆弱性|
|	1016|XMLDecoderパース脆弱性|
|	1017|LDAPパース脆弱性|
|	1018|CORS Allowed Origin設定することによって、起きる脆弱性|
|	1019|SpringSecurityデバックモードを設定しているによって、起きる脆弱性|
|	1020|hard-coded password vulnerability|
|	1021|@RequestMappingを使っているメソッドはpublicとなっていること|
|	1022|Spring session fixation attack|
|	1023|乱数generatorの脆弱性|
|	1024|OpenSAML2認証をスキップする攻撃|
|	1025|IP adress hard-coded vulnerability|
【プログラマーのための統計学】 共分散と共分散行列

## 目次
[プログラマーのための統計学 - 目次](http://qiita.com/Esfahan/items/bd9e52837bbaeb168b9f)

## 概要
共分散と共分散行列(または分散共分散行列)について書く。
pythonのmultivariate_normalとかで使うやつ。

```py
import numpy as np

# 期待値
mean = np.array([3, 5])
# 分散共分散行列（covariance matrix）
cov = np.array([[4, -1.2], [-1.2, 1]])

# 多変量正規分布に従う乱数を生成
np.random.multivariate_normal(mean, cov, size=200)
```

## 前提条件
この記事を読むには、以下を理解していることが前提となります。

https://qiita.com/Esfahan/items/2e70635552d7d661bc6b#%E5%81%8F%E5%B7%AE

## 共分散とは？何の役に立つの？
国語の点数が高い人は、数学の点数も高いのか？といった傾向を見るときに役に立つ。
Xが国語の点数、Yが数学の点数としたとき、 「Xの偏差 × Yの偏差」の平均 を出すことで求められる。


以下の生徒の共分散を算出してみる。(100点満点)

| 生徒 | 国語 | 数学 |
| --- | --: | --: |
| A | 50 | 50 |
| B | 50 | 70 |
| C | 80 | 60 |
| D | 70 | 90 |
| E | 90 | 100 |

偏差の出し方については以下を参照
> 偏差とは、平均値と各データの差を全て足したものの平均のことです。
https://qiita.com/Esfahan/items/2e70635552d7d661bc6b#%E5%88%86%E6%95%A3

国語の平均点

```math
68 = \dfrac{1}{5}(50+50+80+70+90)
```

数学の平均点

```math
74 = \dfrac{1}{5}(50+70+60+90+100)
```

それぞれの「国語の偏差 × 数学の偏差」は以下のようになる。

```math
\begin{align}
(A) \, 432 &= (50−68)(50−74) \\
(B) \, 72 &= (50-68)(70-74) \\
(C) \, −168 &= (80-68)(60-74) \\
(D) \, 32 &= (70-68)(90-74)) \\
(E) \, 572 &= (90-68)(100-74)
\end{align}
```

共分散は， 「Xの偏差 × Yの偏差」の平均なので，

```math
188 = \dfrac{1}{5}(432+72-168+32+572)
```
​
となる。

この値が正の値であれば、国語の点数が高い人は数学も高い、(国語の点数が低い人は数学も低い、も成り立つ)
負の値であれば、国語の点数が高い人は数学の点数が低い、
0であれば（に近ければ）2つの科目に関係性は薄い、ということになる。

上記の例では188という大きな値が出ているので、国語の点数が高い人は数学も高い、という結果が得られたことになる。

共分散は以下の式で表すことができる。

```math
Sxy = \frac{1}{n}(x-\vec{x})^{'}(y-\vec{y})
```

### 共分散の問題点
上記の例では100点満点同士の科目の比較をしたが、仮に片方が100点満点、もう片方が10点満点のように、単位が異なる場合共分散の数値が大きく変わってしまうので、共分散の値だけを見て一概に判断はできないという問題がある。

この問題を解消するには、相関係数というものを用いる。（今回は説明しない）
https://manabitimes.jp/math/854

## 分散共分散行列

### 分散共分散行列の求め方
https://manabitimes.jp/math/1020

上記の例と同じデータの分散共分散行列を求めてみる。

| 生徒 | 国語 | 数学 |
| --- | --: | --: |
| A | 50 | 50 |
| B | 50 | 70 |
| C | 80 | 60 |
| D | 70 | 90 |
| E | 90 | 100 |

国語の平均点

```math
E[X] = 68 = \dfrac{1}{5}(50+50+80+70+90)
```

数学の平均点

```math
E[Y] = 74 = \dfrac{1}{5}(50+70+60+90+100)
```

偏差ベクトル（平均からの差）

| 生徒 | 国語 | 数学 |
| --- | --: | --: |
| A | (50−68) | (50−74) |
| B | (50-68) | (70-74) |
| C | (80-68) | (60-74) |
| D | (70-68) | (90-74) |
| E | (90-68) | (100-74) |


国語の分散

```math
σ^2_{x} = 256 = \dfrac{1280}{5} = \dfrac{1}{5}((50−68)^2+(50-68)^2+(80-68)^2+(70-68)^2+(90-68)^2)
```

数学の分散

```math
σ^2_{y} = 344 = \dfrac{1720}{5} = \dfrac{1}{5}((50−74)^2+(70-74)^2+(60-74)^2+(90-74)^2+(100-74)^2)
```

国語と数学の共分散(前項で算出してるので過程は省略)

```math
\sigma_{XY} = 188 = \dfrac{1}{5}(432+72-168+32+572)
```

分散共分散行列は以下となる。


```math
Σ = \begin{pmatrix}
256 & 188 \\
188 & 344
\end{pmatrix}
```

### 共分散行列のまとめ
共分散行列は以下のように表すことができる。

```math
\begin{bmatrix}
S_{xx} & S_{xy} \\
S_{xy} & S_{yy}
\end{bmatrix}
```

式の形から、「xの分散」は「xとxの共分散」と同じなのでSxxと表す。(前述の例では国語の分散=256)
同様に、「yの分散」は「yとyの共分散」と同じなので Syyで表す。(前述の例では数学の分散=344)

```math
xの分散 = (x - 平均値)^2 = xとxの共分散 = (x - 平均値)(x - 平均値)) \\
yの分散 = (y - 平均値)^2 = yとyの共分散 = (y - 平均値)(y - 平均値))
```

## 参考
https://qiita.com/Esfahan/items/2e70635552d7d661bc6b

https://manabitimes.jp/math/853

https://zellij.hatenablog.com/entry/20130510/p1
BERTに文のペアを入力するときのtoken_type_idsについて

# 概要
BERTを使うとき，2つの文を入力したいときありますよね．別々のデータではなく，文のペアを一つ入力するということです．
質問応答や含意関係認識(NLI)等のタスクでやると思います．
そんなときに，データの前処理がめんどくさかったりします．それをより簡単にやっちゃいましょう．

「そんなの知っとるわ」と思われる方法かもしれませんが，ご了承ください．

(BERTに関する簡単な解説は付け加えていますが，より詳しく知りたい方は自分で調べてください．)

# BERTに文のペアを入力する
本題の前に少し．

BERTはその事前学習において **Next Sentence Predictoin(NSP)** というタスクを行います．
日本語でいうと次文予測です．文字通り文Aに続く文Bを予測するというものです．

その名残(？)なのかは分からないですけど，BertTokenizerで文をエンコードすると，input_idsなどの他にtoken_type_idsと呼ばれる配列が得られます．
これは，2つの文を判別するためにトークンごとに0と1で表したものです．

```python:example
'token_type_ids': [0, 0, 0, 1, 1, 1]
```

この場合，トークンの3つ目までか前半，それ以降が後半の文みたいな感じです ．

これを使えば，BERTに文のペアを入力させられるわけです．

# 条件

Tokenizer = BertJapaneseTokenizer
model = cl-tohoku/bert-base-japanese-whole-word-masking

# よくやるやつ
上で書いた実際のコードがこんな感じ

```python
tokenizer = BertJapaneseTokenizer.from_pretrained('cl-tohoku/bert-base-japanese-whole-word-masking')

text = "私の名前は太郎です。 [SEP] 三時のおやつの時間です。"
inputs = tokenizer(text)
```

文の間にある[SEP]は，特殊トークンと呼ばれるものの一つで，文字通りSeparation 文の区切りを表すためのものです．
これにより，token_type_idsがうまく生成できるはずです．

そしてエンコードして出てくる結果がこれ

```python:inputs
{
'input_ids': [2, 1325, 5, 1381, 9, 5250, 2992, 8, 3, 240, 72, 5, 73, 18874, 5, 640, 2992, 8, 3], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
```

**あれ？**

[SEP]を挿入したにも関わらず，token_type_idsがなぜか全部0です．
これではモデルが文のペアであることを認識できません．

どうやら自分で[SEP]トークンを自分で入れ込んだとしても，tokenizer側はそれを認識はするものの，token_type_idsに反映することはしてくれないそうです．


そんなわけで，こういうことをやるわけです

```python
token_type_ids = [0 if i <= input_ids.index(3) else 1 for i in range(len(input_ids))]
#[0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
```
これは何をしているかというと，[SEP]の場所より前を0，あとを1になるような長さがtoken数のリストを作っています．
要するに，token_type_idsを自作しています．

なんでこんな面倒なことをしなければならないのでしょう？

そもそもtoken_type_idsがちゃんとできるように[SEP]をわざわざ自分で挿入しているわけです．
なのに，encodeしても肝心のtoken_type_idsが全部0になるのはおかしいですよね．

# これで万事解決
解決策は以下のとおりです

```python
text1, text2 = "私の名前は太郎です", "三時のおやつの時間です。"
inputs = tokenizer(text1, text2)
```

実はBertTokenizerは入力文のペアを別々で与えられます．
[SEP]の挿入も必要ありません

そうすると，

```python:inputs
{
'input_ids': [2, 1325, 5, 1381, 9, 5250, 2992, 3, 240, 72, 5, 73, 18874, 5, 640, 2992, 8, 3], 
'token_type_ids': [0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1], 
'attention_mask': [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
}
```

今度はしっかりtoken_type_idsが出力されています．

中身を確認してみます

```python
tokenizer.convert_ids_to_tokens(inputs['input_ids'])
```

```python
['[CLS]',
 '私',
 'の',
 '名前',
 'は',
 '太郎',
 'です',
 '[SEP]',
 '三',
 '時',
 'の',
 'お',
 'やつ',
 'の',
 '時間',
 'です',
 '。',
 '[SEP]']
```

ちゃんと[SEP]が文の間に入っていることも確認できます．

これのおかげで，わざわざ自分で[SEP]を間に入れたり，token_type_idsを自作する必要もなくなりました．
かなり楽になりましたね．

文のペアそれぞれを，別々の変数で与えているので間違いも防げそうです．

# おわりに

そもそもこれが正しい方法なんでしょうね．
Huggingfaceにあるドキュメントを見てみると，

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1741707/20942322-1907-948a-78d7-e371d03d92c9.png)

ちゃんと例として示されてました．
これはしっかり目を通してなかった私が悪いですね．(BertTokenizerの説明にもペアを与えられることを書いていてほしいものですが)

ちなみに，encode()やbatch_encode()では確認していません．

これが初投稿です．見にくい記事ですいません．

# 参考
https://huggingface.co/docs/transformers/model_doc/bert#transformers.BertTokenizer