OmniAICreator/Qiita-1.07M huggingface dataset:
Spot OceanでGKEの利用料を削減してみる(その１)

## この記事について
皆さん、コンテナって使われていますか？専用アプライアンス→仮想化→コンテナという流れで最近コンテナをお使いの企業が増加傾向にあります。AWS, Azure, Google Cloud Platformの三大ベンダーの中でも、Google Cloud PlatformのGKEに関わる機会が増えてきました。
ネットアップが提供する、Spot by NetAppと呼ばれるCloud Opsサービスがあります。このコンテナ需要の増加に相まって、Spot Oceanというコンテナ利用料の最適化サービスも需要が高まるんじゃないかな？と勝手に考えています。既にGKEを集中的にお使いで、コスト最適化をしてみたいなと考えているエンジニアの方に届いてほしいな～と思いながらこの記事を書いています。この記事では、SpotとGoogle Cloud(GKE)の連携から、Oceanで実際にGKEのコスト最適化をしていくところまでを紹介しています。

## Spot by NetAppとは？
「Spot by NetApp」はパブリッククラウドの利用状況を分析・可視化し、クラウド利用コストを最適化するFinOpsソリューションです。お客さまの利用状況にあわせて、リザーブドインスタンスやスポットインスタンスなどの割引プランをAIが自動で管理します。
引用：[クラウド利用コスト最適化サービス Spot by NetApp](https://www.softbank.jp/biz/services/platform/spot/#:~:text=%E3%80%8CSpot%20by%20NetApp%E3%80%8D%E3%81%AF%E3%83%91%E3%83%96%E3%83%AA%E3%83%83%E3%82%AF,%E8%87%AA%E5%8B%95%E3%81%A7%E7%AE%A1%E7%90%86%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

その中で今回使っていくのは、スポットインスタンスを使ったクラウドコンテナの利用料最適化サービス、Oceanです。**SpotはOceanやElastigroupを含めたサービスをサインアップするだけで利用できる無料枠があるので、気軽に試すことができます。**
[https://console.spotinst.com/spt/auth/signUp](https://console.spotinst.com/spt/auth/signUp)からサインアップ可能です。

## SpotとGoogle Cloud Platformを連携させる
まずは、Google Cloud PlatformとSpotを連携させていきます。
1. [Spotコンソールから](https://console.spotinst.com/spt/auth/signIn)でサインアップ・ログインする。

2. Google Cloud Platformを選んでセットアップ手順を進めていく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/5d33e397-740f-b4f5-f2c8-6f0f742303fa.png)

3. GKE内でリソースをデプロイしたりするので、権限を付与するためにservice accountを作れるアカウントを選択する(**Automatically**)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/665fa68f-bd56-99af-ebf6-95e591c08543.png)

4. Project IDを入力と出るので、管理したいGKEクラスターが存在するプロジェクトを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/586758fd-05cf-c3f7-2f74-be346c784f6e.png)

5. service accountを作成するコマンドが出力されるので、Google Cloud Platform内のCloud Shellで実行する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/6f5713f1-8814-4bae-d153-f1ddcb4a1dc6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/99a8af6e-d929-5b9f-5485-8f4aa22aef66.png)

6. service accountが使用する鍵をSpot用に新たに作成、アップロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/e397d731-c0a3-5b96-281e-2d01afbe3bd7.png)

7. service account一覧に入り、service account一覧から[**spotnist-role...**]というアカウントをクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/7083474a-f2c7-f16e-2508-f8b2f4401f5d.png)

8. 新たに鍵を作成・ダウンロードする。[**ADD KEY**]→[**Create new key**]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/01cbbe6d-9cb2-0183-3efd-af9d8740b85d.png)

9. アップロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/baa373d9-f4cd-d164-d41f-c877d652b2db.png)

10. 連携完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/504005/0ba4bb68-67da-a8f7-c73c-8fc6ea45f791.png)

## まとめ & 次回予告
今回は準備段階としてSpotとGoogle Cloud Platformの連携手順を紹介しました。次回はGKEのクラスタをSpot Oceanに登録（インポート）し、スポットインスタンスを使ったコスト最適化の作業に入っていきます。
↓
[Spot OceanでGKEの利用料を削減してみる(その２)](https://qiita.com/buriki/items/27fd67461ef16885de11)
Raspbianにopencvを入れる方法

## **(1)ラズパイのアップデートとアップグレードを行う。**
＊「-y」オプションは「yes or no」を聞かれなくなる。
```
$ sudo apt update
$ sudo apt upgrade -y
```

## **(2)pythonのバージョンを確認**
```
$ python -V
Python 3.7やPython 3.9ならok
$ python3 -V
Python 3.7やPython 3.9ならok
```

## **(3)python3-pipをインストール**
```
$ sudo apt install python3-pip
```

## **(4)opencvをインストール**
```
$ pip3 install opencv-python
```

## **(5)opencv付属パッケージをインストール**
＊「numpy」や「libatlas3-base」は演算などで使用
```
$ pip3 install numpy --upgrade
$ sudo apt install libatlas3-base
```

## **(6)インストールの確認(下記が実施できればok)**
```
$ python3
>>> import cv2
importエラーが出なければok
>>> cv2.__version__
(例)'4.7.0'などと出力される
>>> quit()
```
VSC経由でssh接続したLinuxマシン上でのvenv設定

似た記事は山ほどあると思うのですが、毎回調べるのが面倒で自分用にまとめました。

# 前提
- VSC経由でssh接続のLinuxマシン上での環境構築
- 公式のpython Extentionはインストール済み
- pyenvは設定済み

```
$ pyenv versions
  system
* 3.9.6 
```

# venv設定

venv作成
```
 cd [作業ディレクトリ]
 python -m venv [任意のenv名]
```
アクティベート
```
cd [作業ディレクトリ]
source [任意のenv名]/bin/activate
```

# VSCでの設定
[View]→[Command Palette]→[Python:Select Interpreter]
先ほど作ったenvを選択

# 上記のやり方でenvが出てこない場合
明示的にカーネルを追加する。
以下は、任意のenv名を"venv"とした場合の設定方法。他にvenvという名前の環境があると上書きしてしまうことに注意。
TERMINALで以下を実行
```
(venv)$  ipython kernel install --user --name=venv --display-name=venv
```


# 参考
https://qiita.com/Shiba-You/items/93c4e043e4c8dbc60cad
https://takeg.hatenadiary.jp/entry/2021/05/22/165935
Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure AD管理単位」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure AD管理単位」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure での ID とガバナンスの管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-identities-governance/)
◇対応するモジュール
[管理単位を管理する](https://learn.microsoft.com/ja-jp/training/modules/configure-user-group-accounts/6-create-administrative-units)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure での ID とガバナンスの管理「Azure ADグループアカウント」](https://qiita.com/fsd-jume/items/bd4db1e05dd44ebd4acd)

## Azure AD管理単位
### 管理単位(AU：Administrative units)
・組織を任意の単位に分割し、その単位の管理アクセスを委任可能
⇒単位内のメンバーのみを管理できる管理者を割り当て可能
⇒管理者に割り当てられるロールのアクセス許可を単位内のみに制限
・割り当てる管理者にはAzure AD Premium P1/P2ライセンスが必要
・管理単位のメンバーにはAzure AD Freeライセンスが必要
・管理単位は1つのAzure ADリソース
・管理単位の入れ子は不可

### 管理単位に含めることができるメンバー
**◆ユーザ**
・1つのユーザが複数の管理単位のメンバーになることが可能
・ユーザに対して可能な管理
　-プロパティやパスワードの管理
　-ライセンスの管理
　-ブロックとブロック解除
　-MFAの資格情報の管理

**◆グループ**
・グループ自体の管理は可能だが、グループ内のユーザやデバイスの管理は不可
※ユーザやデバイスが個別にメンバーに追加されている場合を除く
・グループに対して可能な管理
　-グループの作成と削除
　-グループプロパティやメンバーシップの管理
　-グループライセンスの管理

**◆デバイス**
・デバイスに対して可能な管理
　-デバイスの有効化/無効化/削除
　-BitLocker回復キーの読み取り

### 管理単位の管理ツール
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/9b0af98e-6827-554e-e95d-229932034d74.png)

