OmniAICreator/Qiita-1.07M huggingface dataset:
【Unity】Arbor3のParameterContainerの値が変更できない問題の解決方法

# はじめに
この記事は[Hamster Output Advent Calendar 2024](https://qiita.com/advent-calendar/2024/game_hamster)の8日目の記事です！

今回は数日間悩んだ、Arbor3のParameterContainerの値が変更できない問題の解決方法を記事にしたいと思います。

https://arbor.caitsithware.com/

# 結論：同じオブジェクトに付けない
画像のように、ArborFSM(StateMachine)、BehaviourTree、ParameterContainerを同じGameObjectに付けていると...値が、変わらない問題が起きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/7ad95f81-dfe8-b741-81d1-18b2275b60da.png)

解決方法はシンプルで、1つのGameObjectから分ければ解決します。この場合、子階層のGameObjectに変更するだけで問題は解決できます。

# 気づいたきっかけ

ParameterContainerのドキュメントを発見し、○○○ParameterReferenceで値を参照するという方法を見つけました。

https://arbor.caitsithware.com/manual/parametercontainer/


今まで、自分はSet○○○(○○○, 値);のようにSetメソッドを使って値を変更すると思っていましたが、ParameterReferenceでも値を変更できるということが分かりました。

# 実際に確認した

ParameterReferenceにはSerializeField属性をつけて、インスペクタからどのParameterContainerが参照できるのか確認できます。なので、それぞれのParameterContainerに値を作成してどれが参照出来ているのか実験をして見ます！

今回、ArborFSM(StateMachine)、BehaviourTree、ParameterContainerの3つを付けているので、それぞれに、bool変数でState、Behaviour、Parameterという値を作ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/2890ffe5-4263-687f-c485-5b8d3559d590.png)


そしてParameterReferenceの参照先を確認をして見ると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/5035c177-e518-bc70-7e88-299958bce099.png)

**3つ付けてるのに1つしか参照出来ていない！** ということが分かりました。どういう基準で選ばれているのかは謎ですが、同じGameObjectに付けると駄目みたいです。

# まとめ
同じGameObjectにArborFSM(StateMachine)、BehaviourTree、ParameterContainerをアタッチしていると、ParameterContainerを参照したい時に参照先が分からなくなるので、なるべく分けよう！

# 雑メモ

### ・Set○○○が反応しなかった理由
Setメソッドが反応しなかった原因として、参照していたParameterContainerが、違った可能性が高い。それでも、何も情報が無かったら例外やエラー辺りが出てもおかしくはない気がするけども...?

### ・UnityObjectでコンポーネントを持たせる
ParameterContainerにコンポーネントを持たせたい場合、UnityObjectというのを利用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/efcc283f-4866-71be-ac11-b08b5e86daaf.png)

画像のではAnimatorが選択されているが自分で設定をする必要があり、何も設定していないと、ArborEditor上でコンポーネントが認識されないので注意が要りそう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/dd011290-3e85-dfd7-a8ec-bb08443a32ab.png)
AOAI使用時に『Client.__init__() got an unexpected keyword argument 'proxies'』と表示された

## はじめに
Azure OpenAI Serviceを利用している際に、`TypeError: Client.__init__() got an unexpected keyword argument 'proxies'`というエラーに遭遇しました。このエラーの解決方法をまとめた記事です。同じ問題に悩んでいる方の参考になれば幸いです。

- **利用環境**：Google Colab
- **ライブラリ**：`openai`
- **目的**：Azure OpenAI ServiceでRAGを構築

## エラー発生の背景

調査の結果、このエラーは`openai`ライブラリのバージョンが古いことが原因で発生していました。特に、`AzureOpenAI`のようなクラスを使用している場合、ライブラリが最新でないと互換性の問題が発生します。

## エラーが発生したコード例

以下は、エラーが発生したコードの一部です：

```python
from openai import AzureOpenAI

openai_client = AzureOpenAI(
    azure_endpoint="https://example-endpoint.openai.azure.com/",
    api_version="2024-**-**-****",
    api_key="api-key"
)
```

## 解決方法

エラーの原因は、`openai`ライブラリが古いため、新しい機能やクラスがサポートされていなかったことにあります。そのため、ライブラリを最新バージョンにアップグレードすることで解決しました。

```bash
!pip install --upgrade openai
```
Docker

# Dockerの基本と使い方

Dockerとは何かを1から説明します。

読むべき人
・既存のDocker初心者
・既存のDockerfileやcomposeファイルを理解したい人。

対象でない人
・1からDocker環境を作りたい人。

---

## 1. **Dockerを使う目的**
Dockerを使うと、プログラムの動作に必要な環境を簡単に再現できます。例えば：
- チーム全員で同じ環境を使える。
- 自分のPCを汚さずに、新しいツールやプログラムを試せる。
- サーバーやクラウド環境で効率的にプログラムを動かせる。

---

## 2. **Dockerを使う流れ**

### 1. **イメージ（Image）を準備**
- **イメージとは？**  
  プログラムを動かすための「テンプレート」や「設計図」。
- **どこで手に入れる？**  
  - Docker Hubというウェブサイトで配布されています。  
  - 例: Ubuntuのイメージを使いたい場合 → `docker pull ubuntu`

### 2. **イメージを動かしてコンテナを作る**
- **コンテナとは？**  
  イメージを元に作られる「動く環境」。
  - イメージ = 設計図、コンテナ = 動く実物。

- **コマンドでコンテナを作る**  
  - `docker run <イメージ名>`  
    → コンテナを起動して、プログラムが動きます。
  - 例: `docker run ubuntu`  
    → Ubuntu（Linux）が動くコンテナを作成。

---

## 3. **Dockerを操作する重要な用語とコマンド**

### **Docker Hub**
- **役割**: イメージを保存している場所（ウェブサイト）。
- **関係性**: Dockerイメージを取得する出発点。
- **コマンド例**:
  - `docker pull <イメージ名>`  
    → イメージをダウンロード。
  - 例: `docker pull ubuntu`  

### **Dockerイメージ**
- **役割**: プログラムや環境を作るための元データ。
- **関係性**: Dockerコンテナの基盤となる。
- **コマンド例**:
  - ローカルに保存されているイメージ一覧を表示: `docker images`  
  - イメージ削除: `docker rmi <イメージID>`

### **Dockerコンテナ**
- **役割**: イメージから作られる動く環境。
- **関係性**: 実際にプログラムを動かす場。
- **コマンド例**:
  - 実行中のコンテナの一覧: `docker ps`
  - コンテナを作成して起動: `docker run ubuntu`
  - コンテナを停止: `docker stop <コンテナID>`
  - コンテナを削除: `docker rm <コンテナID>`

---

## 4. **コマンド詳細: docker images**
### **docker images**

- **主な情報**:
  - リポジトリ名（`REPOSITORY`）: イメージの名前。
  - タグ（`TAG`）: イメージのバージョン。
  - イメージID（`IMAGE ID`）: イメージを特定するための識別子。
  - 作成日時（`CREATED`）: イメージが作られた日付。
  - サイズ（`SIZE`）: イメージの容量。


### **docker ps**
  - コンテナID（`CONTAINER ID`）: コンテナを特定するための識別子。
  - イメージ（`IMAGE`）: コンテナの元になったイメージ。
  - 状態（`STATUS`）: コンテナが稼働中かどうか。
  - ポート（`PORTS`）: 外部アクセス用のポート情報。
  - 名前（`NAMES`）: コンテナ名。


---

## 5. **`docker run -it bash` の説明**

- **役割**: インタラクティブモードでコンテナを操作。
     -  **インタラクティブモード**: ユーザーが直接コンテナ内の操作を行えるモードのことです。  
コンテナ内でターミナル（コマンド入力画面）を使いながら、リアルタイムでコマンドを実行したり、環境を確認したりできる。
- **関係性**: コンテナ内の環境を確認・変更するために重要。
- **コマンドの意味**:
  - `docker run`: 新しいコンテナを作成して起動。
  - `-it`: 
    - **`-i`**: コンテナに入力を受け付ける（インタラクティブモード）。
    - **`-t`**: ターミナルを割り当てる（コマンド入力用）。
  - `bash`: コンテナ内でBashシェルを実行。

- **実行例**:
  - `docker run -it ubuntu bash`
    - Ubuntuのコンテナを起動し、その中でBashシェルを使って直接コマンドを操作できます。

---

## 6. **Dockerの全体像と関連性**

### **関連図**
1. **Docker Hub** → イメージをダウンロードする場所。
2. **Dockerイメージ** → プログラムを動かす設計図。
3. **Dockerコンテナ** → イメージを元に作られた動く環境。
4. **docker ps** → 実行中のコンテナを管理。
5. **docker run -it bash** → コンテナ内でシェルを直接操作。

---

## 7. **まとめ**
- **Dockerの流れ**:  
  1. Docker Hubからイメージを取得。  
  2. イメージを元にコンテナを作成。  
  3. コンテナ内でプログラムを動かす。  
  4. 必要に応じて整理・削除。  

- **便利ポイント**:
  - `docker ps`でコンテナを管理。
  - `docker run -it bash`でコンテナ内を直接操作。

Dockerは、プログラムを素早く安全に動かせるツールです。ぜひ試してみましょう！
プレーンテキストをHTML形式へ変換するツール（仮）をつくってみる [段落編]

プレーンテキストをHTML形式へ変換するツールをつくってみます。

今回は、Webページでテキストをコピペできるとうれしいため、手軽にリアクティブだかなんだかができるVue.jsを使うことにしましょう。
環境準備もめんどくさいので、CDNのVue.jsを使う方法にします。

# 入出力欄

```html
<div class="cols3">
    <div>
        Input Form
    </div>
    <div>
        Monitor
    </div>
    <div>
        Output Form
    </div>
    <div id="inputForm">
        <textarea v-model="inputText"></textarea>
    </div>
    <div id="monitor" v-html="convertedText"></div>
    <div>
        <textarea v-model="convertedText"></textarea>
    </div>
</div>
```

