OmniAICreator/Qiita-1.07M huggingface dataset:
【Dependabot】ラベルを設定する方法

Dependabotでラベルを設定するには `.github/dependabot.yml` ファイルに `labels` セクションを記述します。
プルリクエストに追加したいラベルをリスト形式で追加します。以下の場合には`dependencies` と `automerge` の2つのラベルが設定されます。

```yaml
version: 2
updates:
  - package-ecosystem: "npm"
    directory: "/"
    schedule:
      interval: "weekly"
    commit-message:
      prefix: "fix"
    labels:
      - "dependencies"
      - "automerge"
```

https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#labels
Powerpointで作った図を高画質で出力する方法

# Microsoft PowerPointで作った図を600dpiで保存します。

Powerpointを駆使して作った図を、論文投稿用の高解像度（300dpiや600dpi）のtiffファイルとして保存する方法のメモです。

試した環境：Windows 11。

## ①レジストリエディタの起動
Windowsキー+R → 「regedit」で起動
![Windowsキー+R → 「regedit」.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744572/93ada660-90d8-bd4c-6ca9-e1decfcefa61.jpeg)

## ②HKEY_CURRENT_USERの編集
HKEY_CURRENT_USER　→　Software　→　Microsoft　→　Office　→　数字(15か16. 多分2016で16?)　→　Powerpoint　→　Options
![HKEY_CURRENT_USER.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744572/8e565f83-f97f-99a9-b94e-85131cf98561.jpeg)

## ③ExportBitmapResolutionの変更
(1) メニューから「編集」 → 「新規」 → 「DWORD（32ビット)値」
(2) 新規追加された項目の名前を「ExportBitmapResolution」変更。ダブルクリック。
(3) 「10進法」値を300や600と入力する。

![ExportBitmapResolution.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744572/deaffa27-fa5a-e1bb-df2c-e5d519734943.jpeg)

## ④これでエディタを閉じると、PowerPointで300dpi（600dpi）で画像を出力する設定に変更できた。

その後、画像を右クリックし、「プログラムから開く」⇒「フォト」を選択。
「フォト」でトリミングする

### このページは以下を参考にしました。

http://blog.nanko-kazuki.main.jp/?eid=73

以上です。
e^xのマクローリン展開をホーナー法で

```math
\begin{align}
e^x &= 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!} + \frac{x^4}{4!} + \cdots \\
&= 1 + x + \frac{x^2}{2!} + \frac{x^3}{3!}(1+\frac{x}{4}\cdots) \\
&= 1 + x + \frac{x^2}{2!}(1 + \frac{x}{3}(1+\frac{x}{4}\cdots)) \\
&= 1 + x(1 + \frac{x}{2}(1 + \frac{x}{3}(1+\frac{x}{4}\cdots))) \\
\end{align}
```

このように計算することで階乗を計算する必要がなくなり、ループ回数iに階乗計算による制限がなくなることで精度を高めることができる。sin,cosは同様にくくり、`r*x*x/(i*(i-1))`の項が現れ、4の剰余で1の符号を判断するなどして計算できる。

```c
#include <stdio.h>
int main()
{
    double r = 1; // result
    double x = 1;

    for (int i = 10; i > 0; --i)
        r = r*x/i + 1;

    printf("%.15lf\n", r);

    return 0;
}
```

美しい。
誰もこのコードを見てネイピア数の計算できるとは思わない（多分）。
Pythonの並列処理ライブラリ「Ray」のメモ

# 前置き
Pythonの並列処理といえば、`threading`や`multiprocessing`、`concurrent`が代表的だが、常々**前置き**が多いのがネックであった。
慣れてしまえば気にならないのだろうが、そう頻繁に使うものでもないので、慣れるまで使うことは少ない。
使うことが少ないので、必要になれば毎回使い方を検索するハメになる。
面倒で仕方がない。

そんな中出会ったのが「Ray」というライブラリ。
並列処理をサポートするライブラリだが、これがまぁ使いやすい。
1. 使うcpuのコア数を決めて
2. 並列化したい関数を`@ray.remote`でデコレートして
3. `ray.get(func.remote(params))`するだけ

たったこれだけで記述できるのが素晴らしい。
皆も使って素晴らしさを体感しよう。

# Rayの使い方
前述の通り、これだけ
```
1. 使うcpuの数を決めて
2. 並列化したい関数を @ray.remote でデコレートして
3. ray.get(func.remote(params)) するだけ
```

## インストール
`pip install ray`でインストールできる。
importも以下のように書くだけ。
```python
import ray
```

## 1. 使うcpuの数を決めて
ここでのcpuの数は、論理コア数のこと。
デフォルト値の場合、（恐らく）全ての論理コアが食われるので注意。

以下の処理を最初に書くだけ。
```python
ray.init(num_cpus=4)
```

この処理には少し時間が必要なので、上手く動かない場合は
```python
ray.init(num_cpus=4)
time.sleep(1)
```
などとして少し待ってあげよう。

## 2. 並列化したい関数を @ray.remote でデコレートして
並列化といえばスクレイピング（偏見）なので、seleniumやbs4を用いた以下のような関数を想定する。
```python
def get_page(url):
    html = chrome_driver.get(url).page_source
    bs = BeautifulSoup(html, features="lxml")
    title = bs.get("title").title
    with open(f"{title}.html", "w") as f:
        f.write(html)
```

この関数は`chrome_driver.get(url)`の処理で待ちが発生するため、記事が多いほど時間がかかってしまうのは当然である。

そこで、`@ray.remote`を使って並列処理に対応させる。
```python
@ray.remote
def get_page(url):
    # 変更不要なので省略
```
なんと、たった1行書くだけで準備完了。
お手軽すぎる。

## 3. ray.get(func.remote(params)) するだけ
最後に、以下のように書くことで並列化させて実行する。
今回は設定したcpuの個数分だけ並列させる。
```python
urls = [...]
rays = []
for url in urls:
    r = get_page.remote(url)
    rays.append(r)
    if len(rays) == 4:
        ray.get(rays)
        rays = []

if len(ray) != 0:
    ray.get(rays)
```

たったこれだけで並列化が実現できる。

# あとがき
皆もこの神ライブラリ「Ray」を使って、煩雑な並列処理コードとサヨナラしよう！

## 参考記事
https://qiita.com/waffoo/items/603bb3df25163fa461e9
プログラミングとHTMLの「class」の違いについて

Qiitaにはマークダウン式で記入するルールというルールがあるのですね。
毎回無視していて申し訳ありません。
マークダウン式が分かっていないので、近日中に必ず学んでマークダウン式で記事を書きたいと思っているので今回は（もしかしたら次回も）この書き方で勘弁してください。

Railsの勉強をしています。
練習課題に日々取り組んでいますが、その中で気になることがありました。
記述していく中で「class ~」と出てくるのですが、これってHTMLのclassと同じ意味なのか、違う意味なのか、ということです。

同じ「class」なんだから同じ意味でしょ！と最初は深く考えていませんでしたが、進めるにつれて「やっぱり意味が違うのでは？」と思うようになりました。

そこで今更ながら、Ruby（プログラミング）とHTMLの「class」の意味の違いをまとめておきたいと思います。

Ruby（プログラミング）の「class」は「設計図」
HTMLの「clss」は「ラベル」

という理解が自分の中ではしっくりきます。

Rubyの「class」は、「class」の中で動作が定義されていきますが、
HTMLの「class」は、同じ「class」（ラベル）のものについてCSSでまとめて設定するものですよね。

確かに全然用途違うわ！何で同じ意味と考えてたんだろうと思ったけど、それは同じ「class」という単語が使われていたからですね！
同じ単語使うの紛らわしいからやめてほしいわー！なんて思うのは私だけでしょうか。


これからは「class」の意味もしっかり考えながら学んでいきたいと思います。
HTTPメソッド「GET」「POST」「PUT」「PATCH」「DELETE」わかりやすい例えを使って説明

HTTPメソッドには「GET」「POST」「PUT」「PATCH」「DELETE」などがありますが、それぞれ異なる役割を持っています。わかりやすい例えを使って説明しますね。
***
### GET
**例え:** メニューを見る行為 **説明:** GETリクエストは、サーバーからデータを取得するために使われます。たとえば、ブログの記事一覧や特定の記事の内容を表示するときに使います。これはデータを「取りに行く」だけで、サーバー側に変更は加えません。

**例:**
`GET /posts` → 投稿一覧を取得する。
`GET /posts/1` → IDが1の投稿を取得する。
***
### POST
**例え:** 注文を新規に行う **説明:** POSTリクエストは、新しいデータをサーバーに送信して作成するために使います。たとえば、新しいブログ投稿を作成したり、ユーザー登録を行う際に使用されます。

**例:**
`POST /posts` → 新しい投稿を作成する。
`POST /register` → ユーザーを登録する。
***
### PUT
**例え:** メニューの注文内容を完全に変更する **説明:** PUTリクエストは、既存のデータを完全に置き換えるために使います。たとえば、既存のブログ投稿の内容をまるごと書き換える場合に使用します。データ全体を上書きするという点でPATCHと異なります。

**例:**
`PUT /posts/1` → IDが1の投稿を完全に更新する。
***
### PATCH
**例え:** 注文内容の一部を修正する **説明:** PATCHリクエストは、既存のデータの一部だけを更新するために使います。たとえば、ブログ投稿のタイトルだけを変更したいときに使用します。PUTのようにデータ全体を更新するわけではなく、部分的な変更です。

