OmniAICreator/Qiita-1.07M huggingface dataset:
引数のデフォルト値について(Ruby)

　　

１、メソッド定義のところで、引数にデフォルト値を指定できる。引数の呼び出しで、引数を省略した場合、デフォルト値が適用される。


```
def introduce(name = "山田") # 山田がデフォルト値
    puts "私は#{name}です。"
end

introduce("島田")
introduce()
```
出力結果
```
私は島田です。
私は山田です。
```
２、引数呼び出して、末尾がハッシュの場合、波カッコ{&emsp;}を省略可能。

```
def introduce(name = "山田", msg)
    puts "私は#{name}です。"
    puts "#{msg[:target]}、#{msg[:greeting]}。"
end
introduce("島田", {target: "世界の皆さん", greeting: "こんにちは"})

# {  }を省略している
introduce("島田", target: "世界の皆さん", greeting: "こんにちは")

# デフォルトの値("山田")で出力するのでnameの引数を省略
introduce(target: "世界の皆さん", greeting: "こんにちは")
```

出力結果
```
私は島田です。
世界の皆さん、こんにちは。
私は島田です。
世界の皆さん、こんにちは。
私は山田です。
世界の皆さん、こんにちは。
```
HTTP Status CodeごとにIT資産の状態を点検する方法

# １．HTTP Status Code
HTTP Status code（ HTTP ステータスコード ）とは HTTP リクエストの成否をサーバーから教えるコードであります。ステータスコードは大きく5クラスに分けられます。各詳細コードでクライアントのリクエストに対するサーバーからのレスポンスの意味を表します。

* 1xx（情報）：リクエストは受け取られ、処理は継続される。
* 2xx（成功）：リクエストは受け取られ、理解され、受理された。
* 3xx（リダイレクション）：リクエストを完了させるために、追加的な処理が必要。
* 4xx（クライアントエラー）：クライアントからのリクエストに誤りがあり、リクエストを処理できない。
* 5xx（サーバーエラー）：サーバがリクエストの処理に失敗した。

もし、あなたがある組織の全サーバーを管理する担当者で、上司から膨大なウェブページのどの部分にどんな状態であるかチェックして、と支持を受けた場合、早めで簡単にチェックする方法はないでしょうか。

# ２．OSINT検索を用いてHTTP Status Codeごとのページを検知
Security OSINTの一種であるCriminal IPの「IT資産検索」機能（https://www.criminalip.io/ja/asset) を使うと、特定コードをリターンしているページを検索できます。一番よく見られる「404 Not foundコード」を検索した結果、なんと5千9百万件以上のページが見つかることを確認できます。
* filter: "status_code:404"
https://www.criminalip.io/ja/asset/search?query=status_code%3A+404
![http_status_code1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/e36d6d2d-7441-78b1-8976-c86c5a196d2b.png)

ここで、キーワードとしてドメイン・アドレスを追加したり、as_nameフィルターを追加して特定のサイトのエラーページで範囲を絞って検索することもできます。
* filter: "Google.com, status_code:404"
https://www.criminalip.io/ja/asset/search?query=Google.com,%20status_code:404
![http_status_code2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/cda9c652-346c-70ce-0a56-b29dc6ef4a25.png)

# ３．status_codeフィルターを活用したセキュリティ脆弱性の検知
403 Forbidden（閲覧禁止）コードは、クライアントの認証情報にかかわらず特定のページへのアクセスが拒否されたことを示すコードであり、すなわち、該当サーバーに重要な情報が含まれていることを間接的に表す印になります。
* filter: "as_name:salesforce.com, Inc. status_code:403"
https://www.criminalip.io/ja/asset/search?query=as_name:%20salesforce.com,%20inc.%20status_code:403
![http_status_code3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/7a343a03-6080-210d-bdc1-54dc7924f5dc.png)
このようなStatus Codeはそのままでセキュリティ脆弱性になりうるため、最近は詳細なエラー情報を表す代わりに統合されたエラーページを見せる形でセキュリティ政策が適用されています。
![http_status_code4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/bab4fc5c-8e3b-d39a-3804-a6828a0b6131.png)
その他にも500番台のコードはサーバーがリクエストを処理できない際に現れるもので、エラーの原因が公開される場合はセキュリティ事故が発生する可能性があります。
![http_status_code5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/31858de0-eeef-ba71-7d22-8f3d6ec48117.png)

上の500コードをリターンするページはエラーの原因と共にどんな言語とサーバーが使われているかも公開されています。ここから公開された 情報で既に知られているそのサーバーの脆弱性への攻撃が起こる可能性があるため、すぐに措置をとる必要があります。

ちなみに、資産検索の結果ページの右側の「統計」または「要素分析」メニューで該当コードを最も多くリターンする製品とサービス、ASネームを確認できます。
* filter: "status_code:500"
https://www.criminalip.io/ja/intelligence/element-analysis/search?query=status_code%3A500
![http_status_code6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3003594/b130d4b2-0d8b-3792-49d7-a00418631976.png)
検索エンジン間の再検索をショートカットキーでできるChrome拡張機能を作ってみた（ReactJS）

インターネッツでリサーチをしていると検索エンジンの結果に不服なことは少なくないかと思います。
Google検索エンジンは大衆向け過ぎるしDuckDuckGoはニッチなワードだと思うような結果がでなかったり。他の検索エンジンも良いところ悪いところがそれぞれあって一長一短。

そこでショートカットキーだけで別の検索エンジンを使って同じキーワードで再検索できるChrome拡張機能、Rapid Re-Searchを作りました。

手前味噌ですが自分で使ってて今のところ役に立っています。

## 成果物
<a href="https://chrome.google.com/webstore/detail/rapid-re-search/palmjbaalcdloidddomcokbjklacojah?hl=ja&authuser=0">Chromeウェブストア[無料]：Rapid Re-Search</a>
![Rapid-Re-Search-1280-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651103/93e77388-381a-e6c3-7ca9-4df2dadd6500.jpeg)
![Dec-20-2022 15-18-05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651103/d224034b-36a3-cb0b-8fbe-4b11a1cd8ca8.gif)

デモ動画のようにショートカットキーのみでも再検索ができます。

あるキーワードで満足しなかった場合は、
MAC: cmd + shift + 1
WIN: ctrl + shift + 1

でそこから
Re-Search Shortcut Key
MAC: cmd + 1 or 2 ...
WIN: ctrl + 1 or 2 ...

のショートカットキーで検索エンジンを選択して再検索します。

### 仕組み
アプリ立ち上げ時に検索ワードに入力したキーワードを取得するスクリプトをブラウザへ実行します。取得したキーワードは保存されます。
そしてアプリ立ち上げ後に入力したキーワードを使ってすぐに再検索できます。

取得したキーワードはchromeブラウザ側で提供しているchromeオブジェクトを使用して保存したりアップデートしています。ユーザーのローカル上で保管されています。

## 作り方
ReactとTypeScriptで作りました。デザインはニューモーフィズムっぽさを意識してます（アイコンは趣味）。
webpackを使ってChrome拡張機能に合わせたディレクトリで出力。

### デバッグが面倒だった
審査へ出す前にChrome拡張機能一覧ページへ出力したファイルをアップロードすることでローカル上で拡張機能を使用できます。

コードを更新しながらローカル上でアプリを立ち上げつつ開発していくのですがデバッグがやりづらかったです。拡張機能には主に３つの概念があります。

Popup（見た目）
ContentScript(ブラウザへ実行するスクリプト)
Background（裏の処理）

の３つがあります。３つ目のBackgroundは今回使用しませんでした。

Popup（見た目）は別タブに表示しながらも開発できるのですがchromeメソッドなどを使用しながら開発する段階になるとタブ上でコードを実行できなくなりました。そのためいちいちアプリを立ち上げながら確認したのが面倒です。
Popupを開いた状態で右クリックするとブラウザと同様に"検証"によってコンソールを開けるのですがPopupが閉じると一緒にコンソールが閉じられて使いづらいです。

ContentScript(ブラウザへ実行するスクリプト)の更新もいちいちChrome拡張機能を削除して再度アップロードしなければコードが反映されませんでした。
そのため検索ぺージからキーワードを取得するスクリプトはブラウザ側のコンソール画面から実行して修正しています。

また、ローカル上へアップロードしたファイルはビルド後のファイルですので更新するたびにビルドしていました。
webpackを使用してファイルを保存する度にビルドするようにしていたのですがビルド毎に１０秒ほどかかっていたのでストレスでした。
次拡張機能を作るならrViteやBunなど別の速そうなビルドツールを使ってみたいです。

### 妥協したこと
baiduなどの検索エンジンはページを開いた直後にスクリプトを実行することができませんでした。
Chrome拡張機能はContentScriptと言って正規マッチするURLが真になるとスクリプトを実行してくれるのですがbaiduなどはそれが通用しなかったためRapid Re-Searchのアプリを立ち上げ時にスクリプトを実行する形になりました。

## 作ってみた上での感想
検索エンジンに対する結論は一つの検索エンジンで人を満足させることは不可能だ。ということです。
天才エンジニアを囲ってるGoogleだって技術以外にも商売、ポリコレ、政治などそれらに対するスタンスを企業として持っていて無視できません。