このように3カラムの入出力欄を設け、それぞれの欄に変数をバインディングします。

```
inputText: プレーンテキスト（入力値）
convertedText: HTML形式テキスト（出力値）
```

一列目はプレーンテキストを貼り付ける場所、三列目は変換したHTMLテキストを表示する場所です。
コピペできるよう、textareaにしておきます。

二列目は変換後のHTMLテキストをサンプル表示する場所です。

二列目は今のところ必要ありませんが、今後ツールに機能を付加した場合に備え、準備しておきます。

JSのほうは以下のような記載です。

```html
<script>
    const { createApp, ref, watch } = Vue

    createApp({
        setup() {
            const inputText = ref("")
            const convertedText = ref("")

            return {
                inputText,
                convertedText,
            }
        }
    }).mount('#app')

</script>
```

# 変換方法

ふたつの文章をわける際には、pタグで段落をわける方法とbrタグで改行する方法がありますので、それらを選択して、変換できるようにします。（普段はpタグで段落をわけるため、brタグは滅多に使いませんが）

```html
<div>
    <label><input type="radio" v-model="settingPerLine" value="first" checked />pタグ付加</label>
    <label><input type="radio" v-model="settingPerLine" value="second" />brタグ付加</label>
</div>
```

https://ja.vuejs.org/guide/essentials/forms.html#radio-1

Vue.jsのドキュメントを参考にして、radioタイプのinputを二つ設けます。
両方に同じ変数setttingPerLineをバインディングし、valueをそれぞれ設定します。

これにより、チェックが入った側の値がsettingPerLineに格納され、選択されたタイプが確認できます。

変換タイプの選択ができるようになったので、次に変換機能本体をつくります。

# 変換機能

変換機能は、関数化します。

```js
function formatText(inputText) {
    const splitedText = inputText.split("\n");
    let tmp1 = "";
    if (settingPerLine.value.includes("first")) {
        tmp1 = splitedText.map(el => "<p>" + el + "</p>\n")
    }
    else {
        tmp1 = splitedText.map(el => el + "<br>\n")
    }
    return tmp1.join("");
}
```

入力があり、出力がある、というシンプルなつくりです。

# フォーム入力、変更の検知

入力フォームへプレーンテキストをペーストした場合、および、変換タイプを変更した場合、HTML形式テキストが変更されてほしいです。
ボタンを押して変換するのでもいいですが、さして重い処理を行うわけではないので、リアルタイムで反映されるようにしましょう。

この要件はつまり、変数`inputText`と`settingPerLine`が変更されたとき、変換処理を行う、ということを意味します。

そこで、Vue.jsのウォッチャーを使い、以下のようにします。

```js
watch(inputText, async (newInput, oldInput) => {
    convertedText.value = formatText(inputText.value);
})
watch(settingPerLine, async (newSetting, oldSetting) => {
    convertedText.value = formatText(inputText.value);
})
```

# 以上をくっつけて

以上のコードをくっつけて、できあがったツールがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821654/2199d8f2-9aed-5066-58d1-8eecbd9a8f60.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821654/241e986c-df4c-1eb2-053c-3172424e156f.png)


# 終わりに

使えるか使えないかよくわからんツールができあがりました。

これだけだと大して使い道のないツールになってしまいますので、おいおい機能をプラスしてみましょう。

今思いつくのは、

- 出力値をクリップボードへコピーする機能
- 複数改行を刈り取ったり、付加したりする機能
- カーソル位置に水平線を入れる機能
- CSS設定をプレビューしながら、整形できる機能
- pixiv形式とかのルビをHTML形式へ変換する機能

こんな機能を、実現方法が思いついたらプラスしていきたいと思います。
Azure Portal 上で表示される予測コストと実コストの内容と取得動作

# What is this?
~~"これは何？" は卒業しました。~~
Azure の予測コスト (Forecast Cost) の取得ロジックを検証していたところ、
Forecast の動作として、実データを保持する DB カラムは存在せず、
API コールタイミングで対象スコープの Forecast を都度計算している、
との仮説が私の中で立ちました。
あくまで仮説であり、実際の実装は不明なのでこの記事は単なる私の推測です。

本記事はその仮定に至るまでの調査事項と関連する API 及び、
調査手順として実施した内容の覚書です。

# 検証内容
[コストの管理と請求 | 概要] - [{対象サブスクリプション}] - [リソース毎のコスト : 詳細を表示] の順で遷移し、[コスト分析] 画面を開きます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/dc2e1db0-9345-6b13-b150-6bb7345d1f45.png)


この際の実行 API は DevTool の "ネットワーク" にて確認が可能です。

ここでは "12月いっぱい" の "リソース毎" 予測コストを確認してみることにします。
Microsoft Edge の DevTool (F12) を開いたのち、"表示" を "Cost by Service"、カレンダーを "12月 2024" に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/1d0c4b53-5f66-cece-569b-cafab9a630c9.png)

このタイミングで、Dev ツールのネットワークには API の履歴が出力されます。
いくつかコールされている API の中に "[forecast](https://learn.microsoft.com/ja-jp/rest/api/cost-management/forecast/usage?view=rest-cost-management-2024-08-01&tabs=HTTP)" の存在を確認できます。
API "forecast" は予測コストを取得するAPI です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/c40a932f-a410-8ddc-eef0-db26ea59ccbe.png)

戻り値としての Json には下記の値が格納されていることが確認できます。
内部には Cost として 39.849586775654195 という値が保持されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/1d5fe930-60ea-8f44-e981-6750948db940.png)

一方で、もう一つ "[query](https://learn.microsoft.com/en-us/rest/api/cost-management/query/usage?view=rest-cost-management-2024-08-01)" も確認可能です。
API "query" は任意の情報を取り出す汎用 API です。
内部には0.11694152925 / 0.366935201189456 / 8.180012629788 の三つの値が Cost として保持されています。
この合算は 8.66388936023, すなわち画面上の Actual Cost (\8.66) に合致します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48302/088dc8c7-2265-3eab-0fe9-ab222faf2ccd.png)

各 Json の値を総合算すると、39.849586775654195 + 8.66388936023 = 48.5134761359 となり、Azure Portal の画面上における予測コストの値 (\48.51) と合致することが確認出来ます。

一方で各種 API の内容から予測コストの値である数値に合致する値は確認できませんでした。

# 総括
検証結果より、画面上の予測コストは "現時点での実コスト" + "(forecast API で取得される) 残期間の予測コスト" であると推測されます。

また、API "Forecast" の取得スコープにリソースグループを指定している場合、
Body 設定できるパラメータの範囲では、スコープ指定した対象の合算値が API の戻り値として返るようです。
このため、予測値をリソース毎に取得したい場合はリソースを指定した Filter を掛けた API をリソース数分ぶん投げる必要がありそうです (=非現実的)。

とはいえ、予測コストはあくまで目安に過ぎないことを考えると妥当な仕様に感じますね。

# 補足
Azure Portal で利用されている API のバージョンとリンクで参照しているドキュメントのバージョンは一致しない場合があります。
(一例として 2024/12/17 時点では Portal の API は "2022-04-01" ですが、最新は "2024-11-01" です。)

# ぼやき
ドキュメントとにらめっこしながら Powershell からしてパラメータ作っては投げてたんですが、Azure Portal のネットワーク履歴を見たら API がそのまま投げられているのに気づき
ひどくがっかりしました。ちくせう。
【Rustのまほう2】#8 Bevy0.15バージョンアップ 


2024年11月29日に、Bevy 0.15 が正式リリースされました。リリースノートはこちらです。

https://bevyengine.org/news/bevy-0-15/

メジャーアップデートなのでAPIがバリバリと破壊的変更されましたが、コミュニティの反応は素早く、数日のうちに多くのライブラリが最新バージョンへの対応を済ませました。はやい！

私の作っているゲームが依存しているライブラリも大半が 0.15 に対応したので、ゲーム本体も対応を進めています。**ビルドエラーは約 450 箇所**となかなかの迫力だったのですが、地道に直していたら2日くらいでなんとか対応ができてきました。私が影響を受けた個所について、いくつか簡単にまとめておきます。

今回の記事は、読んでも読者にはほとんど意味伝わらんですよね……。もっと読みやすい記事を書くように頑張ります。

# Rquired Components 

Bevy本体でRrequired Componentsという機能が追加されたのですが、これが一番影響が大きいかなと思います。Bevyのエンティティはコンポーネントの集合ですが、あのコンポーネントは単独では使えず、別のコンポーネントち常に組にして使わなくてはならない、ということがよくあります。たとえば、`Transform`コンポーネントは`GlobalTransform`コンポーネントと常に組み合わせて使わなければならないのですが、毎回両方を指定して書くのは面倒です。

Bevy0.14までは、バンドル(`Bundle`)というものを使って複数のコンポーネントをまとめて指定できるようになっていました。しかしこのバンドルという機構は、これはこれで扱いづらいものでした。たとえば複数のバンドルに同じ型のコンポーネントが含まれていると、ひとつのエンティティに同じ型のコンポーネントが複数含まれることになってしまい、実行時にエラーになります。また、コードの字面としてもネストが深くなって読みにくいコードになりがちでした。

0.15で導入されたRequired Componentsでは、必要なコンポーネントは自動で追加されます。たとえば、`Transform`コンポーネントをエンティティに追加すると、暗黙の裡に`GlobalTransform`コンポーネントが追加されます。もし必要であれば、明示的に`GlobalTransform`を追加しても問題ありません。これにより、バンドルは不要となりすべて非推奨になりました。これで確かにエンティティの生成部分のコードがフラットで読みやすくなり、追加されるコンポーネントが明示的でわかりやすくなりました。

非推奨のコードを残していても仕方ないので、バンドルを使っていた部分は気合ですべて修正しました。ソースコードのバンドルでネストされていた部分をフラットにするだけなので、変更箇所は多いものの、比較的単純作業で済みました。


