OmniAICreator/Qiita-1.07M huggingface dataset:
（初心者向け）Copernicus Browser からの Sentinel 2 データのダウンロード

# はじめに
## 動機
Sentinel-2のデータダウンロードサイトは2023年10月に新しくなりました。当時、新しいページでダウンロードのメモを書いたのですが、うまくいきませんでした。1年以上たって再度試したらうまくいったのでメモしておきます。

## 以前の記事
必要な方は以下のメモと併せてごらんください。

以前ダウンロードできなかった時の記録：
https://qiita.com/T-ubu/items/321d49d92fee3eedc264

その前のOpen Access Hubからのダウンロード方法：
https://qiita.com/T-ubu/items/e40e49b3321dfc720b78

## 私の環境
Microsoft Edge
Windows 11

# 手順
## Step 1. データスペースのページにアクセス・ログイン
コペルニクスプロジェクトのページにアクセスします。右上のハンバーガーメニューからログインします。（アカウントを作っていない場合は新規に作りましょう。）
https://dataspace.copernicus.eu/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f1d47798-aced-4e74-86c8-84011be018ea.png)

Step 1～２のメモは以前の記事で細かく書いてあります。

https://qiita.com/T-ubu/items/321d49d92fee3eedc264

## Step 2.　データを選ぶブラウザを開く
Explore dataからコペルニクスブラウザ（Copernicus Browser）を選択します。直接行ってってもいいかもしれません。
https://browser.dataspace.copernicus.eu/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/31e33044-fa8a-4716-a67e-73b4ecf4120b.png)


## Step 3.　検索条件などの設定
地図で対象領域を拡大し、「SEARCH」タブをクリックして、検索期間や検索する画像のセンサを選びます。最近の光学画像であればSentinel2がいいと思います。処理レベルはL2Aのものにしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/7c74d4b2-adb2-4527-ba26-3524fe0dec4c.png)

雲マークのバーで雲量の指定もできます。プロダクトタイプについてはこのページ(https://sentinels.copernicus.eu/web/sentinel/user-guides/sentinel-2-msi/product-types )で詳細を確認できますが、L1Cは大気上端反射率データ、L2Aは大気下端反射率データということです。L2Aの大気下端反射率というのは反射率の大気補正を行ったデータのことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/d5f618d5-fc2b-46b3-bb8c-33389d94c2e4.png)

指定をしたら一番下のSearchボタンをクリックします。

## Step 4.　検索結果の確認、データのダウンロード
指定条件に一致する結果があればリストに出てきます。サムネイルのしたのVisualiseをおすとブラウザの上で見られます。（戻るときはまたSearchタブをクリックします。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/1d508a85-34b9-443a-8a44-b899697c6c7e.png)

画像がOKならリストの右下にあるDownloadのアイコンをクリックします。画像のダウンロードが始まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/75211dcf-4828-4e56-87c8-3932ccdf0d65.png)

## Step 5. データの確認
ZIPファイルがダウンロードできました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/78e83f09-95bd-4e2d-808c-2cd536e5292e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/4ad6775b-2193-4b9a-814f-d230888cead5.png)
データがきちんと入っていますね。


## Step 6. （おまけ）その後の処理
これでダウンロード自体は終了ですが、QGISで扱い方は以下のメモなどもご覧ください。
https://qiita.com/T-ubu/items/de0d30e0f2bdcd72ee8a

GDALを使って画像タイルにするには以下のメモも参考になるかもしれません。
https://qiita.com/T-ubu/items/0c737f5d62acde9c3fa2

# まとめ
無事にSentinel-2の画像をダウンロードできました。

# 謝辞
オープンデータとしてSentinel 2画像を提供してくれているCorpernicusプロジェクトに感謝します。


# 参考ページ
https://dataspace.copernicus.eu/

https://qiita.com/T-ubu/items/321d49d92fee3eedc264

https://qiita.com/T-ubu/items/e40e49b3321dfc720b78
文字列の一部を可変にする

Androidのxmlで定義した一部の文字列を変更する方法をメモする。

```xml
<string name="name">%s文字以上で入力してください。</string>
```
```kotlin
val setNameMessage = getString(R.string.name, "7")
println(setNameMessage) // 7文字以上で入力してください。
```


変数を複数入れる場合はgetString()の第3、第4引数へと追加していく。
```xml
<string name="full_name">%s文字以上%s文字以下で入力してください。</string>
```
```kotlin
val setNameMessage = getString(R.string.full_name, "7", "20")
println(setNameMessage) // 7文字以上20文字以下で入力してください。
```

`1$`を追加すれば、引数の順番を変更することもできる。
```xml
<string name="full_name">%2$s文字以上%1$s文字以下で入力してください。</string>
```
```kotlin
val setNameMessage = getString(R.string.full_name, "25", "10")
println(setNameMessage) // 10文字以上25文字以下で入力してください
```
#### 参考

https://y-anz-m.blogspot.com/2011/03/android-xml.html
GitHub Copilotに助けられた話

FastAPI触ってみっか、でいじり始めました。
あっちなみにWeb系ガチ初心者なので。やめてくださいね。いろいろ。

### 流れ
よ～し簡単なログイン画面っぽいの作るか～。
↓
FastAPIだけで出来んのか？わかんねググろ。
↓
う～んなんかよくワカンネ。まあおそらく単体だと出来ねぇんだろ。
↓
Copilotく～ん、ヘルプミ～。

---
以下全文
質問：FastAPIで入力フォームを作るコードを書いてください

↓

返答：

FastAPIで入力フォームを作成するには、fastapiとjinja2テンプレートエンジンを使用します。以下に、基本的な入力フォームを作成するコード例を示します。

まず、必要なライブラリをインストールします。

```
pip install fastapi uvicorn jinja2
```

次に、以下のようにFastAPIアプリケーションを作成します。

```
from fastapi import FastAPI, Form
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from fastapi.requests import Request

app = FastAPI()

templates = Jinja2Templates(directory="templates")

@app.get("/", response_class=HTMLResponse)
async def read_form(request: Request):
    return templates.TemplateResponse("form.html", {"request": request})

@app.post("/submit")
async def handle_form(username: str = Form(...), password: str = Form(...)):
    return {"username": username, "password": password}
```

次に、templatesディレクトリを作成し、その中にform.htmlという名前のテンプレートファイルを作成します。

```
<!DOCTYPE html>
<html>
<head>
    <title>Input Form</title>
</head>
<body>
    <h1>Input Form</h1>
    <form action="/submit" method="post">
        <label for="username">Username:</label>
        <input type="text" id="username" name="username"><br><br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password"><br><br>
        <input type="submit" value="Submit">
    </form>
</body>
</html>
```

このコードでは、/エンドポイントにGETリクエストが来たときに、form.htmlテンプレートをレンダリングして入力フォームを表示します。フォームが送信されると、/submitエンドポイントにPOSTリクエストが送信され、フォームのデータが処理されます。

最後に、以下のコマンドでFastAPIアプリケーションを起動します。
```
uvicorn main:app --reload
```

これで、ブラウザで http://127.0.0.1:8000 にアクセスすると、入力フォームが表示され、フォームを送信するとデータが処理されることを確認できます。

---

もう全部やってくれる。アタシ要るこれ？

HTML必要なのかふんふん、ルーティングってこんな感じなのねふんふん、GetとかPostっていうのがあるのねふんふん、あなたトトロっていうのねふんふん。

という感じで、一から十（過言）までお膳立てしてくれるお陰で勉強がはかどります。

ちょっとしたコード追加をするときも予測して候補をあげてくれるので、タイピングが50％以下で済むのもありがたいです。

思う存分使い倒してやりましょう。AIに労基ってないよね？（暗黒微笑）
AWSでWindows RDS（リモートデスクトップサービス）ライセンス管理するADをリストアしてみました


# 近況

最近は社内システムの内製化？をしており、基本設計やら構築やらを1月中はやっていました。
（利用する部署との会話もそれなりに大変・・・）
できる部分は全部CloudFormationで構築しているんですが、今までコンソールだけで作成してた時と比べると、
裏でこんなリソースが自動作成されているんだなあ～と、学びが多いです。

個人的な目標は「**副業を始めること**」に設定しましたが、今のところ何も進んでいません。。。
学生時代にやっていた個人契約の家庭教師でも再開しようかな。。。

# 本題

11月にAWSからMSのRDSライセンスが直接購入できるようになりました。
ちょうど社内システムの一部が、複数人で同時利用必須だったので、どうしようかなと思っていた時期でした。

https://aws.amazon.com/jp/about-aws/whats-new/2024/11/aws-user-based-subscription-microsoft-remote-desktop-services/

毎度本当に本当にお世話になっているクラメソさんから、発表されて数日後に以下の記事も出ていました。
（早すぎる・・・）

https://dev.classmethod.jp/articles/aws-user-based-subscription-microsoft-remote-desktop-services/

https://dev.classmethod.jp/articles/try-subscribing-rds-sal-on-self-managed-ad/


今回の想定している構成だと後者になるので、参考に構築させていただきました。
この記事がなかったらそれはもういっぱい検証しなければいけなかったので、本当に助かりました・・・

システムを構築したのはいいんですが、もちろん各種試験もしないといけないわけで・・・
AWS上に構築したシステムなので、AWS Backupでバックアップを取得することにしました。
今回の記事の内容はバックアップデータから復元させた際のRDSライセンス周りの挙動についてになります。

# 今回の構成

・Aシステム：複数人(常時10人程度)でRDP接続し利用する。ADのドメインに参加する。
・AD：RDSライセンス管理のために必要。LicenseManagerと紐づけを行う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/6d879763-cde0-d4df-61cd-ecf428c824af.png)


# 今回の実施した内容と結論

