OmniAICreator/Qiita-1.07M huggingface dataset:
天才か？ Azure OpenAI Service の Stream 出力をスムーズに見せかけるトリック

### 追記　2024/03 非同期変更フィルター機能がご利用できます
https://qiita.com/nohanaga/items/4cd9e426e04a75bdc987

Azure OpenAI Service で ChatCompletion API を使用する際、`stream = True` に設定すると、回答がバルクで返ってきてしまいます。

![002.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/d1c53146-d624-ca62-8362-9e72ab2f04b6.gif)

これを OpenAI 本家のようにヌルヌルと出力させる面白いトリックを発見しました。というのも、いつもおなじみの [Azure-Samples/azure-search-openai-demo](https://github.com/Azure-Samples/azure-search-openai-demo) の[更新](https://github.com/Azure-Samples/azure-search-openai-demo/commit/c01d292e7af0e79e4a56063f34d71e3dc8f32977)で実装されてました。

![001_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674344/7efe749f-c629-bbdc-87ba-c8adb1e9db0a.gif)

該当のコードはこれです。バックエンド側はそのままに、フロントエンド側でタイマーをセットして 33 ミリ秒ごとに新しい文字を追加していく仕組みです。フロントエンドの制約に応じて、ここにさまざまな値をセットしてインタラクションを調整できます。数十ミリ秒のような速い値はもちろん自然なインタラクションにつながりますが、数百ミリ秒の値であっても AI が生成しているというエクスペリエンスをユーザーに体感させるのに十分でしょう。

```javascript
const updateState = (newContent: string) => {
    return new Promise(resolve => {
        setTimeout(() => {
            answer += newContent;
            const latestResponse: ChatAppResponse = {
                ...askResponse,
                choices: [{ ...askResponse.choices[0], message: { content: answer, role: askResponse.choices[0].message.role } }]
            };
            setStreamedAnswers([...answers, [question, latestResponse]]);
            resolve(null);
        }, 33);
    });
};
```

これを自分で試すために、該当部分だけ抜き出した超シンプルなサンプルコードを作成しました。すべて Azure-Samples のものを使っています。ありがたいです。

https://github.com/nohanaga/azure-openai-stream-trick

# 参考
https://github.com/Azure-Samples/azure-search-openai-demo

https://github.com/Azure-Samples/chatgpt-quickstart
そろそろ我々はsortedcontainersを使えるようになった方がいい








Pythonのsortedcontainersのチートシートです。
## まえがき
競技プログラミングをやっている人向け：
長年AtCoderのPyPy環境にはC++でいうstd::setやstd::mapにあたるデータ構造が標準で実装されておらず、それらが想定解で要求される問題ではより難しい別解を実装したり、外部のライブラリを借りてきたりする必要がありました。この度、AtCoderのジャッジアップデートによってsortedcontainersライブラリが使えるようになりました。これは非常に強力なデータ構造ライブラリなので、これを機に勉強して使いこなせるようになっておきましょう。

競技プログラミングをやっていない人向け：
sortedcontainersライブラリはPython用のデータ構造ライブラリです。本記事では、https://grantjenks.com/docs/sortedcontainers/# をもとに、SortedSet, SortedList, SortedDict それぞれについてできることを解説し、操作の使い方や計算量について紹介します。

## はじめに

何はともあれ、手元環境で使えるようにするためにインストールしましょう。コンソールでpipを用いてインストールできます。
```install
$ pip install sortedcontainers
```

また、Pythonコードで sortedcontainers を import するわけですが、私は

```header.py
from sortedcontainers import SortedSet, SortedList, SortedDict
```

とすることをお勧めします。sortedcontainers.sortedset（大文字小文字が異なる）などを使うと、意図した動作になりません。↑を書いておけば、次から説明するコード例がそのまま動きます。
以降、特に言及がなければNはその瞬間に対象のデータ構造に格納されている要素数であるとします。
## SortedSet

簡単に言うと set の各要素が常にソートされているデータ構造だと思ってよいです。
### 初期化

```SortedSet.py
S = SortedSet([3, 1, 2])
#SortedSet([1, 2, 3]), 初期化の計算量は O(N * logN)
S.add(4)
#SortedSet([1, 2, 3, 4]), add の計算量は O(logN)
S.add(3)
#SortedSet([1, 2, 3, 4]), 要素は重複しない
S.discard(4)
#SortedSet([1, 2, 3]), 値4を削除 計算量は O(logN) 存在しない要素をdiscardすると、何も起こらない
#S.remove(100) とやると、KeyErrorが出る
S.pop(2)
#S[2]を削除 S.pop()で最大要素の削除 S.pop(0) で最小要素の削除　全部 O(logN)
S[1]
#2 getは O(logN)
S[0:2]
#0 1 スライスなどもできる　これの計算量は長さを k として O(klogN)
len(S)
#2 現在の要素数 O(1)
S.bisect_left(1)
#1
S.bisect_right(1)
#2
#これらは二分探索。 S.bisect_left(x) で、Sにxを挿入する位置(index)を返す。
#S.bisect_right(x) との違いは、すでにxがSにあるときに左に入れるか右に入れるか
#Pythonのbisectと同じ使用感
S.index(2)
#1 Sに2が現れる最初の位置を返す。ないとValueError
S.irange(0,2)
#[1, 2] S に含まれる 0以上2以下（両端含む）の要素を列挙
```

## SortedList

ほとんどSortedSetと同じですが、重複した要素が許されます。

```SortedList.py
S = SortedList([3, 1, 2, 1])
#SortedList([1, 1, 2, 3]), 初期化の計算量は O(N * logN)
S.add(4)
#SortedList([1, 1, 2, 3, 4]), add の計算量は O(logN)
S.add(3)
#SortedList([1, 1, 2, 3, 3, 4]), 要素は重複する
S.discard(3)
#SortedList([1, 1, 2, 3, 4]), 値3を削除 計算量は O(logN) 要素は1個だけ消される
#S.remove(100) とやると、KeyErrorが出る
S.pop(2)
#S[2]を削除 S.pop()で最大要素の削除 S.pop(0) で最小要素の削除　全部 O(logN)
S[1]
#2 getは O(logN)
S[0:2]
#スライスなどもできる　これの計算量はO(klogN)
len(S)
#現在の要素数 O(1)
S.bisect_left(1)
S.bisect_right(1)
#これらは二分探索。 S.bisect_left(x) で、Sにxを挿入する位置(index)を返す。
#S.bisect_right(x) との違いは、すでにxがSにあるときに左に入れるか右に入れるか
#Pythonのbisectと同じ使用感
S.index(2)
#1 Sに2が現れる最初の位置を返す。ないとValueError
S.count(1)
#2 Sに含まれる要素の個数を返す SortedSetにもあるがそっちは使う意味ないので…
S.irange(0,2)
#[1, 2] S に含まれる 0以上2以下（両端含む）の要素を列挙
```

## SortedDict

Dictの要素がソートされたバージョンです。
```SortedList.py
S = SortedDict()
S['c'] = 2
S['b'] = 3
S['a'] = 1
#SortedDict({'a': 1, 'b': 3, 'c': 2}) keyの昇順に格納される O(logN)
S.items()
S.keys()
S.values()
#dictと同じ
S.pop()
#Sのうち、keyが最大のものを返す S.pop(i)でi番目 S.pop(0)で最小 全部 O(logN)
'c' in S
#True
```

## 使用例
AtCoderの問題 ABC217-D 「Cutting Woods」を解いてみるとこうなります。コード量が少ないですね。
https://atcoder.jp/contests/abc217/submissions/47087829

## 注意点

sortedcontainersの利用において，max関数、min関数を使用すべきではありません。これらの関数ではiterableを取得してmax,minをとるので，計算量が $\Omega (N)$ となってしまいます。

## 宣伝（本質情報）
tatyamさんが制作したSortedSetの実装があります。雑に比較したところsortedcontainersよりこちらの方が速いケースが多かったです（そ、そんな…）
https://github.com/tatyam-prime/SortedSet
【Markdown】Mermaid記法を使って、テキストでSAMLとOIDCのシーケンス図を書いてみる

## Mermaid記法って？
Mermaid記法は、Markdownで用いられる**テキストのみで図を書く仕組み**です。

http://mermaid.js.org/#/

シーケンス図やフローチャート、状態遷移図、ER図などなど、幅広く対応しています。
## 実際に、SAMLとOIDCのシーケンス図を書いてみた
### SAML
以下のようにコードを書くと
````
```mermaid
sequenceDiagram
participant client as クライアント
participant idp as IdP(Okta等)
participant sp as SP(アプリ)
    client ->> sp: 利用者がアプリURLにアクセス
    Note right of sp:利用者がアプリに未ログインの場合、SAMLフロー開始
    sp -->> client: IdPにリダイレクト
    client ->> idp: 
    idp -->> client: IdP未ログインの場合、IdPログインを要求
    client ->>+ idp: 利用者がIdPにログイン
     Note right of idp: IdPログイン(＆MFA等)
    idp -->>- client: 
    client ->>+ sp: ログイン成功時、アプリにリダイレクト
    Note left of sp: SAMLアサーション連携
    Note right of sp: アプリ側でSAMLアサーションを検証後、アプリ認証完了
    client ->> sp: アプリのログイン状態が持続している場合、直接アプリにアクセス
```
````
こんな感じで表示されます。
```mermaid
sequenceDiagram
participant client as クライアント
participant idp as IdP(Okta等)
participant sp as SP(アプリ)
    client ->> sp: 利用者がアプリURLにアクセス
    Note right of sp:利用者がアプリに未ログインの場合、SAMLフロー開始
    sp -->> client: IdPにリダイレクト
    client ->> idp: 
    idp -->> client: IdP未ログインの場合、IdPログインを要求
    client ->>+ idp: 利用者がIdPにログイン
     Note right of idp: IdPログイン(＆MFA等)
    idp -->>- client: 
    client ->>+ sp: ログイン成功時、アプリにリダイレクト
    Note left of sp: SAMLアサーション連携
    Note right of sp: アプリ側でSAMLアサーションを検証後、アプリ認証完了
    client ->> sp: アプリのログイン状態が持続している場合、直接アプリにアクセス
```

### OIDC
OIDC(認可コードフロー)の場合も
````
```mermaid
sequenceDiagram
participant client as クライアント
participant idp as IdP(Okta等)
participant sp as SP(アプリ)
    client ->> sp: 利用者がアプリURLにアクセス
    Note right of sp:利用者がアプリに未ログインの場合、OIDCフロー開始
    sp -->> client: IdPにリダイレクト
    client ->> idp: 
    Note right of idp: 認可エンドポイント
    idp -->> client: IdP未ログインの場合、IdPログインを要求
    client ->>+ idp: 利用者がIdPにログイン
     Note right of idp: IdPログイン(＆MFA等)＋同意
    idp -->>- client: 
    client ->>+ sp: ログイン成功時、アプリにリダイレクト
    sp ->> idp: 認可コードを送信
    Note left of idp: トークンエンドポイント
    idp -->> sp: IDトークン(アクセストークン)を返却
    Note right of sp: アプリ側でIDトークンを検証後、アプリ認証完了
    sp ->> idp: IDトークン(アクセストークン)を送信
    Note left of idp: UserInfoエンドポイント
    idp -->> sp: ユーザ情報を連携
    client ->> sp: アプリのログイン状態が持続している場合、直接アプリにアクセス
```
````
このように表示されます。
```mermaid
sequenceDiagram
participant client as クライアント
participant idp as IdP(Okta等)
participant sp as SP(アプリ)
    client ->> sp: 利用者がアプリURLにアクセス
    Note right of sp:利用者がアプリに未ログインの場合、OIDCフロー開始
    sp -->> client: IdPにリダイレクト
    client ->> idp: 
    Note right of idp: 認可エンドポイント
    idp -->> client: IdP未ログインの場合、IdPログインを要求
    client ->>+ idp: 利用者がIdPにログイン
     Note right of idp: IdPログイン(＆MFA等)＋同意
    idp -->>- client: 
    client ->>+ sp: ログイン成功時、アプリにリダイレクト
    sp ->> idp: 認可コードを送信
    Note left of idp: トークンエンドポイント
    idp -->> sp: IDトークン(アクセストークン)を返却
    Note right of sp: アプリ側でIDトークンを検証後、アプリ認証完了
    sp ->> idp: IDトークン(アクセストークン)を送信
    Note left of idp: UserInfoエンドポイント
    idp -->> sp: ユーザ情報を連携
    client ->> sp: アプリのログイン状態が持続している場合、直接アプリにアクセス
```
AWS デベロッパーアソシエイト（DVA-C02）合格体験記（2023/10）

## はじめに
これまでAWSの利用経験はないのですが、AWSを利用する業務に就くことになり、まずは目先の目標としてアソシエイト資格を取っていこうということで、今回はその第一弾でDVAに挑戦してきました。
#DVAは、3年前にCLFとSAAを取った勢いで少し勉強し始めたものの、用語が全く頭に入らず、頓挫してしまってました。。

## 学習方法
### WEB問題集
色々な方のサイトを参考にさせていただいて、今回はCloudLicenseにお世話になりました。
https://cloud-license.com/

問題数が非常に多く、こればっかりやってました。
個人的には、7問1区切りですぐに確認できることが嬉しかったです。
多くの方がおススメされているのも納得でした。

学習方法としては、こんな感じで進めました。
1. とりあえず1周
1. 間違いや分からなかった問題の解説読み込みと他の教材で確認
1. 2の問題に対して再挑戦の繰り返し（100点近くなるまで）
1. 本試験モードを3回くらい（9割は取れるレベルまで）

### ハンズオン
自社の環境で、先輩社員のご指導の元、サーバーレス環境を構築させていただきました。有難い。。
これまで個人で学習していたときは、書籍や問題集ベースで行っていたので用語を覚えるのに非常に苦労していたのですが、実際に触ってみることでだいぶ理解が進みました。

### その他教材
- 徹底攻略 AWS認定デベロッパーアソシエイト[DVA-C01] 教科書

3年前に受けようと思ったときに買った本なのでバージョンが古いものです。
今回は学習し始めにさらっと読んだのと、問題集でわからないときに参考として使いました。

- Udemy AWS認定DeveloperAssociate（DVA-02）試験対策トレーニング

動画で各サービスの説明がされるものです。割と分かりやすかった印象です。
ただ、私が集中して動画を見るのが苦手なので、こちらもテキスト同様に初回にさらっと＋不明点の確認という使い方をしました。
ハンズオンもあったので、ちゃんと使えれば有効だったかもしれません。

## 試験当日
郊外のテストセンターで9時半開始で受けてきました。
小さいビルの狭い部屋だったのですが、逆に人数も少なかったので集中できました。

テストが始まると、1問目から見慣れない問題が・・・いきなり悩む。。
その後も、問題集に頼りすぎていたためか、いくつか見慣れない問題や、思ったより細かい内容の問題がでてきたときの動揺が激しく、、正直かなりヒヤヒヤしました。
感触としては、5割程度が即答できるもの、2~3割が微妙だけどきっと大丈夫でしょう、残りは知らん・・・というような感じでした。

ただ、問題自体は、知ってれば答えられる内容が多く、考えさせられるような問題はあまりなかった印象です。

## 試験結果
なんとか811点取れまして、合格できました。
結果は18時過ぎに認定のページに表示されました。
結果見るまではダメだと思ってへこんでたのですが、なんとか合格できてホッとしました。

## 感想
物覚えの悪い私には、ハンズオンがとても有効でした。
今後の受験に向けても色んなサイトを参考に取り入れていきたいと思います。
WEB問題集もCloudLicenseで良かったです。引き続き使いつつ、他のも探してみようかと。
反省点としては、各サービスのパラメータ定義方法やコマンドレベルの学習がもっと必要だったなと思いました。

## 次は
SAAの更新に挑みたいと思います。
まずは思い出すところから・・・



## AWSの相談・お困りごとありましたら、、、
AWSの活用方法や、お困りごとの相談、随時、お仕事の受付しております。

https://www.cs-cloud-aid.com/
VScode上でシェルスクリプトのデバッグ方法

今回はVScode上でシェルスクリプトのデバッグ方法を紹介します。
rogalmicさんが作ったBash Debugエクステンションを使ってデバッグしていきます。
https://marketplace.visualstudio.com/items?itemName=rogalmic.bash-debug

## debugする方法
通常のdebugと同じようにブレークポイントを設定すればそこで止まります。

## 気を付けること
そのまま実行すると下記のエラーが出る可能性があります。
`Error: Only bash versions 4.* or 5.* are supported.`
これはエクステンションがbash 4.0 & 5.0しか対応してないからです。

その場合homebrewなどを使ってbash 5.0をインストールして、
launch.jsonでbashのパスを指定します。
```
"pathBash": "/opt/homebrew/bin/bash",
```

## 標準入力
bashからパラメーターを渡すケースが多いと思いますが、
その場合launch.jsonで渡すことができます。
```
"args": [1]
```

## サンプルlaunch.json
```json
{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "bashdb",
            "request": "launch",
            "name": "Bash-Debug (simplest configuration)",
            "pathBash": "/opt/homebrew/bin/bash",
            "program": "${file}",
            "args": [1]
        }
    ]
}
```

## 動作確認ようサンプルコード
```bash
#!/bin/bash

function is_even() {
  # Check if the input is an even number
  if [ $(($1 % 2)) -eq 0 ]; then
    echo "Even"
  else
    echo "Odd"
  fi
}

input="$1"

if [[ -z "$input" ]]; then
  echo "ERROR: Missing argument"
  echo "Usage: $0 <number>"
  exit 1
fi

if ! [[ $input =~ ^[0-9]+$ ]]; then
  echo "ERROR: '$input' is not a valid number"
  exit 2
fi

result=$(is_even "$input")
echo "The number $input is $result"
```

## 出力
```
The number 1 is Odd
```

```
The number 2 is Even
```
Qiita CLIの使いづらいところ

## 事象

- Qiita CLI を使っていてなぜか投稿できない

## 動作環境

- OS: MacOS 14 Sonoma
- Qiita CLI: 1.3.0

## 原因

- メタ情報の tags の箇所が 「"」囲みになっている

## 解決法

- メタ情報の tags の箇所が 「"」囲みにしない

```md
---
title: Qiita CLIの使いづらいところ
tags:
  - Qiita CLI　<!-- ここ -->
private: false
updated_at: ""
id: null
organization_url_name: null
slide: false
ignorePublish: false
---
```

## Zenn なら

- 不正な文字が含まれていますと表示してくれます。

![間違った方法](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/ef7cbb76-9cfc-3423-2ff7-3fe6172edf03.png)

![プレビュー](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1312905/0fbe9617-691b-f050-5584-2e5edb7ba00a.png)

## まとめ

Qiita CLI 使用していて、使いづらいと思ったところを記事にしてみました。
後ほど、issue にも上げてみようかと思います。
【Python+dynamodb-local】引継ぎしたシステムにテストがなかったので実装してみたお話

# はじめに
引継ぎしたシステムにテストの実装を試みたので簡単にまとめてみます。
コード内容はぼかしています。

# 技術(一部)
- Docker
- Python
- DynamoDB、dynamodb-local
- 他各種AWSサービス

# 状況
- プロトタイプとして作成されたシステムだったため、テストまでは手を付けられていなかった
- 同様の理由で、コードも単一責任の原則に従っていなかった
- 例えばsend_mailという関数で以下の処理が実装されていた
    - トークンの発行
    - トークンとメールアドレスをDBに保存
    - メール送信

## テスト対象例
```python
# トークンの発行/トークンとメールアドレスをDBに保存/メール送信
def send_enabled_mail(params):
    token = トークンを発行する関数
    url = 認証URL
    message = メール本文

    to_email = params['address']
    response = add_token(token, to_email)
    if response["statusCode"] == 200:
        r = hogehoge.send_email(message, to_email)
        return r
```
## テストコード例
```python
# メール内容のテスト(一部)
def test_send_enabled_mail(params):
    FROM = os.environ.get('FROM')
    DOMAIN_NAME = os.environ.get('DOMAIN_NAME')

    session = boto3.Session(profile_name='default')
    ses = session.client('ses', region_name='ap-northeast-1')

    ses.verify_email_identity(EmailAddress=FROM)
    params['address'] = FROM
    
    response = send_mail(params)
    assert response['statusCode'] == 200
    actual_body = response['body']['Body']
    assert 'hogehoge@hoge.jp' in actual_body

    dynamodb.delete_table(TableName='hogehoge')
```

# やったこと
- テスト対象の関数(send_enabled_mail)にadd_token関数とsend_email関数が含まれているのでそれぞれのテストを書く
- add_token関数でローカルのdynamodbに接続できるようにdynamodb-local環境の設定を追加
- send_email関数ではstatus codeしか返していなかったのでメール本文も返すように修正
- SESや依存している関数などはモック

# おわりに
引継ぎ時点でテストを実装できれば良かったのかもしれませんが、任されるタスクの緊急度やシステムの理解度などから後々の対応となってしまいました。時間がなくてテストを書けないという人の気持ちが少し分かったような気がします。
【経済学】DSGEってなんぞって話

:::note
# はじめに
:::

現代の動的マクロ分析においてグローバルスタンダードモデルになっているDSGE(Dynamic Stochastic General Equilibrium：動学確率一般均衡モデル)ですが、数学的な理解がないと理解さえするのが難しいと思います。

そこで、DSGEをこれから学習する人に向けて、せめて"何をやっているのか"だけでもしていただきたいと思い、執筆していただきました。

:::note
# DSGEってなんぞって話
:::

　DSGEモデルは、RBCモデルの派生で、名目的な硬直性とか、情報非対称性に起因するエージェントコストとか、経済変数のショックを全部組み込んでいるスーパーモデル。
 
　DSGEモデルが開発された動機は「ルーカス批判の克服」である。
 
　昔(1970年代あたり)は、経済主体の行動を誘導型の方程式(消費性向などの諸々のパラメータを外生的に与えることで経済主体の将来の消費などの行動を決めてしまうような方程式)を用いてマクロ経済モデルを構築していた。
 
　その際に、モデルのパラメータは最小二乗法などの手法を用いて過去のデータに基づいて推定されるが、「政策や環境の変更が将来期待を通じて経済主体の行動に影響を与えるメカニズムを考慮できない(将来期待が変わることで誘導型の方程式のパラメータも変わりうる)」という欠点があったため、政策効果分析のツールとして適切でないとルーカスにボロカスに言われた。
 
　そこで、改良版のRBCモデル、すなわちDSGEモデルでは、家計や企業の効用や利潤最大化行動や、時間を通じて一定とされるディープパラメータ(消費代替弾力性などのデータには直接現れない変数)に基づいた、いわゆるミクロ的な基礎付けをしてモデルを構築した。そのことによって、経済理論との整合性が高く保てて、政策や経済ショックの波及こうかを明示的に示すことができるようになった。
 
　(調べたところ、モデルが提唱された1980年代当初は、その学術的な関心の高さからDSGEモデルの改良が進められたけど、すぐには政策当局には導入されなくって、1990年代に入って、価格硬直性をモデルに組込む手法が開発されたことを皮切りに、各国の中央銀行を主導に政策分析のツールとしてDSGEモデルが用いられるようになったらしい。)

　ここで疑問に感じるのは、「ほな、どうやって、ディープパラメータとか普通のパラメータを経済や環境の変化に応じて逐次的に取得してんねん」ってこと。
 
　その直接的な答えになるのが「ベイズ推定」と「最大化問題」。
 
　ベイズ推定は簡単に言うと「情報によって確率を更新すること」。例えば、「明日は雨が降るという予想確率が$30%$だったところに『スズメが低く飛んでいる(湿度が高いとエサである虫が低いところを飛ぶため)』という情報を得たとすると、明日の雨がふる予想確率が$50％$に上がる」という話。経済学に当てて言うと、「時点$t+1$で、『誤差(パラメータ)は平均$μ$で分散は$σ$の範囲の正規分布に従うだろー』って思ってたけど、時点tの各種経済変数の情報を手に入れたことで、『やっぱ平均$μ’$で分散は$σ’$の正規分布に従うっぽい』ってなる」という話。
 
　数学的にいうと、パラメータの事前分布$P(θ)$が、データ$y$という情報を踏まえることで、事後分布$P(θ｜y)$になる、こと。
 
　最大化問題については、事後分布$P(θ｜y)$を最大化するような、$θ$を求める手続きを行うことで乗り切る。
 
　ここで、事後分布$P(θ｜y)$の形はわからないことが多い。そこで登場数するのが、MCMC法。MCMC法では、関数の形がわからないから、手当たり次第にパラメータをぶち込んで、その中で最も事後分布$P(θ｜y)$を最大化するパラメータを最適解$θ*$とするという手続きを行う。

(もちろん、MCMC法は手法の一つなので、他にもさまざまな手法があります。)
 
　したがって、どうやってディープパラメータとか普通のパラメータを経済や環境の変化に応じて得ることができるのかというと、「各時点での経済の情報を踏まえて、ベイズ推定によって、事後分布$P(θ｜y)$を求める(どんなパラメータをどのくらいの確率で取りそうなのかの目星をつける)。続いて、事後分布の形がわからないので、MCMC法という”力業”で最適解$θ*$を得る。これを結果(経済主体がとるであろう行動)として出力する。」というアルゴリズムをぶん回すだけでパラメータできるという理屈。
segmentのEnableReorderingを使って一覧の並び替えを実装してみた

# 目次
1. はじめに
1. 実装方法
1. 最後に

# はじめに
アプリを使っていると、端末の言語設定などの画面で
縦一列に並んでいるデータを指で動かして並び替える機能をよく目にすると思います。

![ezgif-4-0d860b89d0.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/e5ce8927-e2d8-60de-2f70-004f65fad66f.gif)

IrisのSegmentウィジェットには、
EnableReorderingという一覧データを並び替えることができる機能が用意されています。

コーディング不要でプロパティを変更するだけで並び替えを実装できます。
どのようにして設定するか早速紹介していきたいと思います！

:::note
利用可能なプラットフォームは以下となります。
・iOS
・Android
:::


# 完成イメージ
今回の完成イメージはこちらです。
![ezgif-2-54fe7676f3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/26457011-2e80-c752-8954-38d7580a5b35.gif)

完成イメージのように、一覧で並んでいるデータを自由に並び替えできる機能を実装していきましょう！

# 実装方法
まずは画面を作成していきましょう。

## 画面作成
画面はFormにSegmentを入れただけの簡単な画面を作成しました。
![スクリーンショット 0005-10-30 17.24.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/3babc099-d152-f9c7-1506-d39f6ce6a9fc.png)
中のデータは、今回SegmentのMaster Dataを使ってデータを表示するようにしました。
![スクリーンショット 0005-10-30 17.25.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/b6cd46f3-9859-f57a-49e7-c2b6bed184a0.png)
![スクリーンショット 0005-10-30 17.24.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/b44668fe-c4d0-f482-de2f-c0b4c1715b08.png)

## EnableReordering設定
画面が用意できたので、並び替えの設定を行います。
Segment Widgetを選択した状態で、PROPERTIES->Segmentタブをクリックします。

プロパティの中にEnableReorderingという設定値があるので、これをOnに変更してください。
![スクリーンショット 0005-10-30 17.27.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/a57dfc0e-e622-6cff-9037-c52d592a89b7.png)


Androidのみ並び替えを実装する場合は、これで設定完了です。
iOSの場合はもう一つ設定が必要なので、以下を読み進めてください。

## editStyle設定（iOSのみ）
iOSの場合、EnableReorderingをOnに設定するだけでは並び替えが機能しません。

iOSの場合は、EnableReorderingをOnに変更することに加えて、
editStyleをIconに変更するようにしてください。
![スクリーンショット 0005-10-30 17.31.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/ec33d24c-4555-b15b-1af3-f904cfa9f156.png)

:::note
editStyleをIconに設定した場合でも、Androidでも正常に並び替えが機能します。
iOSとAndroidどちらも実装したい場合は、
EnableReorderingをOn、且つeditStyleをIconに設定することをお勧めします。
:::

これで実装は完了です！
最後に動きを見ていきましょう👀

|iOS|Android|
|--|--|
|![ezgif-2-54fe7676f3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/770296d5-0592-3d24-cced-9f664715d653.gif)|![ezgif-4-9747af93a2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592264/37425fb6-f4e9-c29c-beea-fc43f179c1e3.gif)|

iOSとAndroidどちらも自由に一覧データを並び替えできていることがわかりますね！

# 最後に
今回はSegmentのプロパティを使って並び替えの実装方法について紹介しました。
コーディング不要で簡単に並び替えが実装できるのは楽だと思うので、是非活用してみてくださいね！

# 参考
https://opensource.hcltechsw.com/volt-mx-docs/docs/documentation/Iris/iris_widget_prog_guide/Content/Segment_Properties.html
Vitestでモック関数の返り値を指定するメソッド一覧

## はじめに

Vitestでモック関数の返り値を指定するメソッドをご紹介します。紹介するコードでは`vi.fn()`を使用していますが、`vi.spyOn`や`vi.mock`でも使用できます。具体的な使用方法は下記の記事を参考にしてください。

https://qiita.com/mori_goq/items/a99f75ce29098a59df60

https://qiita.com/mori_goq/items/1800261547b23e11266c

## 返り値を指定

### mockReturnValue

```typescript
test('mockReturnValue', () => {
  const mockFn = vi.fn().mockReturnValue(10)

  expect(mockFn()).toBe(10)
})
```

### mockImplementation

引数を渡して返り値を指定できます。

```typescript
test('mockImplementation', () => {
  const mockFn = vi.fn().mockImplementation((value) => value * 10)

  expect(mockFn(1)).toBe(10)
})
```

## 返り値を指定（非同期）

### mockImplementation（非同期）

`async/await`で非同期での返り値を指定できます。

```typescript
test('mockImplementation（非同期）', async () => {
  const mockFn = vi.fn().mockImplementation(async () => Promise.resolve(10))

  expect(await mockFn()).toBe(10)
})
```

### mockResolvedValue

`Promise.resolve`で値を返します。

```typescript
test('mockResolvedValue', async () => {
  const mockFn = vi.fn().mockResolvedValue(10)

  expect(await mockFn()).toBe(10)
})
```

### mockRejectedValue

`Promise.reject`で値を返します。

```typescript
test('mockRejectedValue', async () => {
  const mockFn = vi.fn().mockRejectedValue(10)

  await expect(mockFn()).rejects.toBe(10)
})
```

## 呼び出し毎に返り値を変える

### mockReturnValueOnce

一度だけ引数の値が返ります。

```typescript
test('mockReturnValueOnce', () => {
  const mockFn = vi
    .fn()
    .mockReturnValueOnce(10)
    .mockReturnValueOnce(20)
    .mockReturnValue(30)

  expect(mockFn()).toBe(10)
  expect(mockFn()).toBe(20)

  // 3回目以降は30で固定
  expect(mockFn()).toBe(30)
  expect(mockFn()).toBe(30)
})
```

### mockImplementationOnce

一度だけ引数の値が返ります。

```typescript
test('mockImplementationOnce', () => {
  const mockFn = vi
    .fn()
    .mockImplementationOnce((a) => a * 10)
    .mockImplementationOnce((a) => a * 20)

  expect(mockFn(1)).toBe(10)
  expect(mockFn(1)).toBe(20)

  // ２つしか指定していないため、以降はundefinedとなる
  expect(mockFn(1)).toBe(undefined)
  expect(mockFn(1)).toBe(undefined)
})
```

## 呼び出し毎に返り値を変える（非同期）

### mockResolvedValueOnce

一度だけ`Promise.resolve`で値を返します。

```typescript
test('mockResolvedValueOnce', async () => {
  const mockFn = vi
    .fn()
    .mockResolvedValueOnce(10)
    .mockResolvedValueOnce(20)
    .mockResolvedValue(30)

  expect(await mockFn()).toBe(10)
  expect(await mockFn()).toBe(20)

  // 3回目以降は30で固定
  expect(await mockFn()).toBe(30)
  expect(await mockFn()).toBe(30)
})
```

### mockRejectedValueOnce

一度だけ`Promise.reject`で値を返します。

```typescript
test('mockRejectedValueOnce', async () => {
  const mockFn = vi.fn().mockRejectedValueOnce(10).mockRejectedValueOnce(20)

  await expect(mockFn()).rejects.toBe(10)
  await expect(mockFn()).rejects.toBe(20)

  // ２つしか指定していないため、以降はundefinedとなる（非同期でない）
  expect(mockFn()).toBe(undefined)
  expect(mockFn()).toBe(undefined)
})
```

## まとめ

Vitestでモック関数の返り値を指定するメソッドをご紹介しました。たくさんメソッドがあって覚えるのが大変という方は、`mockImplementation`さえ覚えれば応用が効くのでおすすめです。`***Once`系のメソッドは、指定以降の実行では`undefined`が返り値となるとめ注意が必要です。


## 最後に

### GoQSystemでは一緒に働いてくれる仲間を募集中です！

ご興味がある方は以下リンクよりご確認ください。

https://goqsystem.recruit.site?qiita=2faff78385c9884b8a85
アラート設定やグラフを楽に管理するためにインフラにタグをつけよう！

日々たくさんのインフラを管理する中で、アラートやダッシュボードなど用途やカテゴリごとにまとめて管理したいと思うこと、ありますよね？
そんなあなたにNew Relicでタグ付けしたインフラ群を簡単にまとめてアラートやグラフ作成できる方法をお伝えします！

:::note info
このアップデートの詳細はこちら。
[New Relic アップデート(2023年3月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202303)
[New Relic アップデート](https://newrelic.com/jp/blog/nerdlog/new-relic-update "New Relic アップデート")
:::

## タグの設定方法
タグは「インフラのコンフィグファイルで設定する方法」と「UIから直接設定する方法」の2つあります。
それぞれご紹介したいと思います。

(1)インフラのコンフィグファイルから設定する方法
New Relicのコンフィグファイル newrelic-infra.yml ファイルに追加することで設定可能です。
newrelic-infra.yml ファイルの設定方法の詳細に関しては[こちらのドキュメント](https://docs.newrelic.com/docs/infrastructure/install-infrastructure-agent/configuration/infrastructure-agent-configuration-settings/#custom-attributes)をご参照ください。

yamlファイルへの設定例)
```
custom_attributes:
  environment: production
  service: login service
  team: alpha-team
```

(2)UIから直接設定する方法
New Relic のUIにある「tag」から追加することが可能です。
Add a tag にKey: Value の形で記載し、Enterを押せば追加されます。

![スクリーンショット 2023-10-29 23.07.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/dc4d4a3d-256f-bad7-9c4d-5539e858c21f.png)

ちなみにインストール時にも設定することが可能なので、あらかじめ設定したいタグが決まっているようであればインストール時にも設定することも可能です(スクリーンショットはLinuxですがWindowsでも設定可能です)
この場合はnewrelic-infra.yml に追加されます。

![スクリーンショット 2023-10-29 23.16.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/d2ff83d4-7f31-7963-da8d-29a9dc0b802d.png)


## タグの活用方法
タグはNRQLでサクッとクエリするとこのように見えます。
Systemsampleからyamlファイルに設定したタグをクエリします

```
FROM SystemSample SELECT environment, service, team
```

![スクリーンショット 2023-10-29 23.32.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/b1ebad9e-173b-c2d6-5839-369432290854.png)

UIから直接追加した場合は「tag.XXX」でクエリすることができます

```
FROM SystemSample SELECT hostname , service, team , tags.environment
```
![スクリーンショット 2023-10-29 23.37.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/8a4052b1-587f-04e8-2f34-63e18366ca36.png)

例えばyamlファイルに設定した「Production」のサーバをまとめてグラフ化したい場合は下記のように指定します。

![スクリーンショット 2023-10-30 11.10.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/415e5cbf-a09f-1160-50aa-7fccf6ced241.png)

この条件を使ってアラートを設定することも可能です。
「Create alert」をクリックするとアラートコンディションの設定に遷移します

![スクリーンショット 2023-10-30 11.11.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/120ead58-22a2-6ef6-9d15-c830a5b31287.png)

「Add to dashboard」からダッシュボードに貼り付けることも可能です

![スクリーンショット 2023-10-30 11.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/313446/d87e435e-c518-bcc7-ec6e-430a4e58d519.png)


## まとめ
このように管理しているインフラをタグを活用することで方法でまとめることで、管理の利便性を上げることが可能です。
インフラ監視のやりやすいように自由にタグを設定して、より柔軟な管理にお役立てください！！



:::note info
このアップデートの詳細はこちら。[New Relic アップデート(2023年3月)](https://newrelic.com/jp/blog/nerdlog/new-relic-update-202303)
:::
:::note info
無料のアカウントで試してみよう！
[New Relic フリープランで始めるオブザーバビリティ！](https://qiita.com/ktst79/items/5ee74b34e6adb8a7a6fa)
:::
:::note info
[New Relic株式会社のQiita Organization](https://qiita.com/organizations/newrelic)では、
新機能を含む活用方法を公開していますので、ぜひフォローをお願いします。
:::
Linuxカーネルのメモリ管理

# Linuxカーネルのメモリ管理

Linuxカーネルは、モノリシックカーネルとして設計されており、カーネルの主要なサービスやドライバは同じアドレス空間で実行される。このアドレス空間は仮想的であり、カーネルスペースとして知られる。

## 1. 仮想メモリの導入

モダンなオペレーティングシステムのほとんどは、物理的なメモリとは独立した仮想アドレス空間を使用して動作する。Linuxカーネルも例外ではなく、仮想アドレスを通じて物理メモリにアクセスする。

## 2. メモリマッピング

物理アドレスと仮想アドレスは、ページテーブルというデータ構造を用いて関連付けられる。この関連付けを効率的に行うためのハードウェアコンポーネントとしてMMU（Memory Management Unit）が活用される。

## 3. カーネルスペースとユーザースペース

Linuxでは、メモリアドレス空間は大きく2つに分かれる: カーネルスペースとユーザースペース。カーネルスペースは、OSのコア機能を実行するための専用領域。ユーザースペースは、ユーザープロセスがそれぞれ独立して使用する領域。

## 4. メモリ管理の利点

仮想的なアドレス管理によるオーバーヘッドは存在するが、以下のような利点が得られる:

- メモリの効率的な利用
- プロセス間の隔離と保護
- 物理メモリの断片化の軽減

## 5. カーネルのアドレス空間とプロセスのアドレス空間の確保・動作の流れ

### 1. カーネルのアドレス空間の確保と動作の流れ

- **起動時のマッピング**: システムが起動するとき、ブートローダーはカーネルをメモリにロードし、初期ページテーブルをセットアップします。これにより、カーネルが使用するアドレス空間が最初に確保されます。

- **Direct Mapping**: Linuxカーネルは物理メモリのすべてを仮想アドレス空間の特定の範囲に直接マッピングします。これにより、カーネルは物理アドレスに直接アクセスできるようになります。

- **静的な配置**: カーネルのコード、データセグメント、初期のスタックなどは、起動時に静的に配置されます。これらのセグメントはカーネルのライフサイクル全体で変わることはありません。

- **動的メモリの確保**: カーネルは動的にメモリを確保する必要がある場面で、例えばページキャッシュやslabアロケータなどのメカニズムを使用してメモリを確保します。

### 2. プロセスのアドレス空間の確保と動作の流れ

- **プロセスの生成**: 新しいプロセスは`fork()`や`exec()`などのシステムコールによって生成されます。`fork()`は親プロセスのアドレス空間をコピーし、`exec()`は新しいアドレス空間をセットアップして新しいプログラムをロードします。

- **ページテーブルの作成**: 新しいプロセスが生成される際に、新しいページテーブルがセットアップされます。このページテーブルは、プロセスの仮想アドレスを物理アドレスにマッピングします。

- **セグメントの配置**: プロセスのアドレス空間は、テキスト（コード）、データ、ヒープ、スタックのようないくつかのセグメントに分かれています。これらはプロセスが実行される際に配置されます。

- **動的メモリの確保**: プロセスは、`malloc()`や`new`などの関数を使用してヒープ上に動的にメモリを確保します。また、関数の呼び出しに伴うスタックの成長も動的に行われます。

### 主な違い

1. **起動と配置**: カーネルはシステムの起動時にメモリにロードされ、静的な配置が行われます。一方、プロセスは動的に生成され、アドレス空間が実行時にセットアップされます。

2. **アクセス範囲**: カーネルは物理メモリ全体にアクセスする能力がありますが、プロセスはそのアドレス空間内の仮想アドレスにのみアクセスできます。

3. **メモリ管理の手法**: カーネルは特定のメモリ管理のメカニズム（例: slabアロケータ）を使用してメモリを確保しますが、プロセスはヒープやスタックを使用してメモリを確保・解放します。

## 6. ユーザースペース(プロセス)のアドレス空間レイアウト

Linuxや他の多くのオペレーティングシステムにおけるアドレス空間は、プロセスがメモリにアクセスするための仮想的な領域を指します。この仮想的なアドレス空間は、物理的なRAM上の実際の位置とは独立しています。以下に、ユーザースペースにおけるアドレス空間の主要な特徴を説明します。

### 1. 仮想メモリ:
- 各プロセスは、それ自体が専用のメモリアドレス空間を持っているという観点から実行されます。これにより、一つのプロセスが他のプロセスのメモリ領域に干渉することなく、安全に動作できます。

### 2. アドレス空間のレイアウト:
プロセスのアドレス空間は、以下の主要なセクションに分けられます。

- **テキストセグメント**：この領域にはプログラムの実行可能コードが配置されます。
- **データセグメント**：静的変数やグローバル変数が配置される領域。
- **ヒープ**：動的に確保されるメモリ領域。例えば、C言語のmalloc()やC++のnewによって確保されるメモリはここに配置されます。
- **スタック**：関数の呼び出しやローカル変数のためのメモリ領域。関数が呼び出されるたびに、その情報がスタックにプッシュされ、関数が終了するとポップされます。
- **メモリマップトセグメント**：ファイルをメモリにマッピングするときに使用される領域。

### 3. メモリ保護:
ページテーブルとCPUの機能を組み合わせることで、各プロセスのアドレス空間が他のプロセスやカーネル空間から隔離されていることを保証します。

### 4. アドレス空間のスイッチ:
OSがコンテキストスイッチを行う際、ページテーブルもスイッチされ、新しいプロセスのアドレス空間がアクティブになります。

**わかりにくいので具体例**
Aliceは、彼女のLinuxベースのコンピュータで複数のアプリケーションを同時に実行しています。彼女はWebブラウザを開いて情報を検索しながら、テキストエディタでレポートを書いています。彼女のOSはマルチタスクをサポートしているので、これらのアプリケーションは同時に動作しているように見えます。
この例では、Webブラウザのプロセスと、テキストエディタのプロセスが、高速に切り替わって(switchして)いる。
Python向け UWSC関数移植 NoxPlayerの自動化向け

UWSCにてマクロを作成していましたが、今更UWSCも古いなと思い
興味があった Python へ自分が欲しいなと思った関数を移植してみました
もっと効率のいい関数はあるかもしれないので参考程度にお願いします

Note自体初心者の為、コードは残しますが、見づらかったらすいません
詳しく書きすぎると怒られるのでこの関数 + αで自動化等をくみ上げてください

何か追加でほしい関数や質問等があればコメントを頂ければ出来る限り対応します

```
import cv2
import subprocess
```
```
# Python版 chkimg関数
def chkimg(template_path, target_path, threshold=0.95):
    template = cv2.imread(template_path)
    target = cv2.imread(target_path)

    result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)

    if max_val >= threshold:
        return True
    else:
        return False


# 使用例
template_path = "template.png"  # チェックする画像のテンプレート
target_path = "target.png"      # チェック対象の画像

if chkimg(template_path, target_path, threshold=1):
    print("画像が一致しました。")
else:
    print("画像が一致しません。")
``` 
threshold=0.95 判定する値 0 ~ 1
UWSCと差はないくらいの動きをすると思いますので
探していた方は是非お試しください
戻り値にはTrueかFalseしか返しません


```
# 起動中のNoxデバイスIDを取得する関数
def get_running_nox_device_id():
    nox_adb_process = subprocess.Popen(["nox_adb", "devices"], stdout=subprocess.PIPE, text=True)
    nox_adb_output, _ = nox_adb_process.communicate()
    
    # NoxデバイスIDを取得
    lines = nox_adb_output.strip().split('\n')[1:]  # ヘッダー行をスキップ
    devices = []
    for line in lines:
        parts = line.split('\t')
        if len(parts) == 2 and parts[1] == 'device':
            devices.append(parts[0])
    
    return devices


# 使用例
running_device_ids = get_running_nox_device_id()
    
    if running_device_ids:
        # 最初のデバイスIDを使用する場合
        device_id = running_device_ids[0]
        print(f"利用可能なNoxデバイスID: {running_device_ids}")
```
```
# nox_adbコマンドを送信する関数
def doscmd(command, shell=True):
    try:
        result = subprocess.run(command, shell=shell, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
        return result
    except subprocess.CalledProcessError as e:
        return e

def adb(cmd):
    return doscmd(cmd)

直接コマンドを投げれるように変更
DOS側に直接投げてもいいがわかりやすく ADB という関数にした

# 使用例
_cmd = nox_adb ・・・・・
adb(_cmd)
```
話題のbedrockを使おうとしてerrorMessage": "An error occurred (AccessDeniedException) が出た時の対処法

bedrockが最近話題に上がっていますよね。
僕も使ってみたいと思い、lambdaで使ってみようとしたところ下記のエラーが出てしましました。

```
when calling the InvokeModel operation: Your account is not authorized to invoke this API operation.",
```

下記の記事を参考に作っており、ロールやポリシーには問題がないはず。

https://dev.classmethod.jp/articles/invoke-bedrock-form-lambda-function/

https://dev.classmethod.jp/articles/bedrock-lambda-stable-diffusion/

そこで、調べてみると同じような課題を持った人の質問を発見
https://repost.aws/de/questions/QUksxQi1VkRfez5TvYF2sXhw/bedrock-api-call-error-your-account-is-not-authorized-to-invoke-this-api-operation

Answerを見ていると、下記のような回答がありました
> Before using a foundational model in Bedrock your account needs to be granted access first. For some reason the workshop does not mention this.
Follow the steps here to add models:
https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html#add-model-access
Some models require some additional information and take some time before you are granted access. Once the model shows "Access granted" on the Model Access page, you should be able to call the invoke_model() function without the error.

つまり、Bedrockのモデルを使うには最初にアクセスの認可を取る必要があるとのことでした。

簡単に解決できたので、ここからはその認可の取り方について解説します。

## 認可の取り方
### 1. bedrockの管理画面に移動
まずは、AWSのサービスの検索フォームから「bedrock」を調べて管理画面に移動します。そして、「Get Started」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2040900/0f4dd606-8c44-d870-1e65-bd5633915eee.png)

### 2. model accessページに移動
「Get Started」をクリックすると、下記のようなモーダルが表示されると思うので「Manage model access」をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2040900/911b1ea8-a344-233d-71bf-52fcfe84da4c.png)

### 3. 認可してほしいmodelにチェックを入れて保存する
model accessページでは下記のようにモデルの一覧が表示されています。ここでステータスが「Access granted」となっているモデルしか使うことができません。

最初は「Access granted」のモデルが一つもないはずです。

まず、右上の「Edit」を押すと左側にチェックボックスが出てくるのでそれをチェックします。その後ページ下部にある「Save changes」をクリックします。

すると、数分後には認可が下り指定したモデルが使えるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2040900/8c887e75-5166-a2ae-e719-722a20321910.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2040900/b7f29194-f538-fc71-170e-822e8955c350.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2040900/840e73fe-bc86-8732-b6a7-a82fa4325125.png)

## 最後に
同じエラーが出てしまって困っている方の参考になれば幸いです。
ご拝読ありがとうございました。
Node.JSのメモ

## Node
### Voltaを使って Node.js をインストールする

作業するディレクトリに入って以下のコマンドを打つだけでOK

```zsh
// LTS版をインストールする場合
$ volta install node
```

```zsh
// 指定バージョンをインストールする場合
$ volta install node@18
```

### node.jsで使ってるJSのモジュールシステム
| モジュール | 概要 | 拡張子 | メモ |
|:--|:--|:-:|:--|
| CommonJS | サーバーサイドで使用できる | .cjs | require / module.exports / exports <br> CJSののモジュールはESMでも読み込める |
| ESModules | ECMAScriptModules（エクマスクリプト）の略 <br> サーバーサイドでもクライアントサイドでも使える | .mjs | import / export <br> 基本的にはESMを推奨 <br> ESMのモジュールはCJSでは読み込めない |


### CommonJS で使えるmodule
```JavaScript
// コードを実行したファイルまでの絶対パス & コードを実行したディレクトリまでの絶対パス
console.log(__filename);
console.log(__dirname);
```

```JavaScript
// ファイルの操作を行うためのメソッドが入ってる
const fs = require('fs')
fs.writeFileSync('./index.html', '<p>hello<p>')
```

```JavaScript
// Promisesを使って処理の完了を待ってから次の処理を実行できる
const fs = require("fs").promises;

(async () => {
  try {
    await fs.writeFile("./index.html", "<h1>Hello World</h1>");
    console.log("File created!!");

    const data = await fs.readFile("./index.html", "utf-8");
    console.log("File data!", data);
  } catch (error) {
    console.log("Error", error);
  }
})();
```
参考記事
[[Node.js]fs.promises APIの使い方](https://tech.chakapoko.com/nodejs/file/promises.html)
[fs Promises API でawaitを使ってファイル読み書きする](https://qiita.com/kulikala/items/135da20465c367348b52)

```JavaScript
// パスの操作を行うためのメソッドが入ってる
const path = require('path')

// path.resolve -> 第一引数にコードのディレクトリ、第二引数に現在のディレクトリから見た相対パス
const srcPath = path.resolve(__dirname, '../src/conponents')
// こちらも同じ意味となる
const srcPath = path.resolve(__dirname, '..', 'src', 'conponents')
```

### CommonJS でのルール
```JavaScript
// moduleを出力する時はmodule.exports
module.exports = hoge
// もしくは
module.exports = {
  hoge
}

// requireするときは拡張子はいらない
const hoge = require('./hoge.js') <- 不要
const hoge = require('./hoge') <- OK
```

### ESModules でのルール
そのままでは使えない。使えるようにする方法は2パターン
- package.jsonに `"type": "module",` 記述する
もしくは
- 拡張子を `.mjs` にする

```JavaScript
// importするときは拡張子が必要
import lib from './lib' <- NG
import lib from './lib.mjs' <- OK

// importする時の書き方
import library from './lib.mjs'
library()

// 一括でimportする時の書き方
import * as library from './lib.mjs'
library.hoge()
library.fuga()
```

### CJSのモジュール を ESMモジュール で呼び出す手順
- package.jsonに `"type": "module",` 記述する
- commonJSのファイルの拡張子を `.cjs` に変更する
- ESMモジュールでは `import lib from './lib.cjs'` のようにimportする

### ESMモジュール で __filename や __dirname を使いたい
```JavaScript
import { fileURLToPath } from 'url'
import { dirname } from 'path'

const __filename = fileURLToPath(import.meta.url)
const __dirname = dirname(__filename)

console.log(__filename);
console.log(__dirname);

// もしくは↓
const __dirname = fileURLToPath(new URL('.', import.meta.url))
```

### グローバルオブジェクトについて
- CommonJS（nodejs） : `global` で取得できる
- ESModules（ブラウザ） : `window` で取得できる
- 両方で動作する：`globalThis` で取得できる（ECMAScriptModulesで定められた）
【備忘録】venvで環境作成

たまにやると忘れるので備忘録です。

# 環境
- Windows 10

# venvで環境作成の流れ

## インストール済みのPythonバージョンを確認

```
$ py --list-paths

 -V:3.11 *        C:\Users\grin\AppData\Local\Programs\Python\Python311\python.exe
 -V:3.9           C:\Users\grin\AppData\Local\Programs\Python\Python39\python.exe
 -V:ContinuumAnalytics/Anaconda36-64 C:\Users\grin\Anaconda3\python.exe
```

## バージョンを指定して環境作成

```
$ py -3.11 -m venv py311
```

## 環境を有効化

```
$ source ./py311/Scripts/activate
```

## 環境を無効化

```
$ source ./py311/Scripts/deactivate
```
CircleCI上でOpenSearchを起動する

OpenSearchを使ったCIをやりたかったで、CircleCI上でOpenSearchを起動させました。

## 前提
- OpenSearch v2.9

## 方法
- 以下のように設定することで可能です。
```yaml
  - image: opensearchproject/opensearch:2.9.0
    environment:
      OPENSEARCH_JAVA_OPTS: "-Xms512m -Xmx512m"
    command: >
      bash -c '
        opensearch-plugin install analysis-kuromoji;
        opensearch-plugin install analysis-icu;
        echo "plugins.security.disabled: true" >> /usr/share/opensearch/config/opensearch.yml;
        echo "node.name: os-node" >> /usr/share/opensearch/config/opensearch.yml;
        echo "cluster.initial_cluster_manager_nodes: os-node" >> /usr/share/opensearch/config/opensearch.yml;
        echo -e "discovery.seed_hosts:\n  - os-node" >> /usr/share/opensearch/config/opensearch.yml;
        opensearch
      '
```

## ポイント
- プラグインは`command`で入れる
- 各種設定は`opensearch.yml`で必要ですが、これもやっぱり`command`で入れる

## 余談
- 上記でCIが動くようになったのですが、データをputしても反映されるの時間がかかるので、ユニットテスト上でやるのは、どうなのか！？って思います。
- テストを並列に実行したかったら、テストケース毎に、インデックスを変えれば良いと思います。
iRICの結果が上手く動画にならない場合手動で作成する方法

例えばコマンドラインで下記を実行すると640x480の動画が作成されます
ffmpeg -r 30 -i img_%04d.png -vcodec libx264 -pix_fmt yuv420p -r 60 -vf "scale=640:480" out.mp4

動画のfpsを変更したい場合

作業フォルダを空にする
del /f out\*.*

動画から連番静止画を抜き出す
ffmpeg -i input.mp4 -vcodec png out\image_%03d.png

連番静止画から動画を作る
ffmpeg -r 30 -i out\image_%03d.png -vcodec libx264 -pix_fmt yuv420p -r 60 out.mp4
           A                                                        B
A: 最終的に作る動画のfps   B: 取り込む静止画をBfpsと見なす

スケールを指定する場合は
ffmpeg -r 30 -i img\img_%04d.png -vcodec libx264 -pix_fmt yuv420p -r 60 -vf "scale=3162:1846" out.mp4

アニメgifにするには
ffmpeg -i breach1.mp4 -vf scale=1280:-1 -r 10 breach1.gif

逆に動画から静止画を抜き出すには
 ffmpeg -i movie.mp4 -ss 144 -t 148 -r 24 -f image2 %06d.jpg
    -i movie.mp4 : 元動画
    -ss 144 : 抜き出し始点(秒)
     -t 148 : 抜き出し終点(秒)
     -r 24 : 1秒あたり何枚抜き出すか
    -f image2 %06d.png : png で[000001.png]から連番で書き出し
Laravel コレクション型について.....


ドキュメント　<font color="orange">Laravel 9.x</font> で　コレクションを確認すると

> Illuminate\Support\Collectionクラスは
>配列データを操作するための、書きやすく使いやすいラッパーです。

なんのこっちゃ。。。。
理解力が足りない私がコレクションについて深掘りします。

 <details><summary>ラッパーとは.....</summary>
  まず、ラッパーって　歌う方のラッパー？となりましたが<br>

```rb
  歌う方のラッパー　＝ Rapper
  ここで出てくるラッパー　＝　Wrapper
```

 全然、別物でした。:raised_hands_tone1:

 Wrapper = 包装紙、カバー、覆うもの、包むもの、などの意味を持つ英単語。
 　　　　　ソフトウェアやプログラム部品などが提供するクラスや関数、データ型などを、本来とは異なる環境や方法で利用できるようにしたものをラッパーという。

勝手な解釈

:::note 
Wrapper＝元々ある複雑で持ちにくい荷物をWrapperで包んで持ちやすくします！
:::

という雰囲気です。。。

 </details>


まず結論として、
<font color="orange"><h3>コレクション型とは、配列のデータを簡単に扱うための型で
コレクション型も配列も使い分けが必要。<h3></font>

私なりに、わかりやすく説明します。

それではまず、同じデータを配列とコレクションで見比べてみます。


配列のデータ

```rb
array:3 [
  0 => array:2 [    "id" => 1    "name" => "John"  ]
  1 => array:2 [    "id" => 2    "name" => "Jane"  ]
  2 => array:2 [    "id" => 3    "name" => "Doe"   ]
]
```

コレクション型のデータ

```rb
Illuminate\Support\Collection {#1
  #items: array:3 [    
    0 => array:2 [      "id" => 1      "name" => "John"    ]
    1 => array:2 [      "id" => 2      "name" => "Jane"    ]
    2 => array:2 [      "id" => 3      "name" => "Doe"     ]
  ]
}
```

異なる点
- 配列の場合 = 直でデータが入っている。
- コレクション型の場合 = #items:という謎のもので包まれている。

コレクションは、ラッパーに包まれているんです！！！
<br>


コレクションはlaravelに含まれる機能で、
コレクションのおかげでたくさんのメソッドが使えるんです!!!
<br>

 <details><summary>メソッドとは.....</summary>

方法、方式、手法、やり方、などの意味を持つ英単語。
オブジェクト指向プログラミングにおけるオブジェクトに対する手続きのことや、
通信プロトコルにおける要求の種類などのことをメソッドということが多い

 </details>
<br>
<br>
<br>

配列とコレクションで同じ事をする場合を比べてみます！！！

まずは、同じデータを配列VerとコレクションVerを確認します。

配列Verのデータ

```rb
$users = [
    ['id' => 1, 'name' => 'John'],
    ['id' => 2, 'name' => 'Jane'],
    ['id' => 3, 'name' => 'Doe'],
];
```
コレクションVerのデータ
```rb
$users = collect([
    ['id' => 1, 'name' => 'John'],
    ['id' => 2, 'name' => 'Jane'],
    ['id' => 3, 'name' => 'Doe'],
]);
```

説明：
usersに3人のidと名前の情報を格納します。
コレクションVerは、collectで変換しています。


<br>
配列の場合とコレクションでメソッドを使って行う場合を比べてみます。<br>


<h3>フィルター機能</h3>
配列の場合

```rb
$filteredUsers = array_filter($users, function($user) {
    return $user['id'] > 1;
});
```
コレクションの場合

```rb
$filteredUsers = $users->where('id', '>', 1);
```

説明：
filteredUsersにidが１以上のユーザーだけを格納します。


<h3>並び替え機能</h3>
配列の場合

```rb
$sortedUsers = $users;
usort($sortedUsers, function($a, $b) {
    return $a['name'] <=> $b['name'];
});
```
コレクションの場合
```rb
$sortedUsers = $users->sortBy('name');
```
説明：
sortedUsersに名前順で並び替えを行なっています。

<h3>合計計算機能</h3>
配列の場合

```rb
$total = array_reduce($users, function($carry, $user) {
    return $carry + $user['id'];
}, 0);
```
コレクションの場合
```rb
$total = $users->sum('id');
```
説明：
totalにidの合計数を格納します。

<br>
<br>

上記は一例ですが
コレクションだと、綺麗にわかりやすくコードをまとめることができます！
<br>

ただ、コレクションはlaravelの機能なので、
案件などによって、色々なフレームワークを使う方は
配列でのやり方を知っていた方が良いのかな。。。とも思ったりします。

<br>
また、何か新しいことを発見した際は
追記していきます！！！

<br>
【Golang】参照型の初期値について

Golangでは、
スライス（slice）、マップ（map）、チャネル（channel）などの参照型の変数は、デフォルトでnilとして初期化されます。
これは、 **参照型が内部的にはポインタを持っており、nilはポインタが無効であることを示す** ためです。そのため、関数がスライスを返す場合、そのスライスがnilであることは有効な状態であり、コンパイラはエラーを生成しません。

## スライスの初期化
以下は、スライスを初期化し、それを返す関数の例です：
```go
package main

import "fmt"

func main() {
    // 初期化
	var slice []int
 
	if slice == nil {
		fmt.Println("スライスはnilです")
	} else {
		fmt.Println("スライスはnilではありません")
	}
     // 結果： スライスはnilです

     fmt.Println(slice)
     // 結果： <nil>
}

```

## マップの初期化
以下は、マップを初期化し、それを返す関数の例です：
```go
package main

import "fmt"

func main() {
    // 初期化
	var m map[string]int

	if m == nil {
		fmt.Println("マップはnilです")
	} else {
		fmt.Println("マップはnilではありません")
	}
     // 結果： マップはnilです

     fmt.Println(m)
     // 結果： <nil>
}

```

## makeを使用した初期化
### makeによるスライスの初期化
```go
package main

import "fmt"

func main() {
	// makeによるスライスの初期化
	slice := make([]int, 0)
 
	if slice == nil {
		fmt.Println("makeによって初期化したスライスはnilです")
	} else {
		fmt.Println("makeによって初期化したスライスはnilではありません")
	}
     // 結果： makeによって初期化したスライスはnilではありません

     fmt.Println(slice)
     // 結果: []
}

```

### makeによるマップの初期化
```go
package main

import "fmt"

func main() {
	// makeによるマップの初期化
	m := make(map[string]int)
 
	if m == nil {
		fmt.Println("makeによって初期化したマップはnilです")
	} else {
		fmt.Println("makeによって初期化したマップはnilではありません")
	}
     // 結果： makeによって初期化したマップはnilではありません

     fmt.Println(m)
     // 結果： map[]
}

```

## まとめ
:::note info
参照型の変数は、デフォルトでnilとして初期化
参照型が内部的にはポインタを持ち、nilはポインタが無効であることを示す
:::

:::note warn
make関数を使用すると初期化はnilではなく空のスライスまたは空のマップとなる
:::
BicepでNSG規則をパラメータ化する

NSG受信規則、送信規則の設定をBicepファイルではなくBicepパラメータファイルで管理できないかやってみたので残します。

# リポジトリ構成
* 以下のようにモジュール化、パラメータ化しています。

```リポジトリ構成
.
├── main.bicep
├── main.bicepparam
└── modules
    └── nsg.bicep
```

# Bicepパラメータファイル
* NSG定義をパラメータファイルに配列で持たせておきます。

```main.bicepparam
using 'main.bicep'

param location = 'japaneast'

param networkSecurityGroupName = 'myNsg'

param nsgSecurityRules = [
  {
    name: 'allow-3389'
    properties: {
      priority: 1000
      access: 'Allow'
      direction: 'Inbound'
      destinationPortRange: '3389'
      protocol: 'Tcp'
      sourcePortRange: '*'
      sourceAddressPrefix: '10.0.0.0/24'
      destinationAddressPrefix: '*'
    }
  }
  {
    name: 'allow-443'
    properties: {
      priority: 1100
      access: 'Allow'
      direction: 'Inbound'
      destinationPortRange: '443'
      protocol: 'Tcp'
      sourcePortRange: '*'
      sourceAddressPrefix: '10.0.0.0/24'
      destinationAddressPrefix: '*'
    }
  }
  {
    name: 'deny-80'
    properties: {
      priority: 1200
      access: 'Deny'
      direction: 'Inbound'
      destinationPortRange: '80'
      protocol: 'Tcp'
      sourcePortRange: '*'
      sourceAddressPrefix: '*'
      destinationAddressPrefix: '*'
    }
  }
]
```

# Bicepファイル
* mainからモジュールを呼び出すようにしています。

```main.bicep

param location string

param networkSecurityGroupName string
param nsgSecurityRules array

module networkSecurityGroupModule './modules/nsg.bicep' = {
  name: 'networkSecurityGroupModule'
  params: {
    location: location
    networkSecurityGroupName: networkSecurityGroupName
    nsgSecurityRules: nsgSecurityRules
  }
}
```

* パラメータとして設定したNSG定義の配列をループで設定していきます。

```nsg.bicep
param location string
param networkSecurityGroupName string
param nsgSecurityRules array

resource networkSecurityGroup 'Microsoft.Network/networkSecurityGroups@2023-05-01' = {
  name: networkSecurityGroupName
  location: location
  properties: {
    securityRules: [ for rule in nsgSecurityRules : {
      name: rule.name
      properties: {
        priority: rule.properties.priority
        access: rule.properties.access
        direction: rule.properties.direction
        destinationPortRange: rule.properties.destinationPortRange
        protocol: rule.properties.protocol
        sourcePortRange: rule.properties.sourcePortRange
        sourceAddressPrefix: rule.properties.sourceAddressPrefix
        destinationAddressPrefix: rule.properties.destinationAddressPrefix
      }
    }]
  }
}

output networkSecurityGroupId string = networkSecurityGroup.id
```

# 実行
* パラメータを指定してデプロイし、NSGが問題なく作成され、規則が設定されたことを確認します。

```
az deployment group create --resource-group [Your Resource Group Name] --template-file main.bicep --parameters main.bicepparam
```

以上です
ハロウィンから学ぶ基本演算

この時期になると見聞きする "trick or treat" について、orを別の演算にして行ったらどうなるのかというのを友人とネタにしていた中で生まれたpythonコードを供養するべくここに残します。来年くらいにまた作り直したい。

中身としては実行ごとに "trick {or, and, xor, nor, nand} treat!" を１個ランダムで表示し、それに対する適切な対応を1-5の選択肢で答えるというもので、各演算の真理値表で"1"をとるものを答えにしてます。
選択肢は
1.お菓子あげるだけ
2.悪戯受けるだけ
3.お菓子あげて悪戯も受ける
4.何もしない
5.この中にはない
です。
例えば"trick or treat!"なら
1.お菓子あげるだけ、2.悪戯受けるだけ、3.お菓子あげて悪戯も受ける、の３つが答えになります。

以下、コードです。

```python:tritre.py
import random
N = random.randint(1, 5)

print("Happy Halloween!!")
if N == 1:
    print("trick or treat!")
    ans = ["1","2","3"]
elif N == 2:
    print("trick and treat!")
    ans = ["3"]
elif N == 3:
    print("trick xor treat!")
    ans = ["1","2"]
elif N == 4:
    print("trick nor treat!")
    ans = ["4"]
elif N == 5:
    print("trick nand treat!")
    ans = ["1","2","4"]
print()
print("QUESTION:")
print("In this case, which choices are the best?")
print("choose ALL choices and type the number.")
print()
print("1:Just giving sweets")           # 1.お菓子あげるだけ
print("2:Just taken pranks")            # 2.悪戯受けるだけ
print("3:Give sweets and taken planks") # 3.お菓子あげて悪戯も受ける
print("4:Do nothing")                   # 4.何もしない
print("5:Not in these")                 # 5.この中にはない(そんなことない)
print()
print("Please type your answer (ONLY NUMBER)")
print("If more than one, separate them with ONE space(Ex.2 4)")#複数ある場合は半角スペースで区切る
playersAnswer = input().split()
playersAnswer = list(playersAnswer)
if playersAnswer == ans:
    print("That's Correct!")
else:
    print("Sorry. That's incorrect...")
    print("the answer is " + str(ans) + ".")
```
※英訳もpythonも適切でない可能性が高いですが勘弁してください
書き方が違うとかここ間違ってるとかあれば教えていただけると幸いです
【VB.NET】MySQLを使用した時のプリペアドステートメントの設定方法

## きっかけ
VB.NETでプリペアドステートメントを使用してInsert文を書いて実行したら、以下のエラーが出た。
```
unknown data type
```
使用するクラス？ライブラリ？が違っていることに気が付くのに時間がかかったのでメモとして残す。


## MySQL ServerとSQL Serverで使用するクラス？ライブラリ？が違う。
やりたいこと：DBに接続したい
MySQL Serverの場合：`MySqlConnection`　を使用
SQL Serverの場合：`SqlConnection`　を使用

Insert文を書いたときは、MySQLConnectionでMySQL Serverに接続し、
SqlCommandを使用してプリペアドステートメントを設定していた。
→違うDBサーバーのコマンドを使用してしまったのが原因

## MySQL Serverを使用、プリペアドステートメントを設定する書き方
```vb
Imports MySql.Data.MySqlClient

Dim builder = New MySqlConnectionStringBuilder()
builder.Server = "localhost"
builder.Port = 3306
builder.UserID = "root"
builder.Password = "任意のパスワード"
builder.Database = "任意のDB名"
Dim conStr = builder.ToString()

' MySQLに接続
Dim con As New MySqlConnection
con.ConnectionString = conStr
con.Open()

' レコードを追加
Dim cmd As New MySqlCommand("INSERT INTO User(name, age) VALUES (?name, ?age);", con)
cmd.Parameters.Add(New MySqlParameter("?name", "鈴木"))
cmd.Parameters.Add(New MySqlParameter("?age", 30))
cmd.Prepare()
cmd.ExecuteNonQuery()
con.close()
```

## 注意
以下のサイトはすべてSQL Serverの場合のソースが記述されているので、MySQL Serverを使用するときは注意。

SQLインジェクション対策
https://www.kzweb.info/kzweb/articles/vbnet/article.aspx?articleid=33

【VB.NET】テーブルにレコードを追加するには？
https://masagoroku.com/%E3%80%90vb-net%E3%80%91%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%AB%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF%EF%BC%9F

## 参考サイト
MySQLリファレンスマニュアル
http://download.nust.na/pub6/mysql/doc/refman/5.1/ja/connector-net-examples-mysqlcommand.html#connector-net-examples-mysqlcommand-prepare
掌握成功海外工作的關鍵：英文自我介紹和面試技巧

在現今全球化的職場中，越來越多的人尋求在國外工作的機會。特別是對於那些希望前往[美國工作](https://www.apexcharity.org/news/3/85)的人來說，英文自我介紹和面試技巧變得至關重要。在這篇文章中，我們將探討[海外工作](https://www.apexcharity.org/news/3/86)的一些關鍵要素，包括如何妥善處理英文自我介紹和面試，以幫助您成功開展國際職涯。

[英文自我介紹](https://www.apexcharity.org/news/3/92)的重要性
首先，讓我們談談英文自我介紹的重要性。這是您在海外工作申請過程中的第一個機會，可以展示您的專業和個人特質。一個出色的自我介紹可以留下深刻印象，為您爭取面試的機會。

當您撰寫自我介紹時，要確保充分准備，並強調您的學歷、工作經驗和技能。同時，請不要忘記強調您的動機，即為什麼想要在美國工作，以及您如何能夠為該公司或機構帶來價值。簡潔明瞭的自我介紹是打開海外工作大門的關鍵。

[英文面試](https://www.apexcharity.org/news/3/93)的技巧
一旦您成功通過自我介紹階段，接下來的挑戰就是面試。英文面試可能令人緊張，但充分的準備可以幫助您克服這種情感。以下是一些英文面試的技巧：

練習口語表達能力： 在面試中，流利的口語表達非常重要。練習英文口語，可以通過參加語言課程、與英語母語者互動或錄製自己的回答來實現。

了解公司文化： 在面試前，瞭解您申請的公司文化和價值觀是很有幫助的。這可以幫助您回答與公司相關的問題，同時展示您的適應能力。

回答常見問題： 準備回答一些常見的面試問題，如您的強項和弱項，職業目標，以及為什麼選擇該公司。這些問題可能在面試中被問到。

問題提問： 在面試結束時，通常會要求您提問一些問題。準備一些有深度的問題，表明您對公司和職位感興趣。

禮貌和自信： 最後但同樣重要的是，保持禮貌和自信。積極的態度和自信的表現會讓您在面試中更具吸引力。

無論您是剛開始尋求海外工作的機會，還是已經在國際職場中穩定發展，精通英文自我介紹和面試技巧都是關鍵要素。這些技能可以幫助您在競爭激烈的環境中脫穎而出，實現您的海外工作夢想。不要忘記，準備和自信是成功的關鍵！