OmniAICreator/Qiita-1.07M huggingface dataset:
[IRNA] APIレスポンスのヘッダーとContent-Typeの変更方法

## はじめに
IBM Rapid Network Automation (IRNA)のデフォルト設定では、APIレスポンスのヘッダーに任意のヘッダーを付与できず、メディア・タイプ (Content-Typeヘッダー) が「application/json」で固定になっています。

この記事では、APIの応答ヘッダーとメディア・タイプを変更するための設定方法を紹介します。


## デフォルトのAPI応答の構成画面
APIの応答は、Workflowのデプロイ画面の`Custom Response Configuration`で定義します。デフォルトの設定では応答としてマッピングできるのは、`Status Code`, `Body`, `Format`の3項目のみとなっています。
![CustomResponse Configuration_default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468543/ca0af35a-6b57-5cc4-6d7e-289d5d68bdc5.png)


## 環境変数の設定
製品マニュアルの「[Implicit response configuration](https://www.ibm.com/docs/en/rapid-network-auto/1.1.x?topic=apis-workflow-authentication-api-gateway)」の記載に従って、`rna-core-pliant-front`と`rna-core-pliant-app-gateway`の2つDeploymentに対して環境変数`ENABLE_INSECURE_MAPPINGS`定義を追加し、値に`1`をセットします。(デフォルトでは該当環境変数定義はなく無効になっています。)


### Deploymentの編集
以下のコマンドでDeployment `rna-core-pliant-front`を直接編集し、`ENABLE_INSECURE_MAPPINGS=1`を追加します。

```terminal
[root@rna ~]# kubectl -n rna-core edit deployment rna-core-pliant-front
```


```yaml:rna-core-pliant-front
... (omit)
spec:
  ... (omit)
  template:
    ... (omit)
    spec:
      containers:
      - env:
        - name: ENABLE_INSECURE_MAPPINGS         ### 追記 ###
          value: "1"　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　       ### 追記 ###
        - name: WHITELABELING_DEFAULT_TO_EMPTY
          value: "1"
... (omit)
```

変更を保存すると下記Podが再起動されるので、正常起動されたことを確認します。
```terminal
[root@rna ~]# kubectl -n rna-core get pod | grep front
rna-core-pliant-front-7797558cdb-qxxpq                  1/1     Running     0             25s
rna-core-pliant-front-7797558cdb-p52bc                  1/1     Running     0             25s
```

同様に、`rna-core-pliant-app-gateway`にも環境変数を追加し保存します。

```yaml:rna-core-pliant-app-gateway
... (omit)
spec:
  ... (omit)
  template:
    ... (omit)
    spec:
      containers:
      - env:
        - name: ENABLE_INSECURE_MAPPINGS       ### 追記 ###
          value: "1"　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　     ### 追記 ###
        - name: API_URI
          value: http://pliant-api:8080
        ... (omit)
```
変更を保存すると下記Podが再起動されるので、正常起動されたことを確認します。
```terminal
[root@rna ~]# kubectl -n rna-core get pod | grep app
rna-core-pliant-app-gateway-8679965d7c-4cgc4            1/1     Running     0             36s
```

## 環境変数設定後のAPI応答の構成画面
再度Workflowのデプロイ画面の`Custom Response Configuration`を開くと、`Headers`と`Content-Type`の項目が追加され、設定できるようになりました。
![CustomResponse Configuration_after-settings.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468543/6c6c1848-9483-f502-7d42-d1a5a196f81c.png)

任意の応答ヘッダーを定義したい場合は、ワークフロー内でobject形式で変数を定義し、`Headers`でその変数を選択します。
`Content-Type`は以下のリストから値を選択可能です。

<dl>
  <dt>Content-Typeの選択肢</dt>
  <dd>application/json</dd>
  <dd>application/xml</dd>
  <dd>application/octet-stream</dd>
  <dd>application/zip</dd>
  <dd>application/gzip</dd>
  <dd>image/png</dd>
  <dd>image/svg+xml</dd>
  <dd>image/x-icon</dd>
  <dd>text/css</dd>
  <dd>text/html</dd>
  <dd>text/javascript</dd>
  <dd>text/plain</dd>
</dl>


以上、APIの応答ヘッダーとメディア・タイプを変更するための設定方法の紹介でした。
AWS Lambda にPythonウェブサーバーを立てる最小のDockerfileを書いた

関数URLにアクセスすれば
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118083/3231bf48-ede2-f3f8-7dca-8fb3780a2abb.png)

これが動くなら言語、フレームワーク問わずどんなウェブサーバーも動かせそうですね
```Dockerfile
FROM public.ecr.aws/lambda/python:3.12
COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.8.3 /lambda-adapter /opt/extensions/lambda-adapter
ENV PORT=8080
RUN printf "\n\
import os, http.server, socketserver\n\
class MyHandler(http.server.SimpleHTTPRequestHandler):\n\
    def do_GET(self):\n\
        self.send_response(200)\n\
        self.send_header('Content-type', 'text/html')\n\
        self.end_headers()\n\
        self.wfile.write(b'Hello World from Lambda')\n\
PORT = int(os.getenv('PORT'))\n\
with socketserver.TCPServer(('', PORT), MyHandler) as httpd:\n\
    print(f'Serving on port {PORT}')\n\
    httpd.serve_forever()\n\
" > test_server.py
ENTRYPOINT python test_server.py
```
paiza

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3527006/f9f01c74-2354-28b1-5433-06fcb92cb81e.png)
DとかCの問題ばっか解きまくってたらいつの間にか結構な数になってた
Aランクの問題はいつになったら解けるのかな
まだ自信ないなあ
プログラミング難しい

今日は教材は学ばず自分のサイトをいじっていました。
GPTに頼ったりもしていましたが、CSSとHTMLへの理解がちょっとだけ深まった気がします。
ただやはりまだまだ難しいことは変わりなく…。
いつか頼らずともすらすら書けるようになりたいですね。
【初心者用】Reactでよく使用される三項演算子の例


# はじめに

三項演算子は少し難しく感じることがありますが、適切に使用すると簡潔で読みやすいコードを書くことができます。以下に、よく使われる三項演算子を紹介しますので、初学者の方はこれらのパターンから理解できるようにしてきましょう:writing_hand:

# 1. 条件に基づいて値を代入する

```javascript
const age = 20;
const canDrink = age >= 21 ? "Yes" : "No";
```

# 2. nullチェックと同時にデフォルト値を設定する

```javascript
const username = user.name ? user.name : "Anonymous";
```

# 3. 条件に基づいてCSSクラスを切り替える（React等のフレームワークでよく使用）

```jsx
<div className={isActive ? "active" : "inactive"}>
  Content
</div>
```

# 4. 条件付きメソッド呼び出し

```javascript
const result = isValid ? processData() : handleError();
```

# 5. 簡単な算術演算

```javascript
const absoluteValue = number < 0 ? -number : number;
```

# 6. 配列内の条件付き要素追加:

```javascript
const items = [
  'Always present item',
  isSpecial ? 'Special item' : null,
  'Another always present item'
].filter(Boolean);
```

この例では、`isSpecial`が`true`の場合のみ'Special item'が配列に含まれます。`filter(Boolean)`は`null`や`undefined`を除去します。

# 7. オブジェクトのプロパティを条件付きで追加

```javascript
const user = {
  name: 'John',
  ...(isAdmin ? { role: 'admin' } : {})
};
```

`isAdmin`が`true`の場合のみ、`role`プロパティがオブジェクトに追加されます。

# 8. 条件付きのPromise chain

```javascript
someAsyncFunction()
  .then(result => result.success ? processSuccess(result) : Promise.reject(result.error))
  .catch(handleError);
```

この例では非同期処理の結果に基づいて成功時の処理を続けるか、エラーを発生させるかを決定しています。

# 9. API レスポンスの処理（null合体演算子）

```javascript
const response = await fetchUserData();
const username = response.user?.name ?? 'Anonymous';
```


# 10. JSXでの条件付きレンダリング（論理AND演算子）

```jsx
<div>
  {isLoggedIn && <WelcomeMessage />}
  {!isLoggedIn && <LoginPrompt />}
</div>
```

**9と10は三項演算子ではありませんが、同様の条件付きロジックを実現する簡潔な方法です。**


# おわりに
後半は少し難しかったかもしれませんが、ひとまずここに挙げているパターンをパッと見て理解できるようになれば、React使うのにも抵抗感はなくなるレベルかなと思います:writing_hand:
スプレッドシートに配列の内容を一括で出力する

