OmniAICreator/Qiita-1.07M huggingface dataset:
ARReferenceImage を使って精度を上げる

ARCore Geospatial API の精度はそこそこよい。API から取得できる値を見ても水平方向 20cm とかの精度がでてるんだけど、実際の見た目でいうと 20cm ズレるとそこそこ気になる。
![moar2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/ef83b28b-7ec2-aa3f-5c99-42415cb9e162.jpeg)
壁面に実際に描かれている QR コードと AR 表示している QR コードのテクスチャ位置はデータ的にはピッタリ同じにしてるんだけど Geospatial API で位置あわせするとズレて見える。

MoAR を起動して最初に体験するコンテンツは [Mo(AR)^2](https://whatever.co/moar/ja/moar2/) という壁面の QR コードが飛び出してくるものなので、ここがズレてるのはやだなーなんか対策ないかなーというとこで思いついたのが、VPS だけじゃなくて従来のイメージマーカーを併用する方法。

# ARKit でイメージマーカーを使う方法

[Detecting Images in an AR Experience \| Apple Developer Documentation](https://developer.apple.com/documentation/arkit/content_anchors/detecting_images_in_an_ar_experience)

[`ARReferenceImage.referenceImages`](https://developer.apple.com/documentation/arkit/arreferenceimage) でマーカー画像を読み込んで [`ARWorldTrackingConfiguration.detectionImages`](https://developer.apple.com/documentation/arkit/arworldtrackingconfiguration/2941063-detectionimages) にセットすればあとは `ARSCNView` の delegate で各画像に対応する ARImageAnchor の情報が得られるので適当に動かすなりする。

MoAR では以下の2つの画像を AR Reference Image として使っている。位置は全く同じなんだけど昼と夜でかなり見た目が変わるので昼の画像だけだと夜は認識してくれない。
![ref](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/21c59c49-6dbd-971b-6762-f31fcb49e615.jpeg)
画像登録時にはその画像が現実空間でどれぐらいのサイズかを正確に入力する必要がある。このサイズが間違ってると認識してくれないか、認識してもなんか動きがおかしい、みたいなことなる。（なった）
![imagesize](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/bb2782c0-dc3b-c341-5d73-f258bb03bfce.png)

ちなみに似たような画像を複数登録すると Xcode が画像が似てるぞーっと警告を出す。
![Screen Shot 2022-12-08 at 15.13.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2595/09d7f947-f3b2-3b3e-5040-697b776766f6.png)
実際、夕方とかのどっちの画像にも近いような条件だと昼の画像にマッチすることもあれば夜の画像にマッチすることもあるのでしっかり区別をつけたい場合は、警告が出ないような画像にする必要がありそう。MoAR はどっちにマッチしたとしても位置は同じなので警告は無視。

# 実装した

<iframe width="100%" height="700" src="https://www.youtube.com/embed/RBpx0dzpepU" title="Improve VPS tracking acurracy by using ARReferenceImage" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br/><br/>

最初数秒間は VPS だけの状態で、壁面のリアル QR コードと AR 上の QR メッシュモデルがずれてるけど、その後マーカー画像を認識するとピタっと位置が合うようになった。

# VPS いらないのでは？

マーカーでそこまでピッタリ位置が合うなら VPS いらないのでは？と思ってやってみたのだが、<br/><br/>

<iframe width="100%" height="700" src="https://www.youtube.com/embed/0Xr9myk3imk" title="Using ARReferenceImage in building scale" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe><br/><br/>

マーカー付近はピッタンコなんだけどマーカーから離れた上端付近がプルプルする。マーカーの回転角の推定誤差がマーカーから離れるにしたがって見た目上大きくなってくのでプルプルするんだと思う。

このプルプルはマーカーの回転値を使わずに位置だけ（具体的には `SCNNode.simdWorldPosition`）をマーカーのものを使って回転値は画像全体から推定された VPS 側の値をを使えば収まる。

もう一つマーカー画像の弱点はマーカー画像全体が画面内に収まっていないとトラッキングできなくなるという点。あたりまえなのだけどこの制限があるので、ビル全体やその周辺までキャンバスにする必要がある MoAR では単純にデカいマーカーをトラッキングするだけではだめでやっぱり VPS が必要だった。
【Unity】マテリアルの色味が元素材と違って見えるときの対処法

## この記事について
マテリアルに素材を貼り付けると、素材の色合いと違って見える時の対処法です
![Test1.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534018/621dda96-39af-9fe5-7b03-92d394a59fd0.png)

Unity Version：`2021.3.6f1 LTS`
## 原因
まずマテリアルというのは材質という意味です。
色や光沢によって金属やプラスチックなどの物質の材質を表現しています。

色合いが違って見えている原因は、色や光の影響を受けすぎているためです。

## 解決方法
### シェーダーを変更する方法
1. MaterialのShaderをUnlit/Textureに変更
![Test1.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534018/addb69ef-a606-57fe-aca0-6fb77038bdb0.png)

→Unlitにすることでライトによる陰影が付かず、他のオブジェクトに影を落とすことも、別オブジェクトの影響を受けることもありません。

### lightingの反射を無くす方法
1. MaterialのインスペクターにあるSpecular Highlight とReflectionsのチェックを外す
![Test1.001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2534018/4144127f-d14c-6277-a03c-58680a7a654a.png)
→ハイライトが効きすぎていると感じる場合におすすめです。Shaderはstandardなので、ライトによる陰影もつきます。
くじ引き



中身クラス
---
くじ引きの中のクラスです
```php
public class nakami {

	int n;

	nakami(int number){
		n=number;
	}

	public String toString() {

			  if(n==0) {
			return n+" : 大吉";
		}else if(n==1) {
			return n+" : 中吉";
		}else if(n==2) {
			return n+" : 小吉";
		}else if(n==3) {
			return n+" : 吉";
		}else if(n==4) {
			return n+" : 末吉";
		}else if(n==5) {
			return n+" : 凶";
		}else if(n==6) {
			return n+" : 大凶";
		}else if(n==7) {
			return n+" : 諭吉";
		}else if(n==8) {
			return n+" : ピース又吉";
		}else if(n==9) {
			return n+" : 吉田沙保里";
		}else {
			return null;
		}

	}

}
```

くじ引き（動作確認）クラス
---
くじを引くためのクラスです。
```

import java.util.Scanner;

public class kujibiki {

	public static void main(String[] args) {

		System.out.println("くじを引きましょう！　（ 0 ～ 9 を入力）");
		Scanner num=new Scanner(System.in);
		int n=num.nextInt();

		nakami un=new nakami(n);
		System.out.println(un);

	}

}

```
【AWS】Amplifyを使ってReactアプリを自動デプロイしてみる

前回まで→
今回はAmplifyを使ってローカルで変更したものを自動デプロイしてみる

1. create react appで作った`App.tsx`の中身を変更する
```typescript
function App() {
  return (
    <div className="App">
      <header className="App-header">
        <h1>Hello React Amplify</h1>
//####################################################
```
例えば、`<h1>Hello React Amplify</h1>`を加えてみる

2. ローカルとデプロイ環境で確認する
ローカル環境では変更が加えられているが、デプロイ環境では変更が加えられていない
3. GitHubにプッシュする
```cmd
$ git add .
$ git commit -m "自動デプロイの確認"
$ git push
```
でプッシュをする。反映されるのに少し時間がかかるので待つ。

時間が経つと、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/cc7bd432-7a60-5984-187a-dfaff07d6ec1.png)
反映された！

このようにして簡単に自動デプロイが可能だった。
【AWS】Amplifyのチュートリアルを使ってReactアプリをデプロイしてみる

AWSのサービスであるAmplifyを使って、Reactアプリをデプロイするチュートリアルを行ってみたいと思います。
公式サイトは→https://aws.amazon.com/jp/getting-started/hands-on/build-react-app-amplify-graphql/

1. AWSでAmplifyと検索してウェブアプリケーションをホストをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/94775832-fa38-02bb-00a2-7609cdec15e9.png)

2. ホスティングの開始方法でGitHubを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/bb8bcb34-b4ea-8337-d3bd-8d97f4832969.png)

3. GitHubの認証画面が出てくるのでパスワードを入力してサインイン
4. VSCodeで任意のフォルダにReactアプリを作成する
今回はTypeScriptで作成するので`npx create-react-app aws-tutorial-with-react-amplify --template typescript`
5. aws-tutorial-with-react-amplifyに移動し、`npm start`で起動確認
6. GitHubで新規リポジトリを作成し、 `…or create a new repository on the command line`の下のコマンドをすべてコピーする
7. VSCodeに戻り、`npm start`している以外のターミナルを開き、先ほどコピーしたものをペースト
8. git pushでGitHubにプッシュ
9. AWSの画面に戻り、リポジトリを先ほど作成したものを選択して次へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/684bfd26-8280-38ea-2371-d0bbdef19508.png)
10. 最後に保存してデプロイボタンを押す
11. 画面右側のデプロイまでチェックマークがついたら、URLをクリックしてデプロイが完了していることを確認する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2884542/90e7dca3-9db4-ca34-a453-0984862255a5.png)
Windowsが超少ない会社でもWindows端末をMDM管理したいｯ！！！！