## `Style`コンポーネント

UI部分では、`Node`コンポーネントの中の`style`プロパティで幅や高さなどの外観を設定していましたが、これが`Node`コンポーネント自体のプロパティとなってフラットになり、コードが読みやすくなりました。これも`NodeBundle`の箇所のネストをフラットに直すだけです。

これに伴い、ZIndexの指定方法も変わったらしく、`ZIndex`と`GlobalZIndex`が別々に用意されたみたいです。

https://bevyengine.org/news/bevy-0-15/#required-components


# `Gamepad`

以前は `Res<ButtonInput<GamepadButton>>`、`Res<Axis<GamepadButton>>`、`Res<Axis<GamepadAxis>>`などの複数のシステムパラメータを指定してゲームパッドの状態を取得していたのですが、それが`Query<&Gamepad>`だけで済むようになりました。私もゲームパッド周りはなんかすげえ面倒で変なAPIだと思っていたのですが、これで凄くすっきりしました。

https://bevyengine.org/news/bevy-0-15/#gamepads-as-entities





# bevy_rapier

Bevyのバージョンアップのタイミングに合わせて、各ライブラリも破壊的変更をぶっこんできているようです。物理エンジンのbevy_rapierは今まで同時にひとつまでの物理エンジン世界を持てなかったのですが、それが同時に複数の物理世界を持てるようになりました。これに伴い、物理世界の初期化の方法が変わったようです。今までは物理世界はリソースだったのですが、エンティティになりました。重力などの設定も、物理世界ごとに個別に設定する形になっています。

https://github.com/dimforge/bevy_rapier/blob/master/CHANGELOG.md




# bevy_aseprite_ultra

Asepriteの2D画像を読み込むライブラリのbevy_aseprite_ultraでは、`AsepriteSliceBundle`などのバンドルが削除されており、`AseSpriteSlice`などのコンポーネントに置き換える必要があります。`slice`というプロパティ名が`name`に変わったりという微妙な変更もありました。

https://github.com/Lommix/bevy_aseprite_ultra
T-DASHを使ってみた！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660761/1db6e1f4-e3be-75d2-3c64-96466f3ac890.png)

## 良かった点：とても作りやすかった


### 繰り返し作業が楽になる
T-DASHでは、繰り返し行うテスト作業を簡単に自動化できるため、手作業で何度も同じテストを行っていた工程が大幅に省略できました。手間が少なくなり、他の業務に集中できるため、非常に助かります。特に、QAエンジニアにとっては、反復作業が減ることが大きな利点でした。

## 悪かった点：幅が利かない
#### 複雑な操作への対応が難しい
また、T-DASHの標準機能では対応しきれない場面もあり、少し複雑な操作が必要になることがあります。もちろん、基本的なテストは問題なく実行できますが、特殊な環境や要件に対応する際には限界を感じることがありました。特に開発者とQAエンジニアの間での調整が多くなると、機能面での物足りなさを感じることがあります。
自動化簡単にできるので楽しすぎる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660761/1db6e1f4-e3be-75d2-3c64-96466f3ac890.png)


## 簡単に設定できる
#### 思ったよりも手軽な導入
テスト自動化ツールは、初めて使うときでも簡単に導入できることが多いです。設定の手順が明確で、必要な項目を順番に進めていけば、すぐに使える状態になります。初めての人でも戸惑うことなく、ツールを使いこなすことができ、スムーズに自動化作業が始められる点が非常に楽しいと感じました。

## スクリプト作成が遊び感覚
#### 複雑な作業が簡単に
テストスクリプトの作成も、最初は少し手間がかかるかもしれませんが、すぐにコツをつかめます。最初は単純な操作から始め、徐々に複雑なシナリオに挑戦していくと、まるでゲームをクリアするような感覚で進められます。簡単なステップをこなすだけで成果が見えるので、どんどん楽しくなります。

## 目に見える成果がやりがいに
#### 成果がすぐにわかる
自動化ツールを使うと、成果が目に見えてわかりやすいのも大きな魅力です。手動で行っていたテストが数分で終わったり、エラーの原因が即座に分かることで、達成感や満足感が高まります。次々と課題が解決できるので、やりがいを感じながら楽しんで作業できるようになります。
進捗報告 (2024-12-07 19:18:57)

# 音声入力による自動記録アプリの開発進捗

## 概要
現在、介護現場向けに音声入力を利用した自動記録アプリを開発しています。このアプリは、音声で入力されたテキストをデータベースとしてGoogleスプレッドシートに保存し、記録漏れを防ぐことを目的としています。

## 仕組み
アプリの主なフローは以下の通りです。

1. **音声入力のテキスト化**:
   - ユーザーが音声で入力した内容をテキストとして取得します。

2. **OpenAI APIへのリクエスト**:
   - テキストをOpenAIのAPIに送信し、操作対象のテーブルと顧客名を特定します。

3. **カラム一覧の取得**:
   - 受け取ったレスポンスに基づき、再度OpenAIのAPIにリクエストを行い、操作対象テーブルのカラム一覧を取得します。

4. **編集モーダルの表示**:
   - 特定したカラムに基づいて編集モーダルを展開し、音声入力結果を表示します。ユーザーはこのモーダルで手動編集が可能です。

5. **自動での時間取得**:
   - 入力された記録に対して、時間を自動で取得し入力します。

6. **Googleスプレッドシートとの連携**:
   - 入力された情報はGoogleスプレッドシートに自動で反映されるように設定されています。これにより、記録漏れ（例: 天気、服薬、食事の記録）が減少します。

## 次のステップ
今後の目標として、現在使用しているGoogleスプレッドシートのレコードと、運用中のExcelシートをリアルタイムで連動させることを目指しています。この連携により、データの一貫性と即時性を向上させることが期待されます。

## 結論
音声入力を活用したこのアプリは、介護現場における記録作業の効率化を図るものであり、今後の機能追加や改善を通じて、さらなる利便性向上を目指していきます。
自動化は楽（確信）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660761/1db6e1f4-e3be-75d2-3c64-96466f3ac890.png)

## 手軽に始められた自動化ツール
#### 初期設定がシンプルだった
テスト自動化を始めるにあたって、特に難しさを感じることなく、すぐに設定を進めることができました。自動化ツールが非常に直感的で、環境構築や初期設定に時間を取られることがなく、スムーズにテストを開始できました。ツール自体がユーザーフレンドリーであり、わかりやすいインターフェースが提供されていたため、手軽に導入できました。

## スクリプト作成が思ったより簡単
#### 誰でも扱いやすかった
自動化スクリプトの作成も予想以上に簡単に感じました。複雑なコーディングをしなくても、ツールの機能を活用することで、基本的なテストケースはあっという間に作成できました。もちろん、難しいシナリオが求められる場合もありますが、簡単なものはすぐに自動化でき、テスト実行が楽しくなりました。

## 素早い結果確認で効率化
#### 時間短縮が実感できた
自動化によって、手作業で行っていたテストの時間が大幅に短縮され、効率化が実感できました。特に、繰り返し行うべきテストケースに関しては、手動で行っていた頃と比べて、圧倒的に短い時間で結果を得ることができました。これにより、品質管理にかかる時間を他の作業に充てられるようになり、全体の業務が軽くなったと感じました。
[ffmpeg]動画の1枚目の画像を切り出したい

## まえがき
next.jsで作ったサイトのvideo要素にposter属性でサムネイル設定しないと
スマホで表示した時にサムネイルが非表示になるんだよね
いちいちpremiereとか起動するのもめんどい

## 結論
ffmpegでやるといいよね。

## Homebrewがインストールされてるか確認
```
brew -v
```

## HomebrewでFFmpegをインストール
```
brew install ffmpeg
```
## FFmpegがインストールされてるか確かめる
```
ffmpeg -version
```
## 動画の1フレーム名を指定し切り出す
```
ffmpeg -i /path/to/video.mp4 -ss 00:00:01.000 -vframes 1 /path/to/poster.jpg
```
GitHub Issueの親子関係を管理する

こんにちは！めゆです！

GitHub dockyardアドベントカレンダー7日目です！

こちらの記事ではGitHub IssuesにIssueを親子関係をつけられるようになった話をしようと思います。

以前までは、GitHub上では明示的なIssueの親子関係をつけることができませんでした。なので、Issueの概要に書いたり、ラベルを付けることで親子関係のIssueを管理していました。

ですが下記の変更でIssueの親子関係を明示的に示せるようになりました。
https://github.blog/changelog/2024-10-01-evolving-github-issues-public-beta/

今はパブリックベータなので、WaitリストにOrganizationを登録し、Waitリストを通過したOrganizationで使用できます。

Waitリストはこちら
https://github.com/features/issues/signup

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3513808/fdcd3e2e-2cb0-30b6-3111-1c5f1820a8b6.png)

痒い所に手が届くような機能追加で個人的にかなりうれしいです！早くどの環境でも使えるようになってほしいです！
１ページテスト計画

##
これは、大規模開発向けではなく、アジャイル開発向けのテスト計画になります。

JaSST北海道 '21 での発表時に少しだけ触れましたが、10年くらい前から、
ペラ1テスト計画をつくっています。
その時のスライドがこちらです。
https://www.jasst.jp/symposium/jasst21hokkaido/pdf/S3A-2.pdf

## IEEE29119-3を使って、ペラ1テスト計画を書く
まず、テストドキュメントを扱った、IEEE29119-3のテストドキュメントについて書かれたものを
確認します。いまは翻訳されたものも見られるので、楽になりましたね。
https://webdesk.jsa.or.jp/books/W11M0070/index
その他、いろいろなメディアや本で紹介されていますので、そういった物を参照されてもよいでしょう。

この中から、自分たちのチームに必要な項目を抜き出し、１枚にまとめます。
あとは、それを埋めるだけです。