**例:**
`PATCH /posts/1` → IDが1の投稿の一部を更新する。
***
### DELETE
**例え:** 注文をキャンセルする **説明:** DELETEリクエストは、サーバーからデータを削除するために使います。たとえば、ブログ投稿を削除する場合に使用します。

**例:**
`DELETE /posts/1` → IDが1の投稿を削除する。
***
このように、各HTTPメソッドにはそれぞれの役割があり、操作内容に応じて使い分けます。
cmakeをアップデートしよう

# cmakeのアップデート

Ubuntuの最新版ではそこまで気にすることではないのかもしれませんが、もしものためにcmakeの更新方法を挙げておきます。

### ①パッケージのダウンロード
ソフトウェアを保存しておくディレクトリを作っておくとよいです。
```bash
mkdir -p $HOME/Important_Software/ && cd $HOME/Important_Software/
```
パッケージをダウンロード。
```bash
wget https://github.com/Kitware/CMake/releases/download/v3.30.4/cmake-3.30.4.tar.gz
#解凍・パッケージ削除
tar zxvf cmake-3.30.4.tar.gz && rm cmake-3.30.4.tar.gz
```
### ②cmakeのインストール

ビルド
```bash
cd cmake-3.30.4/
./bootstrap
make
#パスを通す
echo 'export PATH=$HOME/Important_Software/cmake-3.17.1/bin/:$PATH' >> ~/.bashrc
source ~/.bashrc
```

### ③cmakeのバージョン確認
```bash
cmake --version
#cmake version 3.22.1

#CMake suite maintained and supported by Kitware (kitware.com/cmake).
```

以上です。
micro:bitで大きな音を出す方法(アンプキットの利用)

micro:bitはブロックで気軽にコーディングできるマイコンボードです。
最新版のV2ではスピーカーを内蔵していますが、大きな音は出せません。
みんな大好き秋月電子で買えるアンプキット・スピーカーを利用しました。


## 利用したアンプ・スピーカー

アンプキット＠500円

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


スピーカー＠100円

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

## 接続について
micro:bitのスピーカー出力はデフォルトではP0となっています。
その前提で配線は下記となります。

P0(micro:bit) --- A(アンプ基板)
3V(micro:bit) --- V(アンプ基板)
GND(micro:bit) --- G(アンプ基板)

スピーカー(+) --- P(アンプ基板)
スピーカー(-) --- N(アンプ基板)

## その他
内蔵スピーカーは外部スピーカーをつないだ場合、自動的にオフになっていました。
自動判定している模様です。
~~V2を利用する場合はスピーカーが内蔵されています。~~
~~こちらをオフにする場合は音楽メニューの中の下記ブロックを利用します。~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/f9a86b3d-46e7-8b54-9aa6-ef895f3039af.png)

基板上の設定は動作設定：常にON(JP1をショート)、音量設定：音量を大きく(JP2をショート)としました。

## 接続写真
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/71746/a3e1f06b-3136-de24-5cf6-0dcdd839307c.png)
FlutterのTextFormFieldはerrorTextが空でも赤くなる

## ErrorTextになにか文字がある場合
![スクリーンショット 2024-10-12 224643.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844247/19b49c27-2a93-ea1f-fe60-f38da854a775.png)
- StatefulWidgetの`setState()`などでerrorTextプロパティへ文字をセットするかと思います
```errortext_is_not_empty.dart
TextFormField(
  decoration: const InputDecoration(
    icon: Icon(Icons.lock),
    labelText: 'LabelText',
    hintText: 'HintText',
    errorText: 'ErrorText', // 状態が変わったらセット
  ),
)
```
## ErrorTextが空文字`''`の場合
![スクリーンショット 2024-10-12 224710.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844247/452b00ef-397d-deb0-e95d-b4d727b28860.png)
- `setState()`などで空文字でセットしてもエラー扱い（赤くなる）になります
```errortext_is_empty.dart
TextFormField(
  decoration: const InputDecoration(
    icon: Icon(Icons.lock),
    labelText: 'LabelText',
    hintText: 'HintText',
    errorText: '', // 空文字だとエラー扱い（赤くなる）！！　null なら赤くならない
  ),
)
```

## 所感
空文字でリセットを`Riverpod`でstateを管理時に空文字でリセットしていたため、なぜ`ThemeColor`で設定していない赤色になるのかわからず時間がかかりましたが、そもそも`errorText`が空の場合も赤くなっちゃうみたいです
つまり、ErrorText用の変数はNullableな`String?`で作ってnull代入でリセットがよさそうですね。

## 公式レファレンス
https://api.flutter.dev/flutter/material/TextFormField-class.html
ディレクリーツリーの可視化


```python
import os
import streamlit as st

def save_file_list_to_txt(folder_path, output_path="file_list.txt"):
    """指定されたフォルダのファイルリストを.txtに保存"""
    try:
        with open(output_path, "w") as f:
            for dirpath, dirnames, filenames in os.walk(folder_path):
                depth = dirpath.replace(folder_path, "").count(os.sep)
                indent = "    " * depth
                f.write(f"{indent}└── {os.path.basename(dirpath)}/\n")
                for filename in filenames:
                    f.write(f"{indent}    ├── {filename}\n")
        return output_path
    except Exception as e:
        st.error(f"エラーが発生しました: {e}")
        return None

st.title("フォルダのファイルリストを保存")

# フォルダパスの入力
folder_path = st.text_input("フォルダのパスを入力してください:")

if folder_path:
    if st.button("ファイルリストを保存"):
        output_file = save_file_list_to_txt(folder_path)
        if output_file:
            st.success(f"ファイルリストを '{output_file}' に保存しました。")
            with open(output_file, "rb") as file:
                st.download_button(
                    label="ダウンロード",
                    data=file,
                    file_name="file_list.txt",
                    mime="text/plain",
                )


```
ABC375をPythonで（A～D）

パナソニックグループ プログラミングコンテスト2024（AtCoder Beginner Contest 375）の解答等の速報的まとめ

https://atcoder.jp/contests/abc375



# A問題
https://atcoder.jp/contests/abc375/tasks/abc375_a

先頭から順番に条件を満たしているか確かめる
```python:A
n = int(input())
s = input()

ans = 0
for i in range(n - 2):
    if s[i:i+3] == "#.#":
       ans += 1

print(ans)
```
# B問題
https://atcoder.jp/contests/abc375/tasks/abc375_b

スタートとゴールが$(0, 0)$であることに気を付けて距離を足し合わせる
```python:B
def diff(a, b, c, d):
    return ((a - c) ** 2 + (b - d) ** 2) ** 0.5

n = int(input())
data = [list(map(int, input().split())) for _ in range(n)]
data = [[0, 0]] + data + [[0, 0]]

ans = 0
for (x_i, y_i), (x_j, y_j) in zip(data, data[1:]):
    ans += diff(x_i, y_i, x_j, y_j)

print(ans)
```
# C問題
https://atcoder.jp/contests/abc375/tasks/abc375_c

結局のところ外側からの距離に応じて決まった回数だけ回転しているので、各座標ごとに参照箇所が計算で求められる
```python:C
def move(x, y, cnt):
    if cnt % 4 == 0:
        return x, y
    elif cnt % 4 == 1:
        return n - y - 1, x
    elif cnt % 4 == 2:
        return n - x - 1, n - y - 1
    else:
        return y, n - x - 1

n = int(input())
a = [list(input()) for _ in range(n)]
ans = [["."] * n for _ in range(n)]

for i in range(n):
    for j in range(n):
        x, y = move(i, j, min(i + 1, j + 1, n - i, n - j))
        ans[i][j] = a[x][y]

for a_i in ans:
    print("".join(a_i))
```
# D問題
https://atcoder.jp/contests/abc375/tasks/abc375_d

これの答えは同じ文字同士の間にある文字の個数の総和になる
よって線形時間で解を求めるには、各文字において既に出た同じ文字との間にある文字数の総和が計算できれば良い

これは
$($今の座標$-1)\times($既に出た同じ文字の個数$) - ($既に出た同じ文字の座標の和$)$
で求められる
```python:D
s = input()

ans = 0
sum = {chr(i + ord("A")) : 0 for i in range(26)}
cnt = {chr(i + ord("A")) : 0 for i in range(26)}

for i, s_i in enumerate(s):
    ans += (i - 1) * cnt[s_i] - sum[s_i]
    sum[s_i] += i
    cnt[s_i] += 1

print(ans)
```
灰色コーダーによるABC375振り返り

# 灰色コーダーによるABC375振り返り
よし釣れたこのタイトル使えるの二回だけだったw
なぜかというとac-predictorを見てたら入茶してました
今度入茶記事書きます
さて本題書くか

# A

https://atcoder.jp/contests/abc375/tasks/abc375_a

愚直に全探索した
```python
N = int(input())
S = input()
r = 0
for i in range(N - 2):
    if S[i] == "#" and S[i + 2] == "#" and S[i + 1] == ".":
        r += 1

print(r)
```
解説URL

https://atcoder.jp/contests/abc375/editorial/11138

# B

https://atcoder.jp/contests/abc375/tasks/abc375_b

そのまんまユークリッド距離を測った
前の数を変数に保存してやると最初の0,0もカバーできる
ジャッジが遅くて笑った
```python
N = int(input())
x, y = 0, 0
r = 0
for _ in [0] * N:
    a, b = list(map(int, input().split()))

    r += ((a - x) ** 2 + (b - y) ** 2) ** 0.5
    x, y = a, b

r += (x**2 + y**2) ** 0.5
print(r)
```
解説URL