### 管理単位のスコープ
・管理単位のスコープは、管理アクセス許可にのみ適用
⇒管理単位のメンバーと管理者は、管理単位外の他のユーザ/グループ/リソースを参照可能
※管理単位用のロール以外を使用した場合に参照可能

### 管理単位の作成例
・大学でエンジニアリング学部の管理を学部専用のITチームに委任したい場合
①エンジニアリング学部の管理単位Aを作成
②管理単位Aにエンジニアリング学部の学生/スタッフ/リソースのみを追加
③管理単位A内のAzure ADユーザのみを対象とした管理アクセス許可を含むロールBを作成
④専用のITチームにロールBを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2851723/f5637e96-dbe2-1fbc-c161-55c2f6cbafd8.png)

## 次の学習内容
**◆Azureリージョンペア**

https://qiita.com/fsd-jume/items/74c8f56f269d9f1f8fd2

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
yarnについて

```yarn install```
にて、すでに他の人がインストールしているモジュールを、package.jsonに記述されているものを
一括にインストールすることができる。


※package.jsonに記述があるからといってモジュールがインストールされているわけではないので、注意！



メモ
package.json に書いてあっても自動でモジュールがインストールされるわけではないので、pullしたあとにyarn install を実行する必要がありますね…
文字列連結まとめ①(Ruby)

Rubyで文字列連結のプログラムをいくつか実装しました

問題

>3 つの文字列が改行区切りで与えられます。
これらの文字列をバーティカルライン | 区切りで出力してください。

①「<<」で連結する方法

```Ruby
    ans = ""
    for i in 1..3 do
        input_line = gets.chomp
        if i < 3 
            ans = ans << input_line << "|"
        elsif i ==3
            ans = ans << input_line
        end
    end    
    puts ans
```

②「+」で連結する方法

```Ruby
  ans = ""
    for i in 1..3 do
        input_line = gets.chomp
        if i < 3 
            ans = ans + input_line + "|"
        elsif i ==3
            ans = ans + input_line
        end
    end    
    puts ans  
```

以上2つの方法を取り上げました
[Python] PyAutoGUI 画像認識のクリック・待機処理を関数化

作ったプログラムの備忘録

# はじめに
* PyAutoGUIで画像認識させてクリックや待機処理をする際に、同じコードをコピペしまくるのはよくないので関数化
* どのレベルで関数化するかは好みによるかもしれないが、個人的に便利な引数での設定をメモとして記載

[追記] 本記事は基本的なクリックと待機処理のみです。すこし応用した「複数画像のどれか」が表示されたらクリックする関数については以下のリンク先をご覧ください。

https://qiita.com/takafi/items/91a8480ef42cd240de28

## 動作テスト環境
OS: Windows 10 Pro 64bit
言語： Python 3.9.13
ライブラリ：PyAutoGUI 0.9.53

# ソースコード
```Python:
import pyautogui
```
* インポート
## 待機
```Python:
def wait_img(img):
    for i in range(300):
        try:
            if pyautogui.locateOnScreen(f'./img/{img}', grayscale=True, confidence=.8):
                break
        except pyautogui.ImageNotFoundException:
            sleep(0.2)
    sleep(0.01)
```
* 待機処理のみのコード
* 引数として画像のファイル名（image.pngなど）を指定して、その画像が現れるまで待機する処理
* この場合、0.2秒間隔で画像をチェックして、300回待機するので、60秒間は待機処理を継続する
* 最後の0.01秒待機はPyAutoGUIを安定稼働させるための個人的なおまじない（処理が早すぎると安定しないので人間としては気にならないが、PC的には十分遅い処理にする）


## クリック　その1
```Python:
def click_img(img, sleeptime):
    p = pyautogui.locateOnScreen(f'./img/{img}', grayscale=True, confidence=.8)
    x, y = pyautogui.center(p)
    pyautogui.click(x, y, button='left')
    sleep(sleeptime)
```
* 画像認識で指定の画像の真ん中を左クリックして、指定時間待機する処理
* クリック後の待機処理はアプリごとにどの程度強制待機した方がよいかが異なるために引数として指定できるようにしている
* 基本的に`def wait_img()`と組み合わせる前提なので0.01秒や0.1秒程度の指定とすることが多い

## クリック　その2
```Python:
def click_imgoffset(img, offsetx, offsety, sleeptime, conf, gray):
    p = pyautogui.locateOnScreen(f'./img/{img}', grayscale=gray, confidence=conf)
    x, y = pyautogui.center(p)
    pyautogui.click(x + offsetx, y + offsety, button='left')
    sleep(sleeptime)
```
* 画像認識で指定した画像から指定した座標分オフセットした位置をクリックする処理
* クリックしたい位置の画像が複数画面上に存在してしまう場合や特徴があまりないときに、別の画像を起点にクリックさせるために作成
* 引数の`grayscale`, `confidence`を設定できるようにするかは好み。個人的にはなくてもほぼ困っていないが、たまに変えたい場合も発生する

## 使用例
```Python:
wait_img('image1.png')
click_img('image1.png', 0.01)
```
* `image1.png`が現れるのを待って、クリック

```Python:
wait_img('image2.png')
click_imgoffset('image2.png', 0, -55, 0.01, .8, True)
```
* `image1.png`が現れるのを待って、そこからxに0pixel、yに-55pixelの位置をクリック

```Python:
wait_img('image3.png')
pyautogui.typewrite('text', interval=0.001)
```
* ちなみに待機処理とクリック処理を分離させているのは、待機処理後にクリックをしない場合もそこそこ発生するから
* 例としては画面が出てきた際にデフォルトでカーソルがアクティブになる類のソフトウェアでは上記のコードのようにそのまま文字を入力すればいい場合などがある


## 補足
```Python:
p = pyautogui.locateOnScreen(f'./img/{img}', grayscale=True, confidence=.8)
```
* 上記のコードの`grayscale=True`は画像をグレイスケールとして処理する引数。多少処理が速くなるのと処理精度は体感で変化ないので指定している
* `confidence=.8`は画像認識の一致度？を指定している。1だと完全一致らしいが、その指定では画像認識がうまくいかず処理が進まないことが多いので、0.8としてしている（.8という表記は元にしたコードがその表記だったからで正式なものか不明）
* また引数`confidence`を使用する場合は、PyAutoGUIが内部でOpenCVを使用するらしいのでインストールが必要
NetBSDをローカルでインストール

HEADのビルドはevbarm-earmv5になったので、v4のためローカルでビルドしたファイルでインストールできるようにしてみました。

母艦はFreeBSD/amd64です。

ビルド環境はBastilleBSDのjailなのでbastille pkgでmini_httpdをインストールします。

ユーザー権限でプロセスを上げるので、ポートは8080でmini_httpdをあげます。

```
% mini_httpd -p 8080 -d netbsd-src/obj
```

hostでポートをリダイレクトします。

```
% sudo bastille rdr netbsd tcp 8080 8080
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/cbe7e06f-b3fc-9c0c-0f9a-65c57b31656e.png)

USBがあるターゲットはUSB HD(umass)にインストールしています。

ネットの帯域は大切にしましょう。

後日追記

vnetを使うようにしたので、rdrの必要がなくなりました。
OrthoFinderをインストールするときのPython バージョン


python3.9の状態でcondaにてOrthoFinderをインストールすると、実行時に以下のようなエラーが出力される。

```
ERROR: An error occurred, ***please review the error messages*** they may contain useful information about the problem.
```

どうやらOrthoFinderで用いるPythonのバージョンは最新版だと動かないようで、
Pythonのバージョン指定をして仮想環境を作ってインストールしてあげる。

```bash
$ conda create -n orthofinder python=3.7
$ conda activate orthofinder
$ conda install orthofinder
```

テストデータをダウンロードして実行してみる

```bash
$ git clone https://github.com/davidemms/OrthoFinder.git
$ cd OrthoFinder/
$ orthofinder -f tests/Input/ExampleDataset -t 8
```

無事に完了したっぽい

```bash
Reconciling gene trees and species tree
---------------------------------------
Outgroup: Mycoplasma_hyopneumoniae_AE017243
2023-01-15 15:29:16 : Starting Recon and orthologues
2023-01-15 15:29:16 : Starting OF Orthologues
2023-01-15 15:29:16 : Done 0 of 327
2023-01-15 15:29:16 : Done 100 of 327
2023-01-15 15:29:16 : Done 200 of 327
2023-01-15 15:29:17 : Done 300 of 327
2023-01-15 15:29:17 : Done OF Orthologues