この記事は「[Eureka Advent Calendar 2022](https://qiita.com/advent-calendar/2022/eureka)」7日目の記事です。


こんにちは、MISチームのコーポレートエンジニアの @jetkiwi です。WindowsをIntuneでMDM管理したのでそのことについて話したいと思います。

# MacはMDM管理できてるけど、Windowsは台数も少ないし全然管理できてなかった 〜発端は1件のトンデモ事件だった〜
エウレカではMacが標準環境となっており、9割近くのユーザーがMacを使用しています。
しかしながら業務の都合でWindowsを使う必要のあるユーザーもおり、1割程度のユーザーがWindowsを使っています。
上記の理由により大多数を占めるMacについては[2018年にJamf Proを導入し](https://medium.com/eureka-engineering/%E3%81%BC%E3%81%A3%E3%81%A1%E6%83%85%E3%82%B7%E3%82%B9%E3%81%8Cjamf-pro%E3%82%92%E5%B0%8E%E5%85%A5%E3%81%97%E3%81%A6%E3%81%BF%E3%81%9F%E4%BB%B6-c7d5bc867ca2)管理を行っていましたが、
Windowsについては台数が少ないこともありMDMの導入が遅れていました。

ある日、Windows端末を利用している方にトンデモな事件が発生してしまいました。
台数が少ない　というのは実は　重要な端末が少ない　ということでは決してなかったのです。
これはいかん　という事で、WindowsもMDM管理して世界を救うことにしました。

# Windows管理における課題
いままではWindowsの管理については以下の課題がありました。
* 継続的に必要な設定が適用されていることを担保できない
* 一度デプロイした端末への設定変更やアプリケーションの展開が困難
* 台数が少ないためキッティングが手動で時間がかかり、抜け漏れが発生しやすい

この課題を解消するために、MDMを導入しました。

# WindowsにIntuneを導入した
WindowsのMDMはいくつか選択肢がありますが、以下の理由よりエウレカではIntuneを導入しました。

* Macについては既にJamf Proを導入していることから、Windowsの親和性を重視したこと
* 既にMicrosoft 365ライセンスの利用があり、Azure AD環境が存在したため
* 台数が少ないことから、ミニマムライセンスがないこと

またIntuneを導入するうえでAzure AD参加は必須ではないのですが、展開の容易さや今後のAutopilot導入のためにAzure AD参加も同時に行うことにしました。

これによりWindows端末においてもアプリケーションや設定の集中管理、ゼロタッチデプロイが実現し、世界に平和が訪れました。

# 既存端末への展開については妥協したところも
新規で支給する端末についてはOktaの資格情報でログインができる状態が実現しました。
既存の端末についてはAzure AD参加およびIntuneの登録こそ行いましたが、ユーザーアカウントについては引き続きローカルユーザーを利用することにしました。ユーザーアカウントを移行する手間が大きく、またPCのリプレース周期が2年であり最低でも2年後には無くなることが理由です。
今後入社するユーザーは、ゼロタッチデプロイにより平和な世界が維持されます。

# 残る課題は
課題としては、Windowsにログイン後、再度認証を求められずにWebアプリケーションを利用できるようなデスクトップSSOを実現できない点があります。Azure ADをIdPとした場合は実現可能であるため、ここはOktaをIdPとして利用する場合のデメリットといえます。

# まとめ
今回WindowsでもMDMを導入し、ポリシーやアプリケーションの管理、ゼロタッチデプロイが可能になりました。これにより自信をもってWindows端末も管理することができ、安心して年を越せそうです。

明日は、@hisamounaによる「(仮) pairsで利用しているBatchのEKS移行」です。

お楽しみに！
9. Palindrome Number

https://leetcode.com/problems/palindrome-number/

## アプローチ
### Brute force

```java
class Solution {
    public boolean isPalindrome(int x) {
        if (x < 0) {
            return false;
        }
        
        String a = String.valueOf(x);

        StringBuilder b = new StringBuilder();

        for (int i = a.length() - 1; i >= 0; i--) {
            b.append(a.charAt(i));
        }
        return b.toString().equals(a);        
    }
}
```
Burp使用時にバイナリデータでハマった話

# はじめに
こんにちは、株式会社シーエー・アドバンス技術統括本部の@syk_nakayamaです。
今回はセキュリティ診断時にハマった話をしようと思います。

某月某日の業務にて、Burp Suiteを使用しIntruderを実行しようとしたが、どうにもうまく回らない。
結果が全てエラーとなる。正常結果が返却される筈の場所もエラーとなる。
何か変だ、私の知らない改ざん検知に引っかかったのか？となり七転八倒。
原因判明まで時間を要してしまいました。

>Burp Suite (バープ スイート)は、PortSwigger Ltdが開発したJava アプリケーションである。
>Web アプリケーションのセキュリティや侵>入テストに使用されている。[1]　プロキシサーバ（Burp Proxy）、Webクローラ（Burp Spider）、侵入ツール（Burp Intruder）、脆弱性>スキャナ（Burp Scanner）、HTTPリピータ（Burp Repeater）などのツールから構成されている。
>Burp Proxyはアプリケーションの異常な動作を誘発し、バグや関連する脆弱性を特定することを目的として、不適合なデータを注入することが出来る。
>
>出典: フリー百科事典『ウィキペディア（Wikipedia）』
><a href="https://ja.wikipedia.org/wiki/Burp_Suite"> https://ja.wikipedia.org/wiki/Burp_Suite</a>

# なにが起きていたか
・ProxyタブからRepeaterへ設定、送信した場合は上手くいく
・Intruderを回すと、正常結果が返却されるべき箇所でもエラーとなる
・同じ箇所を改ざんしRepeaterで送信するとエラーとなる
・CSRF Tokenはない

# 原因
結論から言うと、原因はBurp SuiteのUserOption設定にありました。
文字化け対策としてUTF-8を設定していたのですが、該当箇所のリクエスト内にバイナリデータが含まれており、意図せずバイナリデータをUTF-8形式へ変換してしまい、結果リクエストに失敗するという動作になっていました。

Optionの箇所
![Burp001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666267/17987bb7-6aea-a86e-1f0b-2fb64179a057.png)

サンプルプロジェクトで動作を説明すると以下のようになります。

サンプルプロジェクトでは、
正常結果の場合、レスポンスのLocationヘッダが以下となります。
```
Location: https://myapp.localhost/merchant
```
不正データと判断された場合は、以下となります。
```
Location: https://myapp.localhost/merchant/service/create
```

ファイル名を改ざんしたリクエストを送信した場合、平文で見る限りなぜ不正データと判断されるのか分かりません。

改ざん箇所
正常値　　　：filename="10kb-01.jpg"
改ざん後の値：filename="10kb-02.jpg"

正常リクエスト
```
POST /merchant/service/create HTTP/1.1
Host: myapp.localhost
～省略～
------WebKitFormBoundaryWe0DIx0pmP9uuvI0
Content-Disposition: form-data; name="image"; filename="10kb-01.jpg"
Content-Type: image/jpeg

����
～省略～
```

正常レスポンス
```
HTTP/1.1 302 Found
～省略～
Location: https://myapp.localhost/merchant
～省略～
```

不正リクエスト
```
POST /merchant/service/create HTTP/1.1
Host: myapp.localhost
～省略～
------WebKitFormBoundaryWe0DIx0pmP9uuvI0
Content-Disposition: form-data; name="image"; filename="10kb-02.jpg"
Content-Type: image/jpeg

����
～省略～
```

不正レスポンス
```
HTTP/1.1 302 Found
～省略～
Location: https://myapp.localhost/merchant/service/create
～省略～
```

# 反省
結果を見ればなるほどと思うかもしれませんが、ハッシュ等で改ざんチェックされているのか？など色々疑ってしまい、苦労しました。
理由がない限り、Optionはデフォルト設定を利用した方がハマらないかもしれません。
脳筋バッチ処理

semantic segmentationにて、バッチ処理を脳筋で進めるロジック

```
def batchFit(model,originFiles,anotatedfiles,oneRoopSize=20,testSize = 0.2,x_image_size=1280,y_image_size=896):
    print("batched fit process start")
    print("len(originFiles) is",len(originFiles))
    print("len(anotatedfiles) is",len(anotatedfiles))
    
    epochSize = 60
    
    # 初期化
    epoch_l,loss_l ,val_loss_l,iou_score_l ,val_iou_score_l = [],[],[],[],[]
    for k in range(len(originFiles)// oneRoopSize): 
        X = []
        Y = []

        for i, file in enumerate(originFiles):
            if (k) * oneRoopSize < i < (k + 1) * oneRoopSize:
                X_image = Image.open(file) #画像の読み込み
                X_image = X_image.convert("RGB") #RGBに変換
                X_image = X_image.resize((x_image_size, y_image_size)) #サイズ変更
                X_data = np.asarray(X_image) #画像データを配列へ変更
                X.append(X_data) #画像データを繰返し追加

        for i, file in enumerate(anotatedfiles):
            if (k) * oneRoopSize < i < (k + 1) * oneRoopSize:
                Y_image = Image.open(file) 
                Y_image = Y_image.convert("P") #パレットモード（インデックスカラー）へ変換
                Y_image = Y_image.resize((x_image_size, y_image_size)) 
                Y_data = np.asarray(Y_image) 
                Y.append(Y_data)
                
        X = np.array(X)

        Y= np_utils.to_categorical(Y,categoryNum)
        X_train, X_valid, Y_train, Y_valid = train_test_split(X, Y , test_size=testSize)
        print("len(X_train) is",len(X_train))
        print("len(Y_train) is",len(Y_train))
        visualizeMulti(X_train,Y_train) # 念の為の1ファイル可視化

        result = model.fit(X_train, Y_train, batch_size=2, epochs=epochSize, 
                       validation_data=(X_valid, Y_valid),
                       callbacks=[model_checkpoint_callback])
        
        print("one batch roop finish current k is",k)
        
        # history生成,epochの処理は一見複雑だが、単純に[0,1,2,3,4,5...]のような配列を生成しているだけ
        addEpoch = map(lambda x: x+(k*epochSize), result.epoch)
        epoch_l = np.concatenate([epoch_l,list(addEpoch)], axis=0)
        
        loss_l = np.concatenate([loss_l,result.history['loss']], axis=0)
        val_loss_l = np.concatenate([val_loss_l,result.history['val_loss']], axis=0)
        iou_score_l = np.concatenate([iou_score_l,result.history['iou_score']], axis=0)
        val_iou_score_l = np.concatenate([val_iou_score_l,result.history['val_iou_score']], axis=0)

    # historyマージ
    result.epoch = epoch_l
    result.history['loss'] = loss_l
    result.history['val_loss'] = val_loss_l
    result.history['iou_score'] = iou_score_l
    result.history['val_iou_score'] = val_iou_score_l
    
    print("batched fit process finish")
    return model,result
Python から Windows のイベントログに記録する

前に調査したけど結局使わなかったネタの供養。

Windows Server 上で Python スクリプトを定期実行する際のログを Windows イベントログとして書き出す方法について。

### 実装
※ `pywin32` のインストールが必要

``` python
from win32evtlog import OpenEventLog, ReportEvent, EVENTLOG_INFORMATION_TYPE, EVENTLOG_WARNING_TYPE, EVENTLOG_ERROR_TYPE


class WindowsEventLogger:
    def __init__(self, name: str):
        self.handle = OpenEventLog(None, name)

    def log(self, message: str, *, type: int, category=0, event_id=0, user_sid=None, raw_data=None):
        return ReportEvent(self.handle, type, category, event_id, user_sid, [message], raw_data)

    def info(self, message: str, **kwargs):
        return self.log(message, type=EVENTLOG_INFORMATION_TYPE, **kwargs)

    def warning(self, message: str, **kwargs):
        return self.log(message, type=EVENTLOG_WARNING_TYPE, **kwargs)

    def error(self, message: str, **kwargs):
        return self.log(message, type=EVENTLOG_ERROR_TYPE, **kwargs)
```

### 使い方
``` python
from traceback import format_exc

logger = WindowsEventLogger("test_app")

try:
    # ... 処理 ...
    logger.info("success!")
except:
    logger.error(format_exc())
```

## イベントログの確認
イベントビューアーから「Windows ログ」>「Application」を確認すると、出力されていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16369/08e4aeec-14f8-680c-0e5d-45b93d6d8669.png)

(本当は「詳細」タブだけでなく「全般」タブのメッセージ欄にも出力したいのだが、Python から実現する方法が不明)

## エラーが出る場合
イベントビューアーを見ると以下のようなエラーログが出ることがある。

> ソース "test_app" からのイベント ID 0 の説明が見つかりません。このイベントを発生させるコンポーネントがローカル コンピューターにインストールされていないか、インストールが壊れています。ローカル コンピューターにコンポーネントをインストールするか、コンポーネントを修復してください。

イベントソースはあらかじめレジストリに登録しておく必要があるらしく、PowerShell で以下のコマンドを実行して登録すればエラーログは出なくなる。

``` powershell
New-EventLog -LogName Application -Source test_app
```

## 参考
- [win32evtlog.OpenEventLog](http://timgolden.me.uk/pywin32-docs/win32evtlog__OpenEventLog_meth.html)
- [win32evtlog.ReportEvent](http://timgolden.me.uk/pywin32-docs/win32evtlog__ReportEvent_meth.html)
GitHubの個人通知をSlackに連携する

GitHub Slack App を利用し、`/github subscribe [owner/repo]` でリポジトリごとの通知を Slack に連携できるのは割とポピュラーです。

しかし、今回は違います。「 **個人通知** 」を Slack に連携する方法です。

https://slack.com/intl/ja-jp/help/articles/232289568-GitHub-%E3%81%A8-Slack-%E3%82%92%E9%80%A3%E6%90%BA%E3%81%95%E3%81%9B%E3%82%8B

### 個人通知って
GitHub Notification に通知があるような、**ワークスペース全体**　での　**自分に対する** PR アサイン、メンション、マージなどの通知をさします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/acf38063-b0d0-e0bf-39cb-cdfbbd971734.png)

※画像は通知が空っぽな Notification の Inbox です。

### 連携手順

１．[Scheduled reminders](https://github.com/settings/reminders) にアクセスする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/1c5b4cd6-3dc6-bee8-a595-4b688f64ec96.png)

２．通知したいワークスペース（Organization）の Edit を押下する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/1cc2bf2d-05c1-8b2d-63e5-d7cb8c138166.png)

３．通知先となる　Slack ワークスペースを認証する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/75f0f10e-4eed-1e54-a6dd-87f99e370b85.png)

認証に成功すると、下記のような Slack 通知が来ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/9ddb8b06-b3b5-4fe1-8f69-465bd498f420.png)

４．通知内容を設定し Create Reminder を押下する

定期リマインダーをしたい場合は、曜日、時間と通知対象を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/99eb6e67-61f2-4535-e648-bb23b9da0b6f.png)

リアルタイム通知をしたい場合は、real-time alerts を有効化し通知対象を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/488859/eba46ee3-941e-49ee-ef4d-c309ec962503.png)

以上で完了です🎉
Hyper-V レプリカを構築する際はwindows admin center(WAC)との同居に注意

# 結論
Hyper-VレプリカとWACどちらも443ポートをデフォルトで使用するため、どちらかのポートをずらしましょう。

# 状況
以下の構成にしようと最初にWACをインストールし、次にHyper-Vのレプリカ設定を行いました。

![AyaioKbLUBQy-rd71AwYrEIInBnqe41vVb5sUb5-QO52DLTUVaggGdYmaO6XfOADJKP-SOcXNav-ScAEdPr2Oh528ao9KdXcNaf-UR62OqfkPfw2SsfUIMgH4b1BGNvHYOc9CKHvCbInHsL1Qf5kc198B9Mh5eijHiYs995cImeMMzA0jjHofIhewjeff5afF6vUyxXv-kFcLO-RLWC0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/d271f6d4-3a41-4f02-d9db-a5692349e043.png)

WACをそれぞれのホストにインストールしたのには必然性はなく、インストーラもはいはい進めていました。

次にHyper-V関係の証明書設定も行い(手順は割愛)、いざ「レプリケーションを有効にする」を実行すると

エラー番号0x00002EFEや
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/77c2d9c3-770c-04f7-86bb-2736e98f505d.png)

エラー番号0x80092007が
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/f3c27839-4e3a-6104-931d-5b9facb3a815.png)

発生してしまい悪戦苦闘していました。

そんななか[Hyper-V Replication Failed - Self Signed Certificates](https://stackoverflow.com/questions/52942322/hyper-v-replication-failed-self-signed-certificates)から以下の記述を発見しました。
(抜粋と機械翻訳)

> We identified the problem was due to a third party software causing a conflict on port 443. Removing this application resulted in the cert working correctly again and no more error.

> この問題は、ポート443で競合を引き起こしているサードパーティソフトウェアが原因であることを突き止めました。このアプリケーションを削除した結果、証明書は再び正しく動作し、エラーは発生しなくなりました。

そういえばWACもインストール時に証明書がどうたら聞いてきたなと思いだし
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109302/29d907e9-6051-2c45-d8a9-80987e5232e5.png)

WACをアンインストールしたらレプリケーションを有効にできました。
また、WACを再度インストールする際にポート番号を444等に変更すれば同居できました。

# まとめ
単品だと問題なしだが組み合わせ次第ではハマることはままあることですが、
そのパターンをネットで探すのは大変だなあと思いました。
誰かの一助になれば幸いです。
Leetcode 872. Leaf-Similar Trees

# 872. Leaf-Similar Trees

https://leetcode.com/problems/leaf-similar-trees/

## 難易度
### Easy

## アプローチ
### DFS

```java
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public ArrayList<Integer> arrayList1;
    public ArrayList<Integer> arrayList2;

    
    public boolean leafSimilar(TreeNode root1, TreeNode root2) {
        arrayList1 = new ArrayList<>();
        arrayList2 = new ArrayList<>();
        dfs1(root1);
        dfs2(root2);

        if (arrayList1.size() != arrayList2.size()) {
            return false;
        }

        for (int i = 0; i < arrayList1.size(); i++) {
            if (arrayList1.get(i).intValue() != arrayList2.get(i).intValue()) {
                return false;
            }
        }

        return true;
    }
    
    public  void dfs1(TreeNode root){
        if(root == null){
            return;
        }

        dfs1(root.left);
        dfs1(root.right);

        if(root.left == null && root.right == null){
            arrayList1.add(root.val);
        }
    }
    
    public  void dfs2(TreeNode root){
        if(root == null){
            return;
        }

        dfs2(root.left);
        dfs2(root.right);

        if(root.left == null && root.right == null){
            arrayList2.add(root.val);
        }
    }
}
```
Google Technical Support Fundamentalsコースの感想

ITの知識がゼロの私は、Googleで無料で学べるTechnical Support Fandamentalsのコースを受講しました。<a href="https://coursera.org/share/bbe2312f92f88a825f0fd0d4dbfee2f5">修了証</a>


#### 私が面白いと感じた講義
- <a href="https://coursera.org/share/cc07bf7f4e860424e05b2686a8580b7b">How to Count in Binary: 2進数の数え方をの説明</a>
- <a href="https://www.coursera.org/lecture/technical-support-fundamentals/putting-it-all-together-kHYGB?utm_source=link&utm_medium=page_share&utm_content=in_course_lecture&utm_campaign=bar_button">Putting it All Together: コンピュータの組み立て方の説明</a>
- <a href="https://coursera.org/share/379627d3995a8eda558104cf816705c0">Troubleshooting Pitfalls to Avoid: 陥りやすい落とし穴の説明</a>
- <a href="https://coursera.org/share/4610b21b7e41bb891952de0c7464470a">Ticketing Systems and Documenting Your Work: 記録に残す重要性の説明
</a>

コースの内容は充実していますが、英語で説明されているので、一回だけ見ただけでは、頭に完全に入ってくるわけではありませんでした。もう一度見たら、もう少し理解できるかもしれません。

プログラミング初心者で、IT全体の知識が少ない場合には、非常に勉強になるコースだと思います。
デスク周りで購入したもの一覧

# はじめに

普段リモートなので自宅のディスプレイ周りにはお金をかけました。その一覧を紹介していきたいと思います。

## ディスプレイ

なんとなく４Kが欲しいなーと思い、探してみました。そしたら社内の方から「Type-C」付きのものが良いと聞き、対応したものを購入しました。お値段は張りますがType-Cに繋げるだけで画面表示も電源供給もできるのでめっちゃ捗ります。

https://www.amazon.co.jp/gp/product/B085TWLMF9/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

## ディスプレイアーム

ディスプレイアームに憧れていたので思い切って購入しました。
デスク周りもスッキリ。

https://www.amazon.co.jp/gp/product/B00MIBN16O/ref=ppx_yo_dt_b_d_asin_title_o00?ie=UTF8&psc=1

## キーボード

打鍵感が良いものをと keychron k2 を買いました。
初めはHHKBを使っていたのですが、十字キーがないのにどうしても慣れなくて売ってしまいました。

https://keychron.jp/

## マウス

ロジクールのいいやつを購入しました。
横スクロールがついていて地味に捗ります。

https://www.amazon.co.jp/gp/product/B07XQ6XD8J/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&th=1

## カメラ

MacBook を閉じて使っているのでカメラが必要ということで適当に買いました。

https://www.amazon.co.jp/gp/product/B07MBQ1PT3/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

## ウッドリストレスト

キーボードには高さがあるので腕が疲れます。ウッドリストレストを使用することで解消できました。

https://www.amazon.co.jp/gp/product/B08C5KXW8G/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&psc=1

# そんなこんなで

結構今のデスク周りは気に入っています。

![IMG_6080.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/378497/51ac97eb-6752-64fd-ebd2-a8df7d665294.jpeg)
メモ：Ubuntu 22.04 LTS に Docker と Docker Compose をインストール！

メモメモ

## GPGキーのインストール

```shell
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
```

## Dockerリポジトリ登録

```shell
echo \
  "deb [arch=$(dpkg --print-architecture)] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" \ 
  | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

## インストール

```shell
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
```

## 確認

```shell
$ sudo docker --version
Docker version 20.10.21, build baeda1f
$ sudo docker compose version
Docker Compose version v2.12.2
```

## 一般ユーザでdocker利用可能に

ここでは現在のログイン中のユーザを指定

```shell
sudo gpasswd -a $USER docker
```
- ユーザ毎
- 実施後はログイン＆ログアウト
DynamoDBの複数のテーブルから一括でデータダウンロード

DynamoDBの複数のテーブルから一括でデータダウンロードするバッチファイルを作成したのでメモを残します。
# 事前準備
## AWS CLIの設定
・[AWS CLIをインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html)します。
・IAM作ります。
・aws configure します。
（aws configureの結果が /.aws/credentials に記録されます。後程、awsコマンドを使うのですが、うまくいかなかった時、credentials の中の region が正しく反映されていなかったので手修正したらawsコマンドが正しく実行されました）
## pythonのインストール
pythonをインストールします。
## csvkitのインストール
in2csvを使うのでcsvkitをインストールします。
```
pip install csvkit
```
# バッチファイル
次のバッチファイルで一括ダウンロードします。
```
@echo off
cd /d %~dp0

echo download 1/3
aws dynamodb scan --table-name table1 > result1.json
in2csv result1.json -k Items -e CP932 > result1.csv
echo download 2/3
aws dynamodb scan --table-name table2 > result2.json
in2csv result2.json -k Items -e CP932 > result2.csv
echo download 3/3
aws dynamodb scan --table-name table3 > result3.json
in2csv result3.json -k Items -e CP932 > result3.csv
```
## 解説
・"table*"はDynamoDBのテーブル名を入れてください（AWSコンソールで確認）。
・"-k"は次のエラーが出たので付けました：[参考リンク](https://qiita.com/yutoman027/items/7c2f6f71582dfb141225)
```
When converting a JSON document with a top-level dictionary element, a key must be specified.
```
## 参考リンク
・[MicrosoftのWindows OSで使用されている機種依存文字を含むシフトJISコードのテキストは「CP932」を指定する必要があります](https://blog.it-see.net/it-dokata/unix/iconv/)
・[【bat】Windowsのバッチファイル(*.bat)の書き方自分用まとめ](https://qiita.com/sksmnagisa/items/8c4c1788af44cc1dc63a)
・[AWS CLI 出力フォーマットの設定](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-usage-output-format.html)

以上
「技術的には可能です」と発声するその前に

技術者はよく、実装可否の問い合わせに対して本当はやりたくない・すべきでないと思っているのにやればできることだからと「技術的には可能です」と答えてしまいハマる⋯って本当ですか？　私は最低でもここ10年は「技術的には可能です」と発言した記憶がありません。なぜそう言うことがないかというと、可否の問い合わせを受けた時点で次のようなことを考えてしまうからです。

- **運用は回る？**<br>人力操作が絡むフローがあるけど利用数が増えたときにちゃんとスケールする？<br>休日深夜対応が必要になりそうだけど要員と人件費コストは確保できてる？<br>カスタマーサポート対応激増しそうだけど（以下同文<br>誤操作があったりしてデータの修正依頼が来たときに訂正しようがない要件っぽいけど大丈夫？<br>エンジニアがDB直操作対応するサービスメニューが存在するけど事故リスク、工数コスト、今後の開発停滞リスクは織り込み済み？　事故の際の責任はエンジニアに？
- **事故リスクは？**<br>操作ミス一発でテナントデータを他社に公開しちゃうことになる要件だけどリスク額はちゃんとコストに含んでいる？<br>警告ダイアログを出すから大丈夫としてあるけど、警告ダイアログを読まずにOKを押すことがない人間っています？
- **セキュリティリスクは？**<br>新しい操作フローの追加で、ユーザーが無限に不当な利益を得られるようなコースが生まれてしまっていない？<br>同じく、知ってはいけない情報を知れるコースが生まれてしまってはいない？<br>同じく、できてはいけない操作を可能にするコースが生まれてしまってはいない？<br>意図しないコースが生まれてしまっていないか検討しきれないほど、操作ルートマップが複雑化してしまわない？
- **保守は？**<br>顧客対応の特別版を作ってしまって、今後の機能追加の際には本流にもすべての顧客対応版にも同じ改修を入れていく感じ？　今後の永続的な開発・QAコスト増は織り込み済み？　改修を計画するときにすべての顧客対応版の仕様と齟齬ないかまで毎回全部考慮していく？<br>特別対応のためにロジックに特別フローを入れてしまって、今後すべての改修（以下同文
- **データ分析は？**<br>画面側の動作モデルを変更して、それでデータの意味論が変わってしまうと既存の集計・レポートロジックが間違ったものになり得るけどその調査棚卸し・修正の工数は積んである？<br>データの変更と誤入力訂正がまたっく同じ操作になっているけど、それは集計・レポートの際に区別が付かないですよ、困りません？<br>この機能の利用実績をレポート・分析する必要が間違いなく出てくるはずだけど、どんな履歴データを持っておきたいか検討済みです？
- **利用増対応は？**<br>利用者数が今の10倍に増えたら、もうまともな時間では画面を表示できなくなりそう。<br>利用者数が今の10倍に増えたら、カスタマーサポート対応も比例して増加するタイプの施策なので人件費増まで織り込んだらそもそも利益計画が成立しないサービスでは？<br>利用者数が今の10倍に増えたら、バッチが突き抜けるようになってシステム動かなくなるのでは？
- **法的な問題は？**<br>個人情報の無許可流用では？<br>著作権の侵害では？<br>顧客との信義則違反では？<br>良俗公序に反するのでは？　公になったら大炎上するやつ、もしくは利用者のレピュテーションリスクが大きい

これらに引っかかってしまう場合、その対策工数も含めて考えたときに答えは「非現実的ですね」「技術的にも解決不能な問題を含んでいますね」にしかならないわけです。何か要件の筋が悪い、やりたくないとあなたが感じるときは、ちゃんと言語化すれば上記のような問題を複数含んでいるはずです。言語化して、技術的にも解決不能であるとちゃんと回答していただければと思います。

では「解決不能」と回答すればそれで依頼者は引き取ってくれるか。そうはならないわけですね。依頼者も依頼者で、解決しないといけない問題を抱えているわけだからです（そうでない、ただの思いつき爆弾の人の存在はここではおいておいて）。
そんなときに前に進むためには、「そうでなくこうすればあなたの問題は解決しませんか？」の案を返すことです。それも複数。

そのためには、その場のアクションとしては背景の深掘りが重要。セリフ回しとしては、「技術的にも解決不能な問題を多く含んでいます。問題解決に協力させていただきたいので背景について詳しく聞かせていただけませんか？」。

そして日頃からの自分のスキル養成として、どんな問題解決にも、設計にも、コーディングするにあたっても常に複数の実現案を出しては、それらのメリデメを出し、今回はこのデメリットを特に重視するからこの方法を取ると意志決定するというトレーニングです。

やり方が上から降ってくるだけで裁量がない仕事であっても、意志決定する直前のステップまでは考えて、「つまり今回ボスはこのメリットを重視していてこのデメリットを特に避けようとしているのだな」と解釈するところまではできますのでトレーニングは同様にできるはずです。ボスとの関係次第では、「今回は○○重視ってことですね、勉強になります！」とフィードバック。そしたら自分が思いついていなかった観点がもらえるかもしれないし、ボスがあまり複数案のメリデメを考慮しない人だった場合にはボスのことも一緒に鍛えられますね！

関連項目
---
この件と同様、問題解決を前に進めるためのセリフ回しのヒント集を最近書きましたので、こういうのもっと読みたいという方はこちらもどうぞ。
- [令和最新版エンジニアのリーダーシップ論 - エムスリーテックブログ](https://www.m3tech.blog/entry/engineers-leadership)
Access VBAで各テーブル/フィールドのプロパティを一括設定する

## ソースコード例
下記設定を**システムテーブル以外の**全テーブルに適用する

- `空文字列の許可: False`
- `IME入力モード: オフ`
- `HideNewField: True`（データシートビューでフィールドの追加欄を隠す）

```vb
Option Compare Database
Option Explicit

Private Sub set_prop(obj As Object, name_obj As String, type_obj As Integer, value_obj As Integer)
    Dim prp As Object

    For Each prp In obj.Properties

        If prp.name = name_obj Then
            obj.Properties.Delete name_obj
            Exit For
        End If

    Next prp

    Set prp = obj.CreateProperty(name_obj, type_obj, value_obj)
    obj.Properties.Append prp
End Sub

Sub set_properties()
    Dim cdb As DAO.Database
    Dim def As Object
    Dim fld As Object

    Set cdb = CurrentDb

    For Each def In cdb.TableDefs

        If (def.Attributes And dbSystemObject) = 0 Then

            set_prop def, "HideNewField", 1, True

            For Each fld In def.Fields
                fld.AllowZeroLength = False
                set_prop fld, "IMEMode", 2, 2
            Next fld

        End If

    Next def

    cdb.Close
    Set cdb = Nothing
End Sub
```

## 躓いたところ

### プロパティによって値の格納場所が異なる

- テーブル全体のプロパティを変える場合
`TableDef.Properties`コレクションから目的のプロパティを探す

```vb
With CurrentDb.TableDefs(i)
    .Properties("HideNewField") = True
End With
```

- テーブル内の各フィールドプロパティを変える場合
`Field`オブジェクト／`Field.Properties`コレクションから目的のプロパティを探す

```vb
With CurrentDb.TableDefs(i).Fields(j)
    .AllowZeroLength = False
    .Properties("IMEMode") = 2
End With
```

### オブジェクト/コレクションに存在しないプロパティがある（？）

#### 現象

デザインビュー上では`IME入力モード`が見えるのに、下記のように書いたら「そんなプロパティないよ？笑」と怒られた

```vb
With CurrentDb.TableDefs(i).Fields(j)
    .Proportites("IMEMode") = 2
End With
```

#### 解決法

`TableDef.CreateProperty`で目的のプロパティを用意し、`Properties.Append`で追加する

```vb
With CurrentDb.TableDefs(i).Fields(j)
    Set prp = .CreateProperty("IMEMode", 2, 2)
    .Properties.Append prp
End With
```

:::note warn

- プロパティのデータ型を間違えると設定が正しく反映されない
- 追加したプロパティの型は後から変更できない
    - `Properties.Delete`で削除し、再度`Properties.Append`する
:::

## おわりに

目的に応じて改造してください。

調べても中々答えに辿り着けず苦労しました。。。
そんな人が少しでも減れば幸いです。

## 参考にしたページ

- [テーブル定義作成をVBAから行う](http://dreamware.blog.fc2.com/blog-entry-20.html)
- [Access2007 のテーブルの ime入力モードを VBA でオフに変更する方法について](https://answers.microsoft.com/ja-jp/msoffice/forum/all/access2007/c7f510f9-cc79-4aeb-b9ed-1c22375cd7e9)
- [Field.Type プロパティ (DAO)](https://learn.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/field-type-property-dao)
- [MS-ACCESSが遅い　リンクテーブルがなかなか開かない](https://asahiparker.com/p-blog/580)
エンジニアではない私もAutifyでテストを作ってみた

※ この記事は [Autify アドベントカレンダー2022](https://qiita.com/advent-calendar/2022/autify) の7日目のエントリです。

---

こんにちは、AutifyカスタマーマーケティングのKoheiです。
勢いよくカレンダーの日程を抑えたにも関わらず、1日遅れの投稿になっていることをここに懺悔します。

私自身はエンジニアではないのでコードを書くことはないのですが、Autifyのプロダクトサイト上で定期的に走らせるテストシナリオを作成することがあったので、その作成時に使ってみて気に入ったAutifyの機能を書いていこうと思います。

## どのようなテストシナリオを作ってみたのか
作成したテストシナリオは次のような流れです。
- Autifyの見逃し配信中セミナーのページに遷移する
    - 例えば、[テスト自動化をはじめよう！](https://autify.com/ja/webinars/lets-begin-test-automation)セミナーの見逃し配信ページなど
- 見逃し配信中セミナーのページ上で登録に必要な情報を入力する
- 必要情報を入力し、フォーム送信する
- フォーム送信後、入力したメールアドレスにメールが送られてくるか確認する
- メール内に記載されているセミナー動画へのリンクが正しいか確認する
- テストで利用したデータの削除 （入力データを保存しているツールにログイン、テストによって入力された情報を削除することでテスト前の状態に戻す）

## どのような機能を活用したか
そのようなテストシナリオの作成を進めていく中で特に活用した機能は次のようなものがあります。次のセクションではこれらの機能がどのようなシーンでどのように役立ったかを書いていきます。
- データドリブンテスト
- メールテスト
- ステップグループ

### データドリブンテスト
Autifyは非常に多くのセミナーを定期的に開催し、セミナーによっては見逃し配信も行っています（宣伝！）。申し込みフォームはセミナーページごとに存在しますが、ページの一部要素やフォームのデザインは全てのセミナーページで共通です。そして、セミナーページURLに応じて、メールで送られる動画リンクが変わります。

そこで、csvデータとしてページのURLと動画URLの組み合わせを用意し、そのデータを最初のページ表示のステップとメールに含まれるURLをチェックするステップで利用しました。
そうすることによって、後からセミナーが追加されたとしても、このcsvデータに該当のセミナーを追加するだけで、テストロジックを再度編集する必要はありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961008/a4e7200e-6c7e-6adf-9546-48ec995d69b8.png)
アップロードしたcsvデータのサンプルはこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961008/a0b36546-de25-67ac-642a-1ede4e8501e4.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961008/129dce9b-914e-f9c4-291e-c4b535a6421d.png)

このようにアップロードしたcsvデータを表示先のURLに指定したり、確認先のURLとして指定することができます。



### メールテスト
これは言わずもがなかもしれません。フォーム送信後、メールを受け取り、そのメールの内容や、そこからも正しく動画へ遷移することを確認したいので、Autify内で使えるテストメールアドレスをフォームの入力情報に入れ、そのメールアドレスで受け取ったメールの情報をAutify内で確認できる必要がありました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961008/d402d6e3-cdb1-8a88-dac6-b4524252beb7.png)
このような感じでAutify内でメールを受け取り、その中の情報を基にした検証ができます。動画リンクをクリックしてその先のページが正しいかどうかも検証できます。

### ステップグループ
ステップグループは、複数のテストシナリオで使う・シナリオ内で何度も使うアクションをグループにまとめる機能です。
今回のケースでは、テスト終了直前のデータ削除処理のところで、他のツールへログインをする必要があるのですが、そのログインをステップグループ化して利用しました。ステップグループにすることにより、他のシナリオでもログインのステップを再利用できるので、こういった共通処理はステップグループ化しておくと便利だなと感じました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961008/3cdceeca-5a4d-56a4-493b-6d58ca16bad3.png)
このような感じで、ステップグループはテストシナリオ内に利用でき、他のシナリオからも利用することができます。

## 最後に
Autifyに所属するものとして結果的に宣伝っぽい内容になってしまったのですが、エンジニアでない私も結構うまくテストシナリオが作れたよということと、活用できる機能があるよ、ということが伝わると嬉しいなと思います！
そして、この記事で紹介したようにAutifyでは定期的にお役立ちコンテンツとしてセミナーなどを実施しております。セミナーによっては見逃し配信もありますのでぜひ興味を持っていただいた方はご覧ください。と、こちらは思いっきり宣伝です。ここまでお読みいただきありがとうございました！

https://autify.com/ja/webinars
重複あるEXCELデータの高速検索

<h1>名前付き範囲で検索する</h1>
<p>Bizroboで、検索したいデータにゆらぎがない（完全一致）場合は、ループで1行ずつ調べるよりも、名前付き範囲内で検索する方が圧倒的に処理速度が速い。<br></p>

> 参考：<a href="https://tech.seagp.com/bizrobo-researchexcel/">https://tech.seagp.com/bizrobo-researchexcel/</a>


<p>しかし、やっていることはエクセルのVLOOKUPとほとんど変わらない処理のため、処理したいデータに重複があると一番最初にヒットした検索データのみしか拾ってこれない。そのため、すべて拾うには多少の工夫が必要になる。</p>

<h1>シチュエーション</h1>

<p>例えば、2011年1月1日から2022年12月31日の「快晴」時の「最低平均気温」を調べたいとする。データは気象庁から簡単にダウンロードできる。これをエクセルデータに直して、Bizrobo内で扱う。

https://www.data.jma.go.jp/risk/obsdl/

一般的には一行ずつを抽出して、最低気温を比較・更新するという手法になるが、すでに検索条件が「快晴」であることが指定されているため、これを検索キーとして探索させる。


<h1>実際の処理</h1>
全体像（ファイルの読み込みは割愛）：

![スクリーンショット 2022-12-08 135435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/33225366-a688-fc2b-1728-7c91e8d8e9e3.png)

大まかな流れとして、次のように分解できる。
１．名前付き範囲[天気概況]から、"快晴"に一致するセルを探索。
２．一致セルを新規の名前付き範囲[快晴]として設定。
３．テストで見つかった最低気温情報を上書きするか判断。
４．名前付き範囲[快晴]の行＋１から行終わりまでを、名前付き範囲[天気概況]として更新。
５．"快晴"が見つからなくなるまで、１～４を繰り返し。
<br>

デザインモードで見ると、どうやって名前付き範囲[天気概況]を更新しているのかわかりやすい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/d8c8aad3-671c-8182-942b-4533553725a6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3036127/dc1203f2-78f3-6242-2002-19f8b8a5ed4e.png)


実行結果を見ると、

```html:デバッグの状態：ログ
Write Log: 実行回数：436
Write Log: 東京の快晴時最低気温は 1/25/18、0.0℃
```

今回使ったデータは4000行程度なので、通常ループに比べると、10分の1程度まで処理回数を少なくできている。ただし、実際の実行時間は通常ループの方が機能が単純な分コンマ数秒速い。

<h1>結論</h1>

実際の業務では何万のデータ行を扱うことになり、大量のデータ処理にはこの手法が最適解である！
　……と声高らかに宣言したいところだが、最大の弱点としてEXCELファイルにしか使えない。

CSVではクラシックモードで名前付き範囲を扱うことができるが、CSVのHTML構造では列の情報を持っていないため、横方向のみにこの手法が使える（と考えられる。試してない）。使えたら報告ください。

参考記事が「ループを回さない」と銘打っている通り、重複が少なければ少ないほど真価をできるため、自身の自動化したい内容に応じて実装してみてほしい。
NISユーザでログインできない原因が、ユーザ情報に指定されたログインシェルの未インストールだった

# 前書き
NISの構築で**ハマったまま気づかずにいると無限に抜け出せなさそう**なある種の落とし穴について書きます。私はかなり長い時間ハマっていました(丸1日くらい)
また、本記事ではNISサーバやNISクライアントの設定について深く突っ込みません。その辺りを詳しく知りたい方は別途調べてください。

# サーバーの構成とNISクライアント構成時の参考情報
NISマスターサーバはCentOS 7を使ってもともと構築されていて、NISクライアントをUbuntu18.04を使って設定しようとしていました。CentOSの方にいるユーザの情報を使ってUbuntuにログインするという構成です。

NISクライアントの設定は以下を参考にして実施しました。とても参考になりました。
https://www.server-world.info/query?os=Ubuntu_18.04&p=nis&f=1


# なぜログインできなかったのか
これはタイトルの通りで、**ユーザ情報に指定されたログインシェルが未インストールだった**ためです。

# NIS設定が正しくてもログインできない
上記リンク先を参考に設定した結果、ypwhich で正しいドメインが表示されるし、ypcat passwd でNISサーバからユーザ情報も正しく持ってこれていて、NISの設定はうまくいっていました。

にもかかわらずログインできない状態でとても不思議だったのですが、結果としてはsshdがログインを拒否していました。
```
Dec  6 20:50:16 serv sshd[2310]: User user001 not allowed because shell /bin/tcsh does not exist
```

このログによると「/bin/tcshがいないからuser001のログインは許可できない」とのこと。
そこで、aptをつかってtcshをインストールしてから改めてログインすると、すんなり成功しました。
```
sudo apt install
```

諸事情により、NISサーバ(CentOS)では各ユーザのログインシェルが/bin/tcshとなっている環境なのですが、確かに Ubuntu 18.04 インストール直後はtcshが入っていなく、bashがデフォルトの環境でした（もしかしたら特殊かもしれない）。

# 長時間ハマった理由
ログを見れば一瞬で解決できるのになぜ長時間ハマったかというと、**ローカルのpasswdにいるアカウントは普通にSSHログインできたからです。**
加えてNISの知識不足もあり、ずっとNISの設定が悪いと思っていたのも理由の一つです。
結局のところしらみつぶしでログを確認し始めてから判明したという感じで、SSHログインのところで問題が発生しているという発想はログを見るまでありませんでした。

# まとめ
- NISユーザが指定しているログインシェルはあらかじめインストールしておこう
- ログはちゃんと見ましょう（当たり前）
NewtとimageKitでGoogleStorageを外部ストレージに設定する

# imagekitに登録する
この辺はいいですね。
こちらから登録しましょう。
https://imagekit.io/

# Newtに登録する
https://www.newt.so/

# imageKitとNewtの外部ストレージにGoolge Cloud Storageを設定する
Newtの説明がわかりやすいです。
以下引用。
https://www.newt.so/docs/advanced-settings

![スクリーンショット 2023-02-23 10.30.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306936/ec9aa596-20a2-d915-10f5-8ae16cd73e75.png)

### 注意
「3. 作成したバケットに公開アクセスを設定する」で設定する権限は「**Storageオブジェクト閲覧者**」、
「4. サービスアカウントを作成」で設定する権限は「**ストレージ管理者**]です。
地味に違うので気をつけましょう。

# imageKitの設定
説明通り、imageKitの設定画面で、External storageを設定します。
https://docs.imagekit.io/integration/configure-origin/google-cloud-storage

問題なければ、GCSだとこのようにURLが設定されますが、
`https://storage.cloud.google.com/bucket-name/rest-of-the-path.jpg`
imageKitだとこのようにURLが取得できます。この辺もドキュメントに書いてあります。
`https://ik.imagekit.io/your_imagekit_id/rest-of-the-path.jpg`

あとはimageKitのExternal storageから設定を行います。
![スクリーンショット 2022-12-08 13.23.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306936/e362e35e-6c99-bffc-59d3-2c84ea882e47.png)

Google service account private KeyとGoogle service account client emailはGoogle Cloudの「IAMと管理」のサービスアカウントに書いてあります。

秘密鍵のjsonアップロードなどを行い設定完了です。

# Newtの設定
Newtの外部ストレージと画像最適化にimagekitを設定します。
スペース設定＞一般
から設定できます。
簡単ですね。
google/runeを動くところまでやってみる

## google/runeとは？

The Rune Programming Language
https://github.com/google/rune

google非公式の新しいプログラミング言語です。

githubから引用

> より速く、より安全で、生産性の高いシステム プログラミング言語 これは公式にサポートされている Google 製品ではありません。 注: ルーンは未完成の言語です。 Rune の優れた新しいセキュリティ機能と効率性機能を気軽に試して評価してください。 Rune は、C および C ライブラリとうまくやり取りできるように設計された、Python にインスパイアされた効率的なシステム プログラミング言語です。 Rune には、メモリの安全性やシークレットの一定時間の処理など、多くのセキュリティ機能があります。 Rune は、Structure-of-Array (SoA) メモリ管理により、ほとんどのメモリ集約型アプリケーションで C よりも高速であることを目指しています。

同じような名前でrune-rsというrust用のライブラリがありましたが、そちらとは別物です。

https://github.com/rune-rs/rune/

動くところまでやってみます。ほとんど作業ログです。

## 準備

### ホスト側
git cloneで必要なリポジトリを落としておきます。

```
$ git clone https://github.com/waywardgeek/datadraw.git
$ git clone https://github.com/google/rune.git
$ git clone https://github.com/pornin/CTTK.git
```

Dockerfileを作成してその中にgoogle/runeをインストールしていきます。

```
FROM ubuntu:22.10
WORKDIR /opt
COPY . .
```





```
$ docker build -t rune .
$ docker run -it rune /bin/bash
```

### コンテナ側
以降はdocker内で実行しているコマンドです。

```
$ apt update
$ apt install bison flex libgmp-dev clang clang-14 gdb automake build-essential
```

runeをコンパイルするのに必要なものを入れていきます。
READMEに書いてあるとおりに進めます。

```
$ cd datadraw
$ ./autogen.sh
$ ./configure
$ make
$ make install
$ cd ..
$ cp CTTK/inc/cttk.h CTTK
$ cd rune
$ make
$ ./runtests.sh
$ make install
```

ここまで特に問題なくセットアップできていれば、
```
$ which rune
/usr/local/bin/rune
```
といった感じでruneコマンドが利用できるようになっているはず。

## 試す

```
$ mkdir -p /opt/app
$ cd /opt/app
$ echo 'println "Hello, World!"' > hello.rn
$ rune -g hello.rn
$ ./hello
Hello, World!
```

デバッグでgdbを利用できるようです。
```
# debug
$ gdb ./hello
...
(gdb)
```



## 所感

python感が感じられるほどまだ触っているわけではないので、もっと触っていけばわかるのだろうか？という感触です。（インスパイアされているだけでpythonとはまた別なんだろう）

自分のIDに似ているので今後の動向に注目していきたいです。
メモ：Dockerコンテナ内にMySQLのタンプファイルをコピーしてリストア


メモメモ

## コンテナ名を調べる

```shell
$ docker compose ps
NAME                 COMMAND                  SERVICE             STATUS              PORTS
xxxxxxxxxxxx-app-1   "/usr/sbin/apachectl…"   app                 running             0.0.0.0:8081->80/tcp
xxxxxxxxxxxx-db-1    "docker-entrypoint.s…"   db                  running             3306/tcp
```

## ファイルをコピーする

```shell
$ docker cp xxxxxxxxxxxx.dump.sql xxxxxxxxxxxx-db-1:/tmp/
```
> `xxxxxxxxxxxx-db-1`は前項で調べたコンテナ名

## コンテナ内へ侵入

```shell
$ docker exec -it xxxxxxxxxxxx-db-1 bash
```

## リストア実行

```shell
# mysql -u root -p -D app < /tmp/xxxxxxxxxxxx.dump.sql
```
WSL上でのGitの初期設定

## WSL上でのGitの初期設定
### インストール
```
sudo apt update
sudo apt install git
```

### 準備
- .gitconfigを設定する
```
git config --global user.name 'Githubのアカウント名'
git config --global user.email 'Githubに登録しているメールアドレス'
git config --global core.editor 'vim'
```
- 一応確認する
```
git config --list
```

### リモートリポジトリへの認証(SSH)設定
- SSHキーの作成
```
cd
ssh-keygen -t rsa
```
何回かEnterを押す。

- Githubに公開鍵を登録
[https://github.com/settings/ssh](https://github.com/settings/ssh)

    「NEW SSH key」をクリック

- Githubの入力欄Titleを入力する(なんでもOK。Ubuntuとか)
- Githubの入力欄Keyを入力する
    下記コマンドで公開鍵の中身をクリップボードへコピーしたあと、Key欄に貼り付ける。
```
cat ~/.ssh/id_rsa.pub | clip.exe
```
- 最後にAdd SSH keyをクリックして完了。

### 接続の確認
- 以下のコマンド入力する
```
ssh -T git@github.com
```
- 途中でyesを入力してEnter。
- 最後にHi~~~~と表示されればOK。

### Gitで管理したいディレクトリを初期登録する
- 管理したいディレクトリへ移動
```
cd 管理したいディレクトリの場所
git init
```
Linux上へのDockerのインストール方法

# Linux上へのDockerのインストール方法
いろいろなソフトウェアを同じ環境下で開発・計算していく場合、共有される実行環境やライブラリの変更によって、あるソフトウェアが動かなくなることがよくあります。
そこで、環境を隔離することができるのがDockerです。

- Linux OS上に、コンテナと呼ばれる複数の隔離されたOS(っぽいもの)を、それぞれが独立した状態で構築することができます。
- 構築した環境をイメージと呼ばれるファイルに換えて、容易に複製したり移行したり配布したりできます。
- 仮想化するよりも軽いのが大きなメリットです。

公式マニュアルは[こちら](https://docs.docker.com/engine/install/ubuntu/)。

## Docker Engine on Ubuntuをインストールする

### 公式マニュアルは[こちら](https://docs.docker.com/engine/install/ubuntu/#set-up-the-repository)。

- 旧バージョンをアンインストール
```
sudo apt remove docker docker-engine docker.io containerd runc
```

- インストールする
まずリポジトリを設定する
```
sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release -y
```
- Docker EngineのGPGキーを設定する
```
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
```
- 以下のコマンドでリポジトリを設定する
```
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
```

- Docker Engineをインストールする
```
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin -y
```

- 管理者以外も利用できるようにする。以下を入力したのち、いったんログアウトして再ログインする。
```
sudo usermod -aG docker $USER
```
- Docker Engineを起動、終了する。
```
sudo systemctl start docker # 起動
sudo systemctl stop docker # 終了
```

- ※WSL上の場合は以下を実行してDocker Daemonを起動する
```
sudo service docker start
sudo service docker stop
```

- 無事インストールされているか確認する
```
docker run hello-world
```
【FileMaker】LINEにとりまメッセするわ

ということってありませんか？
[LINE](https://line.me/ja/)にメッセージを送る方法として、APIやBotツールを使うなど色々ありますが、FileMakerから相手をLINE上で指定してメッセージ送るだけなら「[URL を開く](https://help.claris.com/ja/pro-help/content/open-url.html?)」スクリプトステップ１行だけで実現できます。

# FileMaker対象バージョン
このスクリプトステップは、FileMaker バージョン6以前から実装されているので、ほとんどのバージョンで実装可能と思います。
今回の記事作成用に使用したFileMaker バージョンは、19.6.1です。

# LINE URLスキーム
以下のLINE Developer向け公式資料を参考にしています。

https://developers.line.biz/ja/docs/messaging-api/using-line-url-scheme/#available-line-url-schemes

# 動き
まずは、動きを見てみましょう。

## PCでの動き
PC版LINEでは、非対応だと公式ページに書いてあります。
PCにLINEアプリが入っていても、ブラウザが立ち上がるだけで、Web版プロフィールを公開設定にしていたり公式アカウントが認証されているときはQRコードが出るそうなので、やりたいこと（LINEにメッセージを送ること）がうまく機能しないです。
なので、この「LINEにとりまメッセするわ」は、LINEアプリがインストールされているiOSでお使いください。
![スクリーンショット 2022-12-05 11.51.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/efe9a9d9-5b5d-a809-fe24-e71477fb1a86.png)

## iOSでの動き
すでにLINEアプリがインストールされ、使用されているものとします。
URLを開いてLINEアプリが下からにゅっと出てきた時、つい「LINEアプリを開く」をタップしがちですが、なぜか「Safariで開く」の方でないとうまくいきません。
ので、「Safariで開く」をタップしてください。
まぁ、なんか大人の事情があるんでしょう。。。
![スクリーンショット 2022-12-05 12.01.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/92d6a01f-2e8d-b0e3-9334-62ffb0813514.png)
![スクリーンショット 2022-12-05 12.02.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/86559a92-3962-d024-f91e-863127a68c7b.png)

# 実装
基本、スクリプトステップ１行になります。
![スクリーンショット 2022-12-05 12.08.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60538/7ed956af-36a4-6e7f-7190-887137a58d60.png)
"text"パラメータがメッセージ内容になりますので、この部分を変数にして実装する形になるかと思います。

「[URL を開く](https://help.claris.com/ja/pro-help/content/open-url.html?)」スクリプトステップは、URLがエンコードされた形で実行されるので、エンコード処理は不要です。

# メッセージ送信以外
メッセージを送信する以外にも、URLスキームだけで色々できます。

https://developers.line.biz/ja/docs/messaging-api/using-line-url-scheme/#available-line-url-schemes

「URL を開く」スクリプトステップ、ぜひ活用してくださーい！
Dockerを使ったUbuntu環境構築

## Dockerを使ったUbuntu環境構築
コンテナを使っていつでも気軽に環境作成・構築・削除ができるようになります。

### Docker serviceの起動
```
sudo systemctl start docker
```

WSL上のUbuntuの場合は代わりに以下。
```
sudo service docker start　
```

### Dockerfileの作成
Dockerfileを使うと、書かれている内容の通りのDockerイメージを自動で作成してくれます。

- ファイル名「Dockerfile」を作成
```
touch Dockerfile
```
- Dockerfileの編集
```
vim Dockerfile
```
- Ubuntuのイメージファイルを元にする。
- aptのupdateしたのちにxterm, vim, wget, sudoをインストールする
- 新規ユーザ(user)を作成する
- userのパスワードをXXXXとする
- userにsudo権限を付与する
```
FROM ubuntu
RUN apt update
RUN apt install xterm vim wget sudo -y
RUN sudo useradd --create-home user
RUN echo "user:XXXX"|chpasswd 
RUN sudo usermod -aG sudo user
RUN su - user
```
### Dockerfileを使ったイメージ作成
- Dockerfileを使ってイメージを作成する。ここでは作成するイメージ名をimage-ubuntuとする。
```
docker build . -t image-ubuntu
```
### Dockerのコンテナ作成・起動
- 作成したイメージを使ってコンテナを作成・起動する。ここでは、
  - コンテナ名を「test-ubuntu」
  - オプションに「-dit」(-d: バックグラウンド実行, -i: コンテナにキーボードを繋ぐ, -t: 特殊きーを使用可能にする)を指定
  - -e DISPLAY=$DISPLAYにて、DISPLAYの環境変数を受け渡す
  - ログインするユーザ名はuser
  - イメージ名は「image-ubuntu」
  - 引数に「/bin/bash」(シェルコマンド)を指定
```
docker run -dit --name test-ubuntu -e DISPLAY=$DISPLAY --user=user image-ubuntu /bin/bash
```
- コンテナが無事起動していることを確認する
```
docker ps
```

- コンテナに入る
  - コンテナ名を「ubuntu-test」
  - オプションに「-it」(-i: コンテナにキーボードを繋ぐ, -t: 特殊きーを使用可能にする)を指定
  - 引数に「/bin/bash」(シェルコマンド)を指定
```
docker exec -it test-ubuntu /bin/bash
```


- Ubuntu@Dockerに入れたことを確認する
```
cd ~/
pwd # userのホームディレクトリ(/home/user)が表示されるはず
cat /etc/issue # Ubuntuのバージョンが表示される
```

- 現在ログインしているユーザ名を確認する(userになっているはず)
```
whoami
```
---
### GUIアプリを使えるようにする
- x11-appsをインストールする
```
sudo apt install x11-apps -y
```
- 環境変数に反映させる。~/.bashrcをVimで開いて、最終行に以下を追記して保存する
```
export DISPLAY=$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):0
```
- .bashrcを反映させる
```
source .bashrc
```

- 動作確認。マウスに連動する目玉が出てきたら成功
```
xeyes
```
<img width="133" alt="xlaunch4" src="https://user-images.githubusercontent.com/64639043/204118509-92d7c6c8-0a77-45ad-9989-8eff1024dccf.png">

---

### Ubuntu@Dockerを終了する
- Ubuntu@Dockerのコマンドラインで終了する。
```
exit
```
- コンテナはバックグラウンド実行のままなので、コンテナを停止したい場合は以下。
```
docker stop ubuntu-test
```


これにて、Docker上にUbuntu環境が構築できました。
Dockerの基本的な使い方

## Dockerの基本的な使い方
### Docker Engineの起動・終了
- Linux上で起動、終了する。
```
sudo systemctl start docker # 起動
sudo systemctl stop docker # 終了
```

- WSL上のLinux上で起動、終了する
```
sudo service docker start # 起動
sudo service docker stop # 終了
```

### コンテナの一覧表示
- 動いているコンテナの一覧表示
```
docker ps
```
- 存在するコンテナの一覧表示
```
docker ps -a
```

### コンテナの作成・起動、削除の練習
- コンテナの作成＆起動 (このとき、コンテナの元となるイメージが自動的にダウンロードされる)
```
docker run --name test1 -d httpd # 練習としてApacheのイメージを作成して起動する
```
- コンテナが正常に作成・起動できたことの確認
```
docker ps
```

- コンテナの停止
```
docker stop test1
```

- コンテナの起動
```
docker start test1
```

- コンテナの削除
```
docker stop test1 # まず停止する
docker rm test1 # 次に削除する
```

- コンテナが正常に削除されたことの確認
```
docker ps -a
```

### イメージの確認・削除の練習
コンテナを作成すると、自動的にイメージがダウンロードされて保存されています。
コンテナを削除してもイメージは削除されないので、適宜イメージを削除しましょう。
ただし、既存のコンテナで使っているイメージは削除できません。

- 存在するイメージを確認する
```
docker image ls
```

- イメージを削除する
```
docker image rm httpd # REPOSITORY名がhttpdというイメージを削除する場合
```

- イメージを削除できたことを確認する
```
docker image ls
```
ssh接続切断後もバックグラウンドで実行続ける方法

### 手元のWSLからのSSH接続
- 接続する。
```
ssh -XC ユーザ名@ホスト名
```

- ssh接続を切断する
```
exit
```

### ssh接続切断後もバックグラウンドで実行続ける方法
- 計算実行コマンドの最初にnohupをつけて、最後に&をつける。例えばLAMMPSでin.meltを計算する場合。
```
nohup mpirun -np 12 lmp < in.lmp &
```
- ちなみに、実行中に表示されるコマンドラインは自動的にnohup.outに出力される。途中経過を見たい場合は以下。
```
tail -F nohup.out
```
WSL上Pythonの環境構築＆VSCodeの設定方法

## WSL上へのPythonの環境構築
Pythonのパッケージの状況を使い分けるためには、仮想環境としてPython環境を構築するのがおすすめ。

詳細は[こちら](https://learn.microsoft.com/ja-jp/windows/python/web-frameworks)

### Python3, pip, venvのインストール
- Python3。バージョン番号が表示されればOK。
```
python3 --version
```
- Pythonのパッケージ管理ツールpipのインストール
```
sudo apt install python3-pip
```
- Python仮想環境作成のためのツールvenvをインストール
```
sudo apt install python3-venv
```

### 仮想環境の作成とパッケージのインストール
- 仮想環境「test-env」を作成する
```
python3 -m venv /home/ユーザ名/test-env/
```

- 仮想環境「test-env」をActivateする
```
source /home/ユーザ名/test-env/bin/activate
```
- WSL起動時に自動的に仮想環境が立ち上がるようにするためには、.bashrcの最後に以下を記載する
```
source /home/ユーザ名/test-env/bin/activate
```

- (必要あれば) pipをupgradeする
```
pip install --upgrade pip
```

- パッケージをインストールする(例: numpy, pandas, matplotlibをインストールする)
```
pip install numpy pandas matplotlib
```

- インストール済みのパッケージを表示する
```
pip list
```

- 仮想環境をDeactivateする
```
deactivate
```

## WindowsのVSCodeで、WSL上のVenvを使ったPython仮想環境を使えるようにする
### VSCodeのインストール
[https://azure.microsoft.com/ja-jp/products/visual-studio-code/](https://azure.microsoft.com/ja-jp/products/visual-studio-code/)

### 拡張機能のインストール
- Python
- WSL

### WSLからWindows上のVSCodeを立ち上げる
- 試しにWSL上の任意の場所に、test.pyを作成する
```
echo "print('hello world')" > test.py
```

- VSCodeを立ち上げる
```
code test.py
```
自動的にWindows上でVScodeでtest.pyが開かれる

- WSL上で使うPythonを選ぶ。画面右下、「Pythonインタープリタを選択？」をクリック。「＋インタープリターパスを入力」にvenvで構築した仮想環境のパスを指定する。上述の通りであれば以下。
```
/home/ユーザ名/test-venv/bin/
```
- 完了