## 目的
VBAからGASへの移行作業をしていて、スプレッドシートに一括でデータを書き込みたい場面があり、VBAのノリでチャチャっとできるだろうと思ってやってみると意外とハマったので備忘録として残しました。配列操作の勉強にもなりました。
## 結論
GASにおいてシートに配列を貼り付ける際の注意は以下の通りです。
- 貼り付け対象の配列は必ず**二次元配列**にする
GASの場合、VBAと違い一次元配列だとエラーが発生します。
- 配列の行列サイズと貼り付け範囲の行/列数を一致させる
VBAで言うところの`Resize`のイメージです。
## コード
```outputArrayToSheet.js
// 3行４列のシート範囲に一括貼り付け
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('シート1');

function outputArrayToSheet() {
    sheet.clearContents();      // シートクリア
    var arrTest = [];           // 配列初期化
  // 貼り付け対象の配列作成
    for(var i=1;i<=3;i++){      // ①行ループ(３行)
        var arrTestInt = [];    // ②列要素初期化
        for(var j=1;j<=4;j++){  // ③列ループ(４列)
            arrTestInt.push('test'+i+j);  // ④列要素作成
        }
        arrTest.push(arrTestInt); // ⑤列要素を行成分として格納(二次元配列を作成)
    }
  // ⑥シートに出力 
    var rowSize = arrTest.length    //  貼り付け行サイズ
    var colSize = arrTest[0].length //  貼り付け列サイズ
    sheet.getRange(1,1,rowSize,colSize).setValues(arrTest);
}
```
①〜⑤で貼り付け対象配列の作成、⑥でシートへの貼り付けを行なっています。
①〜⑤の部分は前準備のつもりで軽い気持ちで作ろうとしたのですが、 ~~意外と苦戦した~~ 勉強になったので残しておきました。初期化の時点では一次元配列ですが、配列の各要素に配列を`push`することで二次元配列にしています。
⑥は説明のため、変数として`rowSize, colSize`を宣言しています。引数に直接`arrTest.length`などと記述しても構いません。VBAがわかる方なら以下の記述と同義です。
```vb
' 配列をシートに貼り付ける(Excel VBA)
Sheets("シート１").Cells(1, 1).Resize(rowSize, colSize).Value = arrTest
```
## 実行結果
実行結果は以下の通りです。①の行ループ毎に、二次元配列として要素が順次追加されています。test○△の○が行番号、△が列番号を表し、スプレッドシートにもイメージ通り出力されています。
```text
// 1行目作成
[ [ 'test11', 'test12', 'test13', 'test14' ] ]
// 2行目追加
[ [ 'test11', 'test12', 'test13', 'test14' ],
  [ 'test21', 'test22', 'test23', 'test24' ] ] ←追加
// 3行目追加
[ [ 'test11', 'test12', 'test13', 'test14' ],
  [ 'test21', 'test22', 'test23', 'test24' ],
  [ 'test31', 'test32', 'test33', 'test34' ] ] ←追加
```
### 貼り付け結果
![スクリーンショット 2024-07-19 14.28.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/575325/9869cd05-4183-84fd-87e2-28b74774bddd.png "スプレッドシートに配列の内容を一括で出力する")
### 補足
逆に1行n列のシートデータを配列に格納するとどうなるのか、下記コードで検証してみました。
```confirmRange.js
function confirmRange(){
  var rngData = sheet.getRange(1,1,1,4).getValues();
  console.log(rngData);
}

// 出力結果
// [ [ 'test11', 'test12', 'test13', 'test14' ] ]
```
A1:D1のデータを`getValues`で取得し、結果を出力したものですが、たとえ1行でも二次元配列として返ることがわかります。
実はVBAでも同じ結果になりますが、ExcelVBAでは一次元配列は例外的に1行n列で出力可能です。GASは汎用性が高いからなのか、この辺りは例外なく全て二次元配列で扱っているんでしょうかね？
## あとがき
VBAでは一次元配列でもシートに貼り付けは可能ですが、GASで同じノリだとエラーが発生します。`1行n列`でも必ず二次元配列にします。
また、二次元配列を順々に生成していくのは意外とハマりました。当初はコード内に配列の中身を直書きするつもりでしたが、何か芸がないと思いループを使ってみると予想外の動きをして意外と難航しました。気がつけば(配列の各要素に配列を`push`する)あぁそうだよねという方法ですね。
## リンク
GASにおける二次元配列について、導入から丁寧に説明されているサイトを紹介します。
[【超初心者向け！】GASの二次元配列をやさしく図入り解説！](https://www.yukibnb.com/entry/2019/08/30/114339 "https://www.yukibnb.com/entry/2019/08/30/114339")
初心者から上級者へ：Vimmerになるために覚えるべき必須コマンド

# はじめに
Vimは強力なテキストエディタであり、効果的に使いこなすことで開発速度を大幅に向上させることができます。しかし、その学習曲線の高さから、多くのユーザーが初めて触れるときに挫折してしまいます。この記事では、初心者から上級者までが覚えるべきVimの必須コマンドを紹介し、Vimmerへの道をサポートします。

# 基本的な移動コマンド
Vimの基本は、テキストの移動です。まずは基本的な移動コマンドを覚えましょう。

| コマンド | 説明 |
|:-:|:-:|
| h | 左に移動 |
| j | 下に移動 |
| k | 上に移動 |
| l | 右に移動 |

これらのコマンドは、カーソルキーの代わりに使用します。

# テキスト編集の基本コマンド
次に、基本的なテキスト編集コマンドを覚えましょう。

| コマンド | 説明 |
|:-:|:-:|
| i | 挿入モードに入る |
| a | 挿入モードに入り、カーソルを1つ右に移動 |
| o | 挿入モードに入り、新しい行を開く |
| x | カーソル位置の文字を削除 |
| u | 直前の操作を取り消す |


# テキスト操作の拡張コマンド
さらに高度なテキスト操作のためのコマンドです。

| コマンド | 説明 |
|:-:|:-:|
| yy | 現在の行をコピー |
| dd | 現在の行を削除 |
| p | コピーまたは削除したテキストを貼り付け |
| r | カーソル位置の文字を置き換える |

※yy,dd,p,rはよく使います


# 検索と置換
大規模なテキスト編集には検索と置換が不可欠です。

| コマンド | 説明 |
|:-:|:-:|
| / | 検索モードに入る |
| n | 次の一致する結果に移動 |
| N | 前の一致する結果に移動 |
| :%s/old/new/g | ファイル全体でoldをnewに置換 |

※検索と置換も多用します。


# ファイル操作
Vimを使ってファイルを操作するための基本コマンドです。

| コマンド | 説明 |
|:-:|:-:|
| :w | ファイルを保存 |
| :q | Vimを終了 |
| :wq | 保存して終了 |
| :q! | 保存せずに終了 |

※保存し忘れにご注意を。

# マクロとカスタマイズ
効率を最大化するためにマクロとカスタマイズを学びましょう。

| コマンド | 説明 |
|:-:|:-:|
| q<register> | マクロの記録開始 |
| @<register> | マクロの再生 |
| :map | カスタムキーマッピングの設定 |


# まとめ
Vimは多機能であり、ここで紹介したコマンドはその一部に過ぎません。しかし、これらのコマンドを覚えることで、Vimmerへの道を確実に進むことができます。継続的に練習し、自分に合ったワークフローを見つけてください。

# おわりに
この記事を参考に、Vimの魅力を感じ、効率的なテキスト編集ができるようになることを願っています。質問やコメントがあれば、ぜひお寄せください！
図形認識AI

chatGPTに書いてもらったコードに、必要な箇所だけ修正したり、パスを設定して作りました。ファイル名はshape_and_text_recognition.pyです。Tesseractというのをインストールして環境変数を設定してからコード中にパスを記載し、
Dense(2, activation='softmax')  # クラス数に応じて変更
の部分の数字の2はフォルダの数です。図形を認識できるAIを作りたくてwordの図形描画で描いたものを画像として保存してフォルダにいくつか入れました。
モデルのトレーニングの箇所で、トレーニング用のフォルダのパスを指定します。
train_generator = train_datagen.flow_from_directory(
        r'C:\Users\Owner\Desktop\AI\data\train',
        target_size=(64, 64),
        batch_size=32,
        class_mode='categorical'
    )
最後に下のメイン処理の箇所で
図形認識と文字認識の統合の項目の
image_path = r'C:\Users\Owner\Desktop\triangle0.png'を
認識したい画像のパスを入力して実行するだけです。
あまりうまくはいきませんでしたが、エラーを解決できたのは初めてだったので、今後の改良につなげます。

```:python
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D, MaxPooling2D, Flatten, Dense
from tensorflow.keras.preprocessing.image import ImageDataGenerator
import cv2
import pytesseract
from PIL import Image
import numpy as np

# Tesseractのパス設定（必要に応じて変更）
pytesseract.pytesseract.tesseract_cmd = r'C:\Users\Owner\AppData\Local\Programs\Tesseract-OCR\tesseract.exe'

# 図形認識用のCNNモデル定義
def create_shape_model():
    model = Sequential([
        Conv2D(32, (3, 3), activation='relu', input_shape=(64, 64, 3)),
        MaxPooling2D(pool_size=(2, 2)),
        Conv2D(64, (3, 3), activation='relu'),
        MaxPooling2D(pool_size=(2, 2)),
        Flatten(),
        Dense(128, activation='relu'),
        Dense(2, activation='softmax')  # クラス数に応じて変更
    ])
    model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
    return model

# モデルのトレーニング
def train_shape_model(model):
    train_datagen = ImageDataGenerator(rescale=1./255)
    train_generator = train_datagen.flow_from_directory(
        r'C:\Users\Owner\Desktop\AI\data\train',
        target_size=(64, 64),
        batch_size=32,
        class_mode='categorical'
    )
    model.fit(train_generator, epochs=10)
    model.save('shape_model.h5')

# 図形認識用の前処理
def preprocess_image(img_path):
    img = cv2.imread(img_path)
    img_resized = cv2.resize(img, (64, 64))
    img_array = np.array(img_resized) / 255.0
    return np.expand_dims(img_array, axis=0)

# 図形認識
def recognize_shape(model, img_path):
    preprocessed_img = preprocess_image(img_path)
    predictions = model.predict(preprocessed_img)
    class_index = np.argmax(predictions)
    return class_index  # クラスのインデックスを返す

# 文字認識
def recognize_text(img_path):
    image = cv2.imread(img_path)
    text = pytesseract.image_to_string(Image.fromarray(image))
    return text

# メイン処理
def main():
    # 1. 図形認識モデルの作成とトレーニング
    shape_model = create_shape_model()
    train_shape_model(shape_model)

    # 2. 図形認識と文字認識の統合
    image_path = r'C:\Users\Owner\Desktop\triangle0.png'
    
    # 図形認識の実行
    shape_class = recognize_shape(shape_model, image_path)
    print("Recognized shape class:", shape_class)

    # 文字認識の実行
    text = recognize_text(image_path)
    print("Recognized text:", text)

if __name__ == "__main__":
    main()
```
Lispはクラッキング防御の守護神となれるか？

# 事件
日本のkadokawa社はロシア系のクラッキング集団からランサムウェアにより攻撃をうけ、身代金を要求されているという報道がありました。近年、このような攻撃を受ける例が増加傾向になります。ロシア、中国からの侵入が多いようです。

# 自己言及
私はふと、ゲーデルの不完全性定理のことを思い出しました。自己言及するとき、その証明は不可能になるというものです。そのことはLispを使うと容易に説明、証明できることはチャイティンさんが述べています。私も以前、記事にして投稿しました。

この性質はクラッキングからの防御に使えないだろうか？


# Lispと自己言及
LispはS式という同図像性をその特徴の一つにしています。自分自身を書き換えることさえ可能です。自分自身を書き換えるプログラムがあったとしたら、そしてそれでネットワークの侵入経路を制御するプログラムが書かれていたら？　これはクラッカーに対しての最強の防壁にならないだろうか？状態が変わるのです。

![bandicam 2024-07-19 16-11-41-502.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/5f42b13f-e5df-2a36-2e92-e82e7f5e8721.jpeg)


そう、変異を繰り返すウイルスのようなものです。それを突破するツールを作った頃にはプログラムは姿を変えています。ツールは何の役にも立ちません。この手のプログラムを作れるプログラム言語は存在するでしょうか？　私が知りうる限り、Lispだけです。

```
(defun unprovable-p (x) (not (valid-proof-p x)))
```
上記のコードはチャイティンさんの本にある例です。詳しいことは私の過去記事をご参照ください。

https://qiita.com/sym_num/items/5c23b6d8c740ce353e57



# 具体的に
もう少し具体的に考えてみましょう。脳は学習することでシナプスの繋がり具合を変更していきます。仮に部分的に脳にダメージがあったとしても、その部分を代替する機能が形成されるとのことです。ネットワークにおいて仮に侵入を許してしまったとしても、その部分を直ちに閉鎖、破壊して、代替機能をプログラムすることができれば侵入から防御することができるでしょう。どのように代替機能が形成されるのかは外部からはまったく予想不可能です。脳自体にも予想がつきません。

![bandicam 2024-07-19 16-00-04-031.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/e9854474-3930-292e-d6de-de31c78f7dd2.jpeg)


空き巣へ対処法を考えてみましょう。防犯対策はさまざまありますが、その形態が固定化されているならば、突破されることもあるでしょう。しかし、状況に応じて対抗策が変化するような防犯システムならどうでしょうか？空き巣には予想不可能が場面を作ることになります。その対抗策が犯人に予測されないこと、これが最大の防御ではないでしょうか？

![bandicam 2024-07-19 16-01-38-438.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/23b4fb7f-ed82-faf3-62e4-b17c9049c88c.jpeg)



# 経済価値
kadokawa社に対する身代金は4億とも10億ともいわれています。アメリカ合衆国においてはこの身代金を支払うケースが多いそうです。保険制度があり支払い可能であり、その方が経済効率がいいというのが理由です。日本にはそのような保険はありません。禁止されています。企業はクラッキングをはねのけなければなりません。もしも、そのような手法が開発されるのなら、莫大な経済価値を生むことでしょう。

AIなど主流な分野でPythonにその座を譲り渡したLispです。しかし、まだまだ活躍の場は残っていると私は信じています。
[API] API Gateway と BFF の違い

# まとめ

# 目次

# API Gateway

# BFF


# 参考リンク
- [API Gateway vs Backend For Frontend](https://www.manuelkruisz.com/blog/posts/api-gateway-vs-bff)
- [APIGatewayパターンとBFF](https://kamihikouki.hatenablog.com/entry/2018/07/20/134307)
- [API GatewayとBackend For Frontendの比較](https://kuroco.app/ja/blog/api-gateway-vs-backend-for-frontend/)
- -[マイクロサービス推進に伴うBFFの必要性について振り返る](https://qiita.com/dnd0513/items/a03e50d4ac5f54f8cb2b)
Vercelで本番ブランチをmainブランチ以外に変更する方法

## 目的

デフォルトの本番ブランチ `main` から、別途作成した本番用ブランチ(例: `prd`)がデプロイされるように変更したい。

## 手順

### 手順1: 本番ブランチのブランチ名を変更する
1. 上部メニューの「Settings」をクリック
2. Project Settingsメニューの「Git」をクリック
3. 「Production Branch」の`Branch Name`の値を、設定したいブランチ名に変更し入力する(例: [変更前]`main` → [変更後]`prd`)
4. 「Save」ボタンをクリック

![8b577b978493195e9417-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601631/67b66e22-9fd2-b9b5-67fb-5d867bc10a31.png)


### 手順2: ドメイン設定のブランチを変更する
1. Project Settingsメニューの「Domains」をクリックし、`<project>.vercel.app`の「Edit」ボタンをクリック
![8b577b978493195e9417-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601631/657e6502-2ba2-6484-123e-156a00a3e6b0.png)
2. `Git Branch`のプルダウンから、先ほど変更したブランチをクリックする(例: [変更前]`main` → [変更後]`prd`)
![8b577b978493195e9417-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601631/d9e18467-754c-db92-ae35-4e732762961d.png)
3. 「Save」ボタンをクリック
![8b577b978493195e9417-4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601631/6485ebaa-71cf-6dfa-72a0-ae948389702f.png)
    

### 手順3: (任意)確認のためデプロイする

先ほど変更したブランチから、空のコミットをプッシュする(※GitリポジトリでCI/CD設定済みの前提)などの方法でデプロイする。
デプロイ完了後、`<project>.vercel.app` にアクセスし、確認して完了。

```bash
# 空のコミット & プッシュ 例
git commit --allow-empty -m "test production deploy" && git push
```
[Arduino×VSCode×PlatformIO]コンパイルは通るのにIntelliSenseの波線が消えないときの設定

## コンパイルは通るのにエラー！？
M5Stack Basicの開発環境をVSCodeとPlatformIOで整えて、昔作ったプログラム(Arduino・当時M5Stack上でちゃんと動いていた)を編集しようとしたら、IntelliSenseが変数を定義するときの型のところとか関数の呼び出しとかでエラーの波線が出ました。
![変数型の指定のところにエラーの赤い波線が入ったコード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835597/4a0cdb78-6aa8-081b-b612-b6cb9c19af73.png)

特におかしなところは無かったので、そのままコンパイルをしたら、コンパイルに成功し、M5Stackへの書き込みも出来て、ちゃんと動きました。
なんじゃこりゃ？？というわけで、いろいろ調べた結果、**IntelliSenseの設定が原因**だということがわかったので、備忘録として書き残しておきます。

## 設定のしかた
1. VSCodeの設定を開きます
![VSCodeの設定を開く(ファイル→ユーザー設定→設定)](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835597/20c675f2-08fe-fd92-8caf-59ab3747a229.png)

2. 検索窓に「IntelliSense」と入力して絞り込み、「C_Cpp: Intelli Sense Engine」の項目を「Tag Parser」に変更します
![IntelliSenseで絞り込んだ設定画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835597/58279a67-0683-c7f3-df99-fecb31cadb3f.png)

3. 出てきたダイアログで「再読み込み」をクリックします
![再読み込みを促すダイアログ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835597/9572ed92-1bed-a8b0-8c37-d270a1fd9880.png)

これでエラーの波線が消えるはずです。
![エラーの赤い波線が消えたコード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3835597/8dca5588-00f2-b3f0-c55a-852f08bd44cb.png)

## なんでこれで波線が消えるの？
どうやら、Arduinoは、プロトタイプ宣言などがきちんと行われていなくても、適宜補完してコンパイルしてくれる仕様になっているのですが、VSCodeのC/C++の標準設定になっているIntelliSense Engineの「default」は、厳密に宣言がされていないとエラーと表示するようになっていて、それが原因で（コンパイルは通るのに）エラーと表示されてしまうようです。
また、uint8_tなどの変数型の別名も「default」ではエラーと表示されてしまうみたいです。
そこで、「Tag Parser」という、曖昧さを許可するモードに変更することで、厳密ではない構文もエラーとして弾かれないように出来るようです。
(私なりの解釈ではこんな感じですが、もしかしたら違うかもしれません)

## 参考文献
[【C++】VScodeのC++設定で詰まったこと【備忘録】 - あわーすの徒然日記2](https://ourth.hatenablog.com/entry/2019/06/17/133555)
ITパスポート 開発プロセス

・開発プロセス
開発者が利用者の要件を取り入れながら、実際にシステムを開発するプロセス

・システム要件定義
開発者が利用者にヒアリングして、システム化の対象範囲を明確にし、システムに要求される機能や性能などを定義する

・ソフトウェア要件定義
開発者が利用者にヒアリングして、システムを構成するソフトウェアに要求される機能や性能、インタフェースなどを定義する

・システム設計
開発者がシステム要件をシステムでどのように実現できるか検討する

・ソフトウェア設計
開発者がソフトウェア要件をソフトウェアでどのように実現できるか検討する

・ソフトウェア構築（プログラミング）
開発者がソフトウェア詳細設計書に基づき、プログラムを作成する

・レビュー
定義書や設計書の不備や誤りを早期に発見する目的で、工程ごとに行われる検討会議

・ソフトウェアの品質特性
・機能性
仕様書どおりに操作ができ、正しく動作すること
・使用性
理解や習得、操作がしやすいこと
・信頼性
必要な時に使用でき、故障時には速やかに回復できること
・効率性
応答時間や処理時間などを求められる性能が備わっていること
・保守性
修正がしやすいこと
・移植性
他の環境へ移しやすいこと

・コーディング規約
プログラム内の変数名の付け方やコメントの書き方などの標準的な記述のルール

・セキュリティバイデザイン
システムの企画・設計段階から、セキュリティ対策を組み込むという考え方
Type Script で onClick={function()}がダメな理由

## Type Scriptを書いていて、疑問だった箇所の忘備録

### しがちなミス
```tsx
export const funcA = () => {
    console.log('test')
}

// この呼び出しはエラーになる
<Button 
    onClick={funcA()}
/>
```

### OKな呼び出し
```tsx
export const funcA = () => {
    console.log('test')
}

<Button 
    onClick={funcA}
/>

<Button 
    onClick={() => funcA()}
/>
```

### 違い
```tsx
function()
```

と記載した場合、単純な関数の呼び出し（即時関数）となってしまうため、関数そのものではなく関数の結果（関数の戻り値）がonClickに設定されてしまう。
よって、動かなかったりエラーとなる

下記二つは、関数自体をonClickに渡せている。
アロー関数もOK

```tsx
export const funcA = () => {
    console.log('test')
}

<Button 
    onClick={funcA}
/>

<Button 
    onClick={() => funcA()}
/>
```

単純なことで、lintエラーが出る際なんとなく修正していましたが、ちゃんと理由がわかり納得でした。
普段から、ただ書けるのではなく理解するまで、を心がけないとなぁと反省です。
LogicAppsからRunbook(Hybrid Runbook Worker)に入力パラメータを渡す方法

#### はじめに
LogicAppsにはMicrosoft Defender for EndpointやAzure Monitorのアラートをトリガーとして利用ができます。一方で、Hybrid Runbook WorkerはPowershellを任意の仮想マシンのローカルで起動できるなど、LogicAppsには無い便利な要素があります。
そこで、今回はLogicAppsからRunbookを呼び出して起動するときに、LogicAppsで定義した変数値をRunbookへ渡す方法について検証しましたので、その結果をこちらにまとめます。

## やりたいこと
今回検証していくアプリの処理フローはこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/9f9fe67d-5245-ba59-fe7c-d794b09e0baf.png)
注意：スケジュールの設定をしておりますが、今回の検証では手動でトリガーを起動しています。

#### 前提条件
以下、今回の検証の条件です。

■ Azureの構成
Logic Apps：Standard構成(ここは従量課金でも問題ないと思われます)
Automation：Hybrid Runbook Workerを使用

■ Runbookを起動した仮想マシン
OS：Redhat 8系
PowerShell：7.2

## LogicApps側の設定
Logic AppsにマネージドIDをオンにして、以下権限を割り振っておきます。
+ Automation ジョブオペレーター
+ Automation Runbookオペレーター

:::note info
「Automation Runbookオペレーター」はジョブの起動では必要ないですが、設定する際に必要です。設定後に外しても問題ありません。
:::

LogicApps側はこんな感じで設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/016223ed-8130-848e-ffc0-38b1b7439bb4.png)

Automationへの連携コネクタはCreate Job Response([参考のDocs](https://learn.microsoft.com/ja-jp/connectors/azureautomation/))を使用します。

Parameters内には以下のように記載しています。
~~~ Parameters
{"name": "John Doe", "age": 30}
~~~

## Runbook側の設定
以下内容でRunbookを記載していきます。
~~~ Inputtest
Param
(
  [Parameter (Mandatory= $true)]
  [String] $name,
  
  [Parameter (Mandatory= $true)]
  [Int32] $age
)

Write-Output "My name is $name."
Write-Output "I started a businness at $age."
~~~
Runbookの入力パラメータという機能を使うことで、引き渡したパラメータの使用が可能です。詳しくは[Docs](https://learn.microsoft.com/ja-jp/azure/automation/runbook-input-parameters)を確認してください。

## 結果
LogicAppsの実行履歴を確認します。以下の通りSucceededになっていますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/202f8461-76f0-1fd1-28c3-8ba71c6544e2.png)


Automation Account>Runbook>ジョブ>入力タブで、Runbook側のログの確認ができます。入力タブで入力値がしっかりと引き渡せているか確認できます。見た感じ、大丈夫そうですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/a5ee13f1-5500-4667-1068-a493a5f183f0.png)

そして・・・出力結果はこんな感じで、うまく出力できています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/54778034-16ab-7f21-3601-a23d3d952de7.png)

念のため、エラータブでエラーが発生していないことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678759/b75dcf97-3a94-0817-8483-25b7405a5d31.png)


:::note warn
以下、現状確認できている制約です。もしかしたら解決方法あるかもですが、現在確認中です。知ってる方いたら教えて下さい。
+ Strings型は間にスペースあると、Runbook側でエラーになります
+ Script内のPRAMで定義していない値を渡すと、Runbook側でエラーになります
+ PythonとPowershellでPARAMの記載方法が若干異なるようです。
:::
[rails] pluckとselectの使い分け

## 経緯
あるプロジェクトで、特定のデータを集計して取得する必要がありました。最初にpluckメソッドを使用してデータを取得しましたが、取得したデータをハッシュ化する際に配列の順番を間違えてしまい、エラーが発生しました。これは、pluckメソッドが配列を返すため、各要素の順番を正しく処理する必要があるためでした。

## pluckメソッドとは
pluckメソッドは、ActiveRecordのクエリメソッドの一つで、指定したカラムの値を直接配列として取得する際に使用されます。例えば、以下のように使用します。

```
user_data = User.where(active: true).pluck(:id, :name)

# => [[1, "Alice"], [2, "Bob"], [3, "Charlie"]]
```
このクエリは、activeカラムがtrueのユーザーのidとnameを配列として取得します。しかし、複数のカラムを取得した場合、各要素の順番を意識する必要があります。

#### メリット
・シンプルで高速なクエリ実行
・必要なカラムのみを取得するため、メモリ使用量が少ない

#### デメリット
・データの順番を意識する必要がある
・複数カラムの結果を扱う際に配列を利用するため、可読性が低くなる場合がある

## selectメソッドとは
selectメソッドは、ActiveRecordのクエリメソッドの一つで、指定したカラムを含むActiveRecordオブジェクトのリレーションを返します。例えば、以下のように使用します。

```
user_data = User.select(:id, :name).where(active: true)

# 出力例:
# 1, "Alice"
# 2, "Bob"
# 3, "Charlie"
```
このクエリは、activeカラムがtrueのユーザーのidとnameを含むActiveRecordオブジェクトを返します。返されたオブジェクトはハッシュとして扱えるため、データの順番を意識する必要がありません。

#### メリット
・ActiveRecordオブジェクトとして扱えるため、**データの順番**を意識する必要がない
・結果のデータをハッシュとして処理しやすい
・可読性が高く、複雑なクエリでも扱いやすい

#### デメリット
・取得するデータ量が多い場合、メモリ使用量が多くなる
・クエリ実行速度がpluckより遅くなる場合がある

## 使い分け方
pluckとselectの使い分けは、主にデータの取得方法と扱いやすさに依存します。

単純なカラムの値を配列として取得したい場合：pluckメソッドを使用します。
例えば、特定のカラムの値のみを高速に取得したい場合に適しています。

```
user_ids = User.where(active: true).pluck(:id)
```
複数のカラムを取得し、結果をハッシュとして扱いたい場合：selectメソッドを使用します。例えば、集計結果を含む複数のカラムを取得し、それらを扱いやすい形で処理したい場合に適しています。

```
user_data = User.select(:id, :name).where(active: true)
```

## まとめ
pluckメソッドとselectメソッドは、それぞれメリットとデメリットがあり、使い分けが重要です。単純なカラムの値を取得する場合はpluckを使用し、複数のカラムを取得し、結果をハッシュとして扱いたい場合はselectを使用するのが適切です。これにより、データの取得と処理を効率的に行うことができます。
TypeScriptのinferについて

TypeScriptの`infer`は、型を簡単に推論するための便利な仕組みです。
この記事では、`infer`の使い方を簡単に紹介します。

## 型推論の基礎

TypeScriptは明示的な型注釈がない場合、以下のように型を推論をしてくれます。
```typescript
let str = "Hello, World!"; // strは文字列
```
TypeScriptは自動的に`str`型で推論します。

## inferの使用方法

### 基本的な使用例

`infer`を使って型推論を行う基本的な例：
```typescript
type GetType<T> = T extends infer S ? S : never;
type T1 = GetType<typeof str>; // string
```
この例では、`infer`キーワードを使って`T`の型を`S`として推論しています。

### 配列内の型を推論する

配列内の要素の型を抽出する方法を見てみましょう：
```typescript
let arr = [1, 2, 3];

type GetTypeOfArrayElement<T> = T extends (infer S)[] ? S : never;
type T1 = GetTypeOfArrayElement<typeof arr>; // number
```
この方法で、配列内の要素の型を推論することができます。

### Promiseの型を推論する

Promiseが返す値の型を特定する場合、`infer`が役立ちます：
```typescript
let promise = Promise.resolve([1, 2, 3]); // Promise<number[]>

type GetTypeOfPromise<T> = T extends Promise<infer S> ? S : never;
type T1 = GetTypeOfPromise<typeof promise>; // number[]
```
TypeScriptには、これを支援するビルトインユーティリティ型`Awaited`もあります：
```typescript
type T4 = Awaited<typeof promise>; // number[]
```

### 関数の引数の型を推論する

関数の引数の型を取得するには、次のようにします：
```typescript
type GetTypeOfFirstArgument<T> = T extends (arg: infer U, ...args: any[]) => any ? U : never;
type T1 = GetTypeOfFirstArgument<typeof document.getElementById>; // string
```
この方法で、関数の最初の引数の型を推論することができます。

### Reactコンポーネントのプロップス型を推論する

ライブラリがコンポーネントのプロップスをエクスポートしていない場合でも、`infer`を使ってプロップス型を取得できます：
```typescript
const OutsideComponent: React.FC<{ name: string }> = () => null;

type InferProps<T> = T extends React.FC<infer P> ? P : never;
type Props = InferProps<typeof OutsideComponent>;
```
この技術で、Reactコンポーネントのプロップス型を推論することができます。

## 最後に
今回は`infer`について解説してみました！
inferを取り入れることで、コードを大幅に簡素化し、複雑な型操作をシンプルにし、開発の生産性を向上させることができます。
この仕組みを活用して、TypeScriptの型推論の真の可能性を引き出しましょう!

## 参考
> [サバイバルTypeScript](https://typescriptbook.jp/reference/type-reuse/infer)
土田プロによる「運を可視化する術」

クラスメソッドさんのイベント[DevelopersIO2024](https://event.classmethod.jp/odyssey-offline?day3)で麻雀界で有名なトイツ王子、[土田浩翔プロ](https://twitter.com/tsuchidakosho)のお話を聞いてきたのでブログにしてみました。

## 土田プロからのオープニングトーク

運が良い状態が長く続くのが理想ですよね
運は巡ってくるだけじゃない、自分の生活によって運を寄せられる
麻雀はダークサイドだったけど、今は知育・教育の一環になっていけばと土田プロは考えてる

## 数の世界から離れる

運が９割、技術が１割。土田プロが５０代になった時の印象。３０代の頃は逆だった。

点数が高かったから運が良いわけじゃない
麻雀も仕事も数字は後からついてくる、まずは運を育てる

運は明るい人に寄ってくる
人工物を触る人にはよってこない、スマホばかり触っていると運は寄ってこない

なるべく自然に身に置くとよい
耳から聞こえる自然界の音が大事
自分の中の煩悩をいかに捨てて、自他を比較しない・比較せず自分と向き合う

自分を見つめ直すために自然に身を置いて、自分の考える。麻雀は相手と戦うんじゃなくて、自分と戦う
損得勘定で動いちゃいけない

運は明るいところへ寄ってくる、悲観的にならずに肯定的に生きていくと運が寄ってくる
自分のスキルをどうやってあげるか、自分を高めることをすると良い運が寄ってくる

## 予測力を身につける

予測力をつけるには、気づき
気づきを増やす、日々の生活の中で見逃している気づきを大事にする

市場を大きく見るよりもお客様を個々に見て大事にする（横田社長）

捨てられた牌から気づく、人からのオーラを感じる。

#### 大局観
自分が置かれている位置を俯瞰する力が大事
自分が劣勢に置かれている場合に、切羽詰まって大博打にしにいくことは間違っている

仕事の上でもお客様からの些細な気づきを大切にして交渉する（司会者）

#### 気づきを鍛える
土屋プロが師匠から教わったのは、公共交通機関へ乗った時に次の駅で何人が乗ってくるか？を予測とことが大事と教わったけど土田プロは諦めてしまった
（多分、気づきの積み重ねの集大成として予測ができるようになるんだろうね）

この話は機械学習でもパラメータのあたりをつける時に気づきが大事だったりする（横田社長）

#### 「勘が働く」
勘に基づく行動の方が成功例が多いと思っている
今までの経験値から導いているから、それも予測している

#### 「アヤがつく」
よく自分に回ってくる牌がある、自分に回ってくることがなんなのか？それに気づいてうまく活用するとうまくまわる
アヤがついたからと

大局観を磨くために、画を張らず、自分を客観的に見定める


## 理より感覚を優先する

本能で動く、経験則から導かれる感覚
自然に帰って本能を呼び覚ます

「なかなか難しい」と理で考えると難しいけど、体で「やってみよう」と行動してみるのが大事

上下関係やルールを取り払って行動してみるのに近いかも（横田社長）

## アイスブレイク

葉子戯：麻雀の誕生は？ 1,300年前。中国の唐の時代、高級官僚が妾の葉子さんのために作ったゲーム
麻雀を伝えたのは夏目漱石。名川彦作。日本へ伝わったのは近代。最初に持ち帰ったのは北海道。樺太経由で持ち帰った。

## 運を引き寄せる７つのこと

1. 気分よく生きる。
2. 否定しないこと   
    - 批判しない、ぐちを言わない、否定から生まれない
3. 人を好きになる
    - 誰であれ人間が好き、打算的な愛情ではなく男女関係なく愛情をもつ
4. 気づきの量を増やす
    - 起きた時に気づくこと、起きて目に見えた風景から何かの変化を気づく、気づくことで気遣いが増える・相手のことに気づいて相手にしてあげる
5. 全てを受け入れる
    - 自分に降りかかってきたことを受け入れる、降りかかったことをシャットアウトしない、まずは受け入れて客観的に判断し、感情的にならない、主観的にならず客観的に判断する、
6. 自分の動きから無駄をなくすること
    - 時間は有限だから無駄を減らして時間を増やす、そうすると周りの人の時間が増える、気づきが悪いと人とぶつかったりする
7. 周りと自分を比較しない・嫉妬しない
    - 自分を知る、自分を知らなさすぎるから、もっと自分を知る。相手と比較してても時間の無駄

#### 無償の愛
自分が施したことに対価を求めない、気づきから気遣ったことへの見返りを求めない、愛こそ全て
麻雀で、どんなに点数が低くても、どんなに悪い状況でも、自分に来ている牌たちを愛する
損得で判断せず、見返りを求めない

## 最後に会場で麻雀を知っている方々へ

振り込む、放銃することは良い行為、相手に愛を与える良い行為www
相手の喜びを自分の喜びとしてとらえる（会場が笑いに包まれる）

## 今回のセミナーを聞いた所感

土田さんの運を可視化する話、すごく面白かったし、耳の痛い話だった。
煩悩に振り回されて足掻いているのは自分のせいなんだよね、、、
registerEndpointでは有効な値を返すようにしよう

以下のようなAPIがあり、これを含むコンポーネントをテストしたいとする。
```vue
<template>
  ...
</template>

<script setup lang="ts">
const add = async () => {
  await $fetch("/api/add", {
    method: "POST"
  })
  console.log('追加しました')
}
</script>
```

テストコードで`registerEndpoint`を使い、APIレスポンスをモックする。
ここで、戻り値を使わないので`handler`に空の関数を定義するとエラーとなる。
```typescript
it('test', async () => {
  registerEndpoint("/api/add", {
    method: "POST",
    handler: () => {}
  })

  const component = await mountSuspended(HogeComponent)
  await component.setupState["add"]();
})
```
```plaintext:テスト結果
FAIL  components/HogeComponent.spec.ts > HogeComponent > test
FetchError: [POST] "/api/add": 404 Cannot find any path matching /.
 ❯ $fetch2 node_modules/ofetch/dist/shared/ofetch.37386b05.mjs:268:15
 ❯ components/HogeComponent.spec.ts:22:5
     20|       handler: () => {},
     21|     });
     22|     await $fetch("/api/add", {
       |     ^
     23|       method: "POST",
     24|     });
```

エラー文が分かりづらいですが、`handler`に有効な値を返す関数を追加したところテスト成功しました。
```diff_typescript
it('test', async () => {
  registerEndpoint("/api/add", {
    method: "POST",
-   handler: () => {}
+   handler: () => ""
  })

  const component = await mountSuspended(HogeComponent)
  await component.setupState["add"]();
})
```
本来`/api/add`はvoidを返すAPIなので気持ち悪いですが...
もし他に良い書き方があれば教えて頂けますと幸いです :bow:

---

以下参考
```typescript:エラーになるhandler
() => {}

() => undefined

() => {
  return
}

() => {
  return undefined
}
```

```typescript:成功するhandler
() => null

() => ""

() => 0

() => false

() => {
  return {}
}
```
【Xcode】Simulatorで「＠」と入力する方法

「 **＠** 」と打っても「 **[** 」と表示されちまう....！！！
というときは

### `shift キー`  と  `2` を同時押し
するとキーボードからでも`@`と入力できます！


3年くらい前に先輩に教えていただいたのですが、あのとき聞いていなかったら僕は今も気づかなかっただろうなぁ..と思ったので投稿させていただきました！
ESXi上のAmazonLinux2023でNTP同期を無効化する

ESXi上に起動させたAmazonLinux2023でNTP同期を無効化する方法です。フタをあければ何という事は無いのですが知らないとハマりそう、というか見事にハマりましたので自戒を込めて。

# 1. OS設定変更
まずは以下のコマンドでchronydとsystemd-timesyncd無効化しましょう。
```bash
systemctl stop chronyd
systemctl disable chronyd
systemctl stop systemd-timesyncd
systemctl disable systemd-timesyncd
```

もしtimedatectlでJST9にしている場合は以下のコマンドも実施しておきましょう。
```bash
timedatectl set-local-rtc 1 --adjust-system-clock
```

この時点でいくらdateコマンドを実行しても1分もたたないうちに、時刻が元に戻ってしまいますので次にESXiの設定を変更します。


# 2 . ESXi設定変更
対象仮想マシンの「設定の編集」開き、仮想マシンオプションの「VMware Tools」のプルダウンをクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335933/1d970031-2b29-b6cb-3727-20fc3efdf98c.png)
CentOSなどは「時刻」の「ホストとゲスト時間を同期」にチェックが入っていないのですがAmazonLinux2023はどうやらデフォルトでこれにチェックが入っているようです。。。（知らずに小一時間くらい溶かしました）

チェックを外して保存をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2335933/d2e022ad-a9f2-3c74-3edf-c30669283928.png)

# 3. 時刻手動変更

あとは、dateコマンドで時刻を変更しましょう。

```bash
date -s "2024/07/19 10:00:00"
```

検証が終わったら、もとに戻しておきましょう。
```bash
systemctl start systemd-timesyncd
systemctl enable systemd-timesyncd
systemctl start chronyd
systemctl enable chronyd
```
NWについてのメモ

## Cisco機器から```show lldp neighbors```
* Cisco機器から```show lldp neighbors```コマンドを発行するとlldpが有効になっている機器は応答してくれる
* ただし、PortChannelのポートについてはlldpに乗ってこないので注意

## Ip default gateway
* Vlan超えの場合 Ip default GateWayを設定してあげる必要がある

## macアドレスを確認したい
* sshでCiscoHUBに侵入後
* ```show arp```を確認するとarpテーブルが確認できる
* ただしVlanの範囲のみしか表示されない
* 機器が持っている全てのmacアドレスを表示する場合は```show mac address```で確認が可能
* ↑補完が効かないので注意が必要
AthenaでSimple Notiﬁcation Serviceの送信ログを読み込めるようにした

## S3上にあるログファイルをいい具合に取得したい

最初に、個人的なメモの側面もあるのでご容赦してほしい。

やりたかったことは、送信ログを解析したり、月々の送信数を把握したかった、それだけです。
その為に、s3上のログをいい具合に取り込んで上げる必要があった。参考にしたのは下記のページ。

https://zenn.dev/gomi_ningen/scraps/f2a340b1f2651e

https://staff-blog.faith-sol-tech.com/%E3%80%90%E5%88%9D%E5%BF%83%E8%80%85%E5%90%91%E3%81%91%E3%80%91amazon-athena%E3%81%AE%E3%83%91%E3%83%BC%E3%83%86%E3%82%A3%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%A8%E3%81%AF/

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/partition-projection-setting-up.html

下記クエリもおいておく。パーティションの使い方が非常によく分かった。

```sql
CREATE EXTERNAL TABLE IF NOT EXISTS xxxxxxxxx.sms_usage_report2 (
  `PublishTimeUTC` string,
  `MessageId` string,
  `DestinationPhoneNumber` string,
  `MessageType` string,
  `DeliveryStatus` string,
  `PriceInUSD` float,
  `PartNumber` int,
  `TotalParts` int 
)
PARTITIONED BY (
year INT,
month INT,
day INT
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.OpenCSVSerde'
WITH SERDEPROPERTIES (  'escapeChar'='\\',  'quoteChar'='\"',  'integerization.format' = ',',  'field.delim' = ',' ) 
LOCATION 's3://[backet-name]/SMSUsageReports/ap-northeast-1/'
TBLPROPERTIES (
'classification'='csv',
'skip.header.line.count'='1',

'projection.enabled' = 'true',

'projection.year.type' = 'integer',
'projection.year.range' = '2010,2100',
'projection.year.digits' = '4',

'projection.month.type' = 'integer',
'projection.month.range' = '1,12',
'projection.month.digits' = '2',

'projection.day.type' = 'integer',
'projection.day.range' = '1,31',
'projection.day.digits' = '2',

'storage.location.template' = 's3://xxxxxxxxxxxxx/SMSUsageReports/ap-northeast-1/${year}/${month}/${day}'
)
```
protoc コマンドで php に書き出す方法

# Protocol Buffers のざっくりイメージ
バックエンドの API とフロントエンドのアプリ間で、データをやり取りする間をもってくれる存在。API → ProtoBuf → App みたいな感じでワンクッション挟む感じ。

これが何故いいかは他の方が丁寧に紹介しているので端折る。参考は以下。

https://maku.blog/p/37e6uck/

https://qiita.com/yugui/items/160737021d25d761b353

# .proto ファイルを php にコンパイルするコマンド
手っ取り早く全部コンパイルしたければこれ。
※ パスは環境によって変わると思うのでそこは注意。
```bash
# 全ファイルをインポートできるように指定し、
# ./Proto 以下全てのファイルをコンパイルし、
# ./php_out に書き出す
$ protoc -I ./Proto --php_out=./php_out ./Proto/**/*.proto
```

ちょっと詳しく説明を書いてみる
```bash
# -I: .proto ファイルで import するファイルパス
# --php_out: コンパイルした php ファイルを出力、その書き出し先を指定
# 最後に読み込むファイルを指定 
$ protoc -I {IMPORT_PROTO_FILE_PATH} --php_out={PHP_OUT_PATH} {COMPILE_PROTO_FILE_PATH}
```


# 参考
https://christina04.hatenablog.com/entry/protoc-usage
不用意にパスに日本語を混ぜ込まないこと（自戒）

# なぜかテストクラスを実行すると動かないぞ？

ちょっと kotest を書いてみるかと思い以下のようなテストを書きました。

```kotlin
package sample

import io.kotest.core.spec.style.FunSpec
import io.kotest.datatest.withData
import io.kotest.matchers.shouldBe

internal class SampleTest : FunSpec({
    context("test") {
        data class TestPattern(val num1: Int, val num2: Int, val result: Int)
        withData(
            nameFn = { "${it.num1} + ${it.num2} = ${it.result}" },
            TestPattern(1, 2, 3),
            TestPattern(2, 3, 5),
        ) { (num1, num2, result) ->
            num1 + num2 shouldBe result
        }
    }
})
```

さあ実行してみるかとテストクラスを動かすと何故か ClassNotFoundException……。

> org.gradle.api.internal.tasks.testing.TestSuiteExecutionException: Could not execute test class 'sample.SampleTest'.
> 	（中略）
> Caused by: java.lang.ClassNotFoundException: sample.SampleTest
> 	（以下略）

とりあえずなんとなく intellij 上で 8 行目 ( `context("test")` の行) に表示されている ▶ マークから単体で実行してみると期待通りテストが実行されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801825/59addca4-f52f-746c-5bf5-eddac80fcd43.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/801825/fd63e687-cee3-4d7b-e966-93b01eaceb0a.png)


なぜ。。。

そういえば「とりあえずサンプルで適当に動かすだけだし」と思って `C:\Users\[username]\Downloads\サンプル` 配下にプロジェクトを作成したな？

もしやと思いパスに日本語を含まないように場所を移すと期待通りテストが実行されるようになりました。

単体で動かした場合は何故か動作してしまう理由は調べていませんが、**そもそも不用意に日本語を混ぜるな**ということですね。
DatabricksノートブックでPDFを表示する

最近では、[PDFやExcelのパーシングも簡単](https://qiita.com/taka_yayoi/items/032a2961c1f643b05286)になってきたこともあり、Databricksで作業している際に「このPDFどんな内容だっけ？」となることも増えてきました。考えてみたら、ノートブック上にPDFを表示しようと思ったことも無かった訳で。

結論から言うと、PDFをそのまま表示することはできなかったので画像に変換して表示するアプローチをとっています。

この辺りを参考にさせていただきました。

https://stackoverflow.com/questions/71303643/how-to-convert-a-pdf-to-a-jpg-png-in-python-with-the-highest-possible-quality

`PyMuPDF`を使うといいらしい。でも、ライセンスには注意とのこと。

```py
%pip install PyMuPDF
dbutils.library.restartPython()
```

それと、こちらの情報を組み合わせて。

https://stackoverflow.com/questions/67270736/databricks-view-image

元のPDFはこちらです。
![0000203025-part-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/17840681-d112-193c-d48e-1747b20d9352.png)

```py
import fitz
import matplotlib.pyplot as plt
from PIL import Image
from io import BytesIO

# Volume上のPDFファイル
filename = "/Volumes/takaakiyayoi_catalog/fsi_smart_claims/volume_claims/medical_statements/0000203025-part-3.pdf"

doc = fitz.open(filename)
page = doc.load_page(0)
pixmap = page.get_pixmap(dpi=300)
img = pixmap.tobytes()

# BytesIOから画像の読み込み
im = Image.open(BytesIO(img))

# 画像の表示
dpi = 100
width, height = im.size
plt.figure(figsize = (width/dpi,height/dpi))
plt.imshow(im, aspect='auto')
```

これで、ボリュームに格納されているPDFをノートブックに表示することができます。
![Screenshot 2024-07-19 at 14.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/bcb65a4f-baf5-ff73-f5ba-b2a3bd30c40f.png)



### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
AWSキーペアにED25519形式の鍵ファイルを作成してTerraformで公開鍵を登録する

AWSキーペアに登録するキーペアの作成方法をよく失念するので、一連の流れを備忘録として整理。

1. AWSキーペアに登録するためのキーペア(ED25519)を作成する
    個人的には強度の強いED25519を使っています
    ```shell
    ssh-keygen -t ed25519 -C "公開鍵に記載されるコメント"
    ```
    保存先のパスとパスフレーズ(確認も含め)を入力すると、秘密鍵と公開鍵が作成されます。
1. tfファイルでaws_key_pairリソースを作成する

    ```terraform
    resource "aws_key_pair" "sample" {
      key_name   = "sample"
      public_key = "ssh-ed25519XXXXXXXXXXXXX"
    }
    ```
    publik_keyには1で作成された公開鍵(.pub)の値をコピーする

1. Terraformでplanしてみて意図したものになっているか確認する

    ```shell
    % terraform plan
    〜省略〜
    Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
      + create
    
    Terraform will perform the following actions:
    
      # aws_key_pair.sample will be created
      + resource "aws_key_pair" "sample" {
          + arn             = (known after apply)
          + fingerprint     = (known after apply)
          + id              = (known after apply)
          + key_name        = "sample"
          + key_name_prefix = (known after apply)
          + key_pair_id     = (known after apply)
          + key_type        = (known after apply)
          + public_key      = "ssh-ed25519XXXXXXXXXXXXX"
          + tags_all        = (known after apply)
        }
    
    Plan: 1 to add, 0 to change, 0 to destroy.
    
    ─────────────────────────────────────────────────────────────────────────────────────────────────
    
    Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take exactly these actions if you run "terraform apply" now.
    ```

1. TerraformでApplyする
    Terraform Cloudを使っています
    ![Apply画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43800/c6b18d81-7f12-b5bd-34b5-5d093ea5251d.png)

1. AWS EC2 - キーペア上にもリソースが作成されていることが確認できます

    ![スクリーンショット 2024-07-19 14.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43800/1e764921-0370-c540-10bf-db37d307398c.png)
Node.js v22.5.0でCIのnpmが動作しないバグが発生中

## TL;DR

- Node.js v22.5.0にはバグがある
- CIで使われるnpmのclean-installコマンドが失敗することがある
- v22.5.1がリリースされるまではv22.4系へのダウングレードを推奨

## 経緯

2024年7月18日、私のNode.jsを使ったプロジェクトがCloudflareでのビルドに失敗していることに気づきました。

```
Installing project dependencies: npm clean-install --progress=false
npm error Exit handler never called!
npm error This is an error with npm itself. Please report this error at:
npm error   <https://github.com/npm/cli/issues>
npm error A complete log of this run can be found in: /opt/buildhome/.npm/_logs/2024-07-18T17_33_24_424Z-debug-0.log
```

npmのIssueを調べたところ、同様の報告が複数上がっていました。もっとも詳しい情報が集まっているのは、以下のIssueです。

- [[BUG] Exit handler never called during clean-install, with Node.js v22.5.0 · Issue #7657 · npm/cli](https://github.com/npm/cli/issues/7657)

これによると、問題のバグはNode.js v22.5.0にて発生する一方で、v22.4.1では発生しないようです。また、必ずしもエラーが発生するわけではなく、大量のファイルを扱おうとしたときに発生するとのことです。

npm側ではなく、Node.jsの`fs.closeSync()`にV8 Fast APIを追加したことがバグの原因とみられています。現在、問題を修正するためのPull Requestが提出されています。

- [Fix the bug caused by fast api changes in v22.5.0 and have a post-mortem by anonrig · Pull Request #53934 · nodejs/node](https://github.com/nodejs/node/pull/53934)

## 対応策

問題が修正されるまでは、Node.jsのバージョンを一時的にv22.4.1にダウングレードすることが推奨されます。Node.jsの公式X（旧Twitter）アカウントは、すべてのユーザーに対して一時的なダウングレードを呼びかけています。

<blockquote class="twitter-tweet" data-dnt="true"><p lang="en" dir="ltr">⚠️ We&#39;re encouraging all users to temporarily downgrade to Node.js v22.4.1 due to a bug in v22.5.0.<br><br>Full details here: <a href="https://t.co/N0UFoLqoak">https://t.co/N0UFoLqoak</a></p>&mdash; Node.js (@nodejs) <a href="https://twitter.com/nodejs/status/1814112932650701195?ref_src=twsrc%5Etfw">July 19, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
Microsoft Power Platform Fundamentals PL-900の資格を取得

## 資格取得理由

経歴として丁度2年程度、Power Platformのエンジニアとして
仕事をして参りました。


今丁度仕事も退職し
次はPowerPlatformを教える先生になろう！と思い、
今時間があるので資格を取得をいくつかしようと実際に行動した記録となります。

エンジニアとして仕事をしてきたのは下記の通りです。


PowerApps(モデル駆動型アプリの作成はなし)
PowerAutomate
PowerBI
Copilotを少し
DataverseはTeamsのみ

PowerPageの作成はしてきませんでした。
一番わかってるのはPowerAutomateでしょうか。


下記を繰り返し１週間程度勉強しました。

https://learn.microsoft.com/ja-jp/credentials/certifications/power-platform-fundamentals/practice/assessment?assessment-type=practice&assessmentId=34&practice-assessment-type=certification

これだけは伝えておかなくてはなのですが
上記のテスト内容的に全然かけ離れている問題が出てきて
何の役にも立たず…:joy:
これはUpdateかなにかあったのでしょうかね。

ただプラクティスは勉強にはなりました。

既存の知識をフルで使って何とか合格はできました…
もう年なので、すぐに資格取得、とまではいきませんが
PowerAutomateの資格も含め取得していこうと思います。
仕事をし始めると、
お母さんと仕事の二刀流はかなり難しいですから…:sweat:
Djangoの裏側ではなにがおこっているのか？

:::note info
インフォメーション
本記事は独自で勉強した内容のアウトプットになります。
:::

どうも初めましてエンジニアを目指して勉強中のsteveです。
Djangoを勉強して約二か月経過したので、ここでは,Djangoの概説を説明したいと思います。

#  はじめに　-WebサイトとWebアプリの違いとは？-
簡潔にまとめると、responseするHTMLが動的ならwebアプリ、静的ならwebサイトになります
したがって、ユーザーによって動的に異なったwebページを返せるdjangoは、webアプリになります。

## webアプリの処理手順
キーワードは、webサーバー,APサーバー、データベースになります。

>Webサーバー・・・クライアントから受け取るリクエストの窓口
>APサーバー・・・必要に応じてデータベースと連携をとりレスポンスデーターを作成
>データベース・・・データを保管しているサーバー



* 処理１　ブラウザからwebアプリにリクエストを送る
* 処理２　WEBサーバーが窓口としてリクエストを受け取り、レスポンスに必要なのが、静的コンテンツなのか、動的コンテンツなのか判断
  * 静的コンテンツであれば、処理４へ
  * 動的コンテンツであれば、処理３へ
* 処理３　APサーバーで処理
  * データベースからのデータの取得が必要であれば、データベースと連携し、レスポンスデータを作り、WEBサーバにデータを返す。
* 処理４　WEBサーバーからレスポンスデータをブラウザに返す

#### Djangoでは、処理２、処理３をどのように走らせるかを設定するというわけです。

# Djangoはどのように処理２、処理３を実行するのか
キーワードは、次の3個です

>Model・・・データベースと連携をとるコンポーネント
>Template・・・一般にhtmlファイルのことをさします
>View・・・modelから参照したデータをどのように扱うか
>（上記３つがメインのコンポーネントになるため、頭文字をとってMTVモデルと呼んだりします）


基本的に上記の３つを駆使して、リクエスト情報をさばいていくことになります。

この他にも処理1の部分は、urls.pyが担っているのですが、
djangoをwebアプリたらしめているための要素になってるのがMTVになります。

まず、処理1のリクエストがurls.pyで設定したアプリケーションに届く。
リクエストをurls.pyで指定したアプリケーションが処理する。
アプリケーションがレスポンスデータを返す。

#### では、アプリケーションはどのような処理をしてレスポンスデータを作成しているのでしょうか？？　以下からが本記事のメインテーマになります。

# Djangoの裏側では、何がおこっているのか？

まず、リクエスト情報を受け取り最初に働くコンポーネントがviewになります。

>viewは主に、「このリクエストがきたら、どのようにデータベースのデータを扱い、どのようにHTMLと絡みつけて、レスポンスデータを作成するのか」を設定する部分になります。
>したがって、viewの設定により、どのデータベース（model）を扱うのか、どのhtml（template）を扱うのか　を決めることができるので、viewはDjangoにおける脳のような役目をしているといえます。

>modelは、データベースのテーブル作成をクラスベースの記述で設定できるコンポーネントになります。

>templateは、htmlをどのように動的に表示するのか設定できるコンポーネントになります。具体的には、「もし、ユーザーがログイン状態なら、このデータを表示する」といった内容を、pythonの記述方法に近い方法で記述できます。

つまりまとめると、
#### viewがリクエストを受け取り、必要に応じてレコードをデータベースから取得し、表示するHTMLをtemplateから受け取る。レコードとhtmlの材料をもとに、viewが処理をしてレスポンスデータができあがる。

→処理4へ

これが全体的な動きになります！
ER図：Mermaidについての学習

## はじめに
ER図というものをかくのに際して、いろんな記法があるそうですが、今回はMermaidというものについて私なりに調べたことをアウトプットしたいと思います

## Mermaidについて
![人魚.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777936/22bbf618-6699-0658-d4c6-abc8953a3eaa.jpeg)

- テキストベースのダイアグラムを作成するためのJavaScriptライブラリ
- プログラムコードを用いて視覚的な図を描くことができ、GitHubやMarkdownエディター、Jupyterノートブックなどで広く使われている
- 語源は「人魚」を意味する英単語で、複雑なダイアグラムを簡単に描けるという魅力を持つツールであることを示唆している

公式サイトは以下になります。

https://mermaid.js.org/

### Mermaid記法のメリット
| メリット |  |
| - | - |
| 多機能 | フローチャート、シーケンス図、ER図、ガントチャートなど、多種多様なダイアグラムの生成が可能 |
| 柔軟性 | テキストベースで図を定義するため、視覚的な表現が豊富でカスタマイズしやすい |
| 統合性 | MarkdownエディターやJupyterノートブックなど、様々な開発ツールやプラットフォームと統合して利用可能 |
| バージョン管理 | コードでダイアグラムを表現するため、Gitなどのバージョン管理システムと容易に連携可能。<br>これにより、変更履歴の追跡やチームでの共同作業がしやすくなる |

### Mermaid記法のデメリット
| デメリット |  |
| - | - |
| 学習曲線 | 初めて使う場合、Mermaidの記法を学ぶ必要がある。<br>特に複雑なダイアグラムを描く場合には、記法を理解するための時間が必要 |
| パフォーマンス | 非常に複雑なダイアグラムを描く場合、レンダリングのパフォーマンスが低下することがある |
| カスタマイズの制限 | :標準的な機能やスタイルで満足できない場合、細かいカスタマイズには限界があるため、特定のニーズに完全に対応できないことがある |
| 複雑さ | 多機能ゆえに、シンタックスが複雑になりがち。 |

レンダリング[^1]
[^1]: レンダリング（Rendering）は、データを視覚的な形式に変換するプロセスを指します。コンピュータグラフィックスやウェブ開発、ビデオゲーム、アニメーションなど、さまざまな分野で使われる用語です。

シンタックス[^2]
[^2]: シンタックス（Syntax）とは、プログラミング言語やマークアップ言語における文法のことを指します。具体的には、コードの書き方や構造、記号の使い方、キーワードの配置など、言語が正しく解釈されるためのルールセットです。シンタックスは、コードが意図した通りに動作するために重要です。


## Mermaid想定される利用シーン
**ソフトウェア開発のドキュメント**: 
開発プロセスやシステム構成図、ER図、フローチャートなどを記述する際に便利
**技術的なブログ記事やチュートリアル**: 
テクニカルブログやオンラインチュートリアルで、説明を視覚的に補足するために利用できる
**プレゼンテーション**: 
ダイアグラムを含む技術的なプレゼンテーション資料を作成する際に活用できる
**プロジェクト管理**: 
ガントチャートやタスクフローを視覚的に管理するために使える


## 参考サイト一部紹介

https://zenn.dev/aldagram_tech/articles/a10166f763d30e

https://zenn.dev/kento_mm_ninw/articles/8b10afdbef306a

https://notepm.jp/blog/15456

## さいごに
今回はMermaidについて簡単にまとめてみました。ER図作成にあたりおすすめの方法があればご教示のほどよろしくお願いします。今回の記事、何か参考になれば幸いです:relaxed:
Copilotはcodiumでよくねという話

# Copilotの時代
生成AIが蔓延る第三次AIブームの昨今、`Amazon Q`や`GitHub Copilot`をみなさんお使いでしょう。
そんな中見つけた無料の生成AIアシスタント[`codium`](https://codeium.com/)を紹介させてください。

# 無料という強み
正直仕事や現場では、使用を許可されているもの以外は御法度ですし
私自身「え、有料なん...」という壁のせいで、生成AIを使い始めたのは最近で、結構出遅れました。

ですのでコードアシスタント生成AIについて特段詳しいわけではないのですが
無料かつ、GitHub Copilotくらい早く正確(個人比)な[`codium`](https://codeium.com/)を見つけました。

しかもこいつ、[vimプラグイン](https://github.com/Exafunction/codeium.vim)もすでにある上に
公式の導入チュートリアルが動画で解説されておりめちゃくちゃ丁寧。[無論VSCodeもある](https://qiita.com/SNQ-2001/items/705eb634980ff7fdda99)。

ブラウザで軽くお試しもできます

https://codeium.com/playground

# 気になる精度
私の使用場面だと、「似たようなことの繰り返しだけど地味に面倒」とか
vimの編集じゃちょっと効率悪くてマクロ作るにもなんだか...とか
んーちょっと置換じゃカバーできないな...とか

なんかそういう場面、すなわち
設計はされていて方針も完全だが`手を動かすスピード`を早めたい
ときに重宝しております。

逆に
```js
// 指示コメ厨
```
系の使い方は、たまーにしかしてないです。とはいえちょっとしたメモはコメントで書いておくことで
サジェストに反映してくれるのはありがたい。

こちらをご覧下さい。
未使用関数が2つある状態でちょっと待ちます。
![ok.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/c45f8aec-e709-e96c-065d-cdb14941254b.gif)
ちゃんと正しい使い方で関数を適用してくれています。
なにやらそれっぽい準備がなされている状態だと、かなりよい精度で描きたいことを書いてくれますね。

しかし、指示コメの場合だと
![tmp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/9d26904c-16d3-cc2e-ab4f-17857f25cff1.gif)

高度な指示はなんにも書いてくれません。
まぁこのレベルはGitHubでも無理でしょうが。

もちろん簡単なものであれば書けます。
![qq.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/453310/309602ab-4fdb-7167-99b0-3fdf2e438c1b.gif)
まぁでも若干変ですので手直し、って感じですね。
この程度ならコメント書いてる間にコーディングが終わるのでなくてもいい。

# 結局
当たり前ですが作りたいものの内容によります。
単純な場合でも補完がうまくないときもありますし、そういった際には結局人の手が必要。

であれば無料なcodiumで私は満足しているというお話でした。
docker run のシェルスクリプトを他人の環境でも動くようにする

docker run のシェルスクリプトを他人の環境でも動くようにする
ディレクトリのマウントの記述の改善に関するメモです。

## 前提
docker環境で、host環境のディレクトリをguest環境にマウントすることがある。
`docker run` のoptionで
`-v /home/someone/folder/datasets:/root/project/datasets \`
などと記述する。
機械学習系のモデルファイル・機械学習の学習用データ・推論用データはディスクスペースを大量消費するのでDockerfile 中で COPYをすることは避けます。
 
## 課題
`/home/someone/folder/datasets` という記述は、
そのリポジトリをgit clone した人にとっては違ってくる。
そのため、事前にdocker runを実行するシェルスクリプトを事前に編集してもらう必要を生じる
そのような必要のないシェルスクリプトを記載したい。
host環境のディレクトリを絶対pathで指定することを避けたい。

## 対策
以下のようにすることで、シェルスクリプト中でhost環境のディレクトリを絶対pathを書くことをなくせる。

```
#!/bin/bash
export GIT_ROOT=$(cd $(dirname $0)/.. ; pwd)
sudo docker run -it --rm --net=host --runtime nvidia -e DISPLAY=$DISPLAY \
	-v ${GIT_ROOT}/repo_name/weights:/root/repo_name/weights \
	--device /dev/bus/usb \
	--device /dev/video0:/dev/video0:mwr \
	-v /tmp/.X11-unix/:/tmp/.X11-unix repo_tag:100
```

## 効果
docker runを実行するスクリプトを事前に編集してくださいという作業なしに
そのスクリプトを実行できるようになった。
Localのブランチを削除する

git fetch --pruneでも消せないケースがあったので、スクリプトを作成しました。
https://www.r-staffing.co.jp/engineer/entry/20201023_1

:::note warn
実行すると、コマンドを実行した階層のファイルも削除対象となってしまうのですが、解決方法は未調査です。
例えば、プロジェクトのフォルダにあるREADME.mdとかも、gitのブランチ名と認識され、削除しようとします。
（そんなブランチは存在しないので削除できずエラーになりますが）
:::

```sh
deleteBranchNotExistingInRemote() {
    branchName=$1
    echo "Checking ${branchName}"
    hash=$(git ls-remote origin $branchName)
    if [ -z "${hash}" ]
    then
        echo "${branchName} is not exists."
        echo "Deleting ${branchName}"
        git branch -D ${branchName}
    fi
}

local_branches=$(git branch)
for branch in ${local_branches}
do
    echo "LocalBranch: $branch"
    deleteBranchNotExistingInRemote ${branch}
done
```