Google検索エンジンのアンチカルチャーとして別の検索エンジンやブラウザそのものを開発する猛者も現れましたがそれも結局のところ製作者側の技術以外のスタンスにも左右されます。それにニッチなワードにはそもそも対応していなかったりもします。

だから検索エンジンの使い分けこそがジャスティス。

<a href="https://chrome.google.com/webstore/detail/rapid-re-search/palmjbaalcdloidddomcokbjklacojah?hl=ja&authuser=0">Chromeウェブストア[無料]：Rapid Re-Search</a>
Magento2でメールの返信先アドレスを変更する

Magentoがインストールされているディレクトリで

```
./bin/magento config:set system/smtp/return_path_email mailaddress@youwanttochange
```
とすれば変更できます。確認は

```
./bin/magento config:show
```
で```system/smtp/return_path_email```に表示されているアドレスを見ることで可能です。
WSL2が起動できない

# 環境
Windows10 (22H2)
インストールしたいディストリビューション：Ubuntu　22.04.1 LTS
# エラーの内容
Ubuntuを立ち上げようとすると
```
Press any key to continue...
```
が表示され、キーを押すとウィンドウが閉じる。
# 試した事
Ubuntuの再インストール。（失敗）
```
wsl -l -v
```
を行うと
「Linux 用 Windows サブシステムにディストリビューションがインストールされていません」
と吐く。
```
wsl --install -d ubuntu
```
でUbuntuのインストールを行い、既にインストールされていると表示され、ウィンドウが開くが、
```
Press any key to continue...
```
のループ。
ググったら出てくる手段、コントロールパネルでLinux用Windowsサブシステムの無効化した後に再起動、その後有効化するも失敗。
また、サービスからLxssManagerの起動、再起動も失敗。
# 解決
管理者権限でコマンドプロンプトを開き
```
wsl.exe --update
```
でカーネルを復元。
その後、Ubuntuを起動すると上手くいった。
# 謎
原因は多分UbuntuのファイルをWindows側で弄りまくってた事？
インストールとアンインストールを繰り返した事？
### まぁ、動いてるからヨシ！
[前回の続き実践]mvtecデータセットを読み込む

# 今回は実際に画像を使って読み込む(今回はラベリング無し)

## 使用するデータ
[MVTEC ANOMALY DETECTION DATASET](https://www.mvtec.com/company/research/datasets/mvtec-ad)
から画像データをダウンロードできます。


### bottleを使用
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/b38fea4c-423d-9d5b-374c-51163ecd9dcc.png)

## ダウンロードしたデータについて
mvtec/bottle 
- train good
- test good
-------以下は異常データ-------
- test broken_large
- test broken_small
- test contamination

のようにそれぞれファイル分けされている。
注意すべき事としてtrainの中に異常データは入っていない。

## アドレス読み込み
```
#学習データの場所を指定　アドレスの取得
train=glob.glob(os.path.join("mvtec/bottle/train/good", '*'))


#テスト正常データの場所を指定　アドレスの取得
true_test=glob.glob(os.path.join("mvtec/bottle/test/good", '*'))


#テスト異常データの場所を指定　アドレスの取得
bad_test=glob.glob(os.path.join("mvtec/bottle/test/broken_large", '*'))
   +glob.glob(os.path.join("mvtec/bottle/test/broken_small", '*'))
   +glob.glob(os.path.join("mvtec/bottle/test/contamination", '*'))

```

:::note 
データ場所1+データ場所2+データ場所3
とつけられるのでラベル付けも容易に
:::

## opencvで読み込み

前回と同様に読み込みを行う

:::note alert
データ数が多いと読み込みに時間がかかる場合があるので注意

### 元の画像サイズに注意　
今回使用するのは縦横比が同じ
:::

```
#画像のサイズの指定
#横
x_size=224
#縦
y_size=224


#学習データの格納
x_train=[]
for j in range(len(train)):
        img=cv2.imread(os.path.join(train[j]))
        
        #グレイスケール変換を行うとき
        #img=cv2.cvtColor(timg,cv2.COLOR_BGR2GRAY)
        
        img=np.asarray(img)
        #指定したサイズに変更
        img_resize=cv2.resize(img,(x_size,y_size))
        #格納
        x_train.append(img_resize)



#正常テストデータの格納
x_test=[]
for j in range(len(true_test)):
        img=cv2.imread(os.path.join(true_test[j]))
        
        #グレイスケール変換を行うとき
        #img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        
        img=np.asarray(img)
        #指定したサイズに変更
        img_resize=cv2.resize(img,(x_size,y_size))
        #格納
        x_test.append(img_resize)


#異常テストデータの格納
for j in range(len(bad_test)):
        img=cv2.imread(os.path.join(bad_test[j]))
        
        #グレイスケール変換を行うとき
        #img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
        
        img=np.asarray(img)
        #指定したサイズに変更
        img_resize=cv2.resize(img,(x_size,y_size))
        #格納
        x_test.append(img_resize)


#正規化
x_train=np.float32(x_train)
x_train/=255
x_test=np.float32(x_test)
x_test/=255

```

:::note
x_testには正常異常どちらも入る
:::

以上
ご指摘等ございましたらよろしくお願いします。
職務経歴書

# 直近のプロジェクト
## 某省庁業務支援サービス開発(現行システムのリプレース)プロジェクト (R.4.3/1 ~ 現在)
### 使用技術
Java(Spring)、Typescript、SQL(RDBMSはOracle)、ListCreator(富士通製ミドルウェア、帳票出力で用いる)、doma
### 役割
主に帳票出力機能のbackend(Java、SQL)を担当。
現時点では、Typescriptを用いたフロントエンドの開発にも従事している。
### 取り組んだこと
既存システムのJavaソースを流用することは可能であったが、帳票出力用の部品が既存システムと異なっていたので、先行して帳票出力機能を作成していた担当者との関係構築に注力し、問い合わせができる環境づくりに注力した。
また、ListCreatorを使用するのが初めてであったため、ゴールである帳票出力から逆算し、現在の自身に足りていない知識を紙に書き出し、その点について前述の担当者に教えを乞うた。成果として、3000人が使用する(試算)機能を開発することができた。
また、総合試験仕様書作成工程においては、上位会社より提示された手順書を要約してチームメンバーに展開し、将来はリーダー業務を担当できるようにと積極的に行動を起こした。
それらが評価され、現在は他チームに異動し、新規参画者のフォローも行なっている。

# 一つ前のプロジェクト
## 持株会管理システム改修プロジェクト (R.3.12/1 ~ 1/31)
### 使用技術
Java(独自フレームワーク)、SQL(RDBMSはOracle)
### 役割
Javaで書かれた既存プログラムの改修を担当。
技術的難易度は高くなかったが、詳細設計書の出来がよくなかったため、機能間でデータなどの矛盾が出ないようにする必要があった。そのため、他機能の開発担当者に話を聞きながら詳細設計書の修正に取り組みつつ、開発や単体テストに取り組んだ。

# 一つ前のプロジェクト
## 某省庁管理システム改修プロジェクト (R.3.4/1 ~ 11/31)
### 使用技術
Java(Spring)、SQL(RDBMSはOracle)、Typescript
### 役割
SQL文作成、単体テスト仕様書作成を担当。
単体テストフェーズにおいては、JavaとTypeScriptソースの修正も担当した。
Pythonを改めてちゃんと学ぶメモ #1

# はじめに
以下のような人がPythonを改めてちゃんと学んでいます。
- 元々、他のプログラミング言語はわかる（Perl, Java, JavaScript, C/C++/C#, SQL, ...)
- 最近管理系の仕事が増えてきたが、Pythonをやらなくてはいけなくなった
- せっかくだから、少しでも業務に役立てたい（Excelの困りごととか）
- せっかくだから、4年ぶりにQiita使ってみるか

ここは、Pythonを改めて学んでいるメモを都度書き出していきます。
※ 私の学びを記載するページです。**私が「学んだ」と実感したこと**が記載の基準になります。

次
https://qiita.com/hideh_hash_845/items/56c7a2c5594261f380b2

# 文法の気づき1
- 数値の型が `int` と `float` しかない
    - `double` はないんや… [^1]
- 累乗は `3^3` ではなく `3**3` と書く
- 文字列の連結は `+`
    - `&` とか `,` ではない
    - `+` の方がなじみがあるので良い
- 文字列の繰り返しに掛け算が使える `"hoge"*5`
    - Perlと一緒
- 数値->文字のcastは `str(1)`
- 文字->数値のcastは `int("1")`, `float("12.3")`
- 数値はいったん`str`型にしないとエラー
    - `print()` 内に数値と `str` 型が混在するとエラー
    - PerlやJavaScriptのような型のない言語に慣れ過ぎた
- 単一行コメントは `#`
    - Perlと一緒
- 複数行コメントは `"""`
    - なんだこれ、覚えにくい
- `format` メソッド、呼び出される側が `{​ }`。桁数指定は `{:.2f}` とか
    - Cでいう `printf` だと思うと `%` を使いたくなる 