情報が飛び交うスクラムチームでも、この1枚をみれば、仕様書のURLやステークホルダー、
リリース日などがまとまっています。メンバーが、忌引きなどで突然出社できなくなったような場合でも、
この１枚があれば引継ぎができます。

普段の会話や確認から、自然に埋まるので、時間もかかりません。
記録ものこるので、あとから何があったか追いかけることができます。
便利ですよ！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/156898/7e6a7aaa-e4ff-e540-b998-492c972852d8.png)
IBM Cloud Advanced Architect v2を受けてみた

## IBM Cloud Advanced Architect v2とは

IBM Cloudの認定技術者試験の1つで、最上位であるAdvancedレベルの試験です。当試験に合格するとIBM Advanced Certified Architect - Cloud v2の認定資格を得ることが出来ます。

<img src="https://images.credly.com/images/7619cac8-4e3c-49cb-b83f-ce4162a327ae/C9006300_BADGE_EMBLEM_FILE_AdvArchv2.png" width="128">

認定資格および試験の概要はこちらです。

https://www.ibm.com/training/certification/ibm-certified-advanced-architect-cloud-v2-C9006300

v1は既に持っておりv2はずっと未受験だったのですがこの度受験しまして、無事合格しました。

## 学習方法

IBM公式の学習サイトがありますのでそこで勉強することも可能です。なお私は例によって無勉強で行ってきました。

https://www.ibm.com/training/path/ibm-cloud-advanced-architect-790

なお、昨年まではIBM Cloud Prepという試験対策に特化したサイトがあったのですが残念ながらサンセットしてしまったようです。

## 受験方法

PearsonVUE社のサイトで予約して受験してください。

https://www.pearsonvue.com/jp/ja/ibm.html

## 合格点

60問中37点以上が合格ラインです。

## 感想

ここしばらくIBM Cloudから離れていたのですが、v1があまり難しくなかったのでv2も行けるだろうと思って挑んできました。無事合格点は取れましたが、わからない問題が結構ありました。長文の問題もそこそこあったので集中力を維持するのが大変でした。
ElasticSearchって何？

## 経緯
私は大学の学部３年生で情報検索分野の研究室に所属しています。
最近、ElasticSearchという検索エンジンを耳にし、検索分野の研究室生として知っておいて損はないと思い、調べてみることにしました。

## ElasticSearchって何？
公式によると、
> Elasticsearchはオープンソースの分散型RESTful検索・分析エンジン、スケーラブルなデータストア、ユースケースの急増に対処可能なベクトルデータベースの役割を兼務します。データを一元的に格納することで、超高速検索や、関連性の細かな調整、パワフルな分析が大規模に、手軽に実行可能になります。

## ElasticSearchでできることの一部
- RAG（外部の知識ベースを元にLLMが回答を生成するようにする技術）
- 高速な全文文書検索
- 密検索（入力されたキーワードの意味に近いものを検索する技術）

## ElasticSearchの仕組み

### 分散型アーキテクチャ
まず、分散型アーキテクチャって何？って感じですが、ElasticSearchでは以下のようにデータを管理しているようです。
![スクリーンショット 2024-12-07 17.10.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827013/769a0e6d-65e0-e3b1-aa74-465e1cdda0ac.png)
要は、ノード（＝サーバ）を複数設置することで、並列処理や分散ストレージを実現しているっていうことです。ちなみにクラスタの定義は「ノードの集合体」です。

### JSONベースのRESTful API
ElasticSearchの使用はREST APIを介して行われます。
<details><summary>RESTって何？</summary>
一定のルールが設けられているAPIの一種。Representational State Transferの略称。

以下のルールがあります。

1. クライアント・サーバ方式
2. ステートレス
    - リクエストの情報を保存しない（リクエスト単位で区切られる）
3. 接続性
    - 他のアドレスのリンクを入れることができる
4. 統一されたインターフェース
    - GET（データの取得）、POST（データの登録）、PUT（データの更新）、DELETE（データの削除）
5. アドレス可能性
    -全てのリソースがURIで表現される
</details>

↓ リクエストとレスポンスの例（公式より）
```
// リクエスト例
POST localhost:9200/accounts/person/1 
{
    "name" :"John",
    "lastname" :"Doe",
    "job_description" :"Systems administrator and Linux specialit"
}
```
```
// レスポンス例
{
    "_index": "accounts",
    "_type": "person",
    "_id":"1",
    "_version":1,
    "result": "created",
    "_shards": {
        "total":2,
        "successful":1,
        "failed":0
    },
    "created": true
}
```

### データの管理
データ（ElasticSearchの場合はドキュメントと呼ぶ）は、インデックス（DBのようなもの）とタイプ（テーブルのようなもの）によって管理されているようです。

![スクリーンショット 2024-12-07 19.09.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827013/476ee3aa-4d24-c74d-64e2-f3146a21803d.png)

## まとめ
普段の開発ではRDBしか使ったことがなかったので、DBの種類の良い勉強になりました。
個人で使うにはやや高額なため、すぐに使う予定はないですが、業務等で使う機会があれば**便利さ**を実際に感じてみようと思います。

## 参考にしたサイト

https://www.elastic.co/jp/elasticsearch

https://dev.classmethod.jp/articles/elasticsearch-getting-started-06/
初心者向けにC言語チートシートを自分なりにまとめてみた #2

# 前回
https://qiita.com/PitaQ/items/889ae27d6eb853984cee

# マクロ (macro)
マクロはただ単にコードを置換するだけのものです。
```c
#include <stdio.h>

#define TIME 5
// #define DEBUG

int main() {
    int a = 10;
    
    for (int i = 0; i < TIME; i++) {
        a += 4;
        // DEBUGが定義されているときのみ printf("i: %d, a: %d\n", i, a); が処理される
#ifdef DEBUG
        printf("i: %d, a: %d\n", i, a);
#endif
    }

    printf("a: %d", a);

    return 0;
}
```

# 三項演算子 (ternary operator) b ? x : y
三項演算子はif文と違って短く、簡潔に書くことができます。
どちらがいいかは目的によって異なってきます。
```c
int a = 8, res;

// if文
if (a == 8) {
    res = 1;
} else {
    res = 2;
}

// 三項演算子
res = (a == 8 ? 1 : 2);
```

# 定数2 (const)
前回の定数もマクロですが、ただ単に置換しているだけで定数2とは違って文字列となっています。

```c
const double TAX = 1.10;
```

# ポインタ (pointer) &n
ポインタ変数は変数のアドレスを入れるためのもので、記述方法は変数名の前に*を付けます。
変数のアドレスは&をすでにつくられた変数名の手前に置きます。

以下のように記述します。

```c
int n = 5; // 整数型変数num をつくって 5 を入れる
int *p = &n; // ポインタ変数p に n のアドレスを入れる

// ポインタ変数(nのアドレス)を出力
printf("%p\n", p); // 出力: "0x7ffdf0fdd0d4"

// ポインタの参照元(n)の数値を出力
printf("%d\n", *p); // 出力: "5"
```

ポインタはscanf() のように返り値をそのまま代入せずに呼ぶだけで関数内で値を代入することができます。
%p はポインタのフォーマット指定子です。

# 最後に
三項演算子やマクロって便利ですな！
昔、ポインタで一度混乱したことがありますが、変数(箱)のアドレス(住所)を記したメモ書きと思えばイメージが湧くでしょう。
テスト自動化導入時の効率化と時間短縮の魅力

### 1. テスト作業の効率化
テスト自動化がもたらす最大の利点は、作業の効率化です。従来の手動テストでは、同じテストを繰り返し行う必要があり、時間と労力がかかります。これに対し、テスト自動化を導入することで、手順を一度設定するだけで、テストが自動的に繰り返し実行されます。この繰り返し作業の負担を軽減することにより、チームの負荷が大幅に軽減され、他のタスクに時間を割くことができるようになります。

##### 作業の重複排除
テストケースが多くなると、同じテストを何度も実行しなければならない状況が発生します。しかし、テスト自動化により、同じ手順を何度も手作業で行う必要がなくなります。これにより、テスト作業の重複が排除され、チームは新たな課題に集中することができます。

##### テスト実行の迅速化
手動テストの場合、テストの実行に時間がかかりますが、自動化されたテストは短時間で結果を出すことができます。特に、複数のテストケースを同時に実行する場合、自動化ツールは効率よくテストを並行処理し、より迅速に結果を得ることができます。これにより、開発のスピードが加速し、迅速なフィードバックが可能となります。
テスト自動化あるある3選！

テスト自動化「あるある」と、それに伴う苦労について書いていきます！！


### 環境構築でつまづく
テスト自動化を始めるにあたり、最初の大きな壁が環境構築です。理論上はスムーズに進むはずの設定作業が、実際には予期しない問題や細かな制約に阻まれることがよくあります。特に、チームのスキルセットや使用するツールの特性に応じて、解決策を模索する時間がかかるのは「あるある」の一つです。

### エラーの原因が分からない
テスト自動化のスクリプトを作成しても、実際に動かしてみると予期せぬエラーに遭遇することがよくあります。このエラーが発生する理由が明確でない場合、原因の特定に時間がかかり、挫折しそうになることもあります。特に、システム全体の複雑性が増すと、どの部分でエラーが発生しているのか特定するのがさらに難しくなることがあります。


### スクリプトの更新が追いつかない
開発の進行とともに仕様が変更されると、せっかく作成したスクリプトが使えなくなることもしばしばです。この対応に追われてしまい、本来の効率化が目的であるはずの自動化が、逆に手間を増やしているように感じる場面も少なくありません。この「仕様変更との戦い」も、自動化における大きな苦労の一つです。
転職活動はお見合い