Writing results files
=====================
2023-01-15 15:29:17 : Done orthologues
```

## 参考文献

[OrthoFinder](https://github.com/davidemms/OrthoFinder)

[OrthoFinder: phylogenetic orthology inference for comparative genomics](https://genomebiology.biomedcentral.com/articles/10.1186/s13059-019-1832-y)
AWS Certified SysOps Administrator - Associate(SOA-C02) 合格体験記

# はじめに
2022年11月にAWS Certified SysOps Administrator - Associate(SOA-C02)に合格しました。
SOA-C02から試験ラボが追加されたので、当試験は後回しにしていましたが、逃げてばかりではいけないと思い、勉強した次第です。
同様の試験を受ける方の参考になればと思い、記事を書きます。
結論からお伝えすると、TechStock(koiwaクラブ)の問題集をやるのがオススメです。

# SOA-C02について
AWSのアソシエイトレベルの試験の1つでAWS上の管理、運用に関する試験になります。
以下、公式の引用です。
>この資格は、組織がクラウドイニシアチブを実装するための重要なスキルを持つ人材を
特定して育成するのに役立ちます。AWS Certified SysOps Administrator – Associate の取得により
AWS 上でのワークロードのデプロイ、管理、運用に関する経験を証明できます。

冒頭でも記載しましたが、SOA-C02になってから「試験ラボ」というAWSコンソールかCLIで行うシナリオ試験が追加されましたので、業務経験がある方のほうが多少有利かと思います。
もちろん、業務経験がない方でも試験対策すれば合格できる試験だと思います。

# 勉強方法について
教材は参考書とwebサイトを利用しました。

## 参考書①「AWS認定資格試験テキスト AWS認定SysOpsアドミニストレーター - アソシエイト AWS認定資格試験テキスト」

https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9ASysOps%E3%82%A2%E3%83%89%E3%83%9F%E3%83%8B%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/481560908X

各サービスの詳細が十分に書かれているので、AWS経験が少ない人でも読みやすい本だと思います。
SOA-C02対応の本なので、試験ラボに関する傾向や対応策も記載されています。
1度読んだだけで全部覚えるのは大変なので、試験概要をつかむことを意識して読みました。
他にもいくつか参考書は出版されていますが、上記の本だけ読めば十分かと思います。
## webサイト①「Tech Stock」

https://techstock.jp/

他のAWS試験を目指した方であればお馴染みだと思いますが、Tech Stockの問題集をやるのがオススメです。
SOA-C02の問題集をやるには「有料会員」になる必要があります。
「#01」からやるのがベストですが、後半のほうがSOA-C02の試験に近い内容なので、
後半部分から実施してもよいと思います。
私は下記の流れで実施しました。
　①「#50」から最後まで解く。
　②間違えた問題を解く。
　③①～②をもう一度行う。
　④「AWS認定試験本試験モード」をやる。(5回程度)
「AWS認定試験本試験モード」で正解率が90％程度になってから試験を受けました。

## Webサイト②「AWS認定 模擬試験」

https://explore.skillbuilder.aws/learn

AWS認定 模擬試験が無料で受けられます。
昔は模擬試験が有料で解説がなく、あまり利用する機会がなかったですが、
こちらの様式になってから無料で問題解説付きになりました。
問題数が10問程度で少ないですが、1度は受けておくのをオススメします。

## その他「試験ラボのサンプル問題」
試験の予約をすると、試験ラボのサンプル問題の案内が届きます。
問題の正解、不正解はわかりますが、回答や解説がないのでそこまで優先して実施することもないと思います。
試験ラボが実際にどんな画面で行われるのか確認したい方は実施しておきましょう。

# 試験について
AWS試験はオンライン試験かテストセンターの受験が選択できます。
オンライン試験のほうが便利ではありますが、
試験当日にネット環境の影響で受験できなくなるのが怖かったのでテストセンターで受けました。
試験の予約は、ピアソンVUEで予約できます。

https://www.pearsonvue.co.jp/Clients/Amazon-Web-Services.aspx

いくつか条件はありますが、不合格だった場合、同じ試験の受験費が無料になるキャンペーンがありました。
同じようなキャンペーンがまた開催されるかもしれないので、公式情報は適宜確認してみましょう。

https://pages.awscloud.com/TrainCert-Japan-PearsonVUE-Retake-Terms-and-Conditions-2022.html?trk=7784a855-0788-4d8b-a019-b7f8734692fc&sc_channel=el

選択問題に60分ほど、試験ラボに60分ほど使いました。
選択問題はwebサイトの模擬問題集と似た問題があり、試験ラボは偶然にも業務で経験があった部分でした。
問題数が多く、試験ラボも時間がかかるので、対策していないと試験時間が足りなくなってしまうような気がします。
また、選択問題のあと試験ラボに進むと、選択問題に戻れなくなるので、注意してください。
試験ラボに進むときは、選択問題の見直しも行った上で進むようにしましょう。

# 結果
試験スコア753点でギリギリの合格でした！！800点後半くらいとれているような手応えでしたが危なかったです・・・
試験結果はテスト終了時にすぐ発表されません。
公式では「5営業日以内」となっていますが、受験して4時間後くらいには結果がわかりました。
当初、試験結果がすぐ表示されると思っていたので、試験結果が表示されず、不合格なのかと思いました・・・笑

# おわりに
最後まで読んでいただきありがとうございました。
試験対策を十分にすればAWSの業務経験がなくても対策すれば十分合格できると思いますが、
個人的には、AWS案件の業務経験が1年ほどあったおかげで試験勉強もスムーズに進められて合格できたような気がします。
同様の試験を受ける方の参考になれば幸いです。
VSCodeのちょっとしたTips



VSCodeのちょっとしたTips。
（設定方法をすぐに忘れてしまうので、備忘録として）

Reactのコードを書いていると、複数の要素をまとめて囲いたいことありますよね。
コンポーネントの要素が多くなってくるとネストが深くなってきて、閉じる場所を見失ったりすることありませんか？

VSCodeでは複数要素をまとめて囲うことができるキーバインド設定が可能です。
動作はこんな感じ。
![wrapComp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415206/69c7eddd-4e79-0019-5e70-8a1446725171.gif)

設定は簡単。VSCodeのキーボードショートカットで「Wrap with Abbreviation」のキーバインド設定をするだけです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415206/f567152a-1240-a893-138a-5d49dab83026.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/415206/34b44e48-ae3d-d507-d02d-5468d650fc05.png)

お好きなキーバインドを設定してください。（私は、Option + wにしてます。キー打つ時にCommand + wと間違えやすいのが玉に瑕）

地味に嬉しいTips情報でした。
Googleプロジェクト管理：WBS

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/7c79c997-e4e4-7d71-3686-e01b7badaa3c.png" width="800">

# WBS(Work Breakdown Structure）の定義

各マイルストーンに至るまでの多くのタスクを考慮する方法について説明します。これは、WBSを作成することで可能になります。

WBSは、***<font color="MediumVioletRed">『プロジェクトのマイルストーンとタスクを、完了すべき順に階層的に並べるツール』</font>*** です。

このツールは、プロジェクトという時に威圧的な課題を、より管理しやすい塊に分解するのに役立つからです。報告書の発行や会議の開催といった大きなプロジェクトも、そこに至るまでに必要な作業が段階的に分解され、プロジェクトの始まりから終わりまでの道筋が明確になれば、それほど大変なことではないように思われます。

# WBSを設計する方法

一般的な方法の1つは、プロジェクトのタスクをツリー図にすることです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/e10e8d7d-47c6-e515-afd5-e6f446b39b0a.jpeg" width="700">

# WBSの作成手順

1. プロジェクトの全体像を把握する。チーム内でブレーンストーミングを行い、主な成果物やマイルストーンをリストアップする。
1. これらのマイルストーンを達成するために、実行する必要のあるタスクを特定します。
1. これらのタスクを検討し、さらにサブタスクに分解する。

:::note info
今後、プロジェクト管理を行う際には、プロジェクト全体のタスクをまとめたWBSを作成する可能性があることを覚えておいてください。WBSの作成は、プロジェクトのタスクを視覚化するのに有効ですが、このような図を正式なプロジェクトプランに含めることは通常ありません。代わりに、スプレッドシートや作業管理ソフトウェアに、特定したタスクを入力し、各タスクのオーナーをより簡単に割り当てることができます。
:::


# タスクを割り当てる

WBSを完成させ、スプレッドシートでタスクを整理すると、いくつかのことが明確になります。

- 各マイルストーンの上位に位置する、個別のプロジェクトタスクのセットがあるはずです。あなたとチームメイトは、最初のマイルストーンとその後のマイルストーンに到達するために、何が必要かを正確に把握することができます。
- これらのタスクをプロジェクトチームのメンバーに割り当てることができる状態になります。各メンバーは、自分が担当するタスクとそれを完了するための順序を明確に理解しているはずです。

では、どのようにタスクを割り当てるのでしょうか？
- タスクは、通常、プロジェクトにおける各人の役割に応じて割り当てられます。
- 時には、同じ種類の役割を担うチームメイトが複数いるチームもあります。同じ役割を持つ複数のチームメンバー間でタスクを割り当てるには、各人が目の前のタスクに精通していることを考慮するとよいでしょう。

# タスクを割り当てるベストプラクティス

- 各タスクを ***<font color="MediumBlue">動詞で始める</font>*** とよいでしょう。
    - 例）ウェブサイトのモックアップを作る
    - 例）ウェブサイトに画像を追加する

- タスクを割り当てる際には、 ***<font color="MediumBlue">タイムライン</font>*** を設定します。誰がいつまでに何をするのかが明確になるように、各タスクには担当者と期限を追加してください。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/f3b7730d-113d-06f9-5b4f-d18e50c1a21d.png" width="700">

- ミスコミュニケーションを防ぐために、 ***<font color="MediumBlue">タスクの詳細</font>*** をできるだけ詳しく説明するようにしましょう。対応するファイルや添付ファイルにリンクすることできます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d42a7192-3256-a409-f1d3-ed926d6fc451.png" width="700">

# タスクを割り当てるメリット

- プロジェクトの管理に集中できるようになります。このように、チームメイトが特定の仕事を担当することで、安心感を得ることができます。
- チームメンバーに個人的な責任感を持たせることができます。チームメイトにタスクを割り当てるということは、その人がそのタスクを完了するまで自分のものとして扱うという契約を結ぶということです。チームメンバーにオーナーシップを持たせることは、プロジェクトに参加しているという実感を高めるために重要です。また、自分自身を成長させる場にもなります。

# サンプル

https://docs.google.com/spreadsheets/d/1EfGDZKDxeuEzhcfwNCZAFQck_87-FRCtRrcZVkWGltI/template/preview
VSCodeのChatGPTプラグインを日本語化する

VSCodeにChatGPTプラグイン入れると便利ですね。普段からGithub Copilot使ってるといろいろと補完してくれるけど、それとは違った便利さがあります。コードの説明してくれたり、バグを見つけてくれたり、最適化してくれたり、テストを書いてくれたりとダメプログラマー化が捗ります。プラグインの入れ方はこちらの記事が参考になります。

https://qiita.com/tak001/items/c3000b3ce9b6e72b2ae5

このままだと英語で出力されるので日本語化もしてしまいましょう。設定画面でPrompt（質問文）に日本語を設定してあげると出力も日本語に変わります。

![Settings - work (Workspace) - Visual Studio Code 2023-01-15 15.53.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33704/47131033-006a-b3db-488b-7cb5ad9a815b.png)

Prompt Prefix: Add Tests
```次のコードに対するテストを実装してください```

Prompt Prefix: Find Problems
```次のコードの問題点を見つけてください```

Prompt Prefix: Optimize
```次のコードを最適化してください```

Prompt Prefix: Explain
```次のコードを説明してください```

Prompt Prefix: Add Comments
```次のコードにコメントを追加してください```

捗りましょう！
Project: Set Up Your Salesforce Mobile Developer Tools for Lightning Web Components (step 3)

[Trailhead関係　個別の課題別](https://qiita.com/Keiji_otsubo/items/56eb7a90bb72138ece1f)


+ [Error on SFDX: Preview Component Locally](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Jfs7h)


```
[TITLE] FAILED: Checking SDK root location (0.000 sec)
[DATA] SfError: SDK root location not found. Please set up ANDROID_SDK_ROOT or ANDROID_HOME in your environment.
[TITLE] Requirements (0.000 sec)
[TITLE] FAILED: Checking Android Command Line Tools (0.000 sec)
[DATA] SfError: Android command line tools not found.
[TITLE] Requirements (0.000 sec)
[TITLE] FAILED: Checking SDK Platform Tools (0.000 sec)
[DATA] SfError: No supported Android platform tools found. Minimum supported Android platform tools version is 23.
```

:::note
I've finally found the resolve by myself. It consist:

- install jdk-17 (newest jdk-19 not suitable);
- set variables ANDROID_SDK_HOME and JAVA_HOME;
- install Android SDK Command-line tools in Android Studio;

It's strangely that nothing is said about this in this project.
:::

+ [コードの分析と組織へのリリース　(リリースができない)](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007F23KZ)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/74e41259-f348-4fa0-98e8-34697ddf30ca.png)


この機能が働いているのかもしれません。無効化してみてください。

SLDSをチェックしてくれる優れもの「SLDS Validator」
https://note.com/koji_matae/n/n27b5789f9edf

SLDS Validator for VS Code
https://www.lightningdesignsystem.com/tools/validator/


:::note alert
This command can only be used on orgs that have source tracking enabled, such as sandboxes and scratch orgs
:::

どの環境にプッシュしていますか？

sandboxの場合は本番環境のSource trackingを有効化して、同期する必要があるみたいです。DE環境にはできないようなことも言われています。

Source tracking must be enabled in the Prod org prior to spinning up any sandboxes. Additionally, source tracking does not work on Partial or Full sandboxes, only dev, devpro, and scratch orgs.

スクラッチ組織にはできるみたい。
https://salesforce.stackexchange.com/questions/356987/error-running-forcesourcepush-when-doing-cci-task-run-dx-push-to-a-develop

正しい環境にプッシュしたところ問題なくリリースでき
問題が解決いたしました。
【CSS】Youtube動画の埋め込みにpadding-topは使わない時代

「なんでYoutubeの埋め込みごときに、`padding-top` でダラダラと書かないといけないの？」と思ったことありませんか？

僕はずっと思ってました（ ;  ; ）

今回はそれを覆すプロパティを紹介します。

## 従来のYoutube動画の埋め込み方法（padding-top）

これまでは、iframeに親要素を作り、`padding-top: 56.25%;` or `padding-top: calc(100% * 16 / 9);` を指定することで、`iframe` を `position: absolute;` で絶対配置にしていました。

``` html
<div class="wrapper">
  <iframe src="動画URL" ></iframe>