~~~
# formatメソッドで文字列を挿入
# formatメソッドを利用するときに､挿入する小数の表示桁数を指定することができます｡
month = 9
day = 1
temp = 30.512345
my_str= '{}月{}日の気温は{:.1f​}度です｡'
print(hoge_str.format(my_str))
~~~

[^1]: doubleはないのかと思っていたら、`float`自体が倍精度だそうです（コメントで教えていただきました）【20221226追記】
base64をimg/pngに保存した時にちょっとつまづいたこと。文頭の`data:image/png;base64`は消す。

以下の質問いただきました。
「パソコンのwebカメラで写真撮って、jpgとかpngで保存したいです」


と言うことで、

1. まずは「ブラウザで写真を撮影する方法」を確認したところ、すでに記事があるのでこちらを[参考](https://zenn.dev/tatsuyasusukida/articles/84e789bea68b1e)。

2. また、PHPには`base64_decode`関数がある様子。
(公式は[こちら/base64_decode](https://www.php.net/manual/ja/function.base64-decode.php))

と言うことで,base64形式を取得してデコードすりゃいいんじゃないかと思ったんですが、どうもうまくいかない。

で、確認するとエンコードされたbase64の文頭の`data:image/png;base64`はdecode時には不要なんですね。
[参考](https://stackoverflow.com/questions/15153776/convert-base64-string-to-an-image-file)

ということで、サンプル。
https://github.com/fukushimasurao/base64_to_img_sample
【Tkinter】ネット上の画像を表示する方法

## 前置き
私はPythonのシステム開発でTkinterを使用するのですが、ネット上の画像を表示するために奮闘していました。
便利なライブラリを見つけましたので共有したいと思います。

## どんなライブラリ？
「tkhtmlview」というtkinter上にHTMLを表示できるライブラリです。

【参考】
https://torimakujoukyou.com/python-tkinter-htmllabel/


## インストール
pipインストールでOKです！
```:cmd
>>pip install tkhtmlview
```
## サンプル
```Python:example.py
from tkhtmlview import HTMLLabel
import tkinter as tk

root = tk.Tk()
root.title("テスト")
root.geometry("800x500")


# 画像表示（※「ここにURL」と書かれた箇所に画像のURLアドレスを入力してください）
html_label = HTMLLabel(root, html=f"<a href='ここにURL'><img src='ここにURL' width='250' height='250'></a>")
html_label.pack()


root.mainloop()
```
必要に応じてwidthやheightを変更してください。

## HTMLLabelウィジェットは削除できない
tkinterであればwidgetの削除は「.destroy()」で行いますが、HTMLLabelには効かないようです。
その為、何度も生成を繰り返すとメモリを多く消費してしまいます。

そこで下記の様に生成済みのHTMLLabelを編集することが出来ます。
```:Python:example.py
html_label.set_html(f"<p>ああああ</p>")
```
こんな感じで「.set_html」を使用すると内容を変更できます

## 動作が重い時
多くの画像を読み込むと、キャッシュを溜めまくり重くなる場合があります。
残念ながらtkhtmlviewにキャッシュをクリアする機能は実装されていないので、自分で追加する必要があります。
以下の方法はあくまで自己責任です。何があっても責任は追えませんので悪しからず。

下記のPythonファイルを開いてください
```:パス
C:\Users\ユーザー名\AppData\Local\Programs\Python\Python37\Lib\site-packages\tkhtmlview\html_parser.py
```
493行目の下に、この様な追加を行ってください。
```Python:html_parser.py
# ↑省略
elif tag == HTML.Tag.IMG and attrs[HTML.Attrs.SRC]:
    #-------------------------------------------------------------------- [ UNSTYLED_TAGS ]
    image = None
    ##### ここに追加 #####
    if len(self.cached_images) > 50:  # キャッシュが50件たまったら削除
        self.cached_images.clear()  # 削除
    ##### 追加終わり #####

    if attrs[HTML.Attrs.SRC].startswith(("https://" , "ftp://" , "http://")):
        if attrs[HTML.Attrs.SRC] in self.cached_images.keys():
# ↓省略
```
追加部分の「if len(self.cached_images) > 50:」ですが、50件でなくても問題ありません。
好きな整数を入力しておいてください。

これで保存するとキャッシュが50件溜まると削除される機能の実装完了です。
キャッシュの意味あるのかと言われてしまえばそれまでですが、どうぞ優しい目で許してください。

## まとめ
tkhtmlview側でrequestでダウンロードしているようですね。
canvasを用意しなくて良いのは楽ですが、融通が利かないので不便ではあります。
何かご指摘等ありましたらコメントいただけますと幸いです。
[続] Rails Consoleなど任意の場所、Inlineで任意のViewを任意条件でRenderする

# TL;DR

```ruby
ac = ApplicationController.new
ac.instance_variable_set(:@user, User.find(42)) # インスタンス変数をインジェクション
ac.render_to_string 'users/show', # レンダリングしたいテンプレート
                    layout: false, # `layout: false`がないとエラー
                    locals: { params: {} } # ローカル変数が使われる際、セットが必要

=> "<!DOCTYPE html>\n<html lang='ja'>\n<head>\n<meta charset='UTF-8'>\n<title>User ID: 42</title>\n</meta>\n</head>\n<body>\n<h1>User Name: Foo</h1>\n</body>\n</html>\n"
```

# 本文
去年はとある問題を解決するために、**[「Rails Consoleなど任意の場所で任意のViewを任意条件でRenderする」](https://qiita.com/jerrywdlee/items/ccf447f6698fde84fa25)** を作成しました。
今年は別件の調査で、[wicked_pdf](https://github.com/mileszs/wicked_pdf)のサンプルコードにて下記の構文を見つかりました。

```rb
pdf_html = ActionController::Base.new.render_to_string(template: 'controller_name/action_name', layout: 'pdf')
pdf = WickedPdf.new.pdf_from_string(pdf_html)
```

この構文は実際に使えるであれば、去年みたいにinlineでコントローラーを作成せずに、もっと手軽にViewをレンダリングできるはずです。

しかしながら、実際使って見ると、`ActionController::Base`を使う場合Helperが実行されない問題が見つかりました。
`ac.extend(ApplicationHelper)` で救済措置を取ってもViewの中では使えませんでした。

幸い海外の記事を漁っている間、`ApplicationController`のインスタンスなら、Helperが使えるとわかりました。

そしてインスタンス変数を利用したい場合は、ネット上で`locals: { @user => User.first }`のような書き方がありましたが、実際テストしてみたら使えませんでした。

`instance_variable_set(:@user, User.first)`を使えば、無事にインスタンス変数をインジェクションできました。



# 参考
- [Wicked PDF#Super Advanced Usage](https://github.com/mileszs/wicked_pdf#super-advanced-usage)
- [Adding an instance variable to a class in Ruby](https://stackoverflow.com/questions/151338/adding-an-instance-variable-to-a-class-in-ruby)
- [Rails views helper don't seems to work with render_to_string](https://stackoverflow.com/questions/58646135/rails-views-helper-dont-seems-to-work-with-render-to-string)
Google UXデザイン：ソーシャルグッドなデザイン

# はじめに

わたしが[Google UX Design Certificateで得られた素晴らしい体験][google]を、特に重要だと思われるポイントを小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ Google UX Design Certificateを受講してみてください。

[google]: https://qiita.com/mapami/items/7a0d0a3d4661c50f8bec

https://www.coursera.org/professional-certificates/google-ux-design

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/c7b131e0-c561-369b-95c5-22e00e0cf949.png" width="700">

<details><summary>これまでの振り返り</summary>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/d371bce4-836a-0ba5-fd7d-9d2e55f1b909.jpeg" width="700">

</details>

# ソーシャルグッドなデザインとは

ソーシャルグッドなデザインは、他のプロダクトのデザインとどう違うのでしょうか？

これまで学んできたように、すべてのUXデザインプロジェクトは、実際のユーザーが直面しているペインポイントを解決するためのものです。しかし、ソーシャルグッドデザインは、そのコンセプトをさらに一歩進め、"collective social good "につながる解決策を生み出すものです。つまり、

***<font color="MediumVioletRed">『ソーシャルグッドデザインとは、UXデザイナーがコミュニティで起きている問題に取り組み、社会にポジティブな変化をもたらすための方法』</font>*** 

なのです。社会の変化につながるユーザーのペインポイントに焦点を当てることは、利益や利便性の代わりに無視されるかもしれない問題に優先的に取り組むことであり、重要な仕事です。

社会貢献のためのデザインは、

- ***質の高い教育や医療へのアクセスの向上***
- ***貧困の削減***
- ***環境問題への取り組み***

など、公平なアクセスに結びつくことが多いのです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/b2364dd6-2a82-6b4a-08e9-d65fc6cf2f90.png" width="600">

例えば、電気自動車は2000年代半ばから普及が始まりました。それ以前は、自動車業界は石油系燃料を使用する自動車を何百万台も販売していました。そのため、エンジニアや設計者は、持続可能で環境に優しい代替輸送手段の開発に注力しました。現在、エネルギー効率の高い自動車は、世界中の多くの自動車購入者や政府にとって身近なものとなっています。これこそ、ソーシャルグッドなデザインなのです。

UXデザイナーとして歩みを進める中で、あなたのプロジェクトは、世界中のユーザーの生活に影響を与えることができます。ソーシャルグッドな製品をデザインすることは、あなたの仕事が、大きな問題を解決し、多様なコミュニティの生活を向上させることにつながることを意味します。

インスピレーションとなるソーシャルグッドデザインの実例をいくつかご覧ください。

# ソーシャルグッドデザインの実例

### Seeing Music

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/7b2c16f2-b1c6-1dd6-57ff-0de50711da8e.png" width="600">

Seeing Musicは、音を視覚化するためのツールです。コンピュータのマイクに向かって音を歌ったり演奏したりすると、このツールは音の質感やメロディーの道筋や形を表示します。

Seeing Musicのようなツールはなぜ重要なのでしょうか？

世界保健機関（WHO）によると、世界人口の5％以上が聴覚に障害を抱えていると言われています。Seeing Musicは、聴覚に障がいのある方が音楽を芸術として体験し、ユニークな方法で音を探求することを支援します。

https://experiments.withgoogle.com/seeing-music

### Simple

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/73e76fff-0c5f-1d4b-309f-37f3e991812a.png" width="600">

Simpleは、経済発展途上国において心臓病や脳卒中で死亡する人々の数を減らすことを目的とした、無料で使いやすいモバイルアプリケーションです。

このアプリは、医療従事者が患者の情報を20秒以内に記録できるようにすることで、大規模な高血圧や慢性疾患管理プログラムをサポートします。これにより、医療従事者は患者を迅速に調査し、治療することができます。

https://www.simple.org/
[PrismaClientInitializationError] remaining connection slots are reserved for non-replication superuser connections

supabaseのdbを使っていた際に生じたエラー。
ORMにはPrismaを使っていた
# エラー内容
```bash
PrismaError {
  message: PrismaClientInitializationError:
  Invalid `prisma.maker.findMany()` invocation:


  Error querying the database: db error: FATAL: remaining connection slots are reserved for non-replication superuser connections
      at RequestHandler.handleRequestError 
  # ...
  name: 'PrismaError'
}
```

# 結論
:::note info
2023/01/14追記
↓これで解決できました
https://www.prisma.io/docs/guides/database/troubleshooting-orm/help-articles/nextjs-prisma-client-dev-practices
:::

どこかでエラーが生じ(例えばフロントで無限レンダリングされてるとか。。)、その結果prismaが大量にアクセスしたことが原因の可能性がある。
![スクリーンショット 2022-12-26 17.49.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/5b4e27cf-e106-dffb-c206-027c06a65a31.png)

### 調査
```sql
/* 最大でコネクション貼れる数 */
SHOW max_connections;
/* 現状のコネクション数 */
SELECT count(*) FROM pg_stat_activity;

/* コネクションを切る */
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE query_start < current_timestamp;
```

# あまり関係なかった方法
project > settingから再起動したのちConnection Poolingを「オフ」にする
![スクリーンショット_2022-12-26_16_24_44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/787586/31a21ab3-58af-1e63-ca9d-6ee07b7a3e18.png)

原因はdbに繰り返しアクセスが生じ connection poolingの上限に達したためだと考えられる。
開発環境でsupabaseを用いてたためconnection poolingはオフで良い。
ちなみにconnection poolingはDBMSへの接続を切断せず維持するシステム

# 参考
https://github.com/supabase/supabase/discussions/5212

https://e-words.jp/w/%E3%82%B3%E3%83%8D%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E3%83%97%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0.html
ウィンドウズ10でIE11を使い続ける

# あらすじ

Microsoft Surface が修理から戻ってきたら、OSが更新されていた。
IEが使えない！
困った。。２０年前のグループウェアを使い続けている自分はIE必須。
なんとしてもIEを復活させる話。

# どうすればいいの？

IEを起動して使おうとすると、すぐに終了しEdgeが起動されてしまいます。
これはBHOなるIEからEdgeへのリダイレクタが諸悪の根源です。

- レジストリを変更する
- ファイルを削除する

の二通りの方法があります。
基本的にどちらか一方を実施すれば足ります。

## レジストリを変更する方法（上級者向け）

レジストリエディタ `REGEDIT.EXE` を起動し、
`HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Ext\CLSID\1FD49718-1D00-4B19-AF5F-070AF6D5D54C`
の値を `0` に変更して、PCを再起動する。

## ファイルを削除する

レジストリエディタを扱うのは少々危険を伴います。
そこでBHOを行っているファイルを削除してしまう方法もあります。

管理者権限でエクスプローラやコマンドプロンプト、ファイルマネージャ等を起動し、
フォルダ `C:\Program Files (x86)\Microsoft\Edge\Application\92.0.902.67\BHO`
の中にあるファイルを全て（３個）削除し、PCを再起動する。
（注: フォルダ名の 92.0.902.67 は他の数字である場合もあります。適宜読み替えて）

なお、ファイル３個のうち１個は削除に失敗する場合があります。
この場合はそのファイルのファイル名を適当なものに変更してしまいましょう。
ファイル名変更後にPCを再起動すれば削除できます。

# まとめ

IEを無効にしている諸悪の根源はBHOなるリダイレクタ。
レジストリ変更かファイル自体の削除で対処できる。
Edgeのように気持ち悪い情報収集されないIEをみんなで使い続けましょう。
【Linux】splitコマンドで行の途中で分割しない（numberオプション）

# splitコマンドでファイルを分割すると行の途中で切れちゃう…
splitコマンドで行数分割ではなくnumberオプションで分割すると

```shell
split --number=2 --additional-suffix=.csv hoge.csv 
```

のようにやると行の途中でもファイルが分割されてしまいます。そういう場合は

```shell
split --number=l/2 --additional-suffix=.csv hoge.csv 
```

とやると行単位でファイルが分割されます。
以下のドキュメントのオプションを参考にしています。

https://linuxjm.osdn.jp/info/GNU_coreutils/coreutils-ja_31.html

他にも以下のような指定が可能です。

> 	n      input の現在のサイズに基づいて n 個のファイルを生成する。
k/n    n 個中の k 番目のみを標準出力へ出力する。
l/n    n 個のファイルを生成する。行やレコードの途中で分割しない。
l/k/n  同上。ただし、n 個中の k 番目のみを標準出力に出力する。
r/n    ‘l’ に似ている。ただし、分配はラウンド・ロビン方式で行う。
       (訳注： トランプの親がカードを 1 枚づつ子に配るように、
               入力から 1 行 (1 レコード) づつ各出力ファイルに
               分配して行く。)
r/k/n  同上。ただし、n 個中の k 番目のみを標準出力に出力する。
QWERTYから移行しやすい片手用キーボード配列を追求してみた（POEUT配列）

# 動機

- Froggyみたいに片手で全てのキー入力を済ませて、もう片方の手は別のことに使いたい・・本のページをめくったり、ポテチをつまんだり
- キーボードをコンパクトにして机の片隅において、机の真ん中は別のことに使いたい・・はんだごてを置いたり、ノートを広げたり
- 完全に新規の配列を覚えるのはきついので、体に染みついているQWERTY配列をなるべく生かしたい
- キー配列を自分好みにカスタマイズしたい・・楽しそうだし、覚えるのも楽なはず

# 前提

- Helixベース（縦5行、横7列でコントローラ部を除いた32キー）
- 左手用

# コンセプト

- アルファベットの配列は、左手分は極力そのまま、右手分は鏡対称でマッピング
 ![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/d9567ccb-6dc0-0041-0b62-7a80c2919aa6.png)
- 母音（aiueo）はレイヤー0（直押し）にしたいので異なるキーにマッピングする⇒IとHを入れ替え
 ![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/953b73e3-e371-c7fe-1fad-f5db5af853a2.png)

- 母音や使用頻度の高いキーをレイヤー0にして、他方をレイヤー1にする
 最下段(zxcv)はコントロールキーと併用することが多いのでレイヤー0にする
![3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/3ed77a72-e5d1-1a03-5c74-49b92806a857.png)

# 出来上がり
- ESCは左上、DELは右上、Enterは右下、タイプミスが多い間はBSは特等席に、などの個人的なこだわりをいれる
![4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/c9d2eb35-79b5-c0ef-984a-de9d14293f8a.png)　![5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/e522d373-a628-065a-f744-edc3b96dff0f.png)


- 数字レイヤ、ファンクションキーレイヤなどを入れる
![6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/9e2696c3-b1c3-ac28-2299-ad477904f64f.png)　![7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310294/d7cfaa12-3d63-dd14-45a4-37e98272bdaf.png)

# 成果
- 目論見通り、使い始めてすぐでもキーの位置がわからなくてイライラすることは殆どなかった（キーキャップは刻印なし）
- 格子状のキーボードに慣れるまで、隣のキーも同時に押してしまうミスタイプが多かったが、じきに慣れていった
- 数週間、暇な時間に適当な文章を入力する程度の練習で、さほどストレスなく、思考の邪魔をすることなく入力できるようになった
- 机上の省スペースになるだけでなく、手首もほとんど動かさなくていいこのスタイルは、がんがんに入力速度を求めるような場面以外では常用してもいいのではないかと感じ始めた
- このキー配列を**POEUT配列**と命名する


# 感想・学んだこと
- 自作キーボードについても何も知らなかった初心者（私）が、作って動かすだけならほぼ一日で思ったようなものが作れるという今の環境は素晴らしい
- 片手キーボードはフルキーボードに比べてかかるパーツ代も安く、得られるもの（机上スペースなど）も大きく、練習も含めた趣味性も高いので、もっと愛好家がふえてもいいと思う
- Windowsログインで数字を含むパスワードを使う場合、KC_P0～KC_P9のキーコードだと数字が入力できない。KC_0～KC_9のキーコードを使うこと。

# 参考リンク
- [遊舎工房](https://yushakobo.jp/)  ・・自作キーボード専門店
- [QMK Configurator](https://config.qmk.fm/#/helix/rev3_5rows/LAYOUT) ・・キーマップを作製できるWebサービス
- [QMK Toolbox](https://github.com/qmk/qmk_toolbox/releases)  ・・QMK Configuratorで作成したキーマップ（ファームウェア）をコントローラへ書き込むツール


# 謝辞
- Helixを開発された ないん様、Froggyを開発されインスパイアを頂いたtakuma様に謝意を表します
Numberオブジェクトって結構厄介

Numberオブジェクトの挙動が意外にも厄介だったのでまとめておく。

```javascript:something.js
Number("0"); // → 0 
Number("hoge"); // → NaN
Number(""); // → 0 (NaNじゃないんかい)
```
Reactにおいて、以下のようにクエリの値に応じて表示する内容を変えようと思ったのだが、実際にはクエリが指定されていない場合、blockID=0となってしまうため、「0以上やで〜」が表示されてしまう。

```tsx:something.tsx
// 省略

const component = () => {
    // urlは、https://localhost:3000/something
    const location = useLocation();
    const search = location.search;
    const query = new URLSearchParams(search);
    const blockID = Number(query.get("id"));

    return(<>
        {/* 「クエリないで〜」が表示されるようにしたい */}
        {Number.isNaN(blockID) && <div>クエリないで〜</div>}
        {blockID >= 0 && <div>0以上やで〜</div>}
    </>);
}
```
micropythonでcookie管理 (備忘録)

## やりたいこと
pythonのrequests.sessionのようにcookieの保存/管理を行うものが欲しい。

## 環境
| | |
|-|-|
|ureques.py|現時点での最新版([a3d6d29b1b](https://github.com/micropython/micropython-lib/blob/a3d6d29b1b9de2bb147e0751c08a39608ebe06c8/python-ecosys/urequests/urequests.py))|

## 作ったもの
### 注意点
* 複数のドメインにわたってリクエストを送る場合、cookieが流出します (google.comにリクエスト後yahoo.co.jpにリクエストするとyahoo.co.jpにgoogle.comのcookieも流れる)
そのため、使用は所有している個人サーバや単一のドメインに限ってください。

* 3xx番のリダイレクト時はcookieが使用されません (urequests.py側のバグ)

#### その他注意点
* ドメインやパスへの制約などが無い
* 有効期限や期間は無く無期限

### コードと使用例

https://gist.github.com/ASID860/27ccef2f39a12c1c56321fb3f8845e80
Atcoderなにも知らないので登録してみた

### 新規登録
まずは色々と入力して登録してみた！ワクワク

https://atcoder.jp/register?continue=https%3A%2F%2Fatcoder.jp%2F%3Flang%3Dja

### 何をすればいいのかわからない 
TOPページに自動的に遷移しました。初心者は何をどうすればいいんだ...!?
と思ったら、[便利リンク集](https://atcoder.jp/posts/261)で[チュートリアル](https://atcoder.jp/posts/37)を見つけました

プログラミングは出来るけど、何をすれば良いか分からない人は **AtCoder Beginners Selection** に取り組めば良いみたい！

https://atcoder.jp/contests/abs

### C++わからない
AtCoderを解くには基本的にはC++の知識が必要らしい、、、。
この記事にもあるように圧倒的C++人気なのでこの際学んでみようかなと思います!

https://qiita.com/knakajima3027/items/809be5abe5c3d9f29ee7

親切にも、C++の教材が用意されていました！
競技プログラミングに取り組みたい人は3.4章まで読んでみると良いみたいですね。

https://atcoder.jp/contests/apg4b

## まとめ
```mermaid
graph TD;
    プログラミング未経験者-->C++入門AtCoderProgrammingGuideforbeginners;
    プログラミング経験者-->C++以外で取り組みたい-->AtCoderBeginnersSelection;
    プログラミング経験者-->C++で取り組みたい-->C++わからない-->C++入門AtCoderProgrammingGuideforbeginners;
    C++で取り組みたい-->C++わかる-->AtCoderBeginnersSelection;
    C++入門AtCoderProgrammingGuideforbeginners-->AtCoderBeginnersSelection;
    AtCoderBeginnersSelection-->コンテストに参加;
```

## 良さそうなリンク

https://and-engineer.com/articles/YfPo9xAAAB8ATGLv 

## 最後に
AtCoder Beginners Selectionの問題１をRubyで取り組んでみたら解けました。
解いた時の爽快感が楽しくてみんな取り組んでいるのかな？と少し分かった気がします！
Goの開発環境をMac上でDockerで構築する

#### 今回の目的
今回はGoの開発環境をM1 Macbook pro上にRancher desktopを利用してコンテナ環境を構築します。そこで[Tour of Go](https://go-tour-jp.appspot.com/list)の環境を実行します。
オンラインでもできますが、せっかくなので写経的な形で進めるためにGoの環境を用意します。多少環境祭などもでてくるでしょうが細かいことは気にせずにやっていきます。
kubernetesとかを仕事で使っているのですが、Goで作成されている製品なのでGo言語自体の学習もしたいなと思った次第です。



####　環境
```
M1 Macbook pro: macOS Ventura 13.0.1
Rancher desktop v1.7.0
コンテナイメージ： Ubuntu20.04
Go: v1.19.4
```

Rancher desktopはDocker desktopと同じような製品ですが、CRIにdockerとcontainerd選ぶのを選べたりkubernetesのバージョンアップ検証ができたりと便利な製品となっており、無料で使えるにいい機能が揃っています。
今回もコンテナ環境を構築する上でDockerのほうが使い慣れているので、dockerコマンドを利用したいと思っていたのでちょうどよかったです。ローカル環境での開発にはいいものだと思うのでぜひ使ってみてください。

今回はRancher desktopの環境構築方法等は割愛いたします。利用は難しくないので、Docker desktopからの移行を考えている方はインストールしてみてはどうでしょうか。
https://rancherdesktop.io/

#### 環境構築
今回はコンテナ上でGoを実行していきますが、ソースなどはローカルに残しときたいのでディレクトリをマウントしておきたいと思います。
以下でローカルディレクトリをマウントしたコンテナを立ち上げます。
```ctr:mac
docker run -it -d --name tour-of-go -v /Users/takushi/dev-env/go:/go ubuntu:20.04
```

ここからはコンテナ内で作業するためにまずコンテナに入ります。

```ctr:mac
docker container exec -it tour-of-go  bash
```

コンテナ内に入りましたら、Goのダウンロードおよびインストールを実行します。
```ctr:container
apt update
apt install wget
wget https://go.dev/dl/go1.19.4.linux-arm64.tar.gz
tar -C /usr/local/ -xzf go1.19.4.linux-arm64.tar.gz 
```

これでひとまずダウンロードが完了しました。Goを実行するにはGoのPathを通してあげなければなりません。以下のように設定します。
```ctr:cotainer
export PATH=$PATH:/usr/local/go/bin
```
これで問題なくできていればgoのコマンドが通るようになります。
```ctr:container
root@b869a1d8854c:~# go version
go version go1.19.4 linux/arm64
```

ただ、これだと一時的にパスを通したにすぎません。永続的にパスを通したい場合は、`$HOME/.profile`もしくは`/etc/profile `の末尾に以下を追記する必要があります。
```
export PATH=$PATH:/usr/local/go/bin
```
追記後、以下コマンドで永続的にパスを通すことができます。
```ctr:cotanier
sourve $HOME/.profile
```

これで基本的な設定は完了です。ローカルマシンのコンテナにマウントしたパスにファイルを格納することでGoが実行できるか確認します。

#### ソースファイル実行
プログラムを学ぶ時にはやはり`Hello, World`を実行してあげなければ始められません。
なので、以下ソースをマウントしたディレクトリに格納します。
```
package main

import "fmt"

func main() {
  fmt.Println("hello, go")
}
```

配置したらコンテナ環境に戻り実行してみます。
```ctr:container
root@b869a1d8854c:/go# go run hello.go 
hello, go
```

成功です。

今回は最小限の力でGo環境を構築しました。
これからGoの学習を進めていきたいと思います。
GOについてのTipsなど書き残したいことができたらまた投稿しようと思います。
Maven の repositories に http://～ を指定すると mvn install に失敗する

# 事象

`mvn install` 実行時に下記のようなエラーになる。

> Could not transfer artifact xxx from/to maven-default-http-blocker (http://0.0.0.0/): Blocked mirror for repositories: [xxxxx (http://xxxxx, default, releases)]

# 対処

とりあえず http のまま繋ぎたい場合は設定ファイルの下記部分をコメントアウトすればよい。
~~(repository を HTTPS に対応させるのが良いというのはそう)~~

```settings.xml
  <mirrors>
　　～
    <!-- ↓ この部分をコメントアウト -->
    <mirror>
      <id>maven-default-http-blocker</id>
      <mirrorOf>external:http:*</mirrorOf>
      <name>Pseudo repository to mirror external repositories initially using HTTP.</name>
      <url>http://0.0.0.0/</url>
      <blocked>true</blocked>
    </mirror>
  </mirrors>
```

#### ※ 設定ファイルの場所

設定ファイルの場所は ~/.m2/settings.xml だが、intellij (の maven プラグイン) を利用している場合は別の場所になる。
Windows で toolbox を利用して intellij を入れている場合は `～\AppData\Local\JetBrains\Toolbox\apps\IDEA-C\ch-0\...\plugins\maven\lib\maven3\conf\settings.xml` にありました。
"..." 部分はプロジェクトによって異なるようなのでプロジェクトごとに修正が必要。

# 原因

3.8.1 からデフォルトで http 接続はブロックされるようになったそうです。

https://maven.apache.org/docs/3.8.1/release-notes.html#how-to-fix-when-i-get-a-http-repository-blocked
チケット管理の改善Tips その壱

こんちは。
最近はフロントエンドより開発プロセスの改善が好きな[とよしー](https://twitter.com/_toyo_sea_)です。
年末ですね。
年末だというのに自分は風邪を引いたり、縁石につまづいて頭から血を出したりしてさんざんな日々です。

さて、そんな満身創痍な自分はここ数週間、チケット管理について改善活動を試みてきたので、
今回はそのTipsを紹介しようと思います。
もしかしたらシリーズ化するので「その壱」と題しています。

## 課題
まず自チームの以前のチケット管理の課題についてこのようなものがありました。
- 開発着手時に、担当の開発者が「チケットのゴールはどうすべきか」と関係者に逐一確認することでリードタイムが発生していた

すなわち、チケットのゴールが見えづらい状況でした。
例えば、不具合内容は書いてあるが、この不具合が治った期待値が記載されていないといったことが散見されていました。


## やったこと
そのような課題を解決するために、下記を試みました。

1. チケットテンプレートに完了条件を追記
2. 既存のチケット(80件くらいある...)の完了条件を定めるため、各関係者にインタビューの旅に出た


【1.チケットテンプレートに完了条件を追記】
チケットテンプレートに完了条件を記載しておくことで、これ以上完了条件が見えないチケットが起票されるのを防ぐために行いました。
「どこまでやればこのチケットはOKなのか」というゴールを定めて、成果物の透明性を見えるようにしました。

ちなみに自チームではスクラムを採用していないですが、アイデアとしてはスクラムの「Doneの定義」あたりを参考にしています。

【2.既存のチケットの完了条件を定めるため、各関係者にインタビューの旅に出た】
いままで既存のチケットに関して管理をしていなかったわけではないです。
定期的にチケットの棚卸しはしていたのですが、「やる/やらない」の判断で留まっていた感じでした。
なので、いかにチケットを着手できる状態にするか...という考えのもと、各関係者に
「このチケットの目指すゴールってなんですか」
と問いかけるためアマゾンの奥地へと向かったのだった...。（うそです）

## そもそもなぜやるのか？
- 余計なリードタイムをなくすことで、ユーザーに早く価値を届けるため

です。

## 結果
1. 新たに起票されるチケットは、完了条件が書かれるようになりました。

2. 既存チケットに関して各関係者にインタビューしてみると
「これもう治っているな」
「これもうクローズしちゃっていいやつですね」
といった声もいただき、少々チケットの母数を減らすこともできました。

3. 嬉しかったこととして、チケット起票以前の不具合発見フェーズで「こうなっていてほしい」と期待値を書いてくださる人もちらほら出てきました。
「こうなっていてほしい」を不具合発見フェーズで書くことで、ユーザーの価値はほんとにこの期待値なのか？という対話が生まれる可能性があります。
こういう文化がどんどん浸透していくといいなと思っています。

4. めっちゃ体感で恐縮ですが、チケット着手時の手戻り率が減った気がします。
すなわち着手から実装完了までのリードタイムが短くなった気がする。
これを計測してなかったのは反省。



## まとめ
以上、チケット管理の改善Tips その壱でした。
今回は完了条件を書くことについて取り上げました。
「当たり前だよそんなの」と思う方もいるかもしれませんが、いかなる状況でも当たり前のことを当たり前にやることが意外とむずかったりするのです。
自分は、それをいかに仕組み化するかが大事だと思っています。

加えて、自分は対症療法的な改善のアプローチも大事だとは思いますが、
予防医療的な改善のアプローチも大事だと思います。
要は、**未然に**無駄やバグを防ぐアプローチです。
システムも予防医療的な視点で未然にバグや無駄を防ぐアプローチを今後も考えていきたいですね。


それではまた。
\includegraphicsで画像を入れたときエラーが出た

macのtexshopを使ってプリントを作成しているときに、画像を入れるとエラーが出たので解決法メモ




\includegraphicsを使ってイラストレーターで作成したpdfの画像を入れようとしたら



Latex warning file not found on input line size of graphic in no boundingbox

みたいなエラーが出る。
そのまま検索してみると
https://teokure.net/technology/tex-image-notfound/

しかし、ちゃんとパッケージを読み込むときにdvipdfmxもつけている。

いろいろいじっていると、usepackage[dvipdfmx]{graphicx}の読み込む順番を一番初めに持ってくるとうまくいった。
謎。


一応、読み込んでいたものは
\usepackage{bxpapersize}
\usepackage{amssymb}
\usepackage{mhchem}
\usepackage{enumerate}

この一番最後に入れるとエラーで表示できないが、一番上に持ってくるとちゃんと表示された。

謎。

どのパッケージとぶつかっているのか調べるために徐々に記述場所を下げていくと
\usepackage{mhchem}
の後まで持ってきた段階でエラーが出た。
mhchemというパッケージと何かがぶつかっているのかも
各 Concrete CMS バージョンの jQuery や他のライブラリのバージョンを調べる方法


脆弱性診断などで、JSライブラリのバージョンをクライアントから聞かれることがあるので、GitHub で調べる方法を書いておきます。

# STEP 1: 調べたいライブラリのファイルを GitHub で開く

- GitHub の [Concrete CMS のプロジェクト](https://github.com/concretecms/concretecms) に訪問する
- ファイルを辿って調べたいファイルを開く
	- JS ファイルは `concrete/js` 配下を見る
	- 例: jQuery の場合は `concrete/js/jquery.js`

![githubproject.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44367/e0a7290f-7575-7143-d503-a0a137dfbea2.png)

# STEP 2: 目的のバージョンを選択する

- パンくずの左にあるブランチ名「develop」をクリックしてプルダウンメニューを開く
- `Tags` タブを開いて希望するバージョンを選択する
![version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44367/1d878796-9cd4-1629-37ac-520a95618d34.png)
- jQuery ファイル1行目のバージョン番号を確認する。


# Concrete CMS での jQuery 補足話

## v8.5.x のバージョンは 1.12.2 問題ないらしい (2022年末時点)

ちなみに、Concrete CMS 8.5.x まで、多くのバージョンで jQuery 1.12.2 を利用しています。

jQuery の後のバージョンで、非常にまずい脆弱性が見つかっているのですが、1.12.2 は脆弱性の穴が開く前のバージョンらしいとのことです。

もちろん、他の脆弱性が見つかるかもしれないので、この見解は古くなる場合があります。


## v9 のjQuery バージョン


Concrete CMS Version | jQuery Version
------------|--------
9.0.0~9.1.3 | 3.6.0
【python】勉強メモ　速習Flask④


### DB更新（記事編集）

[【python】勉強メモ　速習Flask③](https://qiita.com/qiitataro/items/5f12300c4b238d2b6170)の続きとなります。

以下の様に変更。htmlファイルは変更の必要はありません。

```app.py
from flask import Flask
from flask import render_template
from flask import request
from flask import redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
import pytz

app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///blog.db"
db = SQLAlchemy(app)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title= db.Column(db.String(50), nullable=True)
    body = db.Column(db.String(300), nullable=True)
    created_at = db.Column(db.DateTime, nullable=False,default=datetime.now(pytz.timezone('Asia/Tokyo')))

# GETとPOSTを受け取れる様にする。
@app.route("/", methods=['GET', 'POST'])
def hello():
    # ページにアクセスしたら（HTTP GETでアクセスしたら）
    if request.method == 'GET':
        # DBに登録されたデーターを全てPostで取得する。取得したデーターは、postsに、リスト形式で格納される。
        posts = Post.query.all()
        # index.htmlに表示するため、posts=postsで、取得したデーターを渡す。
        return render_template('index.html', posts=posts)


@app.route("/create", methods=['GET', 'POST']) 
def create():
    if request.method == 'POST':
        title = request.form.get('title')
        body = request.form.get('body')

        post = Post(title=title, body=body)

        db.session.add(post)
        # 変更を保存
        db.session.commit()

        return redirect('/')
    else:
        return render_template('create.html')

# update処理を作成
@app.route("/<int:id>/update", methods=['GET', 'POST']) 
def update(id):
    post = Post.query.get(id)
    
    if request.method == 'GET':
        return render_template('update.html', post=post)
    
    # 更新ボタンが押されると、POSTが送信されるめ、eles移行が実行される
    else:
        post.title = request.form.get('title') # 書き換え
        post.body = request.form.get('body') # 書き換え
        
        # 不要なのでコメントアウト
        # post = Post(title=title, body=body)
        
        # db.session.add(post) 更新なので、addする必要はないため削除
        # commitだけすれば良い
        db.session.commit()

        return redirect('/')
        # return render_template('create.html')

```

ブラウザで`127.0.0.1:5000`にアクセスし、変更対象記事の**編集**ボタンをクリック
![Flask-19.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3014502/49ba03ca-2aae-a10d-a419-acfdbddbe44b.png)


編集を行い、**更新**ボタンを押す。
![Flask-20.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3014502/805d7e53-de68-4e0e-87b3-2942a10ad696.png)



記事が更新されていることを確認。
![Flask-21.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3014502/333a17ef-8993-9689-1360-0110eeb19ac1.png)

次回は、DB（投稿記事）の削除。
PythonでhCaptcha をバイパスする


ウェブマスターの多くは、自動化から保護する手立てとしてGoogle ReCaptchaを使用しています。しかし、これは市場で手に入る唯一のソリューションというわけではありません。最も一般的な代替手段の1つはhCaptchaです。現在、DDoS対策市場のリーダーであり、現時点では主要なCDNプロバイダーの1社であるCloudflareによって使用されています。これは、もしCloudflareがあなたを疑わしいと判断した場合、遅かれ早かれhCaptchaに遭遇することを意味します。

Cloudflareは、Google ReCaptchaからIntuition MachinesのhCaptchaに移行することを発表しました。この動きは、データの機密性に関する懸念とCAPTCHAの柔軟性に大きく貢献しました。現在、攻撃に対する保護はさらに適応的です。これは、Cloudflareのすべての顧客が影響を受けます。

また、 hCaptchaは

Googleとは異なり、個人データを収集しません。
CDNが世界中に分散されているため、CAPTCHAは高速かつ完璧に動作します。
ReCaptchaと互換性があるため、移行が非常に簡単です。
障害のある方に適しています。

素晴らしいことのように聞こえますよね？しかし、CloudflareでhCaptchaを迂回することについてはどうでしょうか?

hCaptchaの高速な自動化のために、2captcha-pythonモジュールを使用します。 Python 3.xが必要で、pipでインストールできます。

``` python
pip3 install 2captcha-python
```

​​または、リポジトリをクローンすることもできますが、事前にrequestsモジュールをインストールすることを忘れないでください。

``` python
git clone https://github.com/2captcha/2captcha-python.git
```

準備

APIキーを送信する2Captchaクラスの新しいインスタンスを作成する必要があります。

``` python
from twocaptcha import twoCaptcha #module import solver = 2Captcha('YOUR_API_KEY') #your 2captcha API key
```

CAPTCHA突破

それでは、CAPTCHA解決アルゴリズムを作成しましょう。

``` python
result = solver.hcaptcha(sitekey='10000000-ffff-ffff-ffff-000000000001',                             url='https://www.site.com/page/',                              proxy={
                                'type': 'HTTPS',
                                'uri': 'username:password@1.2.3.4:1234'
                            })
```

CloudflareはhCaptchaトークンの検証中にIPアドレスをチェックすることに注意してください。したがって、CAPTCHAは、送信元と同じIPアドレスから突破する必要があります。 CloudflareでhCaptchaを正常にバイパスするには、他のCAPTCHAパラメータとともにプロキシを送信する必要があります。

このコールは、CAPTCHAを迂回するトークンを返します。

``` python
{'captchaId': '64793693810', 'code': 'P0_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUz...'} 
```

ソリューションの使用

コードからのトークンは、h-captcha-responseフィールドとg-recaptcha-response フィールドでウェブサイトに送信されます。ブラウザを使用する場合にこれを行う最も簡単な方法は、JavaScriptを使うことです。それ以外の場合は、適切なHTTPリクエストでトークンを送信します。

``` python
let submitToken = (token) => {
   document.querySelector('[name=g-recaptcha-response]').innerText = token
   document.querySelector('[name=h-captcha-response]').innerText = token
   document.querySelector('.challenge-form').submit()
}
submitToken('TOKEN_STRING')
```

時間をかける価値はありそうですか？私たちは、絶対にそうだと断言します。数行のコードで多くの時間を節約できます。また、セルフホスト型ソリューションを実行することにした場合、2captchaはさらに収益性が高くなります。
【OfficeAdd-ins】Excel上で動作するテキストエディタを拵える

# 概要

Office Add-ins の作成から公開までの流れを体験するため、
Excel の画面上で動作するテキストエディタを作成しました。

# 全体像

エディタ (ダークモード)
<img width="60%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/62f573aa-7da8-e29d-18c0-fd97862cf5cd.png">

設定画面 (ライトモード)
<img width="60%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/219708/290c62b9-3e8f-8b73-6769-193bcb0b29aa.png">

# 使用したもの

* Yeoman ([generator-office](https://github.com/OfficeDev/generator-office))
* TypeScript
* React
* Google Fonts
* [FluentUI](https://developer.microsoft.com/ja-jp/fluentui)
* [monaco-editor/react](https://github.com/suren-atoyan/monaco-react#readme)


UIライブラリについてはMSなので `FluentUI` が推奨されています。
認証ポリシーの中に 「FluentUI を使用していること」という一文を見かけたような気がしましたが、
ストアにある Office-Addins を見る限り、FluentUI を使用しなければならないということはなさそうでした。
FluentUI は多少のとっつきにくさはあったけど、なかなか使いやすいと思いました。
やはりさすがに Office アプリケーションとよく馴染むなぁといった感じです。

今回は Excel との連携が全くないアドインを作成しましたが、
本来は `Excel JavaScriptAPI` を通して相互作用をするものを作る感じになりますね。

# 特有のポイント

### 設定値

Office Add-ins 自体が何かしらの設定値を持っている場合が多いと思います。
今回の例でいうとテーマや言語など、設定画面に並んでいる項目がそれにあたります。

このような設定は
* 変更した時に画面上に反映される
* 次回起動時に前回の状態が復元される

の、2つの実装をする必要がありました。

例としてテーマを変更した際の実装は以下のような感じです。


```typescript
const [selectedTheme, setSelectedTheme] = React.useState<string | undefined>(props.theme)
const onThemeChange = React.useCallback((_event: React.SyntheticEvent<HTMLElement>, option: IChoiceGroupOption) => {
    const changedTheme = option.key
    setSelectedTheme(changedTheme)
    props.setTheme(changedTheme)

    Office.context.document.settings.set('theme', changedTheme)
    Office.context.document.settings.saveAsync((asyncResult) => {
        if (asyncResult.status == Office.AsyncResultStatus.Failed) {
            isLogging && console.log(`[Addins] [${moduleName}] Save Failed : Theme "${changedTheme}"`)
        } else {
            isLogging && console.log(`[Addins] [${moduleName}] Save Doned : Theme "${changedTheme}"`)
        }
    })
}, [])
```

プロダクトの規模感が小さかったので、すべての設定値は `useState` で扱うことにしました。
上記のように設定値が更新された場合にはまず state を更新することで画面に反映させています。

その後 `Office.context.document.settings` に対してもその設定値を保持させています。
これは OfficeAdd-ins が実行しているコンテキストのファイルに埋め込むということなので、
今回の場合だと Excel ファイルに設定値が保存されます。

OfficeAdd-ins 起動時には `Office.context.document.settings` から対象の設定値を各 `State` に読み出しますが、
設定値が存在しなければ (初回起動時など)、既定値を流し込みます。
大体の OfficeAdd-ins で設定値の運用はこの形でいけるかと思います。

### テーマ

`FluentUI` でもテーマは `ThemeProvider` でシンプルに実装できました。

```jsx 
import { ThemeProvider } from "@fluentui/react"

//......

const render = (Component) => {
  ReactDOM.render(
    <AppContainer>
      <ThemeProvider>
        <Component title={title} isOfficeInitialized={isOfficeInitialized} />
      </ThemeProvider>
    </AppContainer>,
    document.getElementById("container")
  )
}
```

# 公開

結論からいうと Office ストアへの公開は不可能でした。
審査がどうこう以前に、開発者登録の時点でリジェクトの嵐に見舞われ突破できませんでした。

VSCode の Extension の場合はこの辺り簡単に公開ができたのですが、
Office-Addins は MS Partner Center から開発者登録をする必要があります。

これがまた画面遷移のたらい回しにあったり、書類を揃えたり、
そうこうしているうちに「…あ、もういいですわ…」ってなってしまうこと請け合いです。

せっかくWeb技術で開発ができます！セキュリティ面も安全です！マルチプラットフォームです！な基盤を用意したのに、
最後の公開部分がここまで大きな壁になっているのは残念としか言えないです。
bitlockerで暗号化されたNTFSパーティションをマウント

## 参考

* [How to mount a Bitlocker NTFS partition with NTFS3 and Cryptsetup : ManjaroLinux](https://www.reddit.com/r/ManjaroLinux/comments/trejc3/how_to_mount_a_bitlocker_ntfs_partition_with/)
* [【Linux】Cryptsetupを用いたディスク（デバイス）の暗号化 | ぺんぎんや](https://e-penguiner.com/encrypt-device-using-cryptsetup/)

## 手順

### インストール

```sh
apt install -y cryptsetup
```

### mount

```sh
# bitlockerのパスワード入力
cryptsetup bitlkOpen /dev/sdb1 encrypt_shared
```

```sh
mount -t ntfs3 /dev/mapper/encrypt_shared /mnt/shared
```

### umount

```sh
umount /mnt/shared
```

```sh
cryptsetup bitlkClose encrypt_shared
```
昨日まで接続できていたDBに拒否された。

昨日まで接続できていたサーバーから拒否されてしまった。
コードはいじっていなかったためadminで確認したところ、ユーザー権限の一覧から登録していたユーザーが消えていた。
でも、shellでユーザー一覧を確認したところ、DBには存在していた。

shellにて該当のユーザーを削除し、再作成したところ、解決した。
【Mysql】UPDATE文

# UPDATE文

## 基本構文
```sql
UPDATE テーブル名 SET カラム名 = 値 WHERE 条件式;
```
※条件式には「id = 0001」のような条件を記載します。

## 複数構文
```sql
UPDATE テーブル名 SET カラム名 = 値, カラム名 ＝ 値 WHERE 条件式;
```
【React】useCallbackとset関数を同時に使う方法

# useStateを定義する

ここでは`count`という名前の変数を例として定義しています。

```react
//const [状態変数, 状態を変更するための関数] = useState(状態の初期値);
const [price, setPrice] = useState(initialState)
```

# useCallback関数を定義する

doSomethingという例として関数を用意しています。

```react
const sampleFunc = useCallback(
  () => {doSomething(a, b)}, [a, b]
);
```

# set関数をコールバック関数に入れる
下記の例では本の金額をフォーム上などで変更したい時にuseCallbackとset関数を同時に使っています。


```react
const onChangePrice = useCallback(
  (price: BookPriceInput) => {
    setPrice({
      ...book,
      price,
    });
  },
  [book]
);
```

Bookエンティティに依存しているpriceのstate関数と依存配列である`[book]`を記述して、`useCallback`として使っています。
`...book`はスプレッド構文というものでbookの配列の要素を展開する構文になります。

この記述によりuseCallbackは値の変更がなければメモ化によって再計算することなく値を返してくれるので
onChangePriceにpriceを渡して、値が変更された場合（priceを変更した場合）にはset関数で状態を保持した上で再計算した値を返します。

次またonChangePriceにpriceを渡して同じ値だった場合は再計算することなく値を返却してくれます。
MySQLのdatetime型の列に現在日時を入れたい時

TBL定義のdefaultでcurrent_datestampを指定する。
コードで現在日時を取得する必要はない。
ちなみに、update時の現在日時を入れたい時は、TBL定義のon updateでcurrent_timestampを指定すればOK。
ALTER TABLEが遅い、、キャンセルする方法

# 背景
既存のテーブルに複合主キーをつけようとmysqlで
`mysql> ALTER TABLE users_exam_results ADD PRIMARY KEY (column1,column2,column3,column4,column5,column6);`

をSQLで実行したのだが遅い遅い。。遅すぎる。
一向に終わりそうにないのでいっそのこと一旦キャンセルしたくなった


# 原因
そもそも遅い原因なのだが
ALTE TABLE の対象テーブルusers_exam_resultsにはすでに60万件ものデータが入っていた
これは流石にすぐには終わるわけないだろう。。

ローカルのテスト環境だったこともあり、一旦、このALTER TABLEの処理をキャンセルして、
テーブルの中身をbackupした上で、truncateで削除して中身を空にしてから、
ALTER TABLEをしようと思う

# キャンセル手順

##### ①プロセスの確認

```
mysql> show processlist;
+----+------+-----------+-------------+---------+------+----------------+------------------------------------------------------------------------------------------------------+
| Id | User | Host      | db          | Command | Time | State          | Info                                                                                                 |
+----+------+-----------+-------------+---------+------+----------------+------------------------------------------------------------------------------------------------------+
| 35 | root | localhost | test        | Query   |  269 | altering table | ALTER TABLE users_exam_results ADD PRIMARY KEY (column1,column2,column3,column4,column5 |
| 39 | root | localhost | NULL        | Query   |    0 | starting       | show processlist                                                                                     |
+----+------+-----------+-------------+---------+------+----------------+------------------------------------------------------------------------------------------------------+
2 rows in set (0.00 sec)
```

プロセスを確認したことで、
該当のALTER TABLEをしているプロセスのIDは 35ということがわかった

##### ②プロセスをkill

あとは 以下のようにプロセスIDを指定してkillをする。
```
mysql> kill 35;
Query OK, 0 rows affected (0.00 sec)
```
そしたら別ウィンドウで開いてみていたmysqlの処理結果が以下のように変わった

```
mysql> ALTER TABLE users_exam_results ADD PRIMARY KEY (column1,column2,column3,column4,column5,column6);
ERROR 2013 (HY000): Lost connection to MySQL server during query
```

そして自分はphpmyadminを使っているのでそこからtruncateでテーブルの中身だけを削除し、
再度ALTER TABLEを実行

```
mysql> ALTER TABLE users_exam_results ADD PRIMARY KEY (column1,column2,column3,column4,column5,column6);

ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id:    84
Current database: test

Query OK, 0 rows affected (0.30 sec)
```

その後
` desc users_exam_detail;`
でテーブル構成をみたら、無事keyにprimary keyがセットされていた

![スクリーンショット 2022-12-26 14.54.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462069/e0a8477b-09f6-cb6c-c6cc-f63733763edc.png)
Tanzu Kubernetes Gridで仮想マシンのリソースサイズを変更する

TKGの仮想マシンのリソースサイズの変更方法のメモ。

TKGでの仮想マシンは`MachineDeployment`リソースで管理されている。この中で、ControlPlaneとWorkerNodeのベースとなるリソース情報を以下のように定義している（`kubectl get machinedeployment -o yaml`で分かる）。

```yaml
    spec:
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
          kind: KubeadmConfigTemplate
          name: tkg-test-md-0
      clusterName: tkg-test
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: VSphereMachineTemplate
        name: tkg-test-worker
      version: v1.23.8+vmware.2
```
WorkerNodeについては`kind: VSphereMachineTemplate`というテンプレートで管理されている。
そのため、デプロイしている仮想マシンのリソースサイズを変更したい場合は、このテンプレートを修正することで変更することが出来る。

現状のテンプレートを以下で取得する。なお編集で楽をするために`kubectl neat plugin`を利用している
```
kubectl get  vspheremachinetemplates tkg-test-worker -o yaml  |kubectl neat -f - > ./tkg-test-worker.yaml
```

ここでは利用しているCPU数を増やしてみる。
現状、以下のようになっている。
![1672033337188.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/ec8cdd0d-7166-0c9a-f164-6230044d0d83.png)

習得した`vspheremachinetemplates`リソースを以下のように修正する。
```diff
--- tkg-test-worker.yaml.orig	2022-12-26 14:30:40.562410200 +0900
+++ tkg-test-worker.yaml	2022-12-26 14:30:50.174396235 +0900
@@ -3,7 +3,7 @@
 metadata:
   annotations:
     vmTemplateMoid: vm-56
-  name: tkg-test-worker
+  name: tkg-test-worker-2
   namespace: default
 spec:
   template:
@@ -18,7 +18,7 @@
         devices:
         - dhcp4: true
           networkName: /vSAN-DC/network/VM Network
-      numCPUs: 2
+      numCPUs: 4
       resourcePool: /vSAN-DC/host/vSAN-Cluster/Resources/tkg
       server: 10.180.96.119
       storagePolicyName: ""
```
`vspheremachinetemplates`リソースは変更が出来ないため、新規にリソースを作ってそちらを利用するようMachineDeploymentを変更することで対応する。
```
kubectl apply -f tkg-test-worker.yaml
```

`MachineDeployment`リソースについては修正できるため、先程作成した`vspheremachinetemplates`リソースを使うようにeditする。
```
kubectl edit machinedeployment  -o yaml tkg-test-md-0
```
以下のような感じで、`infrastructureRef`で指している名前を差し替える。
```
      infrastructureRef:
        apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
        kind: VSphereMachineTemplate
        name: tkg-test-worker-2
```
変更して保存すると、直ぐに仮想マシンの再作成が走る。
![1672033459642.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/a9ec223b-2030-274b-931e-534b39519914.png)

このように、CPU数が4となった仮想マシンが再作成される。
![1672033619116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/f9801995-0642-d745-a08e-bcd4ea657ca9.png)

古い仮想マシンはしばらくすると自動的に削除される。