:::note
この記事は、[転職活動して気づいた「これをやっていれば.../やってよかった」をシェアしよう by 転職ドラフト Advent Calendar 2024](https://qiita.com/advent-calendar/2024/engineering-careers-2)への寄稿です。
:::

# はじめに

初めての方は初めまして、ご無沙汰の方はお久しぶりです。かれこれ10年くらいやってきたiOSエンジニアです。

実はこれまで1回だけしか転職したことがなくて、当時のことも退職エントリーとして[記事書いていました](https://elhoshino.hatenablog.com/entry/2017/09/30/000000)ので、そちらも併せて読んでいただけるとより多くの視点からの情報が見えると思います。簡単にまとめると、当時は天井が見えてきたのが一番の原因で、ついでに開発スタイルの違いや給与面の不満もやはりあったから、勢いで退職願出して転職活動始めたのです。

# 当時の転職活動を簡単に振り返る

転職活動にあたって、私は知り合いのエンジニアさんからの勧誘と、いわゆる転職エージェントさんからの紹介両方経験しました。実は当時は本当に初めての転職で右も左もわからず、今となっては当たり前のような転職ドラフトさんみたいな転職仲介サービスの存在すら知らなかったので試せなかったです。まあうまく転職できたので結果オーライです。ちなみに最終的に転職で入社したゆめみはエージェントさんからの紹介です。

# 本題

さて、本題に入りましょう。転職活動して気づいた「やってよかったこと」ですね。今回は2つお話しできたらと思います。

## 勉強会に参加したことによる収穫

まず私が一番やってよかったことは、転職活動前から様々な勉強会で顔を出して、場合によっては登壇もしたことです。別に転職活動を見据えた活動ではなく、単純に一人で独学したから限界が見えたから、同じ仕事やってる仲間がほしいという単純な理由で勉強会参加したのです。ただ結果として、仕事のスキルだけでなく、今でもよく一緒に遊ぶ友達もできたのは一番の収穫だったと思います。友達は本当に心強いです。転職活動においても所属会社紹介してもらったり、エンジニア面接の時も「あーloveeさんですね知ってる知ってる」とプチ有名人気分になれるのももちろんですが、普段の開発でつまづいた時の相談もできるし、そこからさらに発展してなぜか[技術書の共著](https://peaks.cc/lovee/iOS_architecture)までできたので、本当に最高です。なのでもしまだ勉強会に参加したことがない方が行ったら、ご自身の分野の勉強会ぜひ参加してみてください。特にオフラインのものです。スキル以上に遥かに貴重な収穫ができます。

## 転職活動はお見合い、という心構え

次はタイトル通り、「転職活動はお見合い」という心構えです。

### 偽りなく誠実に対応しよう

何を言いたいかというと、お見合いだから、特にまだ若いエンジニアさんなら自分のことをよく見せようという気持ちはもちろんわかりますが、やりすぎたり嘘ついたりするのは絶対禁物です。むしろある程度ありのままの自分を晒した方がいいと思います。これから入る（かもしれない）会社は、これから長い付き合いになります。長く一緒にいられるコツはお互いどんなに相手のことが好きかではなく、どれくらい相手の嫌な部分を我慢できるかです。だから仮に憧れのあの会社さんに入りたいがために、もしくは早く次の会社に入りたいと焦ってしまうがために、面接で必死に背伸びして、本当は嫌なことやできないことまで「喜んで！」「できます！」と言ってしまうと、もし入社できたらそれらのこととずっと付き合っていかないといけないのです。本当にそんなことできますか？

ここで自分の転職活動の時のエピソードを一つ披露します。私は先ほど今入った会社はエージェントの紹介で知った会社と話しましたが、実は面接前に、エージェントさんは必死に「面接の時は転職理由に給与の話を絶対に入れるな！」「『怠惰』は普通に聞こえが悪いから避けた方がいい！」「Swiftしかやりたくないとかの発言は強気すぎるから絶対言っちゃダメ！」と口説きました。そして私は「はいわかりました」と言いながら面接の時全部破りました。なぜならそれが私の当時の本当の気持ちです（というか今でも相変わらずです）。嘘つきたくないし隠したくないです。それが効いて「この人は誠実な人だ」と思われたからかはわかりませんが、とりあえずお陰様で今でも社内でSwift以外の開発の仕事任されたことなくて穏やかな生活が送れています。

### 対等な立場でお互いリスペクトし合おう

ちなみに「転職活動はお見合い」はもう一つの意味があります、それは求職者と会社はお互い対等の立場だと思います。これも特に若いエンジニアさんがやりがちなミスかと思いますが、あなたが給与のために仕事を求めてるからと言って、卑しい態度を取ったり不必要なまで相手を持ち上げたりする必要が全くないです。なぜなら会社も同じくらい、仕事を回すために従業員を求めているのです。もちろんだからと言って自分から面接官を責めたり偉そうに大口を叩くのもダメです。お互い対等な立場で、リスペクトし合いながら面談や面接に臨みましょう。

# 最後に

以上、転職活動して気づいた「やってよかった」ことでした。これで皆さんの転職活動に少しでも役に立てたら幸いです。
T-DASHを使ってみて：良い点と改善点

テスト専門会社バルテスが開発したテスト自動化ツール「T-DASH」は、多くの現場で活用されています。私も今年、プロジェクトの一環として使用しましたが、その際に感じた良かった点と改善が必要だと感じた点についてお話しします。


### テスト結果の一元管理
さらに、テスト結果を分かりやすく管理できる機能も印象的でした。一つのツール内でエラーの状況や進捗を確認できるため、プロジェクト全体の把握がしやすく、迅速な意思決定に繋がります。

### 改善を望む点

一方で、T-DASHのUI（ユーザーインターフェース）は、操作性の面でやや課題があると感じました。直感的に使えない部分があり、初めて利用するユーザーにとっては、ツールの機能を十分に活用するまでに時間がかかる印象です。例えば、設定画面が複雑だったり、操作手順が分かりにくいと感じることがありました。もっとスムーズに操作できるような設計であれば、さらに多くのユーザーにとって使いやすいツールになるでしょう。


T-DASHは、その豊富な自動化機能で現場の効率化を実現する大変便利なツールです。一方で、UIの改善が進めば、さらに幅広いユーザー層に使いやすいものになると感じました。これからも進化を続けるT-DASHに期待しながら、引き続き現場で活用していきたいと思います。
【Blender】シンプルな目玉を作る

【この記事のゴール】
Blenderを使って、球体モデルと画像テクスチャを作成します。

完成系のイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/866846d0-bdd2-a2a7-a851-a2e7d5381e18.png)

## 球体を配置
### モデルの作成
blenderを開いたら、レイアウトタブのオブジェクトモードで、
「Shift + a」で、メッシュ > UV球 を選択し、球体を配置します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/db9a2a8d-af62-8d21-ea3c-1a3178858d37.png)

### モデルの調整
球体モデルを選択した状態で、「r → x → 90」を入力し、向きを90°傾けます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/9b6ebcdb-68df-9d13-06eb-80969393d009.png)

右クリック > スムーズシェード で表面を滑らかにしておきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/82422426-bdf4-1bad-cebe-109302b8c9a9.png)

## UVマップを作成する
### シームを入れる
左上で編集モードに切り替え後、選択モードを「辺選択モード」にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/a195279e-a178-5291-83b6-4d3115a045eb.png)

Altキーを押しながら球体の真ん中の線を選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/33355c26-ea8d-9827-aed4-5857e6e3e38e.png)

右クリック > シームをマーク を選択します（選択後、線が赤くなればシームマーク状態）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/2fe06f05-02f2-5ec4-946b-2595f27e4497.png)

### UVマップを確認
UV編集タブに切り替え後、モデルにカーソルを当てながら「L」キーでモデルを選択状態にします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/e5a836ef-7695-b276-f6b3-e3ddc739a716.png)

その状態で「U」キーを押し、UVマッピングの展開を選択します（左のウィンドウに円形のUVマップが表示されたらOK）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/bc773b56-6e15-2925-ede0-35399d0b0920.png)

## テクスチャを作成する
### マテリアルを設定する
シェーディングタブに切り替えて、画面中央の「新規」ボタンでマテリアルを追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/5cb5fff2-6d88-bb43-4ec9-65e2cfdfdc55.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/547512cd-9f06-ea45-c40a-d97f404e44f3.png)


マテリアルウィンドウ上で、「Shift + a」を入力し、テクスチャ > 画像テクスチャ を追加します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/0235fc42-2a38-0fd1-6b72-f248372672d5.png)

画像テクスチャのカラーとプリンシプルBSDFのベースカラーをつなぎます（黄色い線の部分）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/0d93987e-5f72-83d6-a86b-f833b12c7762.png)

画像テクスチャの「新規」ボタンから画像を作成します
適当な名前をつけ、カラーを設定します（ここでは白にしています）
「新規画像」ボタンで上部のビューに反映されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/4363daa7-9b78-5087-c551-a17b02cf5dc3.png)

### テクスチャを描く
テクスチャペイントタブに切り替えます
このとき、右上のビューポートシェーディングをマテリアルプレビューにしておくと見やすいです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/334e86a0-ed4f-51ed-1b1b-7afaf15b3395.png)

左側のビューにペイントしていきます（右側のモデルに描くこともできます）

デフォルトだと減衰が「カスタム」でぼやけて見えるため、
「一定」に変更してから描きこみました（減衰ボタンは右にスクロールするとあります）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213957/866846d0-bdd2-a2a7-a851-a2e7d5381e18.png)

これで完成です。
MacにWindowsからSSH接続する

## 背景
我が家には大学時代に使用していたMacが1台あるのですが、めったに使わないので取り出しにくいところにしまってあります。いざ使うとなったときに取り出すのが面倒なので1軍のWindowsから操作することにしました。

## 追記(2025/04/19)
SSH接続の設定の前にMacのIPアドレスを固定しましょう。
固定にしなくてもいいですが、IPアドレスが変わるたび設定を変えないといけないので非常に面倒です(経験談)。

https://qiita.com/sion_neko/items/f5c16362d7253cdde240

## Mac側の設定
SSH接続するためにMac側で下記設定を行います。
OSはSonomaです。

設定 -> 一般 -> 共有 -> リモートログインをON
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931306/d42c21d9-d07a-c875-02d7-aecc9ce6c97c.png)