</div>
```

``` css
.wrapper {
  position: relative;
  padding-top: 56.25%;
}

iframe {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}
```

## padding-topは使わず16:9でYoutube動画を埋め込む方法（aspect-ratio）

2021年頃あたり？から `aspect-ratio` を使うだけで、16:9のアスペクト比で固定されます。

``` css
iframe {
  aspect-ratio: 16/9;
  width: 100%;
  height: 100%;
}
```

そして気になるのが、対応ブラウザですよね。

## aspect-ratioの対応ブラウザ

`aspect-ratio` は現在、全モダンブラウザ（最新版）で使えます。

[Can I use - aspect-ratio](https://caniuse.com/mdn-css_properties_aspect-ratio)

![スクリーンショット 2023-01-16 8.53.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2949803/a53d9841-d0d2-6d01-5a5a-4992b2705321.png)

これが新時代ですね💡
アセンブリ　Intel記法　まとめ

■レジスタ
・関数で使用する場合、、
EAX・・・関数の戻り値
EBX・・・第一引数
ECX・・・第二引数
EDX・・・第三引数

■代入
・eaxに0x1を代入
mov eax, 0x1

■stackに対し…
・valueを追加
push value

・トップ(先頭)の値をvalueに移動
pop value

■四則演算（a○b）
add a, b
sub a, b


■条件分岐
・if ○
if FLG
　〜
end


・if not ○
if not FLG
　〜
end

■ジャンプ
※ジャンプ後、そのまま一行ずつ実行される
→処理終了時には、末尾のexit:に飛ばす


…更新中…
Administer Nonprofit Success Pack (NPSP) を完了できません


# The flow component on the opportunity page doesn’t appear to be configured properly. Check your settings against the instructions and click Verify again.

+ [unable to complete Administer Nonprofit Success Pack (NPSP)](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfpFE)

**私の回答**

:::note
just finished this NPSP project and worked for me in the end, had similar errors, here are some points:
- installing NPSP from the link was a challenge (4th time worked), must be in a new hands-on org, an org I do only NPSP projects.
- Donations in NPSP are Opportunities, so New Donation = New Opportunity, then you will have to select the record type  Donation  then Next
- why wasn't working for me at the biginning : when you Debug the flow add your Donation or Opp ID, the 18 numbers one to avoid the fail. Check the filters again, very easy to get one or 2 wrong, 

https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Bt5yaSAB
:::

この NPSP プロジェクトを終了し、最終的に私のために働きましたが、同様のエラーがありました。ここにいくつかのポイントがあります

- リンクから NPSP をインストールするのは難題でした (4 回目の作業)。新しいハンズオン組織、つまり私が NPSP プロジェクトのみを行っている組織にいる必要があります。
- NPSP の寄付は商談であるため、新しい寄付 = 新しい商談です。次に、レコード タイプの寄付を選択してから次へを選択する必要があります。
- 最初にうまくいかなかった理由: フローをデバッグするときに、寄付または Opp ID (失敗を避けるための 18 の数字) を追加します。フィルターをもう一度確認してください。1 つまたは 2 つの間違いを犯すのは非常に簡単です。



**ほかの回答**

:::note
I think I may have figured it out.  In Setup navigate to the Object Manager then to the Opportunity Object.  Click on Lightning Record Pages.  I updated the 2nd "NPSP Opportunity Record Page" listed and I passed the challenge.

If that one doesn't work, try the first "NPSP Opportunity Record Page" (there are 2).
:::

たぶんわかったと思います。 [設定] で、オブジェクト マネージャに移動してから、商談オブジェクトに移動します。 [Lightning レコード ページ] をクリックします。記載されている 2 番目の「NPSP 案件記録ページ」を更新し、チャレンジに合格しました。

それが機能しない場合は、最初の「NPSP 商談レコード ページ」を試してください (2 つあります)。
MySQLでPIDファイルエラーが出た時の対処法(ERROR! The server quit without updating PID file)

# エラーは突然に

TypeORMを使って migrationファイルを作ろうと思い、```mysql.server start```でサーバーを起動すると…

```
ERROR! The server quit without updating PID file
```

突如現れたPIDのエラー。とりあえずネットで調べた対処法を実践しました。

## そもそもPIDファイルがあるのかどうか

```/usr/local/var/mysql```にファイルがない場合は作りましょうと書いてあったので、確認するとPIDファイルは存在していた。。

## PIDファイルに適切な権限が付与されていない

mysqlに権限がないとエラーになると記事で見たので、

```
sudo chown -R _mysql:_mysql /usr/local/var/mysql/
```

ファイルの所有者を全て_mysqlにするように変更。

結果は変わらず…

## MySQLの環境をリセット

結局、解決したのはこの方法でした。

※すでにデータが格納済みの場合は、バックアップをとってから実施してください

まずはmysqlを削除します。

```
brew remove mysql
brew cleanup
```

mysql関連のファイルが残っている場合は、合わせて削除します。

```
sudo rm -rf /usr/local/Cellar/mysql*
sudo rm -rf /usr/local/bin/mysql*
sudo rm -rf /usr/local/var/mysql*
sudo rm -rf /usr/local/etc/my.cnf
sudo rm -rf /usr/local/share/mysql*
sudo rm -rf /usr/local/opt/mysql*
sudo rm -rf /etc/my.cnf
```

そして、再度mysqlをインストールします。

```
brew install mysql@8.0
```

8.0の部分は、5.7でも大丈夫です。使いたい環境をインストールしてください。

これで```mysql.server start```を実行すると無事にサーバーが立ち上がりました。

本当によくわからないエラーでしたね🥺

## 参考記事

エラー解決でお世話になった記事です。先人には感謝です。

https://usimaru.net/tips-mysqlpiderror/

https://qiita.com/jonakp/items/477a18d4a94c01a31583
複数入力のPytorchモデルをCoreMLモデルに変換する

# 複数入力のモデルを扱う
機械学習モデルには複数の入力を必要とするモデルがある。
そのようなモデルのCoreMLへの変換はどうすればいいか。

![スクリーンショット 2023-01-10 18.10.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/1025386c-aa4a-8fac-d7b0-37483b50d14e.png)

# 方法
xとyという二つの入力を持つモデルを変換するとする。

```python
import torch
import coremltools as ct