https://atcoder.jp/contests/abc375/editorial/11135

# C

https://atcoder.jp/contests/abc375/tasks/abc375_c

Dより難しい解けなかった
TLE解法まではたどり着いたがそこからがわからずパス
解説見てもよくわかんなかった

解説URL

https://atcoder.jp/contests/abc375/editorial/11141

# D
解けた
最初TLEしたがひらめいてACした
~~疲れたので詳細は書かない~~
よくよく見ると改善点あり
```python
S = input()

L = {s: [] for s in list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")}
T = {s: 0 for s in list("ABCDEFGHIJKLMNOPQRSTUVWXYZ")}

r = 0

for i in range(len(S)):
    if len(L[S[i]]) == 0:
        L[S[i]].append(i)
        T[S[i]] += i
        continue

    r += (i * len(L[S[i]])) - T[S[i]] - len(L[S[i]])

    L[S[i]].append(i)
    T[S[i]] += i

print(r)
```

解説URL

https://atcoder.jp/contests/abc375/editorial/11139

# 最後に
入茶できたのとD問題をコンテスト中にACできたのが嬉しかった(レートはまだ不確定)
CよりDのほうが簡単なケース結構あるような気がする

IDよかったら↓↓
[id](https://atcoder.jp/users/hidehico)
manifest.tsって何に使うんだ？？使い方についてちょっと調べてみた

こんにちは。合同会社AI Forwardでエンジニアをしている末永です。

はじめに
この記事の内容
Webアプリケーション開発に携わっている方の多くが、「画像の管理」という課題に直面したことがあるかと思います。

しかし、画像をただ扱うだけでなく、効率的に管理し、アプリのパフォーマンスやSEOを向上させることも重要です。

今回は、manifest.tsファイルを活用することで、画像管理を改善する方法について解説していきます。ぜひ、実際のプロジェクトに取り入れてみてください！


対象読者  
TypeScriptを使ってWebアプリを開発している方  
PWAやSEOに関心があり、アプリのパフォーマンスを改善したい方  
画像管理の効率化に取り組んでいる方  
TypeScriptでのプロジェクト管理やファイル構成に興味がある方

## なぜmanifest.tsに画像パスを登録するのか

主に2つの理由があります：

1. キャッシュ管理の最適化によるパフォーマンス向上
2. ユーザー体験とSEOの改善

それぞれについて、詳しく説明していきます。

1. キャッシュ管理でアプリの応答性を向上  
manifest.tsに画像ファイルを登録すると、以下のような利点があります：

- 効率的なキャッシュ管理: 画像ファイルにユニークなIDが付与され、変更があった場合のみ新しい画像が配信されます。これにより、サーバーの負荷が軽減され、ユーザーへの応答速度が向上します。
- アセットのプリロード: ブラウザがページ表示前に必要な画像を先読みできるようになり、ページの読み込み速度が改善されます。
- 遅延読み込みの実装: 即時に必要でない画像は後から読み込むことが可能になり、初期表示の速度向上に寄与します。

2. ユーザー体験とSEOの改善  
manifest.tsへの画像パス登録は、ユーザー体験とSEOにも好影響を与えます：

- SEOへの効果: Manifestファイルは検索エンジンにとって重要なメタデータとなります。適切に設定されたアイコンや説明文は、検索結果でのアプリの表示を改善します。
- デバイス適応型アイコン: maskableアイコンの指定により、各デバイスのデザインに合わせたアイコン表示が可能になります。細かい配慮ですが、ユーザー体験の向上に貢献します。

## manifest.tsを利用したパフォーマンス向上のメカニズム

### プリロード（Preloading）  
直接コンポーネントに画像パスを記述する場合、画像が必要な時にブラウザがそれをリクエストしますが、ページ全体のレンダリングが始まるタイミングでしか画像を読み込めません。これにより、ページが重い場合やネットワークが遅い場合、ユーザーが画像を閲覧するまでに時間がかかることがあります。

manifest.tsを使用する場合、ブラウザがページをレンダリングする前に、manifest.tsに登録された画像を先読み（プリロード）**することが可能です。これにより、ページが表示されるタイミングですでに画像がキャッシュに存在するため、画像が素早く表示され、ページ全体の読み込み速度が向上します。特に、重要なアイコンやロゴが素早く表示されることは、ユーザー体験向上に寄与します。

### 遅延読み込み（Lazy Loading）  
直接コンポーネントに画像パスを記述する場合、画像の遅延読み込みはコンポーネント内で直接実装可能ですが、通常はJavaScriptなどを使って制御します。必要な実装が増えるため、適切な制御がされていないと、パフォーマンスが低下するリスクがあります。

manifest.tsを使用する場合、画像パスの登録とともに、manifest.tsを利用して遅延読み込みを効率的に設定できます。特定のタイミングで表示されるべき画像（例えば、ページスクロール後に見えるもの）だけを後から読み込むことで、初期表示時のページロードが軽くなります。

## manifest.tsへの画像パス登録：実践例

実際のmanifest.tsでの画像パス登録例を見てみましょう。

```ts
import { BRANDING_LOGO_URL, BRANDING_NAME } from '@/const/branding';

const manifest = (): MetadataRoute.Manifest => ({
  name: BRANDING_NAME,
  icons: [
    {
      purpose: 'any',
      sizes: '192x192',
      url: '/icons/icon-192x192.png',
    },
    {
      purpose: 'maskable',
      sizes: '192x192',
      url: '/icons/icon-192x192.maskable.png',
    },
    {
      purpose: 'any',
      sizes: '512x512',
      url: '/icons/icon-512x512.png',
    },
    {
      purpose: 'maskable',
      sizes: '512x512',
      url: '/icons/icon-512x512.maskable.png',
    },
  ],
});
```

このように設定することで、様々なデバイスや用途に適したアイコンを提供できます。

## まとめ

私も画像パスを使う際にそのままurlを登録していたのですが、manifest.tsへの画像パス登録などの小さな積み重ねで、アプリのパフォーマンス、ユーザー体験、SEOを改善していけたらと思います。  
ぜひ、皆さんのプロジェクトでも試してみてください。

何か質問や感想があれば、コメント欄でお待ちしています。一緒にWebアプリ開発について勉強していけたらと思います。
Pythonで三次元散布図を作る方法について

散布図を書くときどんなツールを使っていますか？
2次元の散布図であればExcelを使って、一瞬で作れますよね。
例えば、時間を第一軸に設定して、センサーの値を第二軸に設定する。そうすると、センサーの値が、経過時間と相関性があるのかを一目で確認することができます。

では、もう一軸追加して、センサーを二つに増やした場合どうなるでしょうか？その場合、2次元の散布図で表現するためには、3つの散布図を作成する必要があります。
・第一軸：時間、第二軸：センサ1の値
・第一軸：時間、第二軸：センサ2の値
・第一軸：センサ1の値、第二軸：センサ2の値
このようにそれぞれの相関性を確認すれば、関係性は見えてきます。
ただ、3つも散布図を書くのは面倒ですし、そもそもわかりにくいですよね？

そんな時に便利なのが、3次元散布図です。
その名の通り、二次元に一次元追加した散布図です。具体的には、奥行方向に軸が追加されます。三次元になることで、3つのパラメータを1つの散布図で表現することが可能になります。

具体的にどうやって作るかについてこちらの記事で紹介しています。
コピペでできるようにコードも公開していますから、ご自分の作りたいようにカスタマイズしてみてください。

https://www.hobbyhappyblog.jp/3dscatter-python-matplotlib
『UI/UX デザインの原則』を読んでみた

# はじめに
ぬいぐるみとTシャツがほしいと思い、初めてアドベントカレンダーを書きます。
がんばって完走しきりたい…。

筆者は都内で働くWebエンジニアで、フロントエンドに関係することが特に好きです。が、まだまだ経験も浅いので雑多に疎かになっている基礎を固めるべく、いろいろな記事を書こうと思います。

今回はUIUXのお話。

# 本のざっくり紹介
最近読んだ『UI/UX デザインの原則』について紹介していきます。

この本はUIUXをどのように考え、どのように改善すると良いのかがまとめられています。

また、いくつかの会社のケーススタディも載っていて、参考になるケースもあるかもしれません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/f86bc02b-0f6b-ceeb-0a9a-faee61353e17.jpeg" width=30%>

# 本書の構成
本書はUI/UXの違いとは何かから始まり、

- 原則1『ユーザー心理/行動に則って考える』ことがUI/UXデザインの第一歩である
- 原則2『ユーザー心理 / 行動』をUI/UXデザインに落とし込む
- 原則3 UI/UXデザインにおける三方良しをつくる
- 原則4 UI/UX思考でこれからのビジネスをデザインする

の4つの原則について紹介されています。

## 個人的に勉強になったところ紹介
本を読んでみて特に気になったところについて感想ベースで3つ紹介していきます。

感想は完全に自分の独断と偏見が含まれているのでご容赦ください。

### 1. UI/UXの違い
UIができていても他サービスとの差別化にはならず、UXを改善することが差別化につながるということが紹介されていました。
 
![スクリーンショット 2024-10-12 22.21.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/7338ee57-6d54-c518-b67b-45bf3bd48565.png)

これを知ってハッとしました。たしかにサイトを見た時にデザインが良いなと思うより悪いなと感じる方が多いですし、操作性が悪いものはまた使おうともならないので、言われて見ればという発見でした。

### 2. 分析する時に数値ばかり見ていませんか？
定量分析（数値を見て分析する）の結果ばかり見て頭打ちになっていないか、本来はその結果と合わせて定性分析（ユーザーボイスなど数値では表せないもの）も行うことで真のユーザーのニーズを掴むことができると紹介されていました。
 
 ![スクリーンショット 2024-10-12 22.34.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/713f2b9c-7148-c2cf-1ae0-55f25ed12783.png)

自分の働いている会社は定量分析がほぼで、数値を見て改善案が出てきますがやってみても効果があまり出ないことは多々あります。めんどくさがらないでユーザーインタビューもやらなければなと思いました。

### 3. サービスを使っている時以外の体験も考えよう
UXはサービスを使っている時はもちろんのこと、サービスを使う前後の体験もデザインすることが大事だと紹介されていました。

![スクリーンショット 2024-10-12 22.35.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3733722/bb3c7f6c-9bbb-c815-3524-c4d66a2424ca.png)

自分はこれに関しては全くできていませんでした。

この機能を作りたいとなったときはその機能のことは考えますが、その機能を使うに至る前後は何も考えていなかったので、より使いやすくするためにも意識していきたいポイントだと思いました。

# おわりに
よくユーザーファーストと言われますが、自分は開発しているとユーザー体験よりもどう実装するかに目がいきがちだなと痛感しました。ただ作るエンジニアではなく、使う人をよりイメージしながら開発できるエンジニアになりたいと思います。
投稿 104 SDN 2024/10/12

本日の勉強時間　6H

ネットワークをソフトウェアの設定だけでネットワーク機器を制御できるSDNは、ネットワーク構成を仮想化する技術です。 複数のネットワークを保有していたとしても、1つのネットワークとして物理統合を行うことで、複雑なパケットの制御やハードウェア単位で行われるシステム設定を集約できる。
関数に引数を指定し、main関数内で文字列を指定して出力する

例1
```
public class Main{
    public static void main(Srting[] args) {
        letters(str: "ABC"); // 出力したい文字列1
        letters(str: "DEF"); // 出力したい文字列2
        letters(str: "GHI"); // 出力したい文字列3
        letters(str: "JKL"); // 出力したい文字列4
        letters(str: "MNO"); // 出力したい文字列5
    }

    public static void letters(String str){
        System.out.println(str); // 文字列型ということだけ指定
    }
}
```

結果
```
ABC
DEF
GHI
JKL
MNO
```
<br>

例2　複数の型を混ぜて複数の引数を渡すこともできる
```
public class Main{
    public static void main(Srting[] args) {
        multiple(str: "ABC", num1: 1, num2: 2);  // 出力したい文字列 + num1 + num2
        multiple(str: "DEF", num1: 3, num2: 4);  // 出力したい文字列 + num1 + num2
        multiple(str: "GHI", num1: 5, num2: 6);  // 出力したい文字列 + num1 + num2
        multiple(str: "JKL", num1: 7, num2: 8);  // 出力したい文字列 + num1 + num2
        multiple(str: "MNO", num1: 9, num2: 10); // 出力したい文字列 + num1 + num2
    }

    public static void multiple(String str, int num1, int num2){
        System.out.println(str);  // 文字列型ということだけ指定
        System.out.println(num1); // 整数型ということだけ指定
        System.out.println(num2); // 整数型ということだけ指定
    }
}
```

結果
```
ABC
1
2
DEF
3
4
GHI
5
6
JKL
7
8
MNO
9
10
```
<br>

改行を入れたくない場合にはprintlnをprintにする
```
public static void multiple(String str, int num1, int num2){
    System.out.print(str);    // 改行を入れない
    System.out.print(num1);   // 改行を入れない
    System.out.println(num2); // 改行を入れる
}
```
結果
```
ABC12
DEF34
GHI56
JKL78
MNO910
```
.astroファイルでprettierが動かない時の備忘録

## 概要
いつも.astroファイルでprettierがエラーになるので備忘録としてメモします。

## エラー内容
.astroファイルを保存した時、prettierがきかない

## 対策
```terminal:インストールする
npm i --save-dev prettier prettier-plugin-astro
```

```js:ファイル追加する .prettier.mjs
// .prettierrc.mjs
/** @type {import("prettier").Config} */
export default {
  plugins: ['prettier-plugin-astro'],
  overrides: [
    {
      files: '*.astro',
      options: {
        parser: 'astro',
      },
    },
  ],
};
```

ここまでやり、プロジェクト内の適当な.astroファイルを保存してみて動いたら成功 :ok_hand:

## 終わりに
基本的にprettierの公式ドキュメントに書いてあることをやっただけですが、いつも忘れて調べてるので、備忘録として残しました。

#### 公式ドキュメント

https://github.com/withastro/prettier-plugin-astro/blob/main/README.md#installation
dirコマンドでファイルパスの一覧を出力する

# dirコマンドでファイルパスの一覧を出力する

```
dir /S /B C:\Path\To\Target
```

実行結果:

```
C:\Path\To\Target\aaa.txt
C:\path\To\Target\DIR1
C:\path\To\Target\DIR1\bbb.txt
C:\path\To\Target\DIR1\DIR2
C:\path\To\Target\DIR1\DIR2\ccc.txt
```

- `/S` : サブディレクトリを再帰的に探索する
- `/B` : パスのみを表示する (見出しを表示しない)

# 対象を指定する

例1. ファイルのみを対象とする。

```
dir /S /B /A-D C:\Path\To\Target
```

例2. フォルダのみを対象とする

```
dir /S /B /AD C:\Path\To\Target
```

- `/A` : 属性を指定する
    - `D` : フォルダのみ
    - `-D` : フォルダ以外 = ファイルの身

例3. 拡張子を指定する

```
dir /S /B /A-D C:\Path\To\Target\*.jar
```


# FORでループする

```
@ECHO OFF

FOR /F %%F IN ('dir /B /S C:\Path\To\Target') do (
  ECHO %%F
)
```

# 環境情報

```
C:\>ver

Microsoft Windows [Version 10.0.22631.4169]
```
脱WPFを目指してWinUI 3 アプリを調べてみた。(その2)、ContentControlの挙動

# はじめに
ContentControlは、WPFで複数の画面をデータに合わせて出し分けるときの肝になるコントロールです。ContentControlがあるお陰で、制作者はDataTemplateとViewModelの組み合わせで画面を出し分けることができます。この機構が無いと予め画面を非表示の状態で置いておいて必要になったら表示状態へ変更するというプログラムを実装する必要があります。ContentControlは、入力されたデータをルールに沿って表示するコントロールですが、プログラムを誤った場合でもクラス名を表示して間違っていることを教えてくれます。試行錯誤しながら実装しているときには、ヒントになることがあります。

# 非常に複雑な挙動
:::note warn
引用
* ContentTemplateにDataTemplateが設定されている場合、ContentプロパティにContentTemplateを適用した結果を表示します。
* ContentTemplateSelectorにDataTemplateSelectorが設定されている場合、ContentプロパティにContentTemplateSelectorが返したDataTemplateを適用した結果を表示します。
* Contentプロパティに設定された値の型に紐づけられたDataTemplateがある場合、そのDataTemplateを適用した結果を表示します。
* ContentプロパティがUIElement型の場合、そのまま表示されます。（UIElementにすでに親がいる場合は例外が出ます）
* Contentプロパティに設定された値の型に紐づけられたTypeConverterでUIElementに変換するものがある場合は、変換した結果を表示します。
* Contentプロパティに設定された値の型に紐づけられたTypeConverterでString型に変換するものがある場合はString型に変換してTextBlockにラップして表示します。
* Contentプロパティに設定された値の型がXmlElementの場合は、InnerTextプロパティの値をTextBlockにラップして表示します。
* Contentプロパティに設定された値をToStringした結果をTextBlockにラップして表示します。
[WPF4.5入門 その47 「コンテンツモデル」](https://blog.okazuki.jp/entry/2014/08/25/164331)
:::
かずきさんのブログでも説明されているように、WPFのコンテンツモデルは非常に複雑怪奇です。
WinUI3の設計者もそう思ったのか、簡略化されているようです。
DataTemplateに、x:DataTypeを設定してContentプロパティに、ViewModelをバインディングしても対応したDataTemplateが表示されません。
もしかすると実装方法が間違っている可能性もありますが、検索してもDataTemplateSelectorを利用して出し分ける方法しか見つかりませんでした。
動作パフォーマンスを最適化する目的で意図的に簡略化しているのかも知れませんね。
画面数が多いとDataTemplateSelectorで実装するのは面倒なので、回避方法が欲しいところです。
Application.Current.Resources["リソース名"]で、リソースが取得できるはずなので、ContentTemplateSelectorに実装して試してみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/7839/4a72a0c0-1e9f-e714-3e66-26df7e8d51fd.png)

うむむ。。。「エラーを特定できません」という例外が発生してしまいました。
Java Gold SE11対策 ネストしたクラスシリーズ② staticインナークラスについて

前回の記事 
[Java Gold SE11対策 ネストしたクラスシリーズ①インナークラスについて](https://qiita.com/hiroki1994/items/8f717157838e05169449)
の続きとして本記事では「static インナークラス」についてまとめていく。

## インナークラスをstaticで修飾したものがstaticインナークラス

インナークラスは外側のクラス「エンクロージングクラス」のメンバであるので、
エンクロージングクラスをインスタンス化しないと利用することができないという制約がある。

この制約のために、例えばエンクロージングクラスに引数を受け取るコンストラクタがあって、そのエンクロージングクラスの中にあるインナークラスがあるとする。
自分はそのインナークラスに用がある場合、用のないエンクロージングクラスをインスタンス化せねばならない。
更にエンクロージングクラスのコンストラクタの引数を具体的にどうするかも特に決まっていないとしたら、意味のない適当な値あてがうという粗末な処理を書くことになる。

この「 **エンクロージングクラスをまずインスタンス化しなくてはならない** 」という制約から解放してくれるのがこの **staticインナークラス** である。

 **staicインナークラスのインスタンス化にはエンクロージングクラスのインスタンスは不要なのだ。**

## staticインナークラスのインスタンス化

インナークラスとstaticインナークラスのインスタンス化の違いを見比べてみよう。

まずは普通のインナークラスだ。
OuterクラスにInnerというインナークラスが実装されている。
```Outer.java
public class Outer {
    class Inner {
        // 何らかの処理
    }
}
```

これをインスタンス化するには下記のようにエンクロージングクラスであるOuterクラスをインスタンス化しなくてはならない。


```Main.java
public class Main {
    public static void main(String args){
        Outer outerClass = new outer();
        Outer.Inner innerClass = outerClass.new Inner();
    } 
}
```

このinnerクラスをstaticに変更する。

 ```Outer.java
public class Outer {
    public static class Inner {
        // 何らかの処理
    }
}
```

static修飾子がつけられたinnerクラスのインスタンス化は下記のようにエンクロージングクラスのインスタンス化は行わない。

```Main.java
public class Main {
    public static void main(String args){
        Outer.Inner innerClass = new Outer.Inner();
    } 
}
```

## エンクロージングクラスのフィールド/メソッドへのアクセス

下記のようなstaitcインナークラスを実装したクラスがあるとする。


staticインナークラスからエンクロージングクラスのstaticなフィールド/メソッドと非staticなフィールド/メソッドにアクセスすると次のようになる。 


エンクロージングクラスのstaticなフィールド/メソッドへのアクセス→ **正常に処理される** 

エンクロージングクラスの非staticなフィールド/メソッドへのアクセス→ **コンパイルエラーになる** 

```Outer.java
public class Outer {

    //staticなフィールド変数
    public static String birthday = 19490914;

    //非staticなフィールド変数
    public int age = "75";

    //staticなメソッド
    public static void staticMethodExample(){
        System.out.println("staticメソッドですよ");
    }

    //非staticなメソッド
    public static void notStaticMethodExample(){
        System.out.println("非staticメソッドですよ");
    }
    
    //staticインナークラス
    public static class Inner {
        
        //問題ない
        System.out.println("誕生日は" + birthday);

        //コンパイルエラーになる
        System.out.println("年齢は" + age);


        //問題ない
        Outer.staticMethodExample();

        //コンパイルエラーになる
        Outer outerclass = new Outer();
        outerclass.notStaticMethodExample();
    }
}
```

staticで修飾されたものは **クラスがロードされたタイミング** で **static領域** に配置されるのに対し、非staticのものは **インスタンス化されたタイミング** で **ヒープ領域** に配置される。

使用可能なタイミングも、配置されるメモリの領域も異なるためにこうした制約があるのだ。

## 

次回はローカルクラスについてまとめる。
015 AI屋さんの　LLMに２００万トークン全文入力と「ずんだもん」と私　実践編


AI屋さんの　LLMに２００万トークン全文入力と「ずんだもん」と私　実践編

LLMとvoicevoxとstreamlitとdockerとcloud runで
LLMに２００万トークン全文入力　追加学習ずみの専門分野特化のLLMの作り方


まずは、ずんだもん先生のための　voicevox サーバーを建てましょう
中身は、pythonの　fastAPI　で出来ています。


いくつか方法がありますが、簡単です。
dockerコマンド一発です。

docker run -d -p 50021:50021 voicevox/voicevox_engine 

イメージ図

![スクリーンショット 2024-10-12 20.15.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237930/87643bdf-fb05-104a-eebd-c172fd5162eb.png)


すると、ローカルにサーバーが完成します。
動作確認でポートを開きます。

http://localhost:50021/docs

fastAPI　ですので、取説サイトを見れます。
次は、動作確認です。

下記コマンドを実行します。
公式　取説参照


echo -n "こんにちは、音声合成の世界へようこそ" >text.txt

curl -s \
    -X POST \
    "127.0.0.1:50021/audio_query?speaker=1"\
    --get --data-urlencode text@text.txt \
    > query.json

curl -s \
    -H "Content-Type: application/json" \
    -X POST \
    -d @query.json \
    "127.0.0.1:50021/synthesis?speaker=1" \
    > audio.wav



無事に、音声ファイルが出来ていれば
ずんだもん先生の完成です。
簡単でしたね。
おめでとうございます。

まずは、動く環境を構築できました。

　→voicevox　ローカル（今回ここ）
　→pythonで　実行
　→voicevox　クラウド
　→pythonで　実行
　→streamlit　クラウド
　→完成
 
一番の難関を　今回クリアできました。
あとは、ちょいと足していくだけですし
基本的にはdocker イメージを作ってから　クラウドのサーバーレスでデプロイするだけです。
既知の内容です。

第十一回：AI屋さんの　dockerでWebアプリをクラウドデプロイ　実践編

https://qiita.com/bono0/items/c9c7add64cb3c593f776

https://
qiita.com/bono0/items/c9c7add64cb3c593f776

  

参照　voicevox　公式

https://voicevox.hiroshiba.jp


https://hub.docker.com/r/voicevox/voicevox_engine


https://github.com/VOICEVOX/voicevox_engine





目次

https://qiita.com/bono0/items/dc1d000c98af7e07c9a7

https://
qiita.com/bono0/items/dc1d000c98af7e07c9a7


今回も、無事に　ローカルずんだもん先生　をお迎えできました。
　AI屋さんの　LLMに２００万トークン全文入力と「ずんだもん」と私　実践編
完成です。おめでとうございます。
まずは、たっぷり、LLMとお喋りしてください。




ー続くー
[Python] JSONファイルに日本語をそのまま出力したい

# 背景と課題
```python
with open('test.json', 'w', encoding='utf-8') as json_file:
    json.dump("あいうえお", json_file)
```
上記のように日本語のテキストをJSONファイルに出力したのち、JSONファイルを開くと下記のように出力された。

"\u3042\u3044\u3046\u3048\u304a"


このように、\uから始まる形式を「**Unicode Escape Sequence**」(以降、UESと呼ぶ)というらしい


# 対応策
- json.dumpの引数にensure_ascii=Falseを設定する
```python
with open('test.json', 'w', encoding='utf-8') as json_file:
    json.dump("あいうえお", json_file, ensure_ascii=False)
```
40代 システム保守11年目の目標

# はじめに
40代 システム保守11年目になりました。
2025年までの目標をまとめました。
現職に入社して4年半弱になりました。来年も引き続き現職で頑張ろうと思います。

## 目標
### 構築の経験を積む
システム移行に伴い実務で構築の経験が積めることになりました。
私にとってはチャンスです。失敗を恐れずに挑戦しようと思います。
**システムで不明点があれば聞きながら、自分で細部まで調べて対応することが大事**

### 非定型の運用保守の経験を積む
システム運用保守の経験が長く、定型作業よりのためより作業手順書を求めるような思考になっています。
**各環境のシステムをより理解して作業手順書を作成する様にする**
**だろうと思ったら注意です。憶測で作業になります。**


# 計画
### Qiitaは技術よりの記事を増やす
現在、学習計画やキャリアについて記事を書いていますが
**今後は実務で学んだ技術のことや躓いたことで解決できたことを記事にします**

### zabbixの知識を増やす
**1日1個目標にzabbixの機能について調べる**
**会議で会話したzabbixの内容をメモして復習する**

### その他
休日に見る
AWS　障害対応の知識を増やす

https://www.udemy.com/share/10bUmj3@BJTLGBSQR2QtLV3G6pnOUH9jq2yjbgSxAnGE76xJ8QFxwUUX5vlZw4IljmtXFmd3CA==/


Linux再入門―カーネル、シェル、ファイルといった基本概念を理解してトラブル

https://www.udemy.com/share/108DCq3@cB1-2Fv6bjAOmoVHFmiDCz9cJwHYCtXvfuPTRB_l9Hf_HAQQJO8k2JQovWt9Bh2PjQ==/


【ひぐま流】ソフトウェア開発入門講座～要件定義や設計などのソフトウェア開発工程を幅広く学び、成長するための土台を築こう～

https://www.udemy.com/share/10aZJi3@fYCoyTx3EYz1AvqLvvpBirAPnkY7A_UlEOcRC7owdXAjGGWVUf1okHO-HqaiMyosLA==/



## AWSの資格を更新
**AWS試験は以下で取得して今はアソシエイト3冠となりました**
引き続き上位資格を取得をしていきます。
SOA　2023-09-04合格
DVA　2024-05-10合格
SAA　2024-09-27合格

AWS上位資格が失効中です。更新しております。

### 2024年12月　SCS 合格　失効
12月に受験する。

**whizlabs 模擬試験65問**
https://www.whizlabs.com/

**休日に以下の問題を理解しながら解く**

以下は65問です
Practice Test I
Practice Test I
Practice Test III
Practice Test IV

**平日 以下の問題を朝に１日5問解く**
WEB問題集を解く。#62問　

whizlabsの模擬試験をすべて復習出来たら
休日にWEB問題集の問題を解く

#### 2025年 3月 SAP 合格 失効
勉強方法を模索中　
また更新します。

#### 2024年 5月 GCP CDL 更新 受験 2025年 5月受験 2025年11月有効期限
勉強方法を模索中　
また更新します。

#### 2024年 8月 GCP ACE  更新 2025年8月受験　 2026年2月有効期限

勉強方法を模索中　
また更新します。

### まとめ
仕事が激務であまり勉強ができないですが、少しづつ対応します
**平日は1日5問問題なく、zabbix1機能を調べる**
**休日 Udemy見たり、模擬試験問題を解く**
#### 少しづつでも学習継続してQiita技術記事投稿の継続、AWS資格の再取得、zabbixの学習をしようと思います
【基本情報】独学マラソン プロトコル Day 12

集めた物は残らず、与えたものが残る

:::note worn
この記事は自分用の備忘録です。
:::

# プロトコルって何回聞いても忘れちゃうので

### プロトコルって？
- 通信するための共通の決まり事

### なんで決まり事が必要？
- ルール決めないと相手が何を言っているのかわからないから通信できない

### どんな決まり事がある？
- IP (Internet Protocol)
    - どこに送るかを決めるための住所の管理を担当
    - 例：192.168.1.1のようなIPアドレスを使ってデータを送り先に届ける

<br>

- TCP (Transmission Control Protocol)
    - データが欠けずに順番通り届くように管理するプロトコル
    - 例：ウェブページやメールのデータを正確に届ける

<br>
 
- UDP (User Datagram Protocol)
    - TCPよりも高速だが、少しのエラーを許容するプロトコル
    - 例：ビデオ通話やオンラインゲームなど、遅延が致命的な場面で使う

<br>

- HTTP/HTTPS（Hypertext Transfer Protocol / Secure）
    - ウェブブラウザでウェブページのやり取りを行うプロトコル
    - HTTPSは暗号化された通信を行うバージョン


# 自宅のPCからWEBページを閲覧するまでの通信の流れ

### 1. **URLを入力してリクエストを作成する（アプリケーション層）**
- ブラウザ（ChromeやSafariなど）で `https://example.com` と入力
  - ブラウザは**HTTPリクエスト**（データを取得する命令）を作成
    ```
    GET /index.html HTTP/1.1
    Host: example.com
    ```
    <br>

### 2. **TCPがデータを分割（トランスポート層）**
- HTTPリクエストは、**TCPプロトコル**を使ってパケット（セグメント）に分割される  
- 各パケットには次の情報が付加される
  - **シーケンス番号**（順番を管理する番号）
  - **ポート番号**：宛先はサーバーの**80番ポート**（HTTP用）  
- これで「順番通りに」「エラーなく」パケットが届くよう、準備が整った状態

<br>

### 3. **IPアドレスを使った宛先の指定（ネットワーク層）**
- ブラウザはDNS（名前解決）を使って、`example.com` を**IPアドレス**に変換  
  - **DNS問い合わせの結果**：`example.com → 93.184.216.34`
- IPパケットの宛先には、この**93.184.216.34**（example.comのサーバー）を指定
  - 送信元IP：`192.168.0.10`（自宅PCのIPアドレス）
  - 宛先IP：`93.184.216.34`

<br>

### 4. **パケットをフレームにカプセル化する（データリンク層）**
- パケットに**MACアドレス**を追加して「フレーム」という形式に変換
  - **送信元MAC**：自宅PCのネットワークカード（NIC）のMACアドレス  
  - **宛先MAC**：ルーターのMACアドレス  

<br>

### 5. **LANケーブルやWi-Fiで信号を送信（物理層）**
- フレームは**電気信号**（LANケーブルの場合）や**電波**（Wi-Fiの場合）に変換され、自宅ルーターに送信される
    - 0,1のバイナリデータになる
        - wifiの場合は周波数の違いで0,1を表すらしい

<br>

### 6. **ルーター経由でインターネットへ（経路選択）**
- ルーターは、フレームから**IPパケット**を取り出し、宛先が `93.184.216.34` であることを確認
- その後、**インターネット（WAN）側のゲートウェイ**にパケットを送信
  - この経路では、いくつかのルーター（中継機）を通り、最短経路を使って目的地に向かうらしい

<br>

### 7. **サーバーが応答を返す**
- 目的地である`93.184.216.34`（example.comのサーバー）にパケットが届く
    - 物理層、データリンク層、ネットワーク層、トランスポート層と下位層から登っていく感じ
- IPプロトコルとTCPプロトコルを使って分割されたパケットを再構築
    - IPとTCPを使って受信した複数のパケットを元通りに並べ直す
    - TCPのシーケンス番号に基づいて、順番が狂わないように整列
- サーバーのApacheやNGINXといったWebサーバーソフトが、HTTPリクエストを受け取って解釈
    - GET /index.html HTTP/1.1というリクエストが来たら、「index.htmlというファイルを返せ」と理解する
- HTMLデータを取得し、返事の準備
    - 上位層から下位層へ同様の処理を経て送信元のブラウザまで届ける

<br>

### 8. **送信元が受け取る**
- 上記7のサーバーが通信を受け取った流れと同様にしてブラウザまでデータを送る感じ
    - 物理層
        - 電気信号や電波をバイナリに復元し、次の層へ
    - データリンク層
        - バイナリをフレームにして、MACアドレスから自分宛かどうかを確認
        - 自分宛ならIPパケットを取り出し次の層へ
    - ネットワーク層
        - IPパケットからIPヘッダーを読み取り、IPアドレスが自分宛か確認
        - 自分宛のパケットなら、IPヘッダーを取り除き次の層へ
    - トランスポート層
        - TCPプロトコルが、受け取ったセグメントをシーケンス番号順に並べ直す
        - 全てのデータが揃ったら（HTTPレスポンスの形になったら）、次の層へ
    - アプリケーション層
        - ブラウザがトランスポート層からHTTPレスポンスを受け取る
            - HTTPレスポンスを解釈し、HTML、CSS、JavaScriptの処理を開始
                - 画面にウェブページを表示


# 感想
webページ1つ見るだけで非常に複雑な処理をしていることがわかった
パケット通信が途中で途切れてもなんか上手くいったりするのは、TCPのシーケンス番号のおかげだとわかった

# 参考

https://www.itmanage.co.jp/column/tcp-ip-protocol/
関数を定義して呼び出す

例1
```
public class Main{
    public static void main(String[] args) {
        function(); // 関数を呼び出している
    }

    // ここで関数を定義している
    public static void function() {
        System.out.println("Hello!");
    }
}
```

結果
```
Hello!
```

mainはmain（変えられない）
String[] argsは、配列の型と配列名を指定している

function()の部分は自分で任意の関数名を付けることができる
<br>
例2
```
public class Main{
    public static void main(String[] args) {
        numbers(); // 関数を呼び出している
    }

    // ここで関数を定義している
    public static void numbers() {
        int[] array = new int[]{11, 22, 33, 44};

        // arrayの中身を1つずつ出力する
        for(int value: array){
            System.out.println(value);
        }
    }
}
```
結果
```
11
22
33
44
```
AWS 名前にHubがついているサービスのまとめ

# はじめに
AWSのプラクティショナーの勉強をしていたらHub系の名前がついたサービスがいくつかあったのでまとめておきます。

# 一覧
よく出題される範囲ではこの3つがありました。

- AWS Security Hub
- Cost Optimization Hub
- AWS Migration Hub

それぞれ簡単に紹介します。

# AWS Security Hub

単一のアカウント内だけでなく複数のアカウントをまたがってセキュリティのアラートを集めて一元管理ができるようです。

複数アカウントの指定の方法は以下の２つです。
- AWS Organizationsを使った方法 (推奨)
- AWS Organizationsを使わない方法

上の方法では、AWS Organizationsを使って一元管理されたアカウントを指定できます。
下の方法では、どれかのアカウントを管理アカウントとして、そのアカウントから他アカウントを招待することができます。

# Cost Optimization Hub
こちらもAWSをアカウントをまたがってコスト管理ができるようです。

Cost Optimization Hubは、Billing and Cost Managementの機能の一つなので名前にAWSが付いていません。

<img style="width: 50%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601978/00c7380f-f59e-2067-34d7-f8ba21bb6c6e.png">

# AWS Migration Hub
AWS Migration Hubは、オンプレミス環境からAWSのクラウドへの移行プロセスを管理・監視するためのサービスです。

大規模な移行を実施している際に、リアルタイムに移行状況を把握できます。

こちらは上の２つようにアカウントをまたがって、とかではなく単一のアカウント内を管理するサービスです。

# まとめ
一口にHubといっても、複数アカウントか単一アカウントかのレベルはサービス毎に違うようです。
Hubとくればアカウントをまたがって一括管理、という覚え方はできないようです。
blastengineのC# SDKを使って添付ファイルを追加する

blastengine（ブラストエンジン）はシンプルに使える開発者向けメールサービスを提供しています。何かと面倒なメール配信をシンプルに、かつ確実に送信先へメールを届けられます。

現在、C#向けに、blastengine SDKを開発しています。.NET6以上を対象としているので、macOSを含め幅広い環境で実行できるはずです。

今回は、トランザクションメール（即時配信メール）とバルクメール（一括配信メール）での添付ファイルの送信方法を解説します。

## ユーザ登録する

blastengineにユーザ登録します。管理画面に入るためのユーザID、パスワードが手に入るので、ログインします（ユーザIDは後で使います）。

## 送信元ドメインのSPFを設定する

送信元として利用するドメイン（自分で持っているもの）の設定をします。これは任意のドメイン管理サービスで設定できますが、TXTレコードに以下のSPFを追加します。

```
txt @ v=spf1 include:spf.besender.jp ~all
```

## APIキーを取得する

ログイン後、管理画面の右上にある設定メニューに移動します。

![getting-started-6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/47b2b2ac-2e41-77fe-d84f-0ae0b7541f36.jpeg)

そして設定の中で、APIキーを取得します。

![getting-started-5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2b5ca124-3020-1d39-84e4-911cd4db27e2.png)

## 必要な情報について

SDKを使う上で必要なのは、先ほどのAPIキーとユーザIDになります。

## SDKのインストール

SDKはNuGetでリリースしています。Visual StudioのNuGetパッケージの管理よりインストールしてください。

[NuGet Gallery \| Blastengine](https://www.nuget.org/packages/Blastengine/)

## 初期化

先ほどのAPIキーとユーザIDを使って初期化します。

```csharp
new Blastengine.Client("YOUR_USER_ID", "YOUR_API_KEY");
```

## メールオブジェクトの作成

トランザクション（即時配信）メール、バルク（一括配信）メールオブジェクトを作成します。

```csharp
var transaction = new Blastengine.Transaction();
var bulk = new Blastengine.Bulk();
```

## 必要な情報をセットする

続けて、必要な情報をセットします（トランザクションメールも同様に）。

```csharp
bulk.Subject = "テストメール from C#";
bulk.TextPart = "これはテストメールです to __name__";
bulk.HtmlPart = "<h1>これはテストメールです to __name__</h1>";
bulk.From = new Blastengine.From("info@example.com", "Admin");
```

## 添付ファイルを追加する

添付ファイルは `Attachments` プロパティにファイルのパスをセットします。

```csharp
bulk.Attachments.Add("path/to/file1.txt");
bulk.Attachments.Add("path/to/file2.txt");
```

## 保存する

バルクメールの場合は、 `Begin` メソッドの時に添付ファイルの情報が保存されます。

```csharp
var bol1 = await bulk.Begin();
```

トランザクションメールは、 `Send` で送信した際にそのまま使われます。

```csharp
var bol2 = await transaction.Send();
```

## 宛先データをセットして更新する

バルクメールの場合は、宛先の情報をセットして、更新します。

```csharp
// 置き換えコードあり
bulk.To.Add(new Blastengine.BulkTo("user1@example.jp", new List<Blastengine.InsertCode>() {
	new Blastengine.InsertCode("name", "User1")
}));
// 置き換えコードなし
bulk.To.Add(new Blastengine.BulkTo("user2@example.jp"));

// 宛先を登録
await bulk.Update();
```

## 送信する

バルクメールの場合、送信は `Send` メソッドを使います。引数として、配信予定日時を指定できます。

```csharp
// 即時配信
var res = await bulk.Send();
// 予約配信（10分後）
var res = await bulk.Send(DateTime.Now.AddMinutes(10));
```

## コードについて

コードはGitHubにアップしてあります。ライセンスはMIT Licenseになります。

[blastengineMania/blastengine-csharp: blastengineのC# SDKです](https://github.com/blastengineMania/blastengine-csharp)

## まとめ

blastengineには、他にも1クリックでの購読停止機能や、Webhookなどの仕組みがあります。他の機能も随時実装していきますので、ぜひ皆さんのシステム開発に役立ててください。

[エンジニア向けメール配信システム「ブラストエンジン」](https://blastengine.jp/)
バブルソートを行う

配列の中の数字を小さい数順に並び替えたい時などは、バブルソートを行う

（例）
配列：100, 0, 15, 22, 69, 985, 47

```
public class Exercise {
    public void run(){
        int[] array = new int[] {100, 0, 15, 22, 69, 985, 47};

        // forを使って隣同士の数を比較し、必要に応じて入れ替える
        for(int i = 0; i <= array.length - 1 - 1; i++) {
            for(int j = array.length - 1; j >= i + 1; j--) {
                if(array[j] < array[j - 1]){
                    // tempで一時置き場を作ってarray[j]を一旦置いておく
                    int temp = array[j];
                    // array[j]があったところにarray[j - 1]を置く
                    array[j] = array[j - 1];
                    // array[j - 1]があったところにtempにあるもの（array[j]）を置く
                    array[j - 1] = temp;
                }
            }
        }

        // forを使って並び替え後のarrayの値を1つずつ出力する
        for(int i = 0; i <= array.length - 1; i++){
            System.out.println(array[i]);
        }
    }
}
```

結果
```
0
15
22
47
69
100
985
```
Next.js 14の新機能を徹底解説：最新のアップデートと最適化された開発ワークフロー

### 導入
Next.js 14がリリースされ、最新のWeb開発における重要な改善が数多く追加されました。この記事では、Next.js 14の新機能について徹底的に解説し、開発者にとってどのように有益で、プロジェクトにどのように活用できるかを詳しく紹介します。

### この記事で学べること
- Next.js 14の主要な新機能とその活用方法
- Turbopackによる開発速度の向上について
- ビルドメモリ削減の利点とその活用シーン
- CSS最適化とキャッシュ改善の具体的手法

### 主なアップデート

#### 1. Turbopackの開発向けリリース候補
Next.js 14では、Turbopackの開発向けリリース候補が導入され、開発スピードが劇的に向上しました。これにより、ビルド時間が短縮され、開発者は迅速にフィードバックを得られる環境が整います。従来のWebpackと比較したパフォーマンスの違いについても触れていきます。

**Turbopackの利点**
- ビルド速度が大幅に向上
- 開発環境での即時反映
- Webpackとの比較による効率の違い

#### 2. ビルドメモリの削減
最新バージョンでは、ビルド時のメモリ使用量が大幅に削減されており、大規模なプロジェクトでもより効率的にビルドが行えるようになっています。この改善により、特にリソースが限られた開発環境でもNext.jsの使用が容易になります。

**メモリ削減のポイント**
- 大規模プロジェクトでも快適にビルド可能
- リソース制約のある環境でも対応可能

#### 3. CSSの最適化
新たなCSSの最適化機能により、パフォーマンスが向上しました。特に、CSSのバンドルサイズ削減とキャッシング戦略が改善され、ユーザー体験が一段と向上しています。具体的な実装例やベストプラクティスも紹介します。

**CSS最適化の具体例**
- CSSバンドルサイズの削減
- より効率的なキャッシング戦略

#### 4. キャッシュ改善と新オプション「staleTimes」
Next.js 14では、新たにキャッシュの改善が行われ、「staleTimes」オプションが追加されました。これにより、データフェッチ時のキャッシュの有効期間を柔軟に管理することが可能となり、ユーザーがスムーズに最新データへアクセスできるようになりました。

**キャッシュ管理の改善点**
- 「staleTimes」オプションでのキャッシュ有効期間の柔軟な設定
- スムーズな最新データへのアクセス

#### 5. エラーメッセージの改善
デバッグ時の体験を改善するために、エラーメッセージがさらに分かりやすくなりました。特に、初心者でも理解しやすい詳細なメッセージが追加されており、効率的なトラブルシューティングが可能です。

**改善されたエラーメッセージの特徴**
- 詳細かつ分かりやすい説明
- 効率的なデバッグの支援

### まとめ
Next.js 14は、開発者にとって多くの利点をもたらすアップデートが施されています。特に、Turbopackによる開発スピードの向上やCSS最適化、キャッシュ管理の改善など、現代のWebアプリケーション開発に欠かせない重要な機能が多数導入されています。これらの新機能を活用して、プロジェクトのパフォーマンスをさらに引き上げましょう。

### 次に読むべき記事
次回の記事では、実際にNext.js 14を使って具体的なプロジェクトを構築する方法について解説していきます。興味のある方はぜひお楽しみに！

### 参考リンク
- [Next.js公式サイト](https://nextjs.org/)
- [Next.js 14.2リリースノート](https://nextjs.org/blog/next-14-2)
- [Turbopackについて](https://nextjs.org/docs/turbopack)
useFormが使えない時(Next.js)

Uncaught Error: (0 , react_hook_form__WEBPACK_IMPORTED_MODULE_3__.useForm) is not a function　ってエラーが出たときの対処法




ファイルの先頭に'use client'; を追加したら、Next.jsのクライアントコンポーネントとして指定できる。

Next.js 13以降ではこれを追加しないといけないらしい

![スクリーンショット 2024-10-12 204633.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780514/42ca2574-7e0d-4e81-71ab-057c2e733d61.png)
Python + asyncio でポートフォワーディングをしてみる

ポートフォワーディングといっても、ローカルからローカルに流すやつ。

「あるポートに来た TCP 接続をそのまま別のポートに流す」というやつをやりたくて、まぁそれだけなら `nc` と `mkfifo` を組み合わせたらできるらしいのだけど、それって Python の asyncio で書けるんじゃねえかな？と思って書いてみたらできた、という話。

``` python:port_forward.py
from asyncio import StreamReader, StreamWriter, gather, open_connection, run, start_server
from asyncio.exceptions import CancelledError
from logging import Logger
from typing import NamedTuple


class Addr(NamedTuple):
    host: str
    port: int

    @classmethod
    def parse(cls, addr: str) -> "Addr":
        host, port = addr.split(":")
        return cls(host, int(port))

    def __str__(self):
        return f"{self.host}:{self.port}"


class PortForward:
    def __init__(self, local: Addr, remote: Addr, logger: Logger):
        self.local = local
        self.remote = remote
        self.logger = logger

    async def serve(self, **kwargs):
        server = await start_server(self._handler, *self.local, **kwargs)
        async with server:
            self.logger.info(f"Serving on {self.local}, forwarding to {self.remote}")
            await server.serve_forever()

    async def _handler(self, local_reader: StreamReader, local_writer: StreamWriter):
        try:
            remote_reader, remote_writer = await open_connection(*self.remote)
        except:
            self.logger.exception(f"Failed to connect to remote {self.remote}")
            local_writer.close()
            await local_writer.wait_closed()
            return

        try:
            await gather(pipe(local_reader, remote_writer), pipe(remote_reader, local_writer))
        except CancelledError:
            self.logger.warning("Connection cancelled")
        except:
            self.logger.exception("Connection error")


async def pipe(reader: StreamReader, writer: StreamWriter):
    try:
        while True:
            data = await reader.read(4096)
            if not data:
                break
            writer.write(data)
            await writer.drain()
    finally:
        writer.close()
        await writer.wait_closed()


if __name__ == "__main__":
    import sys
    from logging import basicConfig, getLogger

    basicConfig(level="INFO")

    if len(sys.argv) != 3:
        print(f"Usage:\n  {sys.argv[0]} <local_host>:<local_port> <remote_host>:<remote_port>")
        sys.exit(1)

    try:
        run(PortForward(Addr.parse(sys.argv[1]), Addr.parse(sys.argv[2]), getLogger()).serve())
    except KeyboardInterrupt:
        pass
```

例えばポート 2000 にきた通信をポート 3000 に流したい場合はこう。

``` console
$ python port_forward.py localhost:2000 localhost:3000
```

※ Python 3.9 以上なら動くっぽいことは確認したが、それより古いバージョンだとわからない。

はじめは Transport や Protocol みたいな asyncio の低レベル API を使わないといけないかと思っていたが、これくらいの用途であれば高レベル API だけでいい感じに書けるのだなぁ、という知見を得た。
SwiftUi ポップオーバーを実装

iOS16.4からポップオーバーというものがあるみたいなのでこちら実装して見ようと思います。

こちらの吹き出しみたいな実装です。


![Simulator Screenshot - iPhone 16 Pro - 2024-09-27 at 12.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/18d701d9-ab8a-10f2-b2ec-9ff6549166f8.png)

# サンプルコード
```PopoverSample.swift
struct PopoverSample: View {
    @State private var isShowPopover = false
    
    var body: some View {
        ZStack {
            Button("show popover") {
                isShowPopover = true
            }
            .popover(isPresented: $isShowPopover) {
                PopView()
                    .presentationCompactAdaptation(.popover)
            }
        }
    }
}
```

`sheet`みたいな感じで`popover`実装ができます。
`isShowPopover`で表示非表示を管理してます。
`.presentationCompactAdaptation(.popover)`を設定することで吹き出しみたいな表示になりました。
androidスマホでマイクラのPaperMCサーバを立てて、Java版と統合版クロスプレイできるサーバ作り、外部から接続できるようにする

目指しているのはJava版と統合版クロスプレイできる環境を安価に作る。

楽天モバイルのsimをつけているスマホにTermuxを入れ、そこにUbuntuを入れる。Ubuntuを入れないとインストールできるJavaバージョンが17あたりでPaperMCのpaper-1.20.4-497.jarがエラーになる。Ubuntuを入れたらJava21を入れて他のサイトを参考にしながらPaperMCを入れる。


インストールしたのは
paper-1.20.4-497.jar   Java版マイクラサーバ本体
Geyser-Spigot.jar　　　クロスプレイに必要
floodgate-spigot.jar　クロスプレイに必要
ViaVerSion-5.0.3.jar　マイクラクライアントバージョンチェックを回避するのに必要
　　　　　　　　　　　　(異なるバージョンのJavaマイクラから接続できるようにするもの)

            
このあたりをヒントにほかのサイトでインストールを試みてほしい。

<h3>
ここからがメインの話

楽天モバイルのSIMは10.という内部IPが割り当てられている。これでは他のネットワークから接続できない。そこでlocaltoneというポート転送サービスを利用する。freeプランの場合転送トンネルは1つしか設定できないが、テストはできる。Java版と統合版で使うプロトコルとポートが異なるので、それは調べて設定してほしい。android側はgoogle playからインストールしたlocaltoneのアプリを起動すれば自動的にトンネルを設定してくれる。

Java版はTCP通信で特に苦労なく接続する。
統合版はUDP通信で少し苦労した。
詳しくわからないが<b>自分の楽天モバイルスマホ(ここでマイクラサーバが動いている)へ「同じスマホで動かしているandroid版マイクラクライアント(統合版)」と「楽天モバイルスマホにテザリングしたWindowsPC上の統合版」から「localtoneトンネル経由」での接続はできない。</b>
もちろんスマホのテザリングゲートウェイIP宛てなら接続できる。

試しにWindowsPCを妻のmineoスマホにテザリングに接続したところ<b>「mineoスマホにテザリングしたWindowsPC上の統合版」に接続できた。</b>
UDPの場合そういう仕様なのだろう。

ハマりポイントなのでQuiiaに記録しておく
自己紹介

2023年度新入社員2年目のakiraです。
これからネットワークの学習のためにこちらの学んだことを投稿していきたいと思います。
Qiita自体も初めてのため、自分なりに慣れていきたいと思います。

また、資格ではCCNAを取得しており、CCNPの取得を直近の目標として頑張りたいと思います。

以上、よろしくお願いします。
open3d visualizer 基礎表示



```
-----------
import open3d as o3d
import open3d.visualization.gui as gui
import open3d.visualization.rendering as rendering
import platform


class MainWindow_o3d:
    def __init__(self):
        self._id = 0
        self.window = gui.Application.instance.create_window("open3d visualizer example", 1024, 768)
        self.scene = gui.SceneWidget()
        self.scene.scene = rendering.Open3DScene(self.window.renderer)
        self.scene.scene.set_background([1, 1, 1, 1])
        self.scene.scene.scene.set_sun_light(
            [-1, -1, -1],  # direction
            [1, 1, 1],  # color
            100000)  # intensity
        self.scene.scene.scene.enable_sun_light(True)
        bbox = o3d.geometry.AxisAlignedBoundingBox([-10, -10, -10],
                                                   [10, 10, 10])
        self.scene.setup_camera(60, bbox, [0, 0, 0])

        self.window.add_child(self.scene)

        # 図形描画
        self.func_draw_test()

    def func_draw_test(self):
        self.scene.scene.clear_geometry()  # 画面クリア

        # 点の座標データ
        points = [[0, 0, 0], [10, 10, 10]]
        colors = [[1, 0, 0], [0, 0, 1]]  # 赤、青

        # 点群オブジェクトの作成
        pcd = o3d.geometry.PointCloud()
        pcd.points = o3d.utility.Vector3dVector(points)
        pcd.colors = o3d.utility.Vector3dVector(colors)

        # シーンに点群を追加
        material = rendering.MaterialRecord()
        material.shader = "defaultUnlit"
        self.scene.scene.add_geometry("Points", pcd, material)

        # --- 面の追加 ---
        # 面1 (XY平面) の頂点
        vertices_plane1 = [[0, 0, 0], [10, 0, 0], [10, 10, 0], [0, 10, 0]]
        triangles_plane1 = [[0, 1, 2], [2, 3, 0]]  # 頂点のインデックスで面を作る
        colors_plane1 = [[0, 1, 0]]  # 緑

        # 面1の作成
        mesh_plane1 = o3d.geometry.TriangleMesh()
        mesh_plane1.vertices = o3d.utility.Vector3dVector(vertices_plane1)
        mesh_plane1.triangles = o3d.utility.Vector3iVector(triangles_plane1)
        mesh_plane1.paint_uniform_color(colors_plane1[0])

        # 面2 (YZ平面) の頂点
        vertices_plane2 = [[0, 0, 0], [0, 10, 0], [0, 10, 10], [0, 0, 10]]
        triangles_plane2 = [[0, 1, 2], [2, 3, 0]]
        colors_plane2 = [[0, 0, 1]]  # 青

        # 面2の作成
        mesh_plane2 = o3d.geometry.TriangleMesh()
        mesh_plane2.vertices = o3d.utility.Vector3dVector(vertices_plane2)
        mesh_plane2.triangles = o3d.utility.Vector3iVector(triangles_plane2)
        mesh_plane2.paint_uniform_color(colors_plane2[0])

        # シーンに面を追加
        self.scene.scene.add_geometry("Plane1", mesh_plane1, material)
        self.scene.scene.add_geometry("Plane2", mesh_plane2, material)

        # --- XYZ軸の追加 ---
        # 軸の長さ
        axis_length = 15.0

        # 座標軸を生成
        axes = o3d.geometry.TriangleMesh.create_coordinate_frame(size=axis_length)

        # シーンに軸を追加
        self.scene.scene.add_geometry("Axes", axes, material)


def main():
    gui.Application.instance.initialize()
    MainWindow_o3d()
    gui.Application.instance.run()


if __name__ == "__main__":
    main()
```