## SSH接続する
Mac側の設定ができたら、あとはsshコマンドで接続するだけです。

```:PowerShell
ssh [ユーザ名]@[IPアドレス]
```

## 公開鍵認証で接続する
現状だと毎回パスワードを入力する必要があるので、公開鍵認証で接続するようにしてパスワード入力不要にします。

### 1. `~/.ssh`フォルダに移動して鍵を作成する
Windowsの`~/.ssh`フォルダに移動します。
```:PowerShell
cd ~/.ssh
```

  
下記コマンドで鍵の作成を行います。
実行後に鍵の保存先やパスフレーズが聞かれますが、こだわりがなければ何も入力せずにEnterで問題ありません。
```:PowerShell
ssh-keygen
```

### 2. 公開鍵をMacに登録する。
scpで先ほど作成した公開鍵をMacに渡します。

```:PowerShell
 scp ./id_ed25519.pub [ユーザ名]@[IPアドレス]:~/.ssh
```

続いて、Mac側でターミナルを開き、受け取った公開鍵を`~/.ssh/authorized_keys`に書き込みます。Windowsの公開鍵を登録します。
```:Mac: bash
cd ~/.ssh
```
```: Mac: bash
cat ./id_ed25519.pub >> authorized_keys
```

### 3. configに鍵を追記する。
`~/.ssh/config`に下記を記載します。
```:PowerShell
Host mac
	HostName [IPアドレス]
	User [ユーザ名]
	IdentityFile ~/.ssh/id_ed25519
```

設定は以上です。
configに記載したので下記コマンドでssh接続できます。
```:PowerShell
ssh mac
```

## おわりに
これでMacをすごく取り出しにくい目立たないところに封印できます。
非常に快適です😊

## 参考
下記記事を参考にさせていただきました。
* https://qiita.com/normalsalt/items/066165646643c2501d71
テスト自動化導入の挑戦：技術不足を乗り越えた楽しい経験

## はじめに
数年前、私はソフトウェア開発チームのシステムエンジニアとして、初めてテスト自動化の導入に取り組みました。当時の私は、自動化ツールについての知識がほとんどなく、チーム全体も初めての試みで不安がいっぱいでした。しかし、そのプロセスは難しいながらも楽しい経験となり、今でも強く印象に残っています。

## 導入初期：未知の技術への挑戦
#### 初めてのツール選定
最初に直面したのは、自動化ツールの選定でした。チームメンバーの間でも「どのツールが適切なのか」という議論が続き、技術不足の私は、用語すら理解できない状態でした。それでも、調査を進める中で、操作がシンプルで学習コストが低いツールを選ぶことになり、テストエンジニアの助けを借りながら少しずつ環境構築を進めていきました。

#### スクリプト作成の壁
導入後、スクリプト作成に挑戦する段階で、私は新たな壁に直面しました。特に、アプリケーションのUI部分をテストする際、細かい挙動を再現する方法が分からず、何度も試行錯誤を繰り返しました。一つのテストスクリプトが動作するだけで、チーム全員が喜び、その瞬間の達成感は今でも忘れられません。

## 苦労の中に見つけた楽しさ
#### チームでの学び合い
技術不足を補うため、チーム全員で知識を共有し合う時間が増えました。特に、データサイエンティストがデータの生成方法をアドバイスしてくれたり、QAエンジニアが実際のテストケース作成を手伝ってくれたりすることで、一体感が生まれました。新しい技術を一緒に学ぶ楽しさに気づいたのは、この経験のおかげです。

#### 少しずつ成果が見えてきた
試行錯誤を繰り返した結果、リグレッションテストが自動化され、1日かかっていた手動作業が数時間で終わるようになりました。そのとき、「テスト自動化って本当に効果があるんだ」と初めて実感し、苦労が報われた気持ちになりました。この成功体験が、技術的な自信を育むきっかけとなりました。

## まとめ
テスト自動化導入は、当初技術不足で戸惑うことばかりでしたが、チームで支え合いながら乗り越えたことで、大きな成長と楽しさを感じる経験となりました。技術的なハードルはあったものの、得られた達成感と学びはその苦労以上の価値がありました。今では、あの経験が自分のキャリアの大きな財産だと思っています。
転職先でのコミュニケーションの取り方３選

# はじめに

アドベントカレンダーのタイトル通り、今年は転職をして大きな転機となりました。

転職することでこれまでと違う環境で働くことになります。
中でも大きく変わるのが人間関係です。

全員初めましての関係値からのスタート。
前職で気軽に話していた同期やメンバー・上長は転職先にいません。

入社して分からないことだらけな状況で、個人的に実践していたコミュニケーション方法を今回は紹介します！

# 落ちているボールを拾う
分からないことしかないので、自分の考えをもって聞きにいくということをしていました。
例えば、運用の方から仕様の質問が来た際に自分で調べたり考えた上で、「これってこうだと思うのですが合っていますか」という質問をしに行きました。

これで話しかける理由ができて理解も深められるので一石二鳥です！

# 雑談できる機会を逃さない
朝礼前やMTG開始前の時間など、手持ち無沙汰な時間で雑談をするようにしていました。
お互い話したことがない関係値で質問・相談するのは心理的ハードルがとても高いと感じるので、このハードルを下げるために、とにかく話す（対面や通話がベスト）ことを心がけていました。
逆に、文面のやり取りは相手の感情が読み取りにくいので出来るだけ避けていました。

# 明るく、あいさつはしっかり
入社したばかりですぐの活躍が難しい場合は、元気だけでも撒き散らしましょう。
あいさつは社会人の基本ですが、できていない人が多いです。
仏頂面な人と、明るい人、どちらがコミュニケーション取りやすいかは明らかですよね。
入社したばかりで教えてもらう機会が多い立場なので、話しかけやすい・指摘しやすいように明るく振る舞うことは大事だと思います。

# おわりに
以上、転職先で実践しているコミュニケーションの取り方３選でした。
テスト自動化あるある：発展途上だけど広がる可能性

## はじめに
テスト自動化は、ソフトウェア開発の現場で効率化を図るための重要な技術として注目されています。しかし、現場で実際に運用してみると、まだ課題や「あるある」と呼ばれる現象が多く見られます。それでも、その可能性に期待を感じることが多い技術でもあります。今回は、私がシステムエンジニアとして経験したテスト自動化の「あるある」を事例とともにお伝えし、技術の発展と可能性について考えてみたいと思います。

## テスト自動化の「あるある」事例
#### 初期設定に時間がかかる
テスト自動化を導入する際、最初の準備に多くの時間がかかるという「あるある」があります。例えば、テストエンジニアがWebアプリケーションのUIテストを自動化する際、ツールの設定や環境構築に予想以上の時間を費やすことがありました。一度設定を終えれば効率的に回るのですが、初期段階では「これ、本当に時間短縮になるのか？」と思ってしまうこともしばしばです。

#### 仕様変更に振り回される
もう一つの「あるある」は、仕様変更によるスクリプトの修正です。特にアジャイル開発の現場では、プロジェクトが進行する中で要件が変わることが日常茶飯事です。あるプロジェクトでQAエンジニアがテストシナリオを組んでいた際、仕様変更が連続し、スクリプトの修正が追いつかず、結局手動テストを併用せざるを得なかった経験があります。

## 発展途上だからこその可能性
#### 成長を支える技術の進化
これらの「あるある」は、テスト自動化がまだ発展途上の技術であることを示しています。しかし、その進化のスピードには目を見張るものがあります。たとえば、最近ではAIを活用したテストケースの生成や、自動化ツールのユーザビリティ向上が進んでいます。これにより、エンジニアだけでなく、プロジェクトマネージャーやデザイナーといった非技術者でも簡単に活用できる可能性が広がっています。

#### チーム全体の効率化に寄与
また、テスト自動化は現場全体の効率化に貢献する可能性を秘めています。システムエンジニアがリグレッションテストの負担から解放されることで、新しい機能の開発に集中できたり、プロジェクトマネージャーがリアルタイムで品質状況を把握できたりと、さまざまな形で恩恵をもたらします。

##  まとめ
テスト自動化には「初期設定が大変」「仕様変更に振り回される」といった「あるある」がつきものですが、それは技術が進化している証とも言えます。これらの課題を乗り越えた先には、さらなる効率化や品質向上が期待できるでしょう。まだまだ発展途上の技術ではありますが、その可能性を信じて取り組む価値があると強く感じています。
手軽に使える「T-DASH」：良い点と改善の期待

## 良かった点：手軽に使える便利さ
#### 操作が簡単で初心者にも優しい
T-DASHはその操作性の良さが際立っています。例えば、システムエンジニアが新しいアプリケーションの基本動作を検証する際、複雑なプログラミングスキルがなくても、ドラッグ＆ドロップで簡単にテストケースを作成できます。特に、リグレッションテストのような繰り返し実行が必要なシナリオでは、手動テストに比べて大幅に時間を短縮できました。

#### コストパフォーマンスの高さ
また、T-DASHは比較的リーズナブルな価格設定が魅力的です。スタートアップ企業で働くテストエンジニアの知人は、限られた予算内で効率化を図るためにT-DASHを導入し、その手軽さに助けられたと言います。このように、導入しやすい点は現場での高い評価につながっています。

## 改善を望む点：もう少し効率化の余地
#### 複雑なテストの対応力
一方で、T-DASHを使用して感じた課題として、複雑なテストシナリオへの対応力があります。たとえば、データサイエンティストが大規模データを用いた性能テストを行おうとした際、T-DASHの機能では設定に限界を感じ、スクリプトを別途作成する必要がありました。この部分がもう少し柔軟になれば、さらに効率が上がると感じました。

#### 処理スピードの向上
もう一つ改善が期待されるのは、テスト実行時の処理スピードです。ウェブアプリケーションの大規模テストを実施する際、スクリプトの実行にやや時間がかかることがありました。特に、プロジェクトマネージャーがタイトなスケジュールを求める現場では、スピードの向上が大きなメリットになるでしょう。