traced_model = torch.jit.trace(model, (x,y)) # convert to torchscript
mlmodel = ct.convert(traced_model, inputs=[ct.TensorType(shape=x.shape),ct.TensorType(shape=y.shape)]) # convert to coreml 
```

# Swiftでの使用
変換したモデルをSwiftで実行する。

```swift
do {
    let model = try myModel().model
    let input = myModelInput(x: x, y: y) // x and y are MLMultiArray in this case.
    let out = try model.prediction(from: input)
} catch let error {
    print(error)
}
```

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

機械学習、ARアプリ（Web/iOS）を作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
paiza.ioでelixir その171

# 概要
paiza.ioでelixirやってみた。
「Elixir Zen スタイルって何？」
多分、再帰によるフロー制御を無くす事。

# 参考にしたページ

https://qiita.com/zacky1972/items/619f39cc77fbb52b1bbf

# サンプルコード

```

defmodule FizzBuzz0 do
    def say(nil) do
    end
	def say([]) do
		0
	end
	def say([head | tail]) do
		cond do
		rem(head, 15) == 0 ->
			IO.puts "FizzBuzz"
		rem(head, 3) == 0 ->
			IO.puts "Fizz"
		rem(head, 5) == 0 ->
			IO.puts "Buzz"
		:else ->
			IO.puts head
		end
		say(tail)
	end
end

1..100
|> Enum.take(100)
|> FizzBuzz0.say 


defmodule FizzBuzz1 do
	def say(n) do
		cond do
		rem(n, 15) == 0 ->
			IO.puts "FizzBuzz"
		rem(n, 3) == 0 ->
			IO.puts "Fizz"
		rem(n, 5) == 0 ->
			IO.puts "Buzz"
		:else ->
			IO.puts n
		end
	end
end

1..100
|> Enum.map(fn x ->
    x
    |> FizzBuzz1.say
end)