AシステムとADのEC2を停止させて、AWS Backupから2台を復元しました。
（復元の順序はADから）
復元したAシステムのDNSはADに向けていたので、Aシステムに入ってDNS変更をしてからドメイン参加させます。

その後、Ａシステムに対し4ユーザーでRDP同時接続を試しました。
結果としては、**自動で復元したADがLicense Managerに認識され、同時接続ができました。**

↓↓↓AD復元後↓↓↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/902fe544-5a94-47cd-9e72-7d1887a5e59f.png)

ここに表記される「サーバーIP」はADサーバーやRDSHサーバーではないので注意です。

※後日いろいろあってAWSサポートに問い合わせたんですが、以下の仕様もあるので、接続できた＝License Managerが認識している、ではないので注意です。
**ADとLicense Managerがうまく接続できていなくても、120日間は猶予期間としてあるので、ドメインユーザーでの同時接続はできてしまいます。**

https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/remote/troubleshoot-rds-licensing-guidance#grace-period

License Managerがうまく認識しているかどうかはこの画面で確認できます。

↓↓↓うまくいっていないとき（エンドポイントのステータスに警告マークが出ます）↓↓↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/1ba93d47-21c3-4466-aeee-e7acd6b55da3.png)

※ADの停止中も警告マークが出ます。
　なので、毎日自動起動・停止をしているようなパターンでは、確認するタイミングによっては警告マークがでるかも。

↓↓↓うまくいっているとき↓↓↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3494465/d16c4a16-b864-4b83-a293-c3fee1366742.png)



# さいごに

久しぶりに記事を書きました。
CloudFormationで躓きまくっているので、その苦労のひとかけらでも記事にしていきたいです。
それではまたどこかで。
シングルトンが便利そう

# はじめに

PHPのコードを色々触っている時に、<font color="red">**シングルトン**</font>なるものに出会ったのでまとめます！

# デザインパターンとは
今回のシングルトンというものは、デザインパターンの一つです。
そのために、まずはデザインパターンについて、軽く紹介させていただきます！

>過去のソフトウェア設計者が発見し編み出した設計ノウハウを蓄積し、名前をつけ、再利用しやすいように特定の規約に従ってカタログ化したものである。
[引用元(Wikipedia)](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3_(%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2))

プログラミングには、この場合はこの書き方が正解。的なものがいくつかあります。
その中の一つがシングルトンパターンです。c

# シングルトンパターンとは
とあるクラスのインスタンスを２つ以上作成できないようにし、どのクラスからアクセスしても同じインスタンスを参照されることを保証します。
簡単に言うと<INS>**１つしか作成できないように強制するような機能**</INS>というような感じです。

設計者が「１カ所しか呼び出したくない！」と考えていても、別の箇所から呼び出し可能であれば、設計者の意図をくみ取れないビギナーズが遠慮なくバンバン生成することがありますよね？(私もその中の1人です...汗)

この**バンバン生成**を防ぐためにあるのが、<font color="red">**シングルトン**</font>です。

通常であれば、複数のインスタンスが存在しているが、いくつもインスタンスを作成したくない場合に使用します。

# Q：いくつもインスタンスを作成したくない場合ってどんな状況？

## 設定管理
アプリケーションの設定情報を保持するクラスは、通常一つのインスタンスだけで十分です。
設定情報はアプリケーション全体で共有されるため、複数のインスタンスを持つとデータの一貫性が失われる可能性があるからです。

## データベース接続
データベース接続は、リソースを多く消費して、複数の接続を開くとパフォーマンスが低下する可能性があります。
シングルトンを使うことで、アプリケーション全体で一つのデータベース接続を共有し、リソースの使用を効率化できます。

## ロギング
ログを記録するクラスは、アプリケーション全体で一つだけあれば充分です。
シングルトンを使用すると、ログの記録に一貫性が保たれ、パフォーマンスの問題を避けることができます。

## ハードウェアインターフェースの管理
ハードウェアリソース（プリンターなど）へのアクセスを管理する場合、シングルトンは一つのインスタンスを通じてリソースを共有し、競合することを防ぎます。

## キャッシュ
データキャッシュやオブジェクトキャッシュのようなリソースは、アプリケーション内で一貫性と効率を保つために、通常は単一のインスタンスで管理されます。

複数のインスタンスが存在すると、データの整合性の問題や無駄なリソースの使用、パフォーマンスの低下などさまざまな問題が発生します。
シングルトンは、これらの問題を解決する効果的な方法です。
ですが、使用する際にはその影響範囲と制約を理解して適切に利用できるよう意識することが大事です。


## 近日更新! コードを書いてみよう

<!-- issue_3をここから記載-->
【Gitコマンド】これだけ見ればクローンからプッシュまでできる

## はじめに
最近学習の勢いに拍車がかかってほぼ毎日コードを書いてはGitでcommitやらpushをしてます！
ただ、作業の流れをド忘れてしまうことが多いのでまとめようと思いました。

:::note warn
注意
この記事ではGitHubの概念の説明は行いません。
:::

## Qiita CLI
少し話はそれますが、せっかくならと。
最近実装されたQiitaCLIを使って普段使っているVSCodeで書いています。

https://qiita.com/Qiita/items/666e190490d0af90a92b

純粋な感想を言わせてもらうと結構.....便利...！

今まで使ってきたQiitaの投稿メニュー？も全然使えますし、むしろ不便と思ったことは全くないです。
でもいざ普段使っているエディタで書くと<font color="red">フォントカラー</font>も付くため可読性があがります。
そんな素晴らしい機能を検討・実装してくださったQiitaの関係者様ありがとうございます！

では早速本題へ！

## GitHubを使用した一般的な作業の流れとGitコマンド

1. **リポジトリのクローン**
   - 既存のリポジトリをローカルにコピーする。
     ```bash
     git clone [リポジトリのURL]
     ```

2. **新しいブランチの作成**
   - 新しい機能や修正を行うためのブランチを作成&作成したブランチに切り替える。
     ```bash
     git checkout -b [新しいブランチ名]
     ```

3. **変更をステージングエリアに追加**
   - 変更したファイルをステージングエリアに追加する。
     ```bash
     git add [ファイル名]
     ```

4. **変更のコミット**
   - ステージングエリアの変更をローカルリポジトリにコミットする。
     ```bash
     git commit -m "コミットメッセージ"
     ```

5. **変更のプッシュ**
   - ローカルの変更をリモートリポジトリにアップロードする。
     ```bash
     git push origin [ブランチ名]
     ```