## まとめ
T-DASHは、誰でも簡単に使える手軽さが魅力で、特に基本的なテストを効率化する場面では大変役立ちます。一方で、もう少し柔軟性やスピードが向上すれば、さらに広範囲の業務に対応できるポテンシャルを秘めていると感じました。今後のアップデートに期待しつつ、引き続き活用していきたいと思います。
linux

# Linux

## 目次
1. [はじめに](#はじめに)
2. [Linux](#linux)
3. [みんな大好きmacOSとは](#みんな大好きmacosとは)
4. [LinuxがWindowsよりmacOSに似ている](#linuxがwindowsよりmacosに似ている)
5. [シェルとその役割](#シェルとその役割)
6. [Linux主なコマンド一覧](#linux主なコマンド一覧)
7. [関連年表](#関連年表)
8. [まとめ](#まとめ)

---

## はじめに
LinuxとmacOSは、どちらもUNIXの影響を受けたコンピュータの基本ソフトウェア（OS）です。一方で、Windowsは全く異なる考え方で作られています。この記事では、これらのOSについて、高校生にもわかりやすく解説していきます！

---

## Linuxとは
- **Linuxは「UNIXっぽい」OS**:
  - Linuxは「UNIX」という古いOSの考え方を参考にして作られましたが、元のコードは使っていません。
  - オープンソースなので、誰でも無料で使え、自由に改造することができます。

- **特徴**:
  - **無料**: お金を払わずに使える。
  - **自由にカスタマイズ**: 必要な機能を追加したり、見た目を変えたりできる。
  - **世界中で利用**: サーバーやスマホ（Androidの中身もLinux！）でよく使われています。

---

## みんな大好きmacOSとは
- **Apple製のUNIXベースのOS**:
  - macOSはUNIXをもとにしたOSで、Mac専用に作られています。
  - シンプルでわかりやすいデザインと、Apple独自のアプリや機能が特徴です。

---

## LinuxとmacOS


- LinuxとmacOSでは、同じコマンド（`ls`、`cd`、`pwd`など）を使って、パソコンを操作できます。Windowsでは、コマンドが違います（例: `dir` や `cd`）。
- ファイルやアプリの操作方法が似ています。
- なぜ似ているのか。それはどちらも、UNIXという古いOSの考え方を引き継いでいるから。




#### コマンドの比較表　例

| 操作内容          | Linux/macOSコマンド | Windowsコマンド   |
|-------------------|---------------------|-------------------|
| ディレクトリの内容を見る | `ls`                | `dir`            |
| 現在の場所を確認する | `pwd`               | `cd`             |
| ディレクトリを移動する | `cd /path/to/dir`   | `cd \path\to\dir`|

### 3. シェルが同じ
- LinuxとmacOSでは「シェル」という、コマンドを受け取るためのプログラムが同じです（例: Bash や Zsh）。
- Windowsでは「PowerShell」や「コマンドプロンプト」という、別のシェルが使われます。

---

## シェルとその役割
シェルとは、パソコンに命令を伝えるための「通訳」のようなものです。

### LinuxとmacOSのシェル
- BashやZshを使います。
- これらのシェルは、プログラムを効率的に動かしたり、自動化したりするのが得意です。

### Windowsのシェル
- コマンドプロンプトやPowerShellを使います。
- シェルの仕組みがUNIX系と異なり、Windows独自の動作をします。

---

## Linux主なコマンド一覧

| コマンド       | 説明                          | 使用例                       |
|----------------|-------------------------------|------------------------------|
| `ls`           | ディレクトリの内容を表示      | `ls -l`                      |
| `cd`           | ディレクトリを移動            | `cd /home`                   |
| `pwd`          | 現在のディレクトリを表示      | `pwd`                        |
| `mkdir`        | 新しいフォルダを作成          | `mkdir my_folder`            |
| `rm`           | ファイルやフォルダを削除      | `rm file.txt`                |
| `cp`           | ファイルをコピー              | `cp source.txt dest.txt`     |
| `mv`           | ファイルを移動または名前変更  | `mv old.txt new.txt`         |


---

## まとめ
- LinuxとmacOSは「UNIX」という同じルーツを持っているため、操作や仕組みが似ています。
- Windowsは異なる考え方で作られており、操作方法も違います。
- 各OSの特徴を理解して、自分に合った使い方を見つけましょう！
【Three.js】 PerspectiveCameraPerspectiveCamera・OrthographicCamera

## はじめに
みなさんは、Three.jsでどのカメラを使うか悩むことはないです？
この記事では、Three.jsで使うことができるPerspectiveCameraPerspectiveCameraとOrthographicCameraのまとめました。

## PerspectiveCameraPerspectiveCamera
遠近法を持つ現実のカメラをシミュレートしたものです

↓このように使います。
`PerspectiveCamera(field of view, aspect ratio, near, far)`

+ field of view：画角（45~75くらい）
+ aspect ratio：アスペクト比
+ near・far：レンダリングの距離
    + nearの値より近いオブジェクトはレンダリングされない
    + farの値より遠いオブジェクトはレンダリングされない

```sample.js
const camera = new THREE.PerspectiveCamera(75, 1920/1080, 1, 100 )
```

### sample
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="ByBKzNv" data-pen-title="Three.js test" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/ByBKzNv">
  Three.js test</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## OrthographicCamera
遠近感のないシーンのオルソグラフィックレンダリングを作成するために使用します。Age of EmpireのようなRTSゲームを作るときに便利です。カメラからの距離に関係なく、画面上の要素は同じサイズになります。

↓このように使います。
`OrthographicCamera(left, right, top, bottom, near, far)`

+ left・right・top・bottom：それぞれの方向でカメラが写す画角
+ near・far：レンダリングの距離
    + nearの値より近いオブジェクトはレンダリングされない
    + farの値より遠いオブジェクトはレンダリングされない

```sample.js
const camera = new THREE.OrthographicCamera(- 1, 1, 1, - 1, 0.1, 100)
```

### sample
<p class="codepen" data-height="500" data-default-tab="result" data-slug-hash="mybPOOm" data-pen-title="Three.js - camera (PerspectiveCamera)" data-editable="true" data-user="sp_degu" style="height: 500px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sp_degu/pen/mybPOOm">
  Three.js - camera (PerspectiveCamera)</a> by でぐぅー | Qiita (<a href="https://codepen.io/sp_degu">@sp_degu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>


## まとめ
この記事では、Three.jsで使うことができるPerspectiveCameraPerspectiveCameraとOrthographicCameraのまとめました。

---

最後まで読んでくださってありがとうございます！

普段はデザインやフロントエンドを中心にQiitaで記事を投稿しているので、ぜひQiitaのフォローとX(Twitter)のフォローをお願いします。

https://twitter.com/degudegu2510
ラズパイ　FW設定

１．インストール
```
sudo apt install ufw
```
２．有効化
```
$ sudo ufw enable
```
３．ポート開放　http,https,samba,vnc,ssh,mysql
```
sudo ufw allow 80
sudo ufw allow 443
sudo ufw allow 445
sudo ufw allow 5900
sudo ufw allow 22
sudo ufw allow 3306
```
４．リロード
```
sudo ufw reload
```
５.ルール削除 n番のルール削除
```
sudo ufw delete n
```
６．ルール確認
```
sudo ufw status
```
[Stimulus] select要素で選択した色情報をinput要素に適用する

select要素で選択したdata-colorを別のinput要素に適用する実装例です。
Railsを使用しています。

下記のようなselect要素とinput要素があります
``` sample.html.haml
%div{ data: { controller: 'copy-input-color' } }
  %select{ name: 'color', id: 'color', data: { copy_input_color_target: 'source', action: 'change->copy-input-color#call' } }
    %option{ data: { color: '#FFFFFF' } } 白
    %option{ data: { color: '#FF0000' } } 赤
    %option{ data: { color: '#0000FF' } } 青
    %option{ data: { color: '#FFFF00' } } 黄色
  %input{ type: 'color', value: '#FFFFFF', data: { copy_input_color_target: 'destination' } }
```

select要素をsourceTargetで取得し、input要素はdestinationTargetで取得しています。
sourceTargetの`option:checked`となっているdata-colorを取得し、destinationTargetのvalueにセットします。

``` copy_input_color_controller.js
import { Controller } from "@hotwired/stimulus"

// Connects to data-controller="copy-input-color"
export default class extends Controller {
  static targets = ['source', 'destination']

  call() {
    this.destinationTarget.value = this.sourceTarget.querySelector('option:checked').dataset['color']
  }
}
```

このような動きになります。
![CleanShot 2024-12-07 at 16.42.45.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/653935/e223e526-7f04-f43c-17d4-0e593a73f89b.gif)

## stimulusの気に入っているところ

- 素のJavaScriptよりも簡潔にかける
- HTMLから動きを想像できる
    - ここが参照元(source)で、ここがコピー先(destination)というのがtarget名から分かる

Hotwireも含めて使いこなせるようにしていこうと思っています。
kotlin アルファベットの大文字を小文字に変換方法

アルファベットの大文字を小文字に変換方法です。

```Utils.kt
    fun toLower(text: String): String {
        return text.lowercase()
    }
```

あまり使う時は少ないかもしれませんが、アルファベット大文字を小文字にこれで変換できます。
生成AIがPoCの壁を超えるには

  昨日[Jagu’e’r](https://jaguer.jp/evangelist-3rd/)エバンジェリスト就任しました大前七奈です。今年のお題は「GenAIはPoCの壁を超えたのか」だったので、日頃に考えていたことをこれを機に記事にしたいと思います


## PoCの壁とは何か？
 生成AI、いわゆるLLM（大規模言語モデル）は、従来のAIモデルと違って汎用的なモデルで、チューニングなし（Zero Shot）で利用できるモデルです。しかし、PoC（概念実証）の段階から本番環境への移行、つまり、実用的なサービスとしてLLMを運用するには、様々な課題を克服する必要があります。
  
  PoC段階では、LLMの潜在的な可能性を検証し、具体的なユースケースを特定することが主な目的です。しかし、PoCから本番環境への移行には、以下の課題が立ちはだかります。
- スケーラビリティ: 大量のユーザーからのリクエストにリアルタイムで応えるための処理能力
- 信頼性: 高い精度と安定性を維持し、誤った情報や偏見を含んだ回答を防ぐこと
- セキュリティ: ユーザーデータや機密情報の保護
- コスト: モデルの学習と推論にかかるコストの最適化
- 運用管理: Drift監視と検知やモデルの更新、トラブルシューティングなど、継続的な改善体制



## PoCの壁を超えるには

個人的に最近のトレンドを見ている限り、以下のいくつかの要素がLLMをプロダクションに持っていける可能性をより一層に高めたかと思いました。

### クエリチェーン
LLMに新しい情報を与えたいときに、大量データと訓練するためのリソースが必要になってきます。そこで、１つのLLMにすべての機能を持たせるのではなく、機能を分解することで、個別のLLMが単一のタスクをやってもらいつつ、全体から見ると、複雑な処理ができるようになります。

部品として切り出すことで、ほかのユースケースでの再利用も考えられます。

たとえば、以下のように、LLMを2つに分解し、その間にメタデータ(Augment with external data)を付与することで精度を上げることができます。また、間に誤った情報や偏見をフィルタするようなLLMを噛ませることで、より精度のシステムを構築できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3747743/faaa959e-bc1c-2e95-b4b6-a1a4b9ceb841.png)

### LLMでLLMを評価

ベンチマークの日本語データセットは、一般的に完全一致率、文字ベースF値で回答と参照文章の一致度を評価する事が多いです。ただし、ユースケースがQ&Aではないときに、評価したい文章がどうしても長くなり、人間が評価せざるをえなかったです。または、ROUGE、BLEUを利用した場合、回答が参照テキストと似ていても文字ベースで一致しないと、スコアが低くなります。
そして、人間の代わりに、LLMによる評価(LLM-as-a-judge)を利用することで、より柔軟かつ汎用性の高い評価ができます。

評価用プロンプトの例
```
あなたは、ユーザーからの質問に対する回答評価者です。以下の質問への回答に対して、有用性、関連性、正確性の観点で評価してください。[[rating]]という形式で１から１０までの整数の評価値を出力してください。

質問：
{question}
回答：
{answer}
参考回答:
{refernce_answer}
```

自動評価ツール
- [llm-jp-eval](https://github.com/llm-jp/llm-jp-eval)
    - 一致度を用いる評価が多い、日本語ベンチマーク対応
- [flexeval](https://github.com/sbintuitions/flexeval)
    - LLMによる評価、日本語ベンチマーク対応
- [RAGAS](https://github.com/explodinggradients/ragas)
    - RAG用ではありますが、そんな中で生成文章に関する指標もある
        - faithfullness(忠実度)、answer relevancy（関連性）
        - 参考になった記事: [RAGAS：9つの指標と評価方法をコードを見ながらざっくり解説する](https://zenn.dev/mizunny/articles/cf11a1ab1a5e3a)

LLMで評価するときの注意点
- 位置バイアス
    - 回答が先に言及したとき、スコアが高くなりがち
- 冗長性バイアス
    - 長い回答のほうが好まれる
- 自己選好バイアス
    - 評価対象と評価者が同じLLMの場合、評価が高くなる


### 監視パイプライン（＝継続的な訓練とチューニング）
従来のシステムと比べて、AIを利用したシステムの運用負荷が遥かに高いです。それはなぜかというと、実際にモデルを継続的に現実世界のデータに合わせる必要なためです。監視パイプラインが全然新しいものではないですが、上記の評価指標と併用することで、ユーザーと合意を得た閾値を超えたときに、再度自動的に訓練できれば、より従来のシステム運用（監視指標）に近づけるかと思います。

参考に、GoogleのMLOpsレベル２のシステム図を貼り付けました。以下の図のように、従来のシステムでいう開発環境は実験パイプラインの部分に該当し、本番環境は推論パイプラインに該当します。そして、従来のシステムに当てはまらない部分は監視パイプラインの部分になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3747743/c1c78630-116c-fce8-4bb9-31773c76124a.png)


##  まとめ
その他のお題（PEFTチューニング、評価ツールの詳細）も触れたかったですが、一旦今回の記事はここまでにします。
LLMの未来の進化にわくわくします。

### 参考情報
- [Google:MLOps for Generative AI whitepaper](https://drive.google.com/file/d/150vQ_1f_Ya7rz1Bw8SV6EZErD-Gos4NT/view)
- [MLOps: ML における継続的デリバリーと自動化のパイプライン](https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning?hl=ja)
- [RAG の精度を向上させる Advanced RAG on AWS の道標](https://aws.amazon.com/jp/blogs/news/a-practical-guide-to-improve-rag-systems-with-advanced-rag-on-aws/)
- [大規模言語モデルII](https://amzn.asia/d/5ho1drN)
PukiWikiプラグイン開発から学ぶPHP #2

# 前回

https://qiita.com/PitaQ/items/72703a23b6389edb449d

# 本題
今回は過去、高校生の頃に作ったtimestamp.inc.phpというプラグインをサンプルとして解説します。

https://github.com/PTOM76/PukiWiki-Plugins/blob/main/timestamp.inc.php

このプラグインはタイムスタンプを変更することができるものですが、処理の流れとしては、

`?plugin=timestamp&page=ページ名` にアクセスするとplugin_timestamp_action()が呼ばれます。
大まかには、
1. タイムスタンプ変更画面の表示
1. 管理者パスワードのチェック
1. 編集/閲覧可能かのチェック
1. ファイルの取得
1. recent.dat という更新ページのキャッシュ削除 (タイムスタンプを更新してもキャッシュが残っていると更新ページ一覧がそのままになるため)
1. タイムスタンプの変更
となってます。

# plugin_(プラグイン名)_action()
action関数は `return ['msg' => タイトル名, 'body' => HTMLの文字列];` のようにmsgとbodyがキーとなった配列を返して使います。
bodyが空ならば$vars['page']のページが表示される仕様となってます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1015774/e1c56b98-1a5e-d6d3-5f95-3aa173805215.png)

timestampプラグインでは、タイムスタンプ変更画面(上記の画像)は以下のようになっています。
```php
$msg = PLUGIN_TIMESTAMP_TITLE; // $msg = "タイムスタンプ"
$body = "";

// ページが指定されている (変更ボタンが押された)
if ($vars['page'] != "") {

    [以下略...]

    $body = <<<EOD
    <h2>ページ: {$vars['page']}</h2>
	<form action="?plugin=timestamp" method="POST">
 
         [以下略...]
         
	</form>
	<p>現在のページの更新日時: {$y}年{$m}月{$d}日{$h}時{$min}分{$s}秒</p>
EOD;
} else {
    [以下略...]
}

return array('msg' => $msg, 'body' => $body);
```

$bodyは主に複数行の文字列を扱うことができる記述方法「ヒアドキュメント」を使います。<<<EODとEOD;で囲ってあげて代入することで利用できます。
```php
$body = <<<EOD
    <h1>見出し</h1>
    <p>文章</p>
EOD;
```

ヒアドキュメントはEODでなくてもEOMやEOTなどでも可能で最初の開始識別子の<<<〇〇〇と最後の終了識別子〇〇〇;が一致していればOKです。
また最後〇〇〇; の終了識別子にインデントやら、コメントですら使うとエラーが発生するので気をつけてください。

## 管理者パスワードのチェック
管理者パスワードのチェックには`pkwk_login(パスワード)`を使います。
```php
if (pkwk_login($vars["password"]) == false) {
    return array('msg' => "エラー", 'body' => "<p>パスワードが間違っています。</p>");
}
```

## 編集/閲覧可能チェック

```php
// 編集可能かのチェック
check_editable($vars['page'], true, true);

// 閲覧可能かのチェック
check_readable($vars['page'], true, true);
```

## ページ操作
timestamp.inc.phpでは以下のようにPHP標準関数を使っているのですが...
```php
$filename = "./wiki/" . strtoupper(bin2hex($page)) . ".txt";
if (file_exists($filename)) {
    $source = file_get_contents($source);
    
    [以下略...]

    file_put_contents($filename, $source);
}
```
PukiWikiのページは`wiki/`ディレクトリ内に保存されており、文字列を大文字16進数にエンコードされた名前のテキストファイルとして保存されていますので、bin2hex()で16進数にしてstrtoupper()で大文字にする必要があります。しかし...！

こんなことしなくてもPukiWiki内部のページ操作の関数を使ったほうがいいでしょう。
上記のコードは以下のように変更できます。

```php
// ページの存在チェック is_page($page)
if (is_page($page)) {
    // ページの読み込み get_source($page, $lock = true, $join = false, $raw = false)
    $source = get_source($page, true, true); // 3番引数がtrueなのはstringとして取得するため、デフォルトでは1行ずつの配列となる

    [以下略...]

    // ページを書き込む page_write($page, $postdata, $notimestamp = false)
    page_write($page, $source);
}
```


なお、PukiWiki内部の関数については以下に記載されてます。

https://pukiwiki.sourceforge.io/dev/?%E3%83%97%E3%83%A9%E3%82%B0%E3%82%A4%E3%83%B3/%E9%96%8B%E7%99%BA%E8%80%85%E5%90%91%E3%81%91

またファイル名を収納するにしろbin2hex、strtoupperは使う必要がなくてPukiWikiにはget_filenameというのがありました。
```php
$filename = get_filename($page); // ページのファイル名を取得 (PukiWiki内部関数)

$filetime = filemtime($filename); // ファイルの更新日時を取得

[以下略...]

touch($filename, $filetime); // ファイルの更新日時を書き換え
```