```

# 実行結果

```
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
31
32
Fizz
34
Buzz
Fizz
37
38
Fizz
Buzz
41
Fizz
43
44
FizzBuzz
46
47
Fizz
49
Buzz
Fizz
52
53
Fizz
Buzz
56
Fizz
58
59
FizzBuzz
61
62
Fizz
64
Buzz
Fizz
67
68
Fizz
Buzz
71
Fizz
73
74
FizzBuzz
76
77
Fizz
79
Buzz
Fizz
82
83
Fizz
Buzz
86
Fizz
88
89
FizzBuzz
91
92
Fizz
94
Buzz
Fizz
97
98
Fizz
Buzz
```

# 成果物

https://paiza.io/projects/lTFz14ZSdYKTCGzAQL10cQ?language=elixir


以上。
ホームページのアクセスレベルの障害？


+ [lacking level of access](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000NQcPgSAL)

whenever i open 'home' field in any record its showing me this thing, but when i switch to salesforce classic, it works. Please help me to fix this issue, its causing trouble
任意のレコードで「ホーム」フィールドを開くたびにこのことが表示されますが、Salesforce Classic に切り替えると機能します。この問題を解決するのを手伝ってください。問題を引き起こしています

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/6544dcee-2593-a9b2-cd28-0a62ac240fa7.png)


:::note
Check out 'Home' in Setup:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/70f3f392-22aa-9a65-30ba-34140f5a07f9.png)
:::
未経験からエンジニアになる：ポートについて知ろう！

未経験からエンジニアになりたい人は、プログラミングから始める人が多いと思いますが、
エンジニアの仕事は、プログラミングだけではありません。そして、プログラミングだけでは、エンジニアになれません。同時にプログラミングが苦手でも、システム構成や開発の流れを理解するとエンジニアに近づきます！
今回はポートについて調べてみましょう！

![インスタスライド_202301017.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/d2c5197c-6981-120b-1ca3-cb3821044444.gif)

# ポートとは
サーバにはIPアドレスがあってIPアドレスで通信します
更にポートにより並列通信が出来る様な仕組みになってます
電話のダイヤルインの様な仕組みです

# どういう事？
http://google.co.jp/
は、Port80に接続します。

https://google.co.jp/
は、Port443に接続します。

# ポートを指定してみる
http://google.co.jp:80/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/ed389acc-01dd-249a-5c59-77d9a55c3b23.png)

https://google.co.jp:443/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/1755879f-533e-2601-51b2-72f5cd20efbc.png)

# ポートは決められている
httpは、80ポートを使います。
httpsは、443ポートを使います。

とルールが決められているため、
ポートを指定しなくても自動的に判断されています
逆にポートを指定する事もできます

# httpは、443ポートNG
httpは、443ポートでアクセスするとエラーになります。
http://google.co.jp:443/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/876841e5-6418-a347-5f19-d86dce4b4cb1.png)

# httpとhttps
httpは暗号なしでのWeb通信に使われます
httpsは暗号ありのWeb通信に使われます

最近は全てをhttpsで通信する事が一般的です
ポートは利用ルールが決められています

# ポートは決められている
ポート一覧
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/f1dcad5c-8f7d-956f-84d9-60d1560e3bfc.png)

# 何が言いたいの？
ローカルでプログラミングする時に80ポートや443ポートでなく、

8080ポートや8000ポート等を使う事があります。

# Reactはポート3000
Reactでは、3000ポートが利用されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23130/cbce1cc6-fe6f-6c9f-0c80-e16b68661cbf.png)

# まとめ
・IPアドレスにセットでポート番号というのがある
・ポートは、80,443が使われている
・http:ポート80は、暗号なしのweb
・https:ポート443は、暗号ありのweb
・reactは、3000ポートを使う

# 最後に
未経験の皆さん、若手エンジニアの皆さん、勉強方法について悩みがあればなんでも気軽に質問して下さい！
これからも記事を書いていきますので、モチベーションアップのためフォロー、イイねお願いします。
機械学習を使った鉄鋼材料の金属組織画像の判定

# はじめに
金属組織は、金属の断面を平らに鏡面研磨してから、研磨面を薄い酸などの腐食液に適当な時間浸してわずかに溶かした後、水洗・乾燥して顕微鏡で観察すると見られます。金属組織は材料の強度や耐食性に関係し、熱履歴によって変化することが知られています。特に、熱処理を行う鉄鋼材料においては、同じ鋼種でも様々な金属組織が見られます。このことを利用して、鉄鋼材料で作られた部品が破損したときに金属組織を観察して、熱処理を含めた素材の良否を判定することがあります。しかし、金属組織の判定には経験が必要です。今回は、経験を補う方法として、機械学習アプリTeachableMachineを使って金属組織を判定してみます。

# やり方
前回の[機械学習を使った破断面の画像分類](https://qiita.com/_Moony/items/01ce3d095d95696c399c)と同様です。

学習に用いたデータは
Austenite（オーステナイト）
Ferrite（フェライト）
Ferrite_Perlite（フェライト＋パーライト）
Martensite（マルテンサイト）
Perlite（パーライト）
各30枚です。

<img width="400" alt="Fig.1.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/e1bb3bd5-a2b9-dabb-bb12-3f76dd477667.jpeg">

図1　学習に用いたデータ

# Teachable Machineによる学習

上記画像ファイルをTeachable Machineに読み込み、学習を行います。わずかな時間で学習が終了します。

<img width="600" alt="Fig.2.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/4fe3064c-a9f2-d733-8f25-0d9c23ce02ce.jpeg">

図2　Teachable Machineによる学習

# 作成したモデル

作成したモデルのURLは次のとおりです。

https://teachablemachine.withgoogle.com/models/vzH42r67b/

また、このモデルをダウンロードして、サンプルプログラムやサンプル画像と一緒に以下に格納しております。

https://github.com/repositoryfiles/Metallography

サンプルプログラムの実行については、以下の記事を参考にしてください。

https://qiita.com/_Moony/items/bbf06b4ccb12f4e2dc99


# サンプルプログラムの動作環境

- Windows11
- VSC 1.7.3.1
- Python 3.8.10
- numpy 1.20.0
- keras 2.11.0
- pillow 9.3.0

★使用結果について当方は責任は負いません。

# 終わりに
実務ではさらに細かい判定が必要になると思います。そういった場合は、それに応じた組織画像を用意してモデルを作成することになります。その場合、例えば以下のサイトが参考になると思います。

- 斎藤, ウェブ上での鋼の結晶粒度の評価, 新潟県工業技術総合研究所サイト, http://www.iri.pref.niigata.jp/topics/R3/3kin8.html
- 斎藤, ディープラーニングによるステンレス鋼の鋭敏化組織の認識, 新潟県工業技術総合研究所サイト, 
http://www.iri.pref.niigata.jp/topics/R2/2kin5.html
Power Automate で Dataverse の日付型の列でフィルターする

# はじめに

今回は、Power Automate で Dataverse の以下のような日付型の列でフィルターするアプローチについて、少し癖があるので、自分自身の備忘も兼ねて説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/36f53024-8da4-3e3a-9963-a322784c4ce0.png)

利用シナリオとしては、例えば、日付列をベースに、一定の期間のレコードを削除したり退避する、以下のように、チャットボット (Power Virtual Agents) を通じて、勤務状況をシェアするアプリにデータを登録 ( **該当日付に既にデータがあるかフィルターをし、データがある場合は既存のデータを変更する**) するようなものがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/697a8666-1d7e-94d3-6740-e2f3c8b8e8af.png)

# 実装アプローチ

まず、失敗例からお伝えします。以下のような感じで、Dataverse のデータをフィルターしようとしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/e5e8da2f-40eb-b0c6-d635-572665b96e0b.png)
実行すると、以下のようなエラーで型が異なる旨のエラーが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/5d233faa-dd29-9fcc-d30b-f7d274b89307.png)
最終的には、以下のようにすることで動作しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/10d0beab-12cb-5a94-1e7d-eaa864908f60.png)
肝となるのは以下の部分です。formatDateTime で、変換すること、また、その際、ISO 8601 形式にする必要があることです。
```
formatDateTime(body('時間への追加'),'yyyy-MM-dd')
```
実行してみると、エラーがなく、該当するレコードが取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/241be75a-b36c-158f-b5a2-839c25826ae2.png)
Power Automate で Dataverse の "行を一覧にする" アクションの結果が null かどうか判定する

# はじめに

例えば、外部のシステム等から入力した情報をもとに、データソースから該当するレコードがあるかフィルターをして、存在しない場合は別のアクションを実行したいようなケースがあります。

今回は、Dataverse の "行を一覧にする" アクションをベースに実装アプローチについて紹介します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/1b6bf569-afdd-d8bf-5aac-a96e13972911.png)

# 実装アプローチ

以下のように、Dataverse の "行を一覧にする" の結果をベースに、該当するレコードがない場合は新しい行を追加、存在する場合はそのレコードを更新するようなフローを作成してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/8873ffdc-e6d4-740d-57c5-768ea183bb1d.png)

条件式のポイントについて説明します。
左側は、以下のような感じで、empty 関数で "行を一覧にするアクション" の結果の value を囲みます。

```
empty(outputs('行を一覧にする')?['body']?['value'])
```
右側は、数式で true を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/2bdcd67f-68c5-f6dc-54c3-bf0b6ff648ae.png)

試しに実行してみます。データがない場合、新しい行を追加しているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/c1aec8a0-79df-ace2-9254-11818cff51e8.png)
もう一度同じ内容で実行した場合 (データがある場合)、データを更新しているようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074511/71a7924b-c8b3-14df-ba7a-70d33f9551bc.png)
Keil StudioにSSD1306ライブラリのインストール方法(LPC812)



参考


https://qiita.com/caa45040/items/4e18961edb3d3500b87d




目的
ライブラリのインストール方法
SSD1306の例



![o_cop360.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3a04544b-6d7f-c042-cc08-8dc3ada1f42d.jpeg)




アクティブプロジェクトを作る


![o_cop348.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/09fcd946-a601-2f1d-a60b-d24dea0e6d8c.jpeg)

![o_cop349.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/be7d6fe3-f65e-df52-9a99-5af492295026.jpeg)

oled_itemH_8x8_812_1

![o_cop350.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c3f70c88-0c7c-67ad-0bf2-2063ac6ee496.jpeg)


![o_cop351.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/13ca1769-d818-5621-54c9-bb1c53aba6d5.jpeg)


ライブラリーのインストール


![o_cop352.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c03e92fa-db54-7331-cc2b-ae4b0bca5909.jpeg)

```