6. **プルリクエストの作成**
   - [GitHub](https://github.com/)でプルリクエストを作成する。
   - これにより、変更をメインブランチにマージするためのリクエストが作成される。

7. **コードレビュー**
   - 他のメンバーがプルリクエストの変更をレビューする。
   - 必要に応じてフィードバックや修正が行われる。

8. **プルリクエストのマージ**
   - レビューが完了し、変更が承認されたら、プルリクエストをマージする。
     ```bash
     git merge [ブランチ名]
     ```

9. **ブランチの削除**
   - マージが完了したら、不要になったブランチを削除する。
     ```bash
     git branch -d [ブランチ名]
     ```

10. **最新の変更を取得**
    - リモートリポジトリの最新の変更をローカルに反映する。
      ```bash
      git pull origin [ブランチ名]
      ```


## 最後に
いろいろな記事を見てきましたが、基本的に同じ流れだと思うので
みなさんのGitコマンド辞書的な役割も果たしてくれるのでは？と思ってます！
是非役に立ててくれると嬉しいです。

また、[@maro_webdev](https://x.com/maro_webdev?s=21&t=2FCoa6rJwKWJQZGEcpTjtw)の方もくだらないことしか言ってませんがフォローしてくれると嬉しいです！


## ~~おまけ~~

おまけと表現していいのか分からないくらい本当に良い記事を載せておきます。
GitHub自体分からない人はこちらを参考に勉強してみてください。

https://qiita.com/renesisu727/items/248cb9468a402c622003

https://qiita.com/jesus_isao/items/63557eba36819faa4ad9
Windows(Surface)にRufusを使用してUbuntuをインストールする

大学時代に使用していた Surface Laptop がタンスのこやしになっていたので、
Ubuntuを入れてサーバーの勉強がてら遊んでみようという魂胆

## 1. 方針決定：Ubuntuバージョン選定
### 推奨バージョン
| バージョン | 特徴 | サポート期限 |
|------------|----------|---------------|
| Ubuntu 24.04 LTS | 2024年4月リリース。 | 2029年 |
| Ubuntu 22.04 LTS | 2022年4月リリース。安定稼働実績あり。 | 2027年 |

→ **おすすめは22.04 LTS**  
Surfaceはハードウェアが特殊(タッチパネル)なので、**安定性重視**のLTS版を推奨する。  
Surfaceシリーズは、標準Ubuntuでドライバが完全対応していないことがあるらしい。

## 2. **準備編**
### 必要なもの
- **初期化**された8GB以上のUSBメモリ
- Rufus（Windows用USBブートメディア作成ツール）
- Ubuntu ISOファイル

### 手順
1. [Ubuntu公式サイト(過去ios置き場)](https://old-releases.ubuntu.com/releases/22.04/)から**Ubuntu 22.04 LTS**のISOファイルをダウンロード
今回は`ubuntu-22.04.4-desktop-amd64.iso`をダウンロード
2. Rufusを[公式サイト](https://rufus.ie/ja/#:~:text=%E3%81%BE%E3%81%99%E3%80%82%20(1)-,%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89,-%E6%9C%80%E6%96%B0%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%3A)からダウンロードし起動し、以下の設定でUSBメモリを作成：
   - デバイス → USBメモリを選択
   - ブート選択 → ダウンロードしたISOファイルを指定
   - パーティション構成 → **GPT**
     - ABRとGPTの違いについては[こちらの記事](https://partition.aomei.jp/windows-10/partition-scheme-and-target-system-type-rufus-window-10-7868-tc.html)が分かりやすかったです
   - ファイルシステム → FAT32
   - スタートをクリック
   
以下のようになっていればOK
![{B2071E62-2A97-4180-B028-3A2FC687590F}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4011964/d80512a5-bad7-48eb-a954-f3fe8c6ab314.png)

## 3. **Surface特有の注意点とカスタムポイント**
### インストール前
- **BitLockerを無効化** (使用している場合)
  - Microsoftアカウントと紐づいている場合は[アカウント設定ページ > デバイス](https://account.microsoft.com/devices/recoverykey) から回復キーを確認可能
  - Secure BootをDisableにしてから無効化にすると回復キーを求められて面倒だったのでBitLockerを先にオフにすることを推奨
- **Secure Bootを無効化**（BIOS設定で変更）
- Fast Bootを無効化（必要なら）
- TPMはそのままでOK

### インストール時
1. Rufusで用意したUSBをSurfaceに接続
1. Surface 起動時に**音量ボタン「↓」長押し＋電源ボタン短押し(二つのボタンは同時に話す)**でUSBブート
1. インストール開始 GUIに沿って設定
1. インストール種類 → 「ディスクを削除してUbuntuをインストール」
1. 最後にUSBを外してEnter
1. 必要に応じてパーティションカスタマイズも可

## 4. **インストール後（Surfaceで必要な設定）**
### ドライバと設定（Surfaceの場合、これが重要）
- カーネルアップデート → Surface向けパッチが含まれる新しいカーネルのほうが安定することが多い
- Wi-Fiやカメラなど一部機能が最初は使えない可能性あり

#### Surface特化ドライバ・ツールセット
【参考プロジェクト】  
- [linux-surface公式](https://github.com/linux-surface/linux-surface)

インストール例：
```bash
curl -sSL https://raw.githubusercontent.com/linux-surface/linux-surface/master/pkg/keys/surface.asc | sudo tee /usr/share/keyrings/surface-archive-keyring.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/surface-archive-keyring.gpg] https://pkg.surfacelinux.com/debian release main" | sudo tee /etc/apt/sources.list.d/surface.list
sudo apt update
sudo apt install linux-image-surface linux-headers-surface iptsd
sudo apt upgrade
```

再起動後、タッチやWi-Fi周りが安定するはず。

## 5. **動作確認・仕上げ**
- Wi-Fi、タッチパッド、タッチディスプレイ、サスペンド復帰などを確認
- 必要に応じてデバイスファームウェアアップデート

## 6. **Ubuntu環境セットアップ（開発環境）**
### WSLとの違い
- ネイティブUbuntuなので、systemdやserviceコマンドが標準で使える
- GUI環境がスムーズ（Visual Studio CodeやvimもOK）

### 開発系パッケージ導入
```bash
sudo apt install vim git curl build-essential
```

必要ならPHPやWordPress環境も後で入れていく感じ

## 補足
- **デュアルブートの場合**、Windowsアップデートでブート設定が書き換えられることもあるので注意
- **完全にUbuntu移行**するならデータバックアップは万全に

これでSurface Laptopでも快適にUbuntu環境を作れるはず！
DockerでWindowsServer環境を作る

# 概要
表題の通り、DockerでWindowsServer環境を作成します。
WindowsServer以外にも通常のWindows環境も作れる方法です。

# 環境
- Windows11
- Docker

# 使うもの

https://github.com/dockur/windows



# 実践
## リポジトリをクローン
```
git clone https://github.com/dockur/windows
```

## composeファイルを修正
VERSIONで作成したい環境を指定できます。
今回はWindowsServer2022を指定
Windows11をインストールしたい場合は"11"と設定します。
KVMは使用しない、メモリはとりあえず動けばいいのでテキトーです。

https://github.com/dockur/windows?tab=readme-ov-file#how-do-i-select-the-windows-version

```dockerfile
version: "3"
services:
  windows:
    image: dockurr/windows
    container_name: wincontainer
    environment:
      KVM: "N"
      RAM_SIZE: "16G"
      CPU_CORES: "8"
      VERSION: "2022"
    cap_add:
      - NET_ADMIN
    ports:
      - 8006:8006
      - 3389:3389/tcp
      - 3389:3389/udp
    stop_grace_period: 2m
    restart: on-failure

```

## docker compose up
docker compose upを実行します。
```
docker compose up
```

## Windowsにアクセス
コンテナに入ってWindowsのセットアップを行います。
簡単ですね
デフォルトでnoVNCによるブラウザ経由のアクセスができますが、RDPによるアクセスもできます。

```
http://localhost:8006/
```


# 終わり
簡単ですね。
注意点としてはAppleSilicon環境ではWindowsのバージョンによっては動作しないことや不安定なことがあります。

また、私は今のところ、仮想環境でもAppleSiliconではArm環境しか作成できてないです。
UTMやVirtualBoxなどいろいろ試しているのですがうまくいかず。。。。。
いい方法ないかしらねって感じです

# 参考
https://note.com/rsec/n/n9053ccf4832e
プリザンター（Pleasanter）でのサーバスクリプトの苦労と解決策

プリザンター（Pleasanter）を使用している際に、サーバスクリプトで苦労した部分のコードをコメントつきで公開します（自分用備忘録です）。特に、**JSONデータレイアウト: ViewのColumnFilterHashでClassを設定する際には配列で指定する必要であること**、**サイトIDの取得方法**、 **条件に合致するレコード数のカウント（items.Count）**、**テーブルの更新（items.Update。サーバスクリプトが係れているテーブル以外も作成・更新可能）**に関する部分でつまずいたポイントを詳しく解説します。

## 完成したサーバスクリプト
```JavaScript
(function () {
  //  let 貸出案件ID = model.ClassC; として定義するとString型として認識されるため不可
  let 貸出案件ID = [model.ClassC]; // viewのColumnFilterHashのClassC設定時に配列が必要なた配列として定義 
  
  if (!貸出案件ID || 貸出案件ID.length === 0) {    
      return;
  }
  
  // 貸出明細テーブルのサイトIDを定義
  let siteId = model.SiteId; // Number型
  
  // 貸出明細テーブルの「item.Count(siteId, view)」による検索条件を指定
  let view = {
      "View": {
          "ColumnFilterHash": {
              "CheckA": true, // 「貸出中?」カラム。貸出中の場合はTrue
              
              // 貸出案件IDはStringでなくarrayでなければいけない。
              // 貸出案件IDをarrayにしても"ClassC": 貸出案件IDとするだけではエラーが出る。
              // 以下が正解
              "ClassC": JSON.stringify(貸出案件ID) // 配列をJSON文字列に変換
          },
          
          // 完全一致検索のための記載
          "ColumnFilterSearchTypes": {
              "ClassC": "ExactMatch"
          }
      }
  };
  context.Log("view: " + view);

  // items.Countで条件に合致するレコードの件数を集計できる
  let 貸出明細未返却件数 = items.Count(siteId, JSON.stringify(view));
  // 貸出案件テーブルのCheckA(「返却済?」カラム)の更新
  if (貸出明細未返却件数 == 0) {
    let 貸出案件返却済更新 = {
      CheckHash: {
        CheckA: true
      }
    };
    items.Update(貸出案件ID, JSON.stringify(貸出案件返却済更新));
    context.Log("すべて返却されています");
  } else if (貸出明細未返却件数 != 0) {
    let 貸出案件返却済更新 = {
      CheckHash: {
        CheckA: false
      }
    };

        // items.Updateの第1引数で他のサイトIDを指定すると、他のサイトID（テーブル）のレコードも作成・更新可能
    items.Update(貸出案件ID, JSON.stringify(貸出案件返却済更新));
    context.Log("あと" + 貸出明細未返却件数 + "件の明細分が未返却です");
  } else {
    return false;
  }
})();
```
WindowsからLinuxへSSH公開鍵認証する

## はじめに
SSHサーバー : Linux Mint
SSHクライアント : Windows 10

こんなかんじ

## SSH鍵登録の仕方
:::note info
cmdではなくPowershellでおこなうこと
:::

### キーペアの作成
```
ssh-keygen -t rsa -b 4096
```

### キーをSSHサーバー（接続先）へ送る
```
PS C:\Windows\system32> cat ~/.ssh/id_rsa.pub | ssh USER@192.168.1.1 -p 1024 " mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys "
```
:::note info
USER@192.168.1.1 は環境に合わせて，ユーザー名とホスト名書き換え
ポート番号変えている人は `-p`オプションでポート指定（例は1024）
:::

## ログインしてみる
```
ssh USER@192.168.1.1 -p 1024
```
パスワードが求められることなくログインできるはずである
zsh での表示をシンプルにする（自分が設定した内容のメモ）

タイトル通り、zsh での表示をシンプルにするという話で、その設定に関するメモです。

デモ用などで、表示をシンプルにしたくて設定している内容になります（これまで自分が使ってきた MacBook Pro に設定していたもので、それを昨年購入した Mac mini にも反映させた時のメモ的な記事になります）。

## デフォルトの内容

デフォルトでの表示に関して、`echo $PS1` を実行することで設定に関する内容が確認できます。

![2025-01-11_21-17-55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/dcf759c6-967a-e69e-26d2-6d3fa69146f5.jpeg)

上記をテキストで書き出すと以下のとおりです。

```zsh
echo $PS1
%n@%m %1~ %#
```

[参考サイト](https://zenn.dev/c6tower/scraps/ddaf80fbbb8b28)を見てみると、それぞれ以下の意味になるようです。

![2025-02-16_01-42-57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/26d08368-b85c-4296-bb00-72d2e9d891ca.jpeg)

これを限りなくシンプルになるよう変更してみます。

## 設定の変更
先ほども参照した[参考サイト](https://zenn.dev/c6tower/scraps/ddaf80fbbb8b28)を見つつ、設定変更の候補を 2つあげてみました。

1つは以下の、カレントディレクトリの表示のみとしたシンプルなものです。

```zsh
export PS1="%1~ %# "
```

もう 1つは、上記をさらにシンプルにしたもので、ユーザー種別のみしか表示しない設定です。

```zsh
export PS1="%# "
```

### 永続化
環境変数の永続化のため「.zshrc」にこの設定を記載します。

2つ目のほうを設定した結果、表示は以下となりました。

![2025-01-11_21-37-15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/9a8d0718-39b3-d8bf-22f8-ee8a409dc5b5.jpeg)
ストレージを大雑把に理解する【DAS,NAS,SAN】

###   この記事を作成した経緯
普段ネットワークエンジニアをしていますが、新規案件獲得のためサーバ提案をすることになりました。提案資料の作成担当は僕と先輩なのですが、先輩はサーバに関してはノータッチということなので、自分でサーバ構成のたたき台ぐらいは作成できるようにならなければいけないと思い、LPIC306を始めました。そこでストレージについていろいろと学ぶうちに、ストレージの種類について頭ごちゃごちゃになりましたので、本記事ではDAS、NAS、SANの違いとそれぞれの特徴について解説します。

### DAS,NAS,SANとは
正式名称は以下の通り
* DAS（ダイレクト・アタッチト・ストレージ）
* NAS（ネットワーク・アタッチト・ストレージ）
* SAN（ストレージ・エリア・ネットワーク）

DAS,NAS,SANは**ストレージの接続方法の種類**です。
また、自分が勘違いしていた点として、過去の案件で使用したストレージからNASやSANは製品名とイコールであると思っていました。（例として以下の通り）
* NAS: Buffaloの「TeraStation」
* SAN: 富士通の「ETERNUS」


正しい理解として、あくまで**ストレージの接続方法の種類**を示しているのであって、使い方によってはBuffaloの「TeraStation」がSANに、富士通の「ETERNUS」がNASとして使用されることもある。

### ストレージ概要図
左から【ストレージ種類】→【接続方式（物理）】→【接続方式（論理）】というフローで図を作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1446740/617f4c4e-8855-47e6-b3ae-786f9a36501e.png)

まずストレージの種類は以下の通りです。
* 内蔵HDD
* 外付けHDD
* 磁気テープ
* CD ROM

今回はサーバに使用するストレージの概要図ということで、内蔵HDDと外付けHDDを深堀していきます。

### DAS（Direct Attached Storage）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1446740/88120cfd-9063-47b3-a778-089b410ddf21.png)

DASは**ネットワークを介さず、専用線で接続されたストレージ**を指します。
ネットワークを介さずということはLANケーブルを使用せずUSBやIDE（SATA）で接続するイメージです。

### NAS（Network Attached Storage）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1446740/36b4c904-c963-4dd2-8ead-8215f18bdef9.png)

NASは**ネットワークストレージ、IP接続でデータ共有を目的とするストレージ**を指します。IP接続を目的とするため、LANケーブルまたは光ケーブル（FC）を使用します。ストレージへのアクセス方式として、Windowsファイル共有（SMB）Linuxファイル共有（CIFS）やHTTP/FTPプロトコルを使用します。


### SAN（Storage Area Network）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1446740/7fada0c0-9c85-454a-9872-6209418a6852.png)

SANは**ネットワークストレージ、かつブロックストレージとしてデータ共有を目的とするストレージ**を指します。NASと同じでIP接続でデータ共有をするため、接続方式はLANケーブルや光ケーブル（FC）を使用しますが、NASとの相違点は接続方式（論理）の部分にあります。
* NAS：ファイルストレージ
* SAN：ブロックストレージ

NASは普段Windowsでよく使用しているファイル形式を使用する形ですが、SANは複数のサーバが1つのストレージを利用（1:複）する目的であるため、ファイルストレージのような階層構造ではなく、もっと低いレイヤーで使用される形式となっている。その代わりきめ細やかな制御を行うことが可能となり、効率的なパフォーマンスが可能となる。

そのため、SANではNASで使用していたファイルアクセス方式ではなく、iSCSIというブロックストレージ向けの接続方式が採用される。光ケーブルを使用する場合の接続方式は、FC（Fibre Channel）やiSCSIを光ケーブルで使用可能とするiSCSI over Fibre Channelとなる。

## 以下、用語解説
### IDE（Integrated Drive Electronics）とは
コンピューターにハードディスクを接続するための規格、SATAが出てくるまで主流であった。

### SCSI (Small Computer Systems Interface)とは
コンピュータと周辺機器を接続するための規格

### iSCSI (Internet Small Computer Systems Interface)とは
IPネットワークを利用してSAN（Storage Area Network）を構築するプロトコル規格。つまりSCSIのネットワーク版

SCSI とiSCSI の違いとして、SCSIは直接接続で使用され、iSCSIはネットワーク経由で使用される。

## まとめ
これでサーバ提案書にNASでいくのか、SANでいくのかを論理的に説明できる気がする。あとは冗長化を理解せねば。。。
【React】react-datepickerのポップアップにクラスを指定したい

## 概要
react-datepickerのポップアップに対してz-indexを指定する場合、[React DatePicker calendar showing behind table head](https://stackoverflow.com/questions/52412685/react-datepicker-calendar-showing-behind-table-head)の記事にある通り、規定のクラス名を指定してスタイルを上書くという実装は対応として挙げられます。
とはいえ、私の開発してる環境ではtailwindを使用してるので、可能であればクラス名を指定してスタイルを適用させたいです。しかし`className`に指定してもスタイルが効かなかったので、どうすればよいかというメモ書きです。

## 前提
* 使用したreact-datepickerのバージョンは`8.0.0`です。

## 対応
[datepicker (component)](https://github.com/Hacker0x01/react-datepicker/blob/main/docs/datepicker.md)のドキュメントに記載がある、`popperClassName`を使用します。
tailwindを使用して、z-indexを指定する場合の実装は以下の通りとなります、規定のz-index設定に負けてしまわないうようimportantを付与しています。

```react
<DatePicker
  selected={value}
  onChange={(date) => setValue(date)}
  dateFormat="yyyy/MM/dd"
  popperPlacement="bottom-start"
  popperClassName="!z-20" // ここにtailwindのクラス名を指定
/>
```
個人的備忘録：CloudFront + S3 + ALB の HTTPS 構成の概要整理と、簡単に調べた記事をスクラップしてみた

## はじめに  
Web サービスを AWS 上で構築する際、フロントエンドとバックエンドをどのように設計するかは重要なポイントです。

:::note info
**特に、スケーラビリティやセキュリティを考慮すると、S3 + CloudFront を活用したフロントエンドと、ECS を利用したバックエンドの構成が有力な選択肢となります。**
:::

本記事では、ECS を活用し、S3 + CloudFront + ALB を組み合わせたリクエストフローについて解説します。 

## 書こうと思ったきっかけ  
最近、AWS を利用した Web アプリケーションの構成を考える機会が増えました。

特に、フロントエンドを S3 + CloudFront でホスティングし、バックエンドを ECS で運用するケースが多くなっています。

:::note warn
***しかし、この構成には CORS の考慮が必要であったり、ALB との連携を適切に設計する必要があったりと、気をつけるポイントが多くあります。***
:::

本記事では、それらのポイントを整理し、実践的なリクエストフローを解説することで、同じ課題に直面する方の助けになればと思い、執筆しました。

## 簡単な構成

```css
[ユーザー]
    │
    │ (1) フロントエンドにアクセス (https://example.com)
    ▼
[Route 53] -- (Aレコード) --> [CloudFront] -- (キャッシュ) --> [S3 バケット]
    │
    │ (2) フロントがバックエンド API にリクエスト (https://api.example.com)
    ▼
[Route 53] -- (CNAME) --> [ALB] -- (ロードバランシング) --> [ECS (APIサーバー)]
    │
    │ (3) API のレスポンスをフロントエンドに返す
    ▼
[ユーザーのブラウザで画面が更新]
```

## この構成では CORS が必要
**結論：必要**

CORS (Cross-Origin Resource Sharing) が必要になります。理由は、フロントエンド (example.com) とバックエンド (api.example.com) が異なるオリジンだからです。

## ポイント
- **CloudFront を経由して S3 にアクセス**（S3 のパブリックアクセスをブロック）
- **ALB を利用して複数のバックエンドへリクエストを分散**
- **バックエンドはプライベートサブネットに配置し、ALB 経由でのみアクセス可能にする**
- **React からの API リクエストは環境変数を使用し、ALB のエンドポイントを指定**

## ECS を活用したリクエストフロー

### 1. フロントエンドのルーティング（CloudFront + S3）
- `https://example.com` へアクセスすると、Route 53 の `Aレコード` を通じて CloudFront にルーティング。
- CloudFront は S3 に保存された React (または Vue, Angular) の静的ファイルをキャッシュし、最適化して配信。
- ユーザーのブラウザが `index.html` を取得し、画面を描画。

### 2. バックエンドのルーティング（ECS + ALB）
- フロントエンドが `https://api.example.com` に API リクエストを送信。
- Route 53 の `CNAME` レコードを通じて ALB にルーティング。
- ALB はリクエストをロードバランシングし、**ECS のコンテナ (Fargate or EC2) に転送**。
- ECS の API サーバーがリクエストを処理し、レスポンスを返す。
- フロントエンドがレスポンスを受け取り、画面を更新。

## ECS 化のメリット
- **コンテナ管理が容易** → Docker イメージを ECS にデプロイするだけ。
- **スケーラビリティが向上** → ALB + ECS でコンテナをオートスケール。
- **Fargate を利用すると EC2 不要でサーバーレス運用可能**。
- **ECR (Elastic Container Registry) を利用し、コンテナイメージを安全に管理**。
- **CloudWatch Logs でコンテナのログ管理を一元化**。

## 調べた記事

- [フロントエンドとバックエンドの構成について](https://qiita.com/hyj624117615/items/450f6526c6a9c81848a6)
- [S3 + CloudFront の設定方法](https://zenn.dev/doaradev/scraps/d4f49961865afb)
- [ECS のセットアップ](https://qiita.com/augetlargiendo_10/items/3f5c8302b8edae97836a)
- [S3 のコンテンツを CloudFront 経由で配信](https://dev.classmethod.jp/articles/distributing-s3-content-with-cloudfront/)

## とても参考になった記事

- [CORS 設定のベストプラクティス](https://dev.classmethod.jp/articles/cors-with-cloudfront-response-header-policy/)
- [React ベースの SPA を S3 + CloudFront にデプロイする方法](https://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/patterns/deploy-a-react-based-single-page-application-to-amazon-s3-and-cloudfront.html)

## まとめ  
S3 + CloudFront + ALB + ECS を組み合わせることで、スケーラブルかつセキュアなアーキテクチャを構築できます。

:::note info
***CloudFront を活用して S3 の静的コンテンツを効率的に配信し、ALB を介して ECS の API サーバーと連携することで、負荷分散やスケールアップにも対応できます。***
:::

ただし、異なるオリジン間の通信が発生するため、CORS の適切な設定も欠かせません。**本記事の内容が、AWS を活用した Web アプリケーションの構成を考える際の参考になれば幸いです。**
LaravelのPipelineについて

# はじめに
ちょっとどころかかなり前に執筆しておいて放置していた記事をせっかくなので公開します。

## ドキュメント

Laravel10のドキュメントにはこう書かれてます
```
LaravelのPipelineファサードは、指定する入力を一連の呼び出し可能なクラス、クロージャ、Callableを通して、「パイプ」接続する便利な方法を提供し、各クラスに入力を検査または修正する機会を与え、パイプラインの次のCallableを呼び出します。
```

え？専門用語多すぎて意味分からん
クロージャ？Callable？パイプ？何それ美味しいの？

### Callable
「呼び出すことが出来るもの」という意味。
Laravelに限らず、プログラミング全般で用いられる用語

Laravelにおいて、Callableは「関数」「クロージャ」「オブジェクトのメソッド」などを指します。
確かに上３つは全部「呼び出すことができる物」にあたっている。


### Pipeline
一連の処理をパイプラインのように順々に実行するための仕組み。
Laravelでは「リクエスト処理」や「データ処理」など様々な場面でPipelineで利用されている。

#### Pipelineの仕組み

```plain
データ  -->  処理1  -->  処理2  -->  処理3  -->  結果
```

**具体的な仕組み**

1. 初期化：Pipelineが作成されると、処理の順番が設定されます。
2. データの投入：最初の処理にデータが渡されます。
3. 処理の実行：各処理は、受け取ったデータを加工し、次の処理に渡します。
4. 最終処理：最後の処理が実行され、最終的な結果が得られます。


下記が基本の形です。
```php
Pipeline::send(/*.パイプを通過させたいオブジェクト */)
    ->through(/* 処理させたいメソッドの配列 */)
    ->then(/* 最終処理 */);
```

### パイプを通過させたいオブジェクト
処理させたい対象のオブジェクト。
文字列とか、QueryBuilderとかrequestオブジェクトとか。
なんでもいい。

```php
Pipeline::send($request)
```
とか

```php
$builder = User::query();
$builder = Pipeline::send($builder)
    ->through([
      ConditionGender::class,
    ])->thenReturn();
  return $builder->get(); // queryのget()を実行してる
```


### 処理させたいメソッドの配列
通過させたいオブジェクトに対して処理を行う内容のメソッドです。

### 最終処理
単純に言えばfinallyと同じ。returnで値を返せばそれが返ります。
特に処理を行わない場合は、`then()`の代わりに`thenReturn()`というメソッドを使う。

と言う感じになってます。
少しでも参考になれば嬉しいですっ
Spring Boot環境構築

## 方針
学習のためSpring BootでREST APIを用いたアプリケーションを作成し、
GitHubに上げ、AWSへデプロイするまでを行う。


## ①JDK導入
無料で商用利用できるOpenJDKのEclipse Temurin（Adoptium）を選択。
https://adoptium.net/


- ダウンローダー起動後、Set JAVA_HOME variableをクリックし、「ローカルハードドライブにインストールする」 を選択。
これによりJAVA_HOME環境変数が設定され、Eclipse や Mavenなどが正常に動くようになる。
- 以下のディレクトリが生成される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000113/95677570-ba43-4c4d-9809-1144b2ef2c56.png)


## ②Spring Tools for Eclipse導入
STS（Spring Tool Suite）が付属したEclipse。
https://spring.io/tools

ダウンロードしたZIPファイルを解凍し、中のSpringToolSuite4.exeを実行することで起動。

Microsoft Defender Exclusion Checkのダイアログボックスが出たら、Windows Defender によるスキャンを除外するかどうかを選択。動作が重くなければKeep～(スキャン対象にする)で良さそう。
後で除外したくなったら、[Windows 設定] → [更新とセキュリティ] → [Windows セキュリティ] → [ウイルスと脅威の防止] → [設定の管理] → [除外の追加] → Spring Tools 4 のフォルダを選択

## ③STSが使うJava実行環境(JVM)の設定
-vmオプションを設定することで特定のJDK/JREを実行環境に指定できる。
指定しない場合、システム環境変数のPATHにあるJavaが使われる。

・コマンドプロンプトでwhere javaを実行し、JDKのパスを確認
・STSのフォルダにあるSpringToolSuite4.iniを開き、-vmの設定を、確認したパス\javaw.exeに変更
**※-vmの位置は-startupより上に置く。下だと設定が無視される。**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000113/ee995871-4b91-4032-b9b4-f2d2c5853838.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000113/04c005cf-27f5-47d7-8c4f-c0e49d3812de.png)

これにより複数のJavaバージョンがインストールされていても、適したJDKを確実に使える。
【技術メモ】オフライン会話の距離感の再現をWeb上の通話でやりたい。

:::note info
アドバイスください...。随時更新予定。
アイデア自体は結構いいと思うんだけどね...。
:::

# 独り言

・別にWebsocket使ってリアルタイム双方向かつN人で集まってわいわい通話→そういうことをしたいわけではない。
・WebRTCとか使って電話みたいな感じで1対1通信を確立できれば....。

PannerNodeで音声とか距離感とかシミュレートできる！

https://developer.mozilla.org/ja/docs/Web/API/PannerNode

適当にFastAPIとかでいいのか？手軽にシグナリングサーバー建てる...?
***用語解説***

https://www.nssol.nipponsteel.com/ss/detail/signaling.html#:~:text=%E5%BE%93%E6%9D%A5%E3%81%AE%E5%9B%9E%E7%B7%9A%E4%BA%A4%E6%8F%9B%E7%B6%B2,%E3%81%A8%E5%91%BC%E3%82%93%E3%81%A7%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

WebRTCってマッチングの処理までは賄ってないからそこはフレームワークを用いて開発しないといけない。

https://chatgpt.com/share/67b0b373-a508-8003-bd67-bb8430429acd
[Blender]Import Images as Planesはどこに行ったの？

# 概要
Planeに画像を貼り付けてついでに比率を画像に合わせてくれる「Import Images as Planes」が以前まで標準アドオンとしてありましたが、最新バージョンBlender4.2以降では使えなくなっていました(Add-ons、Extensions両方にありません)

![スクリーンショット 2025-02-16 000203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/edbb8cec-c146-4b8e-91b9-1ebe5b053629.png)


# 本文
最新バージョンではアドオンから消えてしまいましたが、名前を変えてBlenderの標準機能になっていました:tada:

追加からImage > MeshPlaneを選択して画像を指定したら画像付きのPlaneが生成されます。

![スクリーンショット 2025-02-16 000629.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/617265/1b22ff1d-a684-40da-8d0f-04939287e219.png)


# 補足
画像の読み込み方いろいろ
[【Blender】画像の読み込み方法をまとめて基礎解説！](https://vook.vc/n/6144)
参考動画
[Blender 4.2 Tutorial: How to restore the "Import Images as Planes" feature!](https://www.youtube.com/watch?v=bmfDV-c0F9Y)
RHELにMySQL 8.0をインストールしたけどtemporary passwordがどこにもない？

超重い腰を上げてRHEL9のセットアップをしてみました。
EL9からSELINUXの設定がカーネルに移行したという話を聞いていたので。
https://github.com/tomgoodsun/el9_lamp_configs

それはいいのですが、MySQL 8.0のインストールに苦戦しました。
うまく立ち上がらない。
OS再起動、再インストールとかしても、rootユーザー用の`temporary password`がログに記録されない。
OSのAppStreamリポジトリやMySQLのオフィシャルリポジトリ、関係するファイルオーナー、パーミッションを見直しても変化なし。
rootパスワードのリセットや初期化手順などもことごとく失敗。

原因は完全に削除されていなかったためでした。
以下は実行したコマンドです。

```
# MySQLを停止
systemctl stop mysqld  

# パッケージマネージャーでアンインストール（MySQL公式リポジトリを使用している）
dnf remove mysql-community-server 

# 関係するファイルを完全に削除する
rm -rf /var/lib/mysql /var/log/mysqld.log 

# 一応OS再起動
reboot

# MySQLサーバーをインストール
dnf install mysql-community-server

# MySQLを起動
systemctl start --now mysqld

# temporary passwordを確認
grep password /var/log/mysqld.log
```

気を抜いたときにふと思ったところでしたが、案の定ファイルが残っていたので、これを消して解決しました。
それにしても一番最初のrootのパスワードがどこに行ったのか、どのパスワードを設定したのかは全く謎でした。
イベントソーシング: アプリケーションの状態をどのように管理するか

アプリケーションの状態をどのように管理するか。これは多くの開発者が直面する重要な課題です。イベントソーシングは、この課題に対する興味深いアプローチです

## イベントソーシングの基本概念

従来のアプローチでは、アプリケーションの現在の状態のみを保存します。 **一方、イベントソーシングでは、状態の変更を「イベント」として記録し、それらのイベントを再生することで状態を再構築します。**

具体例で見てみましょう：

従来のアプローチ：
```javascript
// データベースに現在の状態のみを保存
{
  "orderId": "123",
  "status": "shipped",
  "updatedAt": "2024-02-15T10:00:00Z"
}
```

イベントソーシング：
```javascript
// 全ての変更をイベントとして保存
[
  {
    "type": "ORDER_CREATED",
    "orderId": "123",
    "timestamp": "2024-02-15T09:00:00Z",
    "data": { "items": [...] }
  },
  {
    "type": "ORDER_SHIPPED",
    "orderId": "123",
    "timestamp": "2024-02-15T10:00:00Z",
    "data": { "trackingNumber": "..." }
  }
]
```

## システムの構成

```mermaid
graph TD
    Client[クライアント] --> OrderService[注文サービス]
    OrderService --> EventStore[イベントストア]
    EventStore --> Events[イベント履歴]
    Events --> State[現在の状態]
    
    style Client fill:#90EE90
    style OrderService fill:#87CEEB
    style EventStore fill:#DDA0DD
    style Events fill:#E6E6FA
    style State fill:#F0F8FF
```

## 基本的な実装

```javascript
class Order {
  constructor(id) {
    this.id = id;
    this.events = [];
    this.currentState = {
      status: null,
      items: []
    };
  }

  // イベントを適用して状態を更新
  applyEvent(event) {
    switch(event.type) {
      case 'ORDER_CREATED':
        this.currentState.status = 'created';
        this.currentState.items = event.data.items;
        break;
      case 'ORDER_SHIPPED':
        this.currentState.status = 'shipped';
        break;
    }
  }

  // 状態を再構築
  rebuildState(events) {
    events.forEach(event => this.applyEvent(event));
    return this.currentState;
  }
}
```

## イベントソーシングの利点

1. **完全な履歴**
   - 全ての変更が記録される
   - 状態の変化を追跡可能
   - 監査が容易

2. **デバッグの容易さ**
   - 問題発生時の状態を再現可能
   - イベントの流れを確認可能

3. **ビジネス分析**
   - 履歴データを活用した分析
   - パターンの発見
   - トレンドの把握

## 考慮すべき課題

1. **複雑性**
    Event sourcingは素晴らしい概念ですが、実装の複雑さには注意が必要です
   - イベントの設計が重要
   - 学習コスト
   - 運用の複雑さ

2. **パフォーマンス**
   - イベントの蓄積による影響
   - 状態再構築のコスト
   - ストレージの要件

## 適用に適したケース

1. **金融システム**
   - 取引履歴の追跡
   - 監査要件への対応
   - 不正検知

2. **Eコマース**
   - 注文処理
   - 在庫管理
   - 顧客サービス

## まとめ

イベントソーシングは、以下のような場合に特に効果を発揮します：
- 完全な履歴が必要
- 監査が重要
- 状態の変更を詳細に追跡したい

一方で、下記のような実装の課題もあり、単純なCRUDで十分な場合は、従来のアプローチの方が適している場合も大いにありそうです。

   - イベントスキーマの設計と進化
   - パフォーマンスの最適化
   - チーム全体の理解度の維持

## 参考リンク

- [Martin Fowler - Event Sourcing](https://martinfowler.com/eaaDev/EventSourcing.html)
- [Microsoft - Event Sourcing Pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing)
- [What is Event Sourcing?](https://newsletter.scalablethread.com/p/what-is-event-sourcing)
【JavaScript】特定のキーのKeyboardEvent.keyを簡単に確認する方法

以下のサイトでKeyboardEvent.keyの値を知りたいキーを押下すると簡単に確認できます。

https://keyboard.events

![スクリーンショット 2025-02-15 23.57.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/40ffc873-015e-4596-9daf-cc9a4328f9f4.png)

## KeyboardEvent.keyについて

https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values#special_values
ロータリーエンコーダーをmicro:bitで使いたい

ロータリーエンコーダー。
半固定抵抗のような形をしていますが、ツマミを制限なく回転させることができるパーツです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/6f411903-4870-4dc8-acf4-ee3af5046479.png)

https://akizukidenshi.com/catalog/g/g105762/

## ロータリーエンコーダーの仕様

A系統/B系統のHigh/Lowを読み取ることでどちら方向に回っているか判断します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/c9d2497d-f655-4bd0-a963-14113d6472c5.png)




## サンプルプログラム
左回転(反時計回り)につまみを回すと左向きの矢印が表示、右回転(時計回り)につまみを回すと右向きの矢印が表示されます
A系統B系統どちらが先にHighになっているかでどちら回転か判断しています。
(P0に端子A、P1に端子B、GNDに端子Cを接続)

https://makecode.microbit.org/S12274-30254-75696-23098
となっています。

## 課題
個体差もあるのかもしれませんがスペックシート通りに波形が出ていません。
時計回りの時はきれいにAにHighが出てからBにHighが出る流れですが、半時計回りの際にはAとB同時にHighとなっています。

連続回転したときもうまく数値を拾えていことがあります。
micro:bitの限界かもしれません。


## 先達たちの記録
先達たちの記録を見るとロータリーエンコーダーの利用は過去と現在の値を見て判断するのがよさそうです。次回のチャレンジ！
https://wave.hatenablog.com/entry/2017/03/14/191000
AWS未経験でDVAに合格しました。

# はじめに
タイトルにもある通りAWSの実務経験が無いなかでDVAに合格しました。ゆっくり取り組んで半年くらい掛かったと思います。インフラの経験もないスタート地点なだけに、学習を続けて受かったことが嬉しかったので記録に残したいと思いました。

# そもそもなぜ受けようと思ったか
転職エージェントとお話しする機会があり、今の自分のスキルにはインフラの知識や経験がなく、紹介できる求人が限定的であると知りました。業務に直結する話でないのはわかっていましたが、いずれインフラを意識した開発をするのであれば今学習を始めてしまおうと思ったのがきっかけです。SNSの合格者を見るとCLFやSAA取得から目指すのが定石のように感じますが、開発実務に直結する内容を問題を通して理解したいと思い、DVA受験を目指しました。


# どう学習したか
最初は以下の書籍で開発したアプリをElasticBeanstalkでデプロイするところから始めました。
[Spring Boot 2 応用: REST x Swagger UI、MyBatisからAWSへのデプロイまで](https://www.amazon.co.jp/gp/product/B08RL67N9S/ref=ppx_yo_dt_b_d_asin_title_351_o00?ie=UTF8&psc=1)
ElasticBeanstalk自体は現場であまり使われないとかいう話も聞きますが、AWSを通してアプリ公開することは比較的簡単に実現できたと思います。なにより自分が開発したアプリを公開できる一つの手段としてAWSを利用できたことは大きかったように思います。
この他にも様々なサービスがあることはDVA試験の試験概要や参考書を通して知りました。
参考書は以下を使用しました。
[徹底攻略AWS認定デベロッパー - アソシエイト教科書＆問題集 第2版 ［DVA-C02］対応 徹底攻略シリーズ](
https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5AWS%E8%AA%8D%E5%AE%9A%E3%83%87%E3%83%99%E3%83%AD%E3%83%83%E3%83%91%E3%83%BC-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8%EF%BC%86%E5%95%8F%E9%A1%8C%E9%9B%86-%E7%AC%AC2%E7%89%88-%EF%BC%BBDVA-C02%EF%BC%BD%E5%AF%BE%E5%BF%9C-%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-ebook/dp/B0CRYSJ58X/ref=sr_1_3?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=MOL0T0FG8WT&dib=eyJ2IjoiMSJ9.PEquUMVnEZ4ZDJ2Yev4ai7GkOTqj1zwRxe46Lmu_57RX8sslV1WRT4VcaDgpcGOssqwXAZeWxZe2REk1ORwymhbRGIaX7Ri8XJ47V8QPO1sPDnYaUX5SWrsO1c78h7b6YtIH1ElmLZpeUlwaGsZvnbWeb1HaW40SvdnCGOQsNJN7xldLp79dPJ4XkR02eFPusr5FI8qhzQIArCrPdgCbDWt-hy7c76jCT22SXJ0Bkw4.L9v4_wz9fgZN6W6snEUJAsvARza61ZqRzTZJYwo4o58&dib_tag=se&keywords=DVA&qid=1739627732&s=digital-text&sprefix=dva%2Cdigital-text%2C454&sr=1-3)
練習問題は問題の数をこなすことに間違いはないので、参考書とは別でUdemyのDVA問題集に取り組みました。公式ドキュメントのリンクが解説についていたので十分に復習ができたと思います。
公式ドキュメントやAWSのblackbeltで気になるテーマを覗いたりしました。実際の試験にも一部出たので最新の情報は見ておくべきだなと思いました。

以上です。
UbuntuでSuper (Windows) キーとAltキーを入れ替え

## キーの入れ替え

https://zenn.dev/oratake/articles/linux-setxkbmap-option

```bash
setxkbmap -option altwin:swap_alt_win
```

オプション一覧は次のコマンドの出力の `!option` 以下で確認できる．

```bash
less /usr/share/X11/xkb/rules/base.lst
```

## Ubuntu起動時に自動的に実行

再起動後，先ほどのコマンドが自動的に実行されるように設定．

```bash
mkdir ~/auto_shell
cd ~/auto_shell
```

`vi swap_alt_win.sh`
```bash:~/auto_shell/swap_alt_win.sh
setxkbmap -option altwin:swap_alt_win
```

```bash
chmod +x swap_alt_win.sh
```

`vi ~/.config/systemd/user/swap_alt_win.service`

`<User Name>` は自身のユーザー名に置き換える．

```ini:~/.config/systemd/user/swap_alt_win.service
[Unit]
Description=swap alt keys with the windows key
After=graphical.target

[Service]
ExecStart=/home/<User Name>/auto_shell/swap_alt_win.sh
Restart=on-failure
RestartSec=10
StartLimitIntervalSec=300
StartLimitBurst=3

[Install]
WantedBy=default.target
```

```bash
systemctl --user daemon-reload
systemctl --user enable swap_alt_win.service
systemctl --user start swap_alt_win.service
```
FileMaker Data API を使う 2025年版 vol.16

 変更が多くなってきたので、現在までのソースコードを以下にまとめてあります。
[Vol.15 まで](https://github.com/GetMyselfBack/filemaker-data-api-examples/tree/main)

 構造は、以下の通りです。
```
.
├── css
│   ├── bootstrap-common.css
│   └── fmda-form.css
├── csv
│   └── standings.csv
├── find-records-test.php
├── find-records-test2.php
├── find-records-test3.php
├── html
│   └── edit-record.html
├── index.php
├── js
│   ├── fmda-form-check.js
│   └── fmda-select-page.js
├── json
│   ├── html-contents.json
│   ├── standings-al-east-2024.json
│   └── standings-all-2024.json
└── php
    ├── bs-builder-class.php
    ├── bs-frame-class.php
    ├── filemaker-data-api-class.php
    ├── php-functions.php
    ├── preferences.php
    └── temporary-functions.php
```
集積回路（IC）設計に使う伝達関数

### **冒頭**

集積回路（IC）設計において重要となる各種伝達関数を整理し、それらの特性をボード線図（Bode Plot）を用いて可視化しました。伝達関数はアナログ回路の動作解析において不可欠であり、周波数特性の把握や安定性の評価に活用されます。特に、本資料では **アンプ回路やフィルタ回路で頻繁に用いられる一次および二次系の伝達関数** を取り上げ、それぞれのゲイン特性と位相特性を示します。これにより、各伝達関数の周波数応答を直感的に理解できるようになります。  
本解析では、Python の **`scipy.signal`** を用いて周波数応答を計算し、ボード線図としてプロットしました。得られた結果は、設計時のパラメータ調整や回路特性の最適化に役立つことを目的としています。  

---


---

### **与えられた伝達関数**

---

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/263e469e-cf38-43e2-8e35-3d71f0613632.png)



### **Pythonで伝達関数をまとめる**

---

#### **Pythonコード**
```python

# 必要なライブラリのインポート
from scipy.signal import freqs
import matplotlib.pyplot as plt
import numpy as np

# 具体的なパラメータの設定（実際の回路設計でありそうな値に調整）
z = 1e3     # 零点の位置 (Hzオーダー)
p = 1e5     # 極の位置 (MHzオーダー)
A = 40      # ゲイン (40dB程度を想定)
B = 1e-6    # 係数 B (時間定数系, 小さい値)
C = 1e-9    # 係数 C (キャパシタンス, nFオーダー)
D = 1e-6    # 係数 D (時間定数, µsオーダー)

# 周波数範囲の設定（10 Hz ～ 10 MHz 相当の範囲）
frequencies = np.logspace(1, 7, 1000)  # 10 rad/s から 10,000,000 rad/s

# 伝達関数の係数定義（分子と分母）
G1_num = [1, -1/z]   # 1 - s/z
G1_den = [1, 1/p]    # 1 + s/p

G2_num = [1, 1/z]    # 1 + s/z
G2_den = [1, 1/p]    # 1 + s/p

G3_num = [A]         # A
G3_den = [1, 1/p]    # 1 + s/p

G4_num = [A * B, A]  # A(1 + sB) = A * sB + A
G4_den = [1]         # 1

G5_num = [-A * B, A] # A(1 - sB) = -A * sB + A
G5_den = [1]         # 1

G6_num = [-A * B, A] # A(1 - sB)
G6_den = [C * D, C + D, 1] # (Cs+1)(Ds+1) = C*D*s^2 + (C+D)s + 1

# 各伝達関数の周波数応答を計算
w, H1 = freqs(G1_num, G1_den, worN=frequencies)
w, H2 = freqs(G2_num, G2_den, worN=frequencies)
w, H3 = freqs(G3_num, G3_den, worN=frequencies)
w, H4 = freqs(G4_num, G4_den, worN=frequencies)
w, H5 = freqs(G5_num, G5_den, worN=frequencies)
w, H6 = freqs(G6_num, G6_den, worN=frequencies)

# ボード線図（ゲインと位相）のプロット
fig, axs = plt.subplots(2, 1, figsize=(10, 8))

# ゲインプロット
axs[0].semilogx(w, 20 * np.log10(abs(H1)), label="G1")
axs[0].semilogx(w, 20 * np.log10(abs(H2)), label="G2")
axs[0].semilogx(w, 20 * np.log10(abs(H3)), label="G3")
axs[0].semilogx(w, 20 * np.log10(abs(H4)), label="G4")
axs[0].semilogx(w, 20 * np.log10(abs(H5)), label="G5")
axs[0].semilogx(w, 20 * np.log10(abs(H6)), label="G6")
axs[0].set_ylabel("Magnitude [dB]")
axs[0].set_title("Bode Magnitude Plot")
axs[0].grid(which="both", linestyle="--")
axs[0].legend()

# 位相プロット
axs[1].semilogx(w, np.angle(H1, deg=True), label="G1")
axs[1].semilogx(w, np.angle(H2, deg=True), label="G2")
axs[1].semilogx(w, np.angle(H3, deg=True), label="G3")
axs[1].semilogx(w, np.angle(H4, deg=True), label="G4")
axs[1].semilogx(w, np.angle(H5, deg=True), label="G5")
axs[1].semilogx(w, np.angle(H6, deg=True), label="G6")
axs[1].set_xlabel("Frequency [rad/s]")
axs[1].set_ylabel("Phase [degrees]")
axs[1].set_title("Bode Phase Plot")
axs[1].grid(which="both", linestyle="--")
axs[1].legend()

# グラフを表示
plt.tight_layout()
plt.show()


```
YouTube の動画 URL から切り抜きやショート動画など関連動画を見つけるサービスを作ってみた

![](https://storage.googleapis.com/zenn-user-upload/8ef49904f4ee-20250207.png)

## 作ったもの

YouTube の動画 URL から切り抜きやショート動画など関連動画を簡単に見つけるサービス ClipSearch をリリースしました。🎉

https://www.clipsearch.jp/

![](https://storage.googleapis.com/zenn-user-upload/d58a571e400e-20250214.gif)

## なぜ作ろうと思ったのか

私は Vtuber の配信を見るのが好きですが、追う対象が多すぎて正直全部見切れてないです。切り抜きチャンネルはフォローしていますが、その中でこの動画の切り抜きどれだ？？と探すのが結構手間だったりします。（特にゲーム実況...）

そこで、動画 URL を貼ったら関連動画が出てくるものがあると嬉しいなと思い、そのまま Web サービスとして開発しました。

## 技術スタック

フロント技術のみのすごくシンプルな構成です。

- Next.js
- TypeScript
- MUI
- Vercel
- YouTube Data API

## YouTube Data API

### 概要

https://developers.google.com/youtube/v3/docs?hl=ja

今回 YouTube の動画を検索するために、YouTube Data API を使用しています。YouTube Data API は、Google Cloud で提供されており、YouTube のコンテンツやユーザーのデータにアクセスすることができます。
具体的には、動画の検索やチャンネル情報の取得などが可能で、これにより自分のアプリケーションやウェブサイトで YouTube のデータを活用することができます。

こめYouTube Data API の使い方に関しては別途記事を作成予定です。

### 1日の上限枠

YouTube Data APIは無料で誰でも利用できますが、1日あたり10,000クォータの利用制限があります。
APIの呼び出しエンドポイントによって1回あたりの消費量が異なり、今回のような動画検索では1回あたり100クォータを使用します。そのため、100回検索を行うと、その日はこれ以上検索できなくなる（リクエストをしても結果が返ってこない）ということになります。

### クォータ増加申請

[YouTube API サービス - 監査と割り当て増加フォーム](https://support.google.com/youtube/contact/yt_api_form?hl=ja)

今回、ClipSearch をリリースするにあたり、1日100回しか検索できないという制限ではサービスの提供に支障をきたすと感じていました。そこで、クォータの割り当て増加が必要だと判断し、上のフォームから申請を行いました。
申請を行なうと、Webサービスに対する審査が行われ、YouTube API の利用規約やポリシーに適合しているかどうかがチェックされます。

審査が完了した後、結果はメールで通知されます。もし審査がNGとなった場合、修正すべき箇所についてメールで指摘があり、それに基づいて修正を行い、再度審査を依頼するというやり取りを繰り返すことになります。
私の場合は、一発合格で驚きました。（何かしら FB が来るだろうと身構えていたので...）
一度審査に通過すれば、12ヶ月以内であれば簡易フォームから追加申請が可能なようです。ユーザー数が増えて再び上限に近づきそうな場合には、再度申請を行なってみようと思います。

https://support.google.com/youtube/contact/yt_api_audited_developer_requests_form?hl=en&sjid=9839119281100380661-NC

※申請に関する具体的な内容については、別途記事としてまとめる予定です。

## よかったこと

### シンプルに作れた

今回、たくさんの人に使ってもらいたいなと思い、以下のことを実行しました。

- 機能としてシンプルでわかりやすいものにする
- 認証などユーザーが面倒に感じるものは入れない
- YouTube Data API の上限枠が開放されてからサービスを広めていく

結果的に意識した通りにサービスを開発でき、個人的に満足しています。
特に YouTube Data API の上限枠に関しては、上述の通りサービスとして 1 日 100 回しか検索できないのはユーザーを落胆させてしまうと思い、上限枠が増えるまでは周知を我慢していました。

### Google の担当者とのやり取り

面倒なクォータ増加申請をやり切れたのは良い経験となりました。重い腰を上げて YouTube の[利用規約](https://www.youtube.com/t/terms)や Google 社の[プライバシーポリシー](http://www.google.com/policies/privacy)をしっかりと読み、規約通りにサービスの開発を行えた点が大きな収穫でした。

たとえば、YouTube の動画を1つ埋め込むにしても YouTube プレーヤーの UI を好き勝手にいじってはならないといった旨の規約があり、詳細な部分まで読み込むのが大変でした。

https://developers.google.com/youtube/terms/required-minimum-functionality?hl=ja#youtube-player-attributes

## 反省点

### スマホ利用には向いてないかも

今回、ClipSearch のアクションとしては動画の URL を入力するというものでした。PC を普段から使っていて動画もほとんど PC で閲覧する私にとっては URL をコピーして貼り付けるのは容易でした。

しかし、スマホかつ YouTube アプリで動画を見ていると URL をコピーするという行為が意外と面倒なんだなということに作ったあとに気づきました。

## さいごに

ここまで読んでいただき、ありがとうございました。
高度な技術を使わなくてもある程度形になるサービスは作れるんだということが学び始めのエンジニアの方に伝わると良いなと思っています。
YouTube Data API は他にも色々なことができるので、今後さらに ClipSearch をアップデートしていきます。
音量変更時のシステム音の消し方

# 手っ取り早い方法
音量のボタンを右クリックして、「音量ミキサーを開く」。
システム音を0にすれば消えます。
# ピンポイントで消す方法
さすがにシステム音を全消しするのはどうなんだ、ということでピンポイントで消す方法も紹介。

音量のボタンを右クリックして、「サウンドの設定」。
下までスクロールすると、「サウンドの詳細設定」があるのでクリック。
「サウンド」タブから、「一般の警告音」を選び、サウンドで(なし)を選択。(なし)は一番上までスクロールするとあります。
そしてOKを押します。

で、再起動します。
# 終わりに
「ピンポイントで消す方法」は、この記事にあったんですが。

https://cocotiie.com/windows-sound-setting/

この音量変更時のシステム音、以前はスクロールなら鳴らなかったり、一般の警告音でなく通知音だったりで、仕様がここ数年で変化しているんですよね。同じwindows11なのに…。だから、再起動が必要というのは、すぐには気づけませんでした。

正直、また仕様が変わってもおかしくないので、システム音いらねって人は、システム音消したほうがいい気がします。書いといてなんなんですけど…
余ったPCパーツでもう一台PCが生えてきたのでOllamaを用いてLocalLLMの検証環境を構築した

# 1. はじめに
最近、ローカル環境で動作するLLM（大規模言語モデル）の実用性が高まってきています。特に、日本語に特化したオープンなモデルの登場や、軽量化されたモデルの充実により、個人レベルでも手軽に試せる環境が整ってきました。
私の場合、自作PCのパーツをアップグレードした際に余ったパーツでLinux機を組んでみたのがきっかけでした。せっかく組み立てたマシンを何か面白いことに使えないかと考えていた時に、ローカルLLMが目に留まりました。検証を始めた動機としては：

- 組み立てたLinux機を活用したアプリケーション開発
- 軽量LLMの実用性の検証
- 日本語特化モデルへの興味
- 既存リソースでの実現（追加コスト不要）

特に注目したのは、最小限のリソースでどこまで実用的なアプリケーションが構築できるかという点です。ChatGPTやClaude等のクラウドサービスと比較すると性能面では劣りますが、プライバシーの確保やカスタマイズ性の高さなど、ローカルLLMならではの利点も期待できます。

# 2. 環境構築
## 検証環境
使用したPCは以下の通りです。
- CPU:AMD Ryzen 5 5500
- メモリ：16GB
- GPU：GeForce GT 730
- ストレージ：500GB(SSD)
- OS:Ubuntu 24.04.1 LTS

## Ollama
ローカルLLMを簡単に導入・実行できるプラットフォームとして今回はOllamaを用いました。
環境構築においてはKaito Sugimotoさんの[Ollamaで体験する国産LLM入門](https://zenn.dev/hellorusk/books/e56548029b391f "Ollamaで体験する国産LLM入門")をなぞるような形となっています。
今回はLinuxへの導入なので[Download Ollama on Linux](https://ollama.com/download/linux "Ollama linux")に準拠して

```bash:install
curl https://ollama.ai/install.sh | sh
```
としてインストールを実行します。
しばらくすると完了するので。
```bash:ollama version test
ollama --version
```
としてバージョンの情報が帰ってきたら成功です。

# 3. 日本語版 Gemma 2 2Bを導入
今回は手始めにGoogleが公開2024/10に公開したモデルである[日本語版 Gemma 2 2B](https://developers-jp.googleblog.com/2024/10/gemma-2-for-japan.html "Gemmajp")を導入してみます。
下記のコマンドを実行すると、Ollamaがモデルを取得したのち実行されます。
```bash:run Gemma
ollama run hf.co/alfredplpl/gemma-2-2b-jpn-it-gguf
```
成功するとコマンドライン上でそのまま入力を待つ形になります。いくつかテストをしてみましょう。
```bash:recipe
>>> 豚肉と玉ねぎがあります子供が喜ぶ野菜が進むようなメニューのレシピを教えてください
## 子供も喜ぶ！豚肉と玉ねぎを使ったレシピ

**【材料】（4人分）**

* 豚肉：150g
* 玉ねぎ：1個
* にんにく：1かけ (お好みで)
* 醤油：大さじ2
* みりん：大さじ1
* 酒：大さじ1
* 砂糖：小さじ1/2
* 片栗粉：大さじ1
* サラダ油：適量

**【作り方】**

1. **豚肉を切る:**  豚肉の大きさを統一して、一口大に切る。
2. **玉ねぎを切る:** 玉ねぎは薄切りにする。
3. **豚肉と玉ねぎを炒める:** フライパンにごま油を熱し、豚肉を炒める。
4. **味付け:** 醤油、みりん、酒、砂糖を加え、弱火でじっくり煮る。
5. **仕上げ:**  玉ねぎを加えて軽く炒め、塩コショウで味を調える。

**【ポイント】**


* **お子様向けに！**  甘さ控えめで、少し酸味が効いている味付けにするのがおすすめです。
* **見た目も楽しい！**  豚肉と玉ねぎをたっぷり使うことで、ボリューム満点の見た目になり、子供も喜ぶでしょう！
```

```bash:mini4WD
>>> ミニ四駆を趣味にしてみようと考えていますどのように楽しむのが良いでしょうか？
ミニ四駆、いいですね！楽しい趣味になると思いますよ！

**楽しむ方法をいくつかご紹介します！**

**1. 基本的な楽しみ方：レースを楽しむ**

* **ミニ四駆レースのイベントに参加:** 地域やオンラインでイベントを開催しているところがあります。
    * 新しいコースや技術を試す良い機会になります！
* **仲間とレース:**  仲間とレースをすることで、競争意識を高めながら、一緒に楽しむことができます。
* **自分のマシンを改良:**  レースの成績向上のため、自分でマシンを改造し、性能を最大限に引き出すのも楽しいです。

**2.  より深く楽しむための工夫:**

* **ミニ四駆の歴史と技術の勉強:**  ミニ四駆の歴史や技術について学ぶことで、より深く楽しめるようになります。
    *  例えば、各メーカーのモデルの特徴や、レースのテクニックについて調べるのも面白いです！
* **オリジナルパーツ製作:**  独自のアイデアで、自分のオリジナルパーツを作ってみましょう！
    *  オリジナルパーツを作ることで、自分だけの特別なマシンを作ることができます。

**3.  コミュニティと交流を楽しむ**

* **ミニ四駆コミュニティに参加:**  オンラインコミュニティやイベントに参加することで、他のミニ四駆愛好家と交流できます。
    *  共通の趣味を持つ仲間と交流することで、モチベーション維持や技術向上に繋がります！
* **ミニ四駆ブログや動画投稿:**   自分のレースやマシンを紹介したり、技術を解説したりして、他のユーザーと共有するのも楽しいです。



**始め方:**

1. **ミニ四駆ショップで入門品を選ぶ:**  初心者向けのミニ四駆セットが販売されています。
2. **オンラインコミュニティに参加:**  ミニ四駆関連のオンラインコミュニティで、他のユーザーと交流しましょう。




ミニ四駆は、自分でマシンを作り、レースを楽しむだけでなく、技術や戦略的な思考を学ぶこともできます。  ぜひ楽しんでください！
```
レシピでは準備した材料(サラダ油・片栗粉・ニンニク)で登場していないものがありますが(ごま油どこから出てきた？)、思った以上に応答も早く、中身もかなりまともな印象です。

# 4. まとめ
今回は、Linux上にローカルLLMの環境を構築し、日本語版 Gemma 2 2Bを動かしてみるところまでを実行してみました。
Ollamaによって、想像以上に環境構築はスムーズにいきました。
今後はDifyなどのGUIを用いたアプリケーションの構築などができればと考えています。