https://os.mbed.com/users/caa45040/code/SMALL_SSD1308_128x64_I2C

```

![o_cop353.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3bc555a9-f8fc-6f2f-07c6-b9ab8796e046.jpeg)


![o_cop354.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/ec70daf1-04bf-70ce-91ad-6822bf42eacc.jpeg)


![o_cop355.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/4382c7c7-5806-1c17-5843-01e276e859aa.jpeg)


![o_cop356.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b88c3546-1d55-f0d7-b572-83fa69261d76.jpeg)


![o_cop357.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/3d67e714-e676-29a1-42d4-ae73950b19a8.jpeg)


![o_cop358.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/54bab00c-f3ff-467a-e996-5c046016818f.jpeg)


![o_cop359.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/914e4405-f0ff-db99-edaa-ec46ef093382.jpeg)



```c++



//oled_itemH_8x8_812_1

//インクルド
#include "mbed.h"
#include "SSD1308.h"

//i2c initialization
//       SDA    SCL
I2C i2c(P0_10, P0_11); //812

// ビットマップデータ
char databytes1[8] = 

{
  0b00001110,
  0b00111001,
  0b01110111,
  0b11111100,

  0b11111110,
  0b01111111,
  0b00111111,
  0b00011110

};

//メイン関数
int main() {

  wait_ms(500); // 0.5秒の待ち

  // Instantiate OLED
  SSD1308 oled = SSD1308(&i2c, SSD1308_SA0);

  int o_row = 0; //ローの定義
  int o_col = 0; //カラムの定義

  //8x8アイテムの表示
  oled.writeBitmap((uint8_t *)databytes1,
                    o_row, (o_row + 1 - 1),
                    o_col, (o_col + 8 - 1));

  //無限ループ
  while (1) {}

} // main





```
手のポーズで操作するコントローラを作ってみた

# はじめに
手のポーズを使って人が簡単にゲーム（gym環境）を操作できるコントローラを作成しました。保存したプレイデータは以下の**模倣学習**や**逆強化学習**に使用することができます。

![supervised_perspective.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/9aa01198-e0c4-8aec-3711-7fc67de1e51f.png)


# 完成したもの
本コントローラを使うと、手のポーズを使って複数の連続値をリアルタイムで入力することができます。
左が強化学習の環境、真ん中が認識結果、右が3次元座標上にプロットした手です。
![lunar.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/d492e155-ae08-d6a0-9893-25afe37a7892.gif)
![robogym.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/697063e9-417e-2b88-1028-6d5804c39723.gif)

Githubにコードを公開しています。

https://github.com/NM512/HandyController

# 人とマシンのインターフェイス
人とマシンのインターフェイスには、連続値と離散値を扱うものがあります。例えばプレイステーションのコントローラでは、連続値の入力にはジョイスティックを、離散値の入力にはボタンを使用しています。車のアクセルやハンドルは連続値の入力です。連続値の場合は入力で微妙な強弱を表現できますが、離散値の場合は0か1だけ、ONかOFFだけの情報になります。

そして、例えば以下のようなDeepmind Control Suiteと呼ばれる環境の操作には多くの連続値の入力が必要となります。そこで、簡単に複数の連続値入力を扱えるように手のポーズを利用します。このコントローラでは、USBカメラで撮影した手のポーズ（各関節の角度）とキーボードを入力として使えます。
![image6.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/ba393035-57c9-0ea6-f1f8-5033d574f22a.gif)



# 構成
手のポーズ認識とキーボードで押されたボタンの認識はそれぞれ別プロセスで処理するようにしてリアルタイム性を担向上させています。マルチプロセス処理には、[multiprocessing](https://docs.python.org/ja/3/library/multiprocessing.html)を、プロセス間通信にはmultiprocessingで提供されている共有メモリ([Array](https://docs.python.org/ja/3/library/multiprocessing.html#multiprocessing.Array))を使用しました。
また、それぞれの認識結果は[openai gym](https://github.com/openai/gym)のWrapper内で、環境に適応させるようにしてコードを再利用しやすいように実装しています。現状はgymのインターフェイスしか用意していませんが、他の環境も需要があれば追加するので、その場合はGithubレポジトリのIssueにコメントをお願いします。


![system.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/2665dee6-03fc-6b2e-48cc-e2a20c9ce2dd.png)


#### 関節角度の計測
ハンドの認識にはgoogleで開発された[mediapipe](https://google.github.io/mediapipe/)を使用しています。
以下のシステム図に書かれているように、手を検出するモデルは毎回実行されているのではなく、最初の1回と手を見失った時だけ実行されるようになっています。そして、それ以外のときには後続で検出される手のランドマーク（関節部）から手の位置を推定して、画像をクロップします。手を見失ったという判定は、ランドマークを検出するネットワークから出力される信頼度に基づいて行われます。このように処理が重い手を検出する部分の実行回数を減らすことで、高速に動作するアルゴリズムを実現しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/08514078-cfc8-ee97-b1b7-8b9745f68270.png)



#### キーボードで押されたキーの認識
スイッチのONとOFFだけの操作など、連続値の入力だけでは扱いにくい環境もあるため、キーボードの入力も扱えるようにしました。[pynput](https://github.com/moses-palmer/pynput)を使うことで、非同期処理でキーボード入力を受け取ることができます。これにより、キーボードが押された瞬間と離された瞬間を見張っておき、共有メモリの値を書き換えるという処理を行いました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/624261/a530ce29-74f0-3f72-9989-4df5a144179d.png)


# 最後に
最後まで読んでいただいてありがとうございました。
コードを公開しているので、興味のある方はぜひ自身の環境で試してみて下さい。

# 参考
[敵対的模倣学習の紹介](https://qiita.com/3110atsu1217/items/c44130d59a0406b148c3)
[ML-Agentsで模倣学習（GAIL）を取り入れた強化学習を行う](https://qiita.com/Rauziii/items/5f86bedbe51226dcb636)
[論文紹介：ドメイン適応模倣学習（前編）](https://qiita.com/hashimo1010/items/564c97b6160866657550)
[Swift UI]Menuに余白ができてしまう時の対処法

結論から伝えるとlabelのところにPaddingを追加すればokです

    @State var selected = -1
    var menu_item = ["item1","item2","item3",]

        Menu {
            ForEach(Array(menu_item.enumerated()), id: \.element) { imdex, item in

                Button {
                    selected = imdex
                } label: {
                    Text(item.description)
                }

            }
        } label: {
            HStack {

                if(selected == -1){
                    Text("選択してください")
                        .padding(.leading, 10)


                }else{
                    
                    Text(menu_item[selected])
                        .padding(.leading, 10)
                }

                Spacer()
                Text("▼")
            }
            .frame(width: 200,height: 30)
            .padding(10) //←コレ
        }
        .menuOrder(.fixed)
        .frame(width: 200,height: 30)

どうしても余白が出てしまいこれどうにかならんかねって丸一日やってたんですが出来ず次の日にやってみたらパッと出来たので忘備録も兼ねて共有です
[Swift Ui]iPadでNumberのみのtextFieldの実装


結論から伝えるとこちら

    @State var editNum = "0"

    TextField("", text: Binding(
        get: {editNum},
        set: {editNum = $0.filter{"0123456789".contains($0)}}))
    .keyboardType(.numberPad)


## iPad以外の場合は下記コードでいけるはず

    @State var editNum = 0 //←もしかしたらここはStringにしないとダメかも

    TextField("Input Number", value: $editNum, format: .number)
        .keyboardType(.numberPad)

numberだけのtextFieldが必要で（iPad以外の場合は下記コードでいけるはず）のコードを試したところ普通にnumber以外のtextが入力できてしまい別の方法ないかググったら結論で伝えたやり方が出てました

忘備録がメインではありますが、誰かの参考になれば幸いです。
2023/1/16主にITとかセキュリティの記事

ITmedia Mobile人気記事より：スマホの「セキュリティ」はバッチリですか……？(1/14)
https://news.yahoo.co.jp/articles/2b94bb458730caff4f2c1d1243bb32f18ca7b50a?source=rss

PC画面に「トロイの木馬に感染」　電話すると片言の日本語で…60代男性が18万円被害(1/14)
https://news.yahoo.co.jp/articles/19ef6493ff4fe86c720f8eda4696759c574f5641?source=rss

スマホ利用者、2割弱がキャッシュレス決済でトラブルに遭遇。MMD研究所調査(1/14)
https://iphone-mania.jp/news-517035/

米検察当局、FTXから不正流出した暗号資産の捜査を開始(1/12)
https://zuuonline.com/archives/243810

セキュリティーに配慮したデータ共有方法、内容や相手によって使い分けを(1/13)
https://active.nikkeibp.co.jp/atcl/act/19/00429/121400002/

米国内線運航は12日に正常化、ＦＡＡのシステム障害で一時大混乱(1/13)
https://jp.reuters.com/article/usa-airlines-faa-idJPL4N33X3QC

第31回 2023年度サイバーリスク対応方針 役員会におけるCISO発言(1/14)
https://www.risktaisaku.com/articles/-/75919

メディアリテラシーとは？意味から身につける方法まで解説(1/13)
https://www.seraku.co.jp/tectec-note/industry/media-literacy/

何故、率直な発言が出来ないのか？【心理的安全性シリーズ 1/3】(1/14)
https://qiita.com/kimuni-i/items/7047c79714ac97ce0ed2
画像をクリックしたら複数画像が新たな要素に複製（コピー）される仕組み

 本稿では、複数のグループからなる画像一覧のうち、１つの画像をクリックすると同じグループに属しているすべての画像が新たな要素に複製される仕組みを作成する。見たほうが分かりやすいのでこちらの[サンプル](https://shineyamamoto.github.io/multipleImageModal/)を参照してください。
　これは画像に限らずどの要素でも通用するので、意外と汎用性はあるかもしれない...

## コード
HTMLおよびCSS
```html:index.html
<section>
    <div class="box">
      <img class="box_img" src="./img/腹痛.png">
      <img class="box_img" src="./img/不安.png">
    </div>
    <div class="box">
      <img class="box_img" src="./img/授業.png">
      <img class="box_img" src="./img/廃棄.png">
    </div>

    <div id="copy_box" class="box"></div>
 </section>
```

```CSS:style.css
section {
    display: block;
    position: relative;
    width: 90%;
    margin: 20px auto;
    
}

.box {
    position: relative;
    display: flex;
    margin: 20px 0;
    background: #e3e3e3;
}

.box .box_img {
    height: 150px;
    padding: 40px 20px;
    margin: 0 auto;
}

section #copy_box {
    background: #ecbadd;
}
```
例えば腹痛.pngの画像をクリックしたら場合、兄弟関係にある要素（今回は不安.png）もすべて複製したい。そのための方法をDOMを使って作成する。なお、複製先は、
```HTML
<div id="copy_box" class="box"></div>
```
にする。次の節でjavascriptのコードを解説する。

## javascript
先に作成したコードを記載しておく。
```javascript:script.js
var boxImg = document.getElementsByClassName("box_img");

for (var i = 0; i < boxImg.length; i++) {
    boxImg[i].addEventListener("click", function() {

        const copyBox = document.getElementById("copy_box"); //コピー先の要素をあらかじめ変数にしておく
        
        // もしすでにコピー要素があればそれを消去する。
        if ( copyBox.childNodes.length !== 0 ) {
            copyBox.innerHTML = "";
            return true;
        }
        
        const parent = this.parentNode;
        const children = parent.children;

        for ( var i = 0, len = children.length; i < len; i++ ) {
            copyBox.appendChild(children[i].cloneNode(true));
        }
    })
}
```

1行目の
```javascript
var boxImg = document.getElementsByClassName("box_img");
```
は、クリックの対象になるすべての画像の要素を変数に変換している。
次の行のfor文
```javascript
for (var i = 0; i < boxImg.length; i++) {
...
```
すべてのbox_img要素に対してクリックされたら処理をしたいので、DOMを複製している。
```javascript
boxImg[i].addEventListener("click", function() {
...
```
特定のbox_img要素がクリックされた際にどのような処理をするかを関数にまとめている。
```javascript
const parent = this.parentNode;
const children = parent.children;
```
この2行が今回の本題で、1行目によってクリックした要素の親要素を一度取得し、2行目でその子要素をすべて変数にまとめる処理をしている。.parentは親要素を取得するメソッドで、.childrenは子要素をすべて取得するメソッドです。（もしかしたらいきなり兄弟要素を全て取得できるメソッドがあるかもしれないので用勉強...。）
あとは次の行のfor文でコピー先の要素に突っ込んでいくだけ。
```javascript
copyBox.appendChild(children[i].cloneNode(true));
```
に使われている.cloneNode()は要素を複製するためのもので、これを使わないと複製ではなくカット&ペーストになってしまうので注意。.cloneNode()の変数をtrueにするとノードの子も複製され、falseの場合は指定したノードのみが複製されます。

## 最後に
この技術自体はあまり役に立たない気がするけど、画像をクリックしたらその画像に関連する画像も一気にモーダルに表示されるような機能は割と汎用性が高いと思う。
Svelte 子→親 ボタンで値渡し

### 親
1. 子コンポーネントに on:xxxx でイベント定義
```javascript:oya
<script>
	import NumberButton from './NumberButton.svelte'

    function show(e) {
		alert(e.detail.num)
    }

</script>
<main>
	<NumberButton number="1" on:show={ show }></NumberButton>
</main>
```


### 子
1. createEventDispatcher をインポートする
1. _dispatch()で親側で定義したon:xxxのイベント名とオブジェクトを渡す
```javascript:ko
<script>
	import { createEventDispatcher } from 'svelte'

	const _dispatch = createEventDispatcher()
    function click() {
        _dispatch('show',{num:number})
    }

	export let number;
</script>

<button on:click={ click }>{number}</button>
```