OmniAICreator/Qiita-1.07M huggingface dataset:
Expressでhttpsを使用する方法

# はじめに
こんにちは！高校生でプログラミング勉強中のCureSabaです。

今回はTwitchのcallbackサーバーを作成しようと思った際、ERR_SSL_PROTOCOL_ERRORが出てアクセスできなかったのでexpressでhttpsを使用する方法をまとめてみました。
# 証明書作成
今回は開発環境用の自己署名とサーバー用の証明書の２つを作る方法を解説します
## localhost用の証明書
まずはlocalhost証明書からです

opensslがインストールされた環境で下記のコマンドを実行し有効期限１０年の自己証明書を作成します
```shell
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout privkey.pem -out fullchain.pem -subj "/CN=localhost"
```

## サーバー用証明書
環境はubuntuを使用しています
### certbotインストール
今回はcloudflare dnsを使用して認証を行うのでcertbotとcloudflareプラグインをインストールします
```shell
sudo apt-get install certbot
sudo apt-get install python3-certbot-dns-cloudflare
```

### cloudflare tokenの取得
cloudflareダッシュボードの左側からアカウントの管理>アカウント APIトークンを選択し
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690099/b10b1776-5642-4fa1-af8b-9fa687596e77.png)
トークンを作成する>APIトークンテンプレート内のゾーンDNSを編集する>テンプレートを使用する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690099/942442f0-2c5f-4675-af25-bd0f4d4c6593.png)

下記画像のselect部を証明書を取得したいドメインに設定>概要に進む>トークンを作成するからトークンをコピーする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/690099/32c86824-15b7-41f7-82fe-0d5a6c0f9a1b.png)

### APIキーの入ったConfigを作成する
以下のコマンドのAPI TOKENを先ほど取得したトークンに置き換える
```shell
sudo touch /etc/letsencrypt/cloudflare.ini
echo 'dns_cloudflare_api_token=API TOKEN' | sudo tee /etc/letsencrypt/cloudflare.ini
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
```

### 証明書を取得する
以下のコマンドを実行して証明書を取得します
```shell
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -m mail@example.com -d example.com -d *.example.com
```
生成した証明書は`/etc/letsencrypt/live/yourdomain.com`に保存されます

# コード作成
コードを作成していきます
## 元のコード例
```js
const express = require('express');
const app = express();

app.get('/', (req, res) => {
    res.send('Hello World!');
});

const server = app.listen(3000, () => {
    const host = server.address().address;
    const port = server.address().port;
    console.log('Example app listening at http://%s:%s', host === '::' ? 'localhost' : host, port);});
```

## 書き換え
`https.createServer(options, requestListener)`を用いて`https.Server`オブジェクトを作成しその後普段と同様に`listen()`で実行できます
```js
const fs = require('fs');
const https = require('https');
const express = require('express');

const app = express();

// 証明書と秘密鍵を読み込む
const privateKey = fs.readFileSync('path_to_cert/privkey.pem', 'utf8');
const certificate = fs.readFileSync('path_to_cert/fullchain.pem', 'utf8');

const credentials = { key: privateKey, cert: certificate };

// ルートパスへのリクエストに対するレスポンス
app.get('/', (req, res) => {
    res.send('Hello, HTTPS world!');
});

// HTTPSサーバーの作成
const httpsServer = https.createServer(credentials, app);

httpsServer.listen(3000, () => {
    const host = httpsServer.address().address;
    const port = httpsServer.address().port;
    console.log('Example app listening at https://%s:%s', host === '::' ? 'localhost' : host, port);
});
```

# 終わりに
もし、この記事が役に立ったと思ったら、ぜひコメントやシェアをお願いします。また、質問や改善点などがあれば気軽にコメントしてください！

それでは、良いプログラミングライフを！
svgのサイズ調整をしながらviewBoxを理解する

## はじめに
普段Web開発でアイコンを入れたりするとfigmaからsvgをコピーしてコンポーネントの中に入れることってよくありますよね。

先週は、すでにプロジェクト内に存在するsvgをサイズだけ小さくして入れる必要がありました。
そこで、いつものようにfigmaからコピーして入れていたら、レビューで「これはすでにあるやつを再利用したいですね」と提案されました。

今まではsvgを勝手に触ったら形が崩れる経験しかしていなかったため苦手意識がありました。
それが、調べてみたら案外簡単な概念だったためブログとして残したいと思います。

## tl;dr
すでに持っているSVGのサイズだけを変更したい場合、`width`と`height`属性を操作するだけで簡単に実現できます。

しかし、なんでそうなるかを完全に理解するには、`viewBox`の役割も理解する必要があります。

## SVGのサイズ調整の基本

SVGのサイズを調整するには主に2つの方法があります。

1. `width`と`height`属性を直接変更
2. CSSでサイズを指定

どちらの方法でも、SVGの比率を維持しながらサイズを変更できます。
cssで簡単に変えられることは、UIライブラリでwidthなどを指定してアイコンのサイズ調整をしたことがある方なら当然だと思うかもですね。

```html
<!-- 幅と高さを直接指定 -->
<svg width="200" height="100">...</svg>

<!-- CSSでサイズ指定 -->
<svg style="width: 200px; height: 100px;">...</svg>
```

## viewBoxとは何か？

それじゃviewBoxってなんでしょうか？

`viewBox`はSVGのコンテンツを表示するための「ウィンドウ」または「視野」を定義します。

現実世界にものが置かれていても私たちの目に見えるものしか認識できないのと同じく、svgはviewBoxの範囲内のものだけを表示します。

以下のような4つの数値で構成されています。

```
viewBox="min-x min-y width height"
```

- min-x, min-y: 表示領域の左上隅の座標
- width, height: 表示領域の幅と高さ

例えば、`viewBox="0 0 100 50"`で、座標(0,0)から始まって幅100、高さ50のビューポートを定義することができます。

## viewBoxの重要性

`viewBox`を使って、SVGのコンテンツと表示領域との関係を定義することができます。

以下のようなことができます。

1. 縦横比の維持
2. 拡大・縮小の制御
3. 座標の指定

## 実際のユースケース
以下はフレームワーク別のsvgのサイズ調整のやり方の例を残しています。
ご参考までに！

### React

```jsx
import React from 'react';

const IconComponent = ({ width = '24px', height = '24px' }) => {
  return (
    <svg 
      width={width} 
      height={height} 
      viewBox="0 0 24 24" 
      xmlns="http://www.w3.org/2000/svg"
    >
      <path d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" 
        stroke="currentColor" 
        strokeWidth="2" 
        fill="none" 
      />
    </svg>
  );
};

export default IconComponent;
```

### Vue

```vue
<template>
  <svg 
    :width="width" 
    :height="height" 
    viewBox="0 0 24 24" 
    xmlns="http://www.w3.org/2000/svg"
  >
    <path 
      d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" 
      stroke="currentColor" 
      stroke-width="2" 
      fill="none" 
    />
  </svg>
</template>

<script>
export default {
  name: 'IconComponent',
  props: {
    width: {
      type: String,
      default: '24px'
    },
    height: {
      type: String,
      default: '24px'
    }
  }
}
</script>
```

### Svelte

```svelte
<script>
  export let width = '24px';
  export let height = '24px';
</script>

<svg 
  {width} 
  {height} 
  viewBox="0 0 24 24" 
  xmlns="http://www.w3.org/2000/svg"
>
  <path 
    d="M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5" 
    stroke="currentColor" 
    stroke-width="2" 
    fill="none" 
  />
</svg>
```

## おわりに
こういう知識を知っているだけで開発するとき時間節約に繋がることを感じるので、色々な分野をもっと勉強していきたいですねー
Pythonでクラスを用いたグラフの実装と幅優先探索

# はじめに
最近、競プロを始めました。現在AtCoderで茶色です。

競プロの勉強をする中で、必ず出てくるのがグラフ（ネットワーク）の実装です。
よくある実装としては隣接リスト表現といって、ノードの番号を入れ子のリストに格納する方法があります。
ただ僕にとっては、その実装は直感的ではないと感じました。せっかくオブジェクト指向の言語を使っているのだから、グラフもクラスを使って表現したいと思ったのです。

そこで、僕がいつもやっているクラスを用いたグラフの実装方法について書いてみたいと思います。言語はPythonです。

# よくあるグラフの実装：隣接リスト
たとえば、こんなグラフを表現したいとします。
```mermaid
flowchart LR
    id0((0))
    id1((1))
    id2((2))
    id3((3))

    id0 <--> id1
    id1 <--> id2
    id3 <--> id1
    
```
隣接リスト表現を使うと、こんな感じになるかと思います。

```python
G = [
    [1], # 頂点0の隣接頂点は1
    [0, 2, 3], # 頂点1の隣接頂点は0, 2, 3
    [1], # 頂点2の隣接頂点は1
    [1], # 頂点3の隣接頂点は1
]
```

# クラスを用いたグラフの実装
次に、クラスを用いた実装をしてみます。まず、頂点を表すためにこんなNodeクラスを用意します。
```python
class Node:
    def __init__(self) -> None:
        self.neighbors: list[Node] = [] # 隣接頂点のリストをアトリビュートとして持つ
```
そして、上記のグラフはこのように表現できます。
```python
nodes = [Node() for _ in range(4)]
nodes[0].neighbors = [nodes[1]] # 頂点0の隣接頂点は1
nodes[1].neighbors = [nodes[0], nodes[2], nodes[3]] # # 頂点1の隣接頂点は0, 2, 3
nodes[2].neighbors = [nodes[1]] # 頂点2の隣接頂点は1
nodes[3].neighbors = [nodes[1]] # 頂点3の隣接頂点は1
```
これで、各頂点オブジェクトのアトリビュートを見るだけで、隣接頂点が分かるようになっています。
# 幅優先探索の実装
これを使って、幅優先探索を実装してみます。
例題として、書籍『[競技プログラミングの鉄則](https://book.mynavi.jp/ec/products/detail/id=131288)』にある以下の問題を解いてみます。

https://atcoder.jp/contests/tessoku-book/tasks/math_and_algorithm_an

>$N$頂点$M$辺の無向グラフが与えられます。各頂点には$1$から$N$までの番号が付けられており、$i$番目の辺は頂点$A_i$と頂点$B_i$を結んでいます。$1$以上$N$以下の全ての整数$k$について、以下の問いに答えてください。
頂点$1$から頂点$k$まで、辺を何本かたどって移動することを考えるとき、たどるべき辺の本数の最小値を出力せよ。ただし、移動不可能な場合は$−1$を出力せよ。

まず、頂点を表すNodeクラスを用意します。頂点0からの距離もこのクラスのアトリビュートとして持たせます。
```python
class Node:
    def __init__(self) -> None:
        self.neighbors: list[Node] = []
        self.distance = -1  # 頂点0からの距離。ただし-1で初期化
```
続いて、標準入力を読み取ってグラフを構成します。
```python
# 標準入力から頂点の数Nと辺の数Mを取得
N, M = map(int, input().split())

# 頂点をN個用意
nodes = [Node() for _ in range(N)]

# 標準入力からM個の辺の情報を取得してグラフを構成
for _ in range(M):
    # 結ぶ頂点の番号a, bを取得
    a, b = map(int, input().split())
    # 頂点リストは0番から始まっているので、-1してインデックスを調整する
    a -= 1
    b -= 1
    
    # 頂点aの隣接頂点リストに頂点bを、頂点bの隣接頂点リストに頂点aを加える
    nodes[a].neighbors.append(nodes[b])
    nodes[b].neighbors.append(nodes[a])
```

そして、幅優先探索の実装は以下のようになります。
```python
# キューの定義
d: deque[Node] = deque()

# キューに0番目の頂点を追加
d.append(nodes[0])

# 0番目の頂点の距離を0で初期化
nodes[0].distance = 0

# 幅優先探索：キューが空になるまで以下の処理を行う
while d:
    # キューから頂点を取得
    node = d.popleft()
    # 各隣接頂点について処理を行う
    for neighbor in node.neighbors:
        # 距離が未確定（-1）であれば距離を確定し、キューに入れる
        if neighbor.distance == -1:
            neighbor.distance = node.distance + 1
            d.append(neighbor)

# 出力
for node in nodes:
    print(node.distance)

```
隣接リスト表現を使う場合は、隣接リスト自体に距離の情報を持たせることができないので、距離を格納するための変数を別途用意する必要があります。
一方この実装だと、距離の情報も頂点オブジェクト自身に持たせることができます。隣接頂点情報の取得も含めて、より直感的なコードになっているのではと思っています。

参考：隣接リスト表現による実装例（『競技プログラミングの鉄則』サポートページより）
https://github.com/E869120/kyopro-tessoku/blob/main/codes/python/chap09/answer_A63.py

# おわりに
競技プログラミングはその場限りで動くコードを書けばよいので、わざわざクラスを定義する人は少数派だと思います。ただ個人的には、クラスを定義することにより考えを整理でき、結果的に早く問題を解けることも多いように感じています。
だれかの参考になれば幸いです。
【HoI4 MOD開発】Crisis of the Empireを作る！#0

HoI4の19世紀MODを制作中！
「Crisis of the Empire」 は、HoI4の世界を19世紀に置き換える大型MOD です！
開始年を1820年に変更し、ナポレオン戦争後のヨーロッパ・特にバルカン・中東を舞台に、新たな歴史を体験できるようにすることを目指しています！

「もし、オスマン帝国がギリシャ独立戦争に勝ったら？」
「もし、オスマン帝国がムハンマド・アリーに勝ったら？」
そんな "IFの歴史" を楽しめるようなMODにしていきたいと考えています！

現在の進捗状況
MOD制作はまだ始まったばかりですが、まずは地図データの作成 に取り組んでいますが、色々苦戦しています。
バニラのマップを活用しながら、新しい国家や州の追加を進める予定です。

また、最終的には以下の要素を追加したいと考えています。

1820年時点の国家・技術・軍事バランスの再構築
新たな国家イベントやディシジョン
19世紀の軍事ユニットの追加（フリントロック銃兵、帆船艦隊 など）
歴史上の重要な戦争や革命を再現するシステム

ただ、現在は 開発メンバーが自分だけの状況です、、、

一緒にMODを作ってくれる仲間を募集しています。
「MOD開発に興味がある！」
「HoI4の改造をやってみたい！」
そんな方は、ぜひ開発に参加してみませんか？

特に以下のような分野で協力してくれる方を探しています！

地図データ編集ができる方（州の追加、地形設定 など）
イベント・ディシジョンのスクリプトが書ける方
歴史に詳しく、データ設定を考えられる方
GUI（UIデザイン）や3Dモデル作成に興味がある方

HoI4のMOD開発経験がなくても大丈夫です！
「一緒に学び、作っていく」というスタンスなので、初心者の方も大歓迎！

興味のある方は、Discord に参加して、気軽に話しましょう！

こちらから→https://discord.gg/8dBrqPPM

これからの開発記事について
このシリーズでは、MOD開発の進捗や、HoI4のMOD制作に関する知識を発信していきます！
「MODの作り方が知りたい！」という方にも役立つ情報を共有できればと思っています。

次回の #1 では地図に関しての勉強して、「地図データの編集方法」 について書く予定です！

ぜひフォロー＆チェックをお願いします！

一緒に19世紀のHoI4を作り上げましょう！

ちなみに、Qiitaの規約に配慮していますが、問題があればご指摘ください！
ReactDockerとGoogle Cloud SDKを使用したデプロイ方法

ポートフォリオをサイトにアップしたいと思い、コストがかからないサーバーを調べたところGoogle Cloud SDKがいいそう。
調査に時間がかかってしまったので、自分用にまとめる。


①準備
以下のツールをインストール
・Docker　https://www.docker.com/
・Google Cloud SDK (gcloud)　https://cloud.google.com/sdk/docs/install?hl=ja

②Google Cloud SDKの登録、課金設定を行う
③Google Cloud SDKのプロジェクトを作成する（コンソールから）

④Dockerfile を作成
作業フォルダの一番上の階層に、「Dockerfile」という名称のファイルを作成する

```Dockerfile
FROM node:18
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
CMD ["npm", "start"]
```
⑤gcloudの認証設定する
gcloud auth login
gcloud config set project [YOUR_PROJECT_ID]

⑥ビルド・デプロイを行う
```sh
gcloud builds submit --tag gcr.io/[YOUR_PROJECT_ID]/react-app
gcloud run deploy react-app --image gcr.io/[YOUR_PROJECT_ID]/react-app --platform managed
```

デプロイ時に、リージョンを選択するが、今回は下記を選択しました。
asia-northeast1



今回初めてサーバーの立ち上げを行いましたが、少し興味が出てきました。
もっと勉強していきたいと思います。
LLMは小数の大小比較が苦手？

## はじめに
LLMが小数の大小比較を苦手としている、という話を耳にしました。
そこで、本当に誤った結果を出すのか、実際に試してみました。
 
## 検証プロンプト
実際に LLM に対し小数の大小比較を行うよう指示し、その回答を検証しました。
```
9.12と9.9、大きいのはどちらですか。
```

## 出力
いくつかのLLMで試してみたところ、GPT-4o、Claude 3.7、Gemini 2.0 Flashが誤った回答をしてしまいました。
### 【不正解】GPT-4o 
```
9.12の方が9.9より大きいです。
```

### 【不正解】Claude 3.7 
```
9.12の方が9.9より大きいです。
9.12 = 9.12
9.9 = 9.90
小数点以下の桁数を揃えてみると、9.12の方が9.90より大きいことがわかります。
```

### 【不正解】Gemini 2.0 Flash 
```
9.12の方が9.9より大きいです。

理由：

小数点の左側はどちらも9で同じです。
小数点の右側を比較すると、12は9より大きいです。
したがって、9.12 > 9.9となります。
```

### 【正解】 o1 
```
小数点以下をそろえて比較すると、9.12 は「9.120」、9.9 は「9.900」と表せます。
この場合 9.120 < 9.900 となるため、9.9 の方が大きいという結論になります。
```

### 【正解】o3-mini 
```
9.9 の方が大きいです。
理由として、9.12 は 9 と 0.12 の合計ですが、9.9 は 9 と 0.9 の合計であり、0.9 の方が 0.12 より大きいため、9.9 の方が大きいと言えます。
```

### 【正解】Gemini 2.0 Flash Thinking Experimental 
```
9.12と9.9ですね。大きいのは 9.9 ですよ。

なぜそうなるか、理由を説明しますね。

小数点以下の数字を比較する

9.12 の小数点以下の部分は 0.12 です。これは100分の12という意味です。
9.9 の小数点以下の部分は 0.9 です。これは10分の9という意味です。
小数点以下の数字だけを比べると、0.12 と 0.9 では、0.9 の方が大きいですよね。

位を揃えて比較する

9.9 を 9.90 と考えると、小数点以下の桁数を揃えて比べやすくなります。

9.12
9.90
この二つを比べると、小数点以下の部分で 12 と 90 を比較することになります。12よりも90の方が大きいので、9.90 (つまり 9.9) の方が大きいと分かります。

別の考え方

9.12 は 9 に 0.12 を足した数、9.9 は 9 に 0.9 を足した数と考えることもできます。

9 + 0.12 = 9.12
9 + 0.9 = 9.9
足している部分を比べると、0.12 よりも 0.9 の方が大きいので、結果として 9.9 の方が大きくなります。

ですから、9.9 の方が 9.12 よりも大きい  ということになります。
```

## 考察
### LLMの誤った比較結果
Gemini 2.0 Flashのケースの場合、誤ったLLMは小数点以下の12と9を比較して、その結果9.12の方が大きいという回答をしていました。
また、Claude 3.7の場合、小数点以下の桁数を揃えたにも関わらず、9.12の方が9.90より大きいという回答をしてしまっています。
### なぜ間違えるのか
LLMが内部的に言語情報を処理する過程で、小数点以下の数値を「整数」として認識してしまった結果、12 と 9 を比較したうえで「9.12の方が大きい」と誤って判断しているという仮説が考えられます。

### 対策
プロンプトに、桁数を揃えたうえで小数であることを留意して計算するよう補足を記載する

## プロンプトを修正して再検証
```
9.12と9.9、大きいのはどちらですか。
小数を比較する際は以下のステップで比較を行ってください

# 小数の比較方法
1. 整数部を比較する
2. 整数部が同じ場合は、小数点以下を桁数を揃えて比較する
```

## 出力
上記の対策を踏まえ、LLM に再度質問したところ、すべてのモデルが正しい回答を出せるようになりました。

### 【正解】GPT-4o
```
9.12 と 9.9 を比較する際、以下のステップで判断します。

1. 整数部の比較
どちらも 9 なので、整数部では同じ。
2. 小数部の比較
9.12 の小数部は .12
9.9 の小数部は .9
小数部の桁数を揃えるため、9.9 を 9.90 と書き換えます。

9.12 → 9.12
9.90 → 9.90
ここで、小数第1位（1 と 9）を比較すると、9.90 の方が大きい とわかります。

したがって、
9.9（9.90）が 9.12 より大きい です。
```

### 【正解】Claude 3.7
```
9.12と9.9を比較します。

整数部を比較:
両方とも整数部は9で同じです。
小数点以下を比較:

9.12は小数点以下が0.12
9.9は小数点以下が0.9または0.90（桁数を揃えると）



小数点以下を比較すると、0.9（または0.90）は0.12より大きいです。
したがって、9.9のほうが9.12より大きいです。
```

### 【正解】Gemini Flash
```
9.12と9.9の大小比較ですね。

小数を比較する際は以下のステップで比較を行います。

小数の比較方法
整数部を比較する
整数部が同じ場合は、小数点以下を桁数を揃えて比較する
今回のケースでは、

整数部はどちらも9なので同じです。
小数点以下を比較すると、9.12は小数点第二位まで、9.9は小数点第一位までなので、桁数を揃えるために9.9を9.90とします。
小数点第二位まで比較すると、9.12と9.90となり、9.90の方が大きいことがわかります。
したがって、9.12と9.9では、9.9の方が大きいです。
```

## まとめ
今回の検証では、LLM が小数の比較を誤る原因として、「小数点以下を整数として扱っている可能性がある」ことがわかりました。

しかし、プロンプトを工夫することで正しい結果を導き出せることも確認できました。
【LangChain】OpenAIをやめてOpenRouterに統一しよ

こんにちは。お久しぶりです。

先日、OpenAIのAPIを久々に実行しようとしたら、クレジットがなくなっていて。愕然としました。
クレジットは1年の制約があったらしい・・・・なんでやねん。

そして、色んなモデルが出てきて、OpenAIだけに執着するのはよくないので、[OpenRouter](https://openrouter.ai/)というサービスを利用することにした。このサービスは、様々なサービスの書き方をインターフェースとして包含してくれるものである。
OpenRouterというサービスを経由するので直叩きより遅くなるが、プライベート用であれば十分だと思う。そして、課金も一括集約されてとても便利。

LangChainを最近触りつつあるんですが、昔はOpenAIで書いていたのでそれをOpenRouterに書き換えたいと思う。
ただそれだけ。

## 手順

1. 初期設定
1. 共通メソッドを作成する
1. LLMを呼び出す

## 詳細

### 初期設定

初期設定は本当に簡単である。

1. pythonの適当なプロジェクトを作成し、下記をpipでインストール
    1. langchain_openai
    1. langchain_core.messages
1. OpenRouterに初期設定を行う。（サインアップ / 初期課金 / API KEYの作成）
1. OPENROUTER_API_KEYという名前で、上記で作成したAPI KEYを環境変数に設定

### 共通メソッドを作成する

下記を共通メソッドとして準備する。
モデルは、[モデル一覧](https://openrouter.ai/models)から好きにデフォルト設定できる。

```llm_util.py
from langchain_openai import ChatOpenAI
from os import getenv

def get_openrouter(model: str = "anthropic/claude-3-sonnet") -> ChatOpenAI:
    """OpenRouter APIを使用してLLMにアクセスするためのChatOpenAIインスタンスを返す

    OpenRouterは複数のLLMプロバイダーへの統一的なアクセスを提供するサービスです。
    直接OpenAIを使用する場合は、ChatOpenAI(model="gpt-4")のように指定することもできます。

    Args:
        model: 使用するモデル名。デフォルトはClaude 3 Sonnet

    Returns:
        ChatOpenAI: 設定済みのChatOpenAIインスタンス
    """
    return ChatOpenAI(
        model=model,
        openai_api_key=getenv("OPENROUTER_API_KEY"),
        openai_api_base="https://openrouter.ai/api/v1"
    )

```

### LLMを呼び出す

後は、このLLMを呼び出す側のメソッドを書くだけでよい。

```main.py
import random
from langchain_core.messages import HumanMessage
from llm_util import get_openrouter

# OpenAIクライアントを使ってOpenRouterにアクセス（モデルは意図的に指定）
model = get_openrouter(model="nousresearch/deephermes-3-llama-3-8b-preview:free")

# 適当な質問をいくつか用意
questions = [
    "もし猫が人間の言葉を話せるようになったら、最初に何を言うと思いますか？",
    "スーパーヒーローの能力を1つ選べるとしたら、どの能力を選びますか？その理由は？",
    "タイムマシンで100年後の日本に行ったら、どんな世界が待っていると思いますか？",
    "もし宇宙人と友達になれるとしたら、一緒にやってみたいことは何ですか？"
]

# ランダムに質問を選んでAIに聞いてみる
question = random.choice(questions)
print(f"質問: {question}\n")

messages = [HumanMessage(content=question)]
ai_message = model.invoke(messages)
print(f"AIの回答:\n{ai_message.content}")
```

簡単に、呼び出すものが作れる。

```bash
質問: もし宇宙人と友達になれるとしたら、一緒にやってみたいことは何ですか？

AIの回答:
宇宙人の友達になりたいなら、次のことがありそうです:

1. 宇宙旅行に行く: もし宇宙人が地球に来ていれば、宇宙旅行に参加して、彼らの故郷を訪ねるのは素晴らしい体験になりそうです。
2. 宇宙人の文化や習慣を学ぶ: 宇宙人が持つ独自の文化や習慣を知ることで、地球人と宇宙人の間でより深い理解を深められると思います。
3. 科学の進歩に貢献する: 宇宙人の知識と技術を活用して、地球上の科学的発見や技術の進歩に貢献できるかもしれません。
4. 平和と協力の促進: 地球と宇宙人の間で平和と協力を促進するために、友好関係を築くことができます。
5. 未来の可能性について議論する: 宇宙人の知恵を受けて、地球の人類の未来に関する考えやアイデアを共有し、発展させていくことができます。
6. 食べ物や料理を共有する: 地球の食文化と宇宙人の食文化を比較することで、両者の間で新しい料理や料理法を見つけ出すことができます。
7. 音楽や芸術を共有する: 地球の音楽や芸術と宇宙人の音楽や芸術を共有し、どちらかが持っていない新しい文化や芸術を発見することができます。

これらのアクティビティを通じて、宇宙人との友情を深め、地球と宇宙人の間でより深い理解を築くことができます。
```


OpenRouterを使うにしても

> from langchain_openai import ChatOpenAI

を使うことが個人的には驚きであった。もしかしたら、本当はもっと正しい書き方があるのかもしれないが・・・。
少なくとも、これで動いたのは確認できた。
初心者でも簡単！ワンオラクルタロット占いで人生の答えを見つける方法

# 初心者でも簡単！ワンオラクルタロット占いで人生の答えを見つける方法

こんにちは、タロット愛好家の佐藤です。今日は私が最近ハマっている「ワンオラクル」というタロット占いについて、体験談を交えながらご紹介します。タロット初心者の方や、毎日の指針が欲しい方に特におすすめの占い方法です！

## ワンオラクルタロット占いとは？

ワンオラクル（One Oracle）は、1枚のカードだけを使った最もシンプルなタロット占いです。「ワン（ONE）」は「1」、「オラクル（ORACLE）」は「神託」や「お告げ」を意味し、1枚のカードを通して神からのメッセージを受け取る方法です。

複雑なスプレッド（カードの並べ方）を覚える必要がなく、タロット初心者の私でも始めやすかったのがこの方法の魅力です。それでいて、深い洞察が得られるのです！


以下は一つの例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907822/8a8700fb-d872-47f5-b353-a677942bbbdc.png)



# ワンオラクル結果 🔮

![魔術師](https://aiuranai.org/api/media/file/01-TheMagician.png)

## 「魔術師」の正位置

---

### 質問:

今日の運勢をおしえて

### 解答:

## 今日の運勢

あなたの質問に対して引かれたカードは**「魔術師」**です。このカードは、あなたの意志の力と創造性を象徴しています。

### カードの意味
- **正位置**の「魔術師」は、意志力、欲望、資源の活用、スキル、能力、集中、具現化を表します。
- このカードは、あなたが持つ潜在能力を引き出し、現実に変える力を持っていることを示しています。

### フォーカスした解釈
- **愛情面**: 「魔術師」は、愛においても具現化を意味します。スキルや創造性、欲望、決意が成功をもたらします。愛を求めているなら、行動を起こし、出会いの機会を作ることが重要です。
- **キャリア面**: あなたの周りにはチャンスがあり、決断を下すことでそれを活かすことができるでしょう。意志とコミットメントがあれば、キャリアでの成功が期待できます。
- **財政面**: 現在、財政的な機会が増えている可能性があります。それを追求するためには、情熱を持って取り組むことが必要です。

### 提案する行動
- 自分の目標を明確にし、それに向かって行動を起こす。
- 新しい出会いの場に積極的に参加する。
- 自分のスキルを磨き、キャリアのチャンスを逃さないようにする。
- 財政的な機会を見逃さず、積極的にアプローチする。
- 自分の内面を整え、外の世界に反映させる。

---

> **あなたは強力な存在です。内なる世界を創造し、外の世界がそれに従うことを忘れないでください。**

このカードは、あなたの可能性を信じ、行動を起こすことの重要性を教えてくれています。

---

*このリーディングは [AI占い - ワンオラクル](https://aiuranai.org/one-orakuru) で生成されました*
*2025/3/2*
React対応のWeb Bluetoothで「NTTドコモF503i（小８付録バージョン）」に接続する

# embot互換のBLE搭載付録

2025年2月28日ごろ発売の小学館スペシャル４月号『小学８年生 はじめてのプログラミング号』には、embot互換のBLEを搭載した付録がついてきます。

https://sho.jp/sho8/80347

Web Bluetoothを使って、付録の「NTTドコモF503i（小８付録バージョン）」に接続できます。

[**Webブラウザーから接続した例（GitHub Pages）**](https://jp-rad.github.io/weblueth-octaechophone/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252891/fe823b5f-b494-4e4d-9c44-4b183e118371.png)

# React対応パッケージ - @weblueth/octaechophone

次のReact対応パッケージを使って、Webブラウザーで動作するアプリを開発できます。

https://www.npmjs.com/package/@weblueth/octaechophone

## サンプルページのコンポーネントについて

このパッケージを使ったサンプルページが、GitHub上で公開されていますが、そのソースコードに含まれているサンプルページのコンポーネントについて説明します。

[`weblueth-octaechophone/pages/app/components/OctaEchoPhoneDevice.tsx`](https://github.com/jp-rad/weblueth-octaechophone/blob/main/pages/app/components/OctaEchoPhoneDevice.tsx)

このコードは、Reactを使用してBluetoothデバイスと通信するためのインターフェースを提供する「OctaEchoPhoneDevice」コンポーネントを定義しています。

### 1. 状態管理
このコンポーネントは `useWbxActor` フックを使用して状態を管理しています。状態は `state` に保存され、 `send` 関数で状態を変更します。

```typescript
const [state, send] = useWbxActor();
const connectionName = state.context.conn.name;
```

### 2. 状態の変更アクション
`reset`、`request`、`connect`、`disconnect` という4つのアクションを定義して、それぞれのボタンに対応させています。

```typescript
const reset = () => send("RESET");
const request = () => send("REQUEST");
const connect = () => send("CONNECT");
const disconnect = () => send("DISCONNECT");
```

### 3. デバイスの接続
Bluetoothデバイスの接続状態を管理し、デバイスの名前を取得するためのハンドラ `onDeviceBound` を定義しています。

```typescript
const [name, setName] = useState<string>(defaultName);
const onDeviceBound: WbBoundCallback<BluetoothDevice> = bound => {
    if (bound.binding) {
        setName(bound.target.name!);
    } else {
        setName(defaultName);
    }
}
```

### 4. Octa Echo Phoneサービス
デバイスからデータを読み取ったり、デバイスの状態を変更するためのハンドラや状態を定義しています。

```typescript
const [octaEchoPhoneService, setOctaEchoPhoneService] = useState<OctaEchoPhoneService | undefined>();
const [cdsValue, setCdsValue] = useState<number | undefined>(undefined);
const [brightnessValue, setBrightnessValue] = useState<number>(0);
const [led0State, setLed0State] = useState<boolean>(false);
// ... 他の状態とハンドラが続きます
```

例えば、CDS（光センサ）の値を読み取るハンドラは以下のように定義されています。

```typescript
const handleUpdateCDS = async () => {
    if (octaEchoPhoneService) {
        const value = await octaEchoPhoneService.readCDS();
        setCdsValue(value);
    } else {
        setCdsValue(undefined);
    }
};
```

### 5. キーパッドの状態
キーパッドの状態を管理し、変更があった場合に更新するためのハンドラを定義しています。

```typescript
const [keypad, setKeypad] = useState<Keypad | undefined>(undefined);
const [keypadText, setKeypadText] = useState<string>(defaultKeyPadText);
const updateKeypad = (keypad: Keypad | undefined) => {
    if (keypad) {
        const binaryString = keypad.value.toString(2);
        setKeypadText(binaryString.padStart(16, '0'));
    } else {
        setKeypadText(defaultKeyPadText);
    }
    setKeypad(keypad);
};
```

このように、このコンポーネントはBluetoothデバイスとの接続と通信を管理し、ユーザーがデバイスの状態を読み取り、変更できるようにするためのインターフェースを提供します。

# おわりに

Web Bluetoothで「NTTドコモF503i（小８付録バージョン）」に接続することができます。
Reactを使ったプログラミングを楽しんでください。
スプリントプランニングを成功させるための具体的な取り組み

# スプリントプランニングを成功させるための具体的な取り組み

スクラム開発において、**スプリントプランニングの質がプロジェクトの成功を左右する** といっても過言ではありません。今回は、スプリントプランニングをより効果的にし、チームの共通認識を強化するために実践した具体的な取り組みを紹介します。

## ✅ バックログをそのまま見せるのではなく、スプリントの目標を明確に伝える

通常、スプリントプランニングではプロダクトバックログのストーリーチケットを順番に確認しながら進めることが多いですが、それだけでは「このスプリントで本当に大事なこと」が伝わりにくいことがあります。

### **📌 取り組み：スプリントのメイン機能を別途資料で説明**
- スプリントで最も重要な機能を**事前にスライドやドキュメントにまとめて紹介**
- 「このスプリントの大きな目標は何か？」をチーム全員で共通認識を持つ
- **デモ予定の資料** があれば開発者が**どう作ればよいデモになるか** を意識できる

🎯 **効果:**
- チームがスプリントの方向性を理解し、**目的意識を持って開発に取り組める**
- **スプリントレビューでのデモの質が向上する**

---

## ✅ ストーリーチケットの説明回を別途実施する

スプリントプランニングだけでなく、**ストーリーチケットごとに別途説明する場を設ける**ことで、開発チームが「なぜこの機能が必要なのか」を深く理解できます。

### **📌 取り組み：チケットの目的と価値を噛み砕いて説明**
- ただの機能説明ではなく、**「今プロダクトが抱えている課題」** から説明を始める
- その機能を追加することで**「どんな価値が生まれるか」** を共有
- デモ担当者は、プレゼンの準備がしやすくなる
- 実装時に**「どのメソッド・クラスを触るのか」**、**「注意点」** も説明することで、スムーズに開発が進む

🎯 **効果:**
- チームの納得感が高まり、**開発中の迷いが減る**
- 「この機能は本当に価値があるのか？」という視点を持ちやすくなる
- **コード設計の方向性が揃い、手戻りが減る**

---

## 🎯 まとめ：スプリントの目標を明確にすることでスクラム開発を加速させる

今回紹介した2つの取り組みを実施することで、
- スプリントプランニング時に「このスプリントで本当に大事なこと」を明確にする
- ストーリーチケットの説明回を通じて、**チームが機能の背景や価値を理解したうえで開発を進める**

このプロセスを回していくことで、**スプリントごとの成果がより明確になり、ステークホルダーやプロダクトオーナーとの信頼関係を強化することができます。**

ぜひ、チームのスクラム運営に取り入れてみてください！

---
【個人開発】Next.jsにHonoを使ってみたくてTodoアプリを作ってみた

こんにちは
今回は、Next.js、Hono、Supabaseを触ってみたくてアプリを作ってみました。まずアプリの紹介を簡単にしたいと思います

## Habitful
https://habit-ful.vercel.app/

人間の習慣化を手助けする目的で作りました。

よくこういうのがあると思います。"明日こそは早起きしよう...!"、"頑張って勉強しよう!"
最初の数日はできてもちょっとしたことで連日の記録が途切れるとその瞬間からもうやらなくなってしまう。

このアプリではどうにかして自信の決めた目的の達成、習慣化を身につけるための手助けをしてあげようというものです。
といっても中身は非常にシンプルです。自信の目的・習慣化しない内容を登録し、毎日それに向けて何をしたかを報告するというものです。ちょっと工夫したのが報告した内容に合わせてAIから応援、励ましのメッセージが送られてくるというものです。

AIとは素晴らしいものです、たとえ達成できなくても彼らは起こりません。次こそ頑張ろうと励ましてくれます
↓これはダイエットを決心したのにコーラを飲んだ私の報告です。
![スクリーンショット 2025-03-02 20.45.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/793703/eb8e530c-c6b9-493b-ae8c-20d2de898099.png)


## 使用技術
- Next.js v15
- Hono
- Supabase
- Drizzle

なんといってもHonoが素晴らしいです。Hono RPCの型推論のおかげで開発者体験が爆上がりです。
自分はよくAPIにはDjango REST frameworkを使っていたのですが、fetchのresponseの型がわからんわ、DRF変更した時にクライアント側の変更忘れるわで結構大変でした。一度Honoを味わっちゃうとDRFに戻れなさそうです。(今度AI関係でDRFでやろうとしているのですが...)

詳しくは↓のブログでも書いておりますので是非是非みていただければと
https://cycle-of-tech.vercel.app/posts

## まとめ
今回はNext.js、Hono、Supabaseを使ってWebアプリケーションを開発しました。しばらくHonoから離れられなそうです。
WEBアプリケーション政策への道#1

初めてのWEBアプリケーション制作の備忘録です
#
今日からWEBアプリケーションを作成していこうと思います。

備忘録なので今現在の状況を簡単に書くと
・Java Silverに何か月か前に気合で合格(理解度は60%位)
・それ以降Javaを本格的に書いていなかったのでほとんどすべて抜けている
・HTMLとCSSは何年か前に触ったきり
・WEBアプリケーションが何なのかも理解できていない

はい、散々ですね。
ここから巻き返しを図っていきます。
#

というわけでそんなこんなで
まず今日からは理解を深めるためUdemyの講座を受講していきます。

1日目の所感としては
・Javaの構文などが曖昧で思い出せない
・HTMLとCSSに関してはあまり問題なさそうなので少し飛ばす
・JSPとサーブレットが全く分からない
・WEBアプリケーションの概要として言っている意味は分かるが理解はできていない漢字が否めない

はい、散々でした。
これからもがんばれ自分。
#0061（2024/02/28）Segment Anything 2 

## 技術的な原理

### モデルアーキテクチャ

Segment Anything 2 (SAM2) は画像・動画の両方に対応した統一的なセグメンテーションモデルであり、主に以下の構成要素から成ります。

- **画像エンコーダ**: 階層型ViT「Hiera」を使用し、高精度な特徴抽出を実現。
- **プロンプトエンコーダ**: ユーザの入力（点やバウンディングボックスなど）をエンコード。
- **マスクデコーダ**: これらの情報をもとにマスクを予測。

SAM2の特徴として、ストリーミングメモリ機構を備えており、動画フレームを順次処理しながら過去フレームの情報を参照できます。初回のフレームで対象物体をユーザがクリックなどで指定すると、そのフレームで得られた物体の**マスク表現（マスクトークン）**が「オブジェクトのポインタ」としてメモリバンクに保存されます。

次のフレーム以降では、現在のフレームの特徴マップに対し、このメモリバンク上のポインタ（過去フレームの物体情報）に**アテンション（Memory Attention）**することで、同じ物体を追跡してセグメンテーションを継続します。

静止画の場合はメモリが空の状態で処理するため、SAM2は**従来のSAMと同様の振る舞い**になります。マスクデコーダはSAM1と同様にトランスフォーマーデコーダ構造ですが、出力解像度向上のために**エンコーダのマルチスケール特徴（ストライド4・8の特徴）**をアップサンプリング時に取り込むよう改良されています。

また、デコーダには**オクルージョン（物体の非可視）検知ヘッド**が追加されており、対象物体が現在フレームで見えているかどうかを予測するスコアを出力します。これにより、一時的に物体が他のものに隠れたりフレーム外に出たりしても、再出現時に途切れず追跡できます。

### 学習方法・データセット

SAM2の学習には、巨大な独自データセットと段階的な学習戦略が採られています。

1. **事前学習**
   - 静止画上でSAM1と同じ「SA-1B」データセット（約11億のマスクを含む大規模画像データ）を使用。
   - 画像エンコーダには自己教師あり手法で事前学習されたHiera（MAEによるプレトレイン済み）を初期値として使用。
   - フォーカルロス＋ダイスロスでマスクを学習。

2. **本学習（fine-tuning）**
   - 新たに構築した大規模動画データセット「SA-V」および関連データでモデルを訓練。
   - SA-Vは51,000本以上の動画と600,000以上のマスクアノテーションから成る。
   - データエンジンを活用し、SAM等のモデルで自動生成したマスクを人間が修正・補完する二段階で効率よくアノテーション。
   - 本学習では、SA-VとSA-1Bの一部サブセット（10%程度）、既存動画データセット（DAVIS、YouTube-VOS、MOSEなど）をミックス。

### 使用技術・ハードウェア要件

- **トランスフォーマーベースのモデル**を採用し、エンコーダには階層ViT（Hiera）を使用。
- メモリ中の過去情報に**クロスアテンション**することで動画セグメンテーションを可能に。
- **GPUによる高速計算**が推奨され、A100 GPU上で約30FPS、B+モデルで約44FPSのリアルタイム処理が可能。
- **Apache 2.0ライセンスのオープンソース**として公開され、開発者が容易に利用可能。

## 適用事例や応用分野

### 想定される活用業界

- **AR/VR（拡張・仮想現実）**
- **ロボティクス**
- **自動運転**
- **動画編集・映像制作**
- **医療画像処理**
- **科学研究（衛星画像解析、細胞画像解析など）**

### 既存の事例・研究

- **Instagram**の画像編集機能（背景差し替えや被写体抽出）。
- **海洋科学**: ソナー画像からサンゴ礁をセグメンテーション。
- **医療分野**: MRIや内視鏡動画での臓器・病変部位の抽出。
- **スポーツ映像解析**: リアルタイムで選手の動きを追跡。

## 競合技術との比較

| **モデル** | **特徴** |
|------------|----------|
| **SAM2** | クラス非依存、画像・動画対応、プロンプト可能なセグメンテーション、リアルタイム処理（30〜44FPS） |
| **SAM1** | クラス非依存、静止画のみ対応、プロンプト可能なセグメンテーション、遅めの処理速度（約21FPS） |
| **Mask R-CNN** | インスタンスセグメンテーション、学習済みクラスのみ対応、静止画向け、動画には非対応 |
| **DeepLabv3+** | セマンティックセグメンテーション、学習済みクラスのみ対応、高精度、リアルタイム化可能（MobileNet版で数十FPS） |

SAM2は、特定クラスの学習が不要であり、画像・動画のどちらでも即座に適用可能な汎用性の高さが特長です。従来のセグメンテーション技術と比較して、

1. **未知の物体にもゼロショットで対応可能**
2. **動画にも対応し、リアルタイムで高精度なセグメンテーションが可能**
3. **オープンソースで提供され、研究・商用利用が容易**

という点で、セグメンテーション技術の新たなスタンダードとなる可能性があります。
【React】Each child in a list should have a unique "key" prop.が発生する

# はじめに
テストコード作成時、表題のエラーが発生しました。動画で学んだなと思いつつ、忘れていたため記事にします。

# 問題
テストコード作成時、テーブル最後の行を取得するように試みたところ、「Each child in a list should have a unique "key" prop.」のエラーが発生

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3993509/ded3cffd-e29d-4981-855d-e499d9063d14.png)

# 解決方法
mapでループして一行ずつレンダリングしている trタグに一意となるkeyを設定する。

※参考動画、ドキュメントより引用
> reactの裏側で動いている仮想DOMの仕組みは、変更前と変更後の差分のみを抽出している。
ループでレンダリングした際に何個目の要素なのかを正確に比較するため、一意となる値の目印をつけてあげる必要がある。

> indexの使用も可だが、非推奨
>>　アイテムが挿入されたり削除されたり、配列の順序が入れ替わったり、アイテムのレンダリング順序は時間の経過とともに変化します。インデックスをキーに指定すると、微妙なバグや混乱を招くことがよくあります。


```diff_jsx:App.jsx
return (
    <>
　　　ー省略ー
    　<div>
      <table>
        <thead></thead>
        <tbody>
          {records.map((record) =>
-            <tr>
+            <tr key={record.id}>
              <td>
                {`${record.title} ${record.time}時間`}
              </td>
              <td>
                <button onClick={() => onClickDelete(record.id)}>削除</button>
              </td>
            </tr>
          )}
        </tbody>
      </table>
      <button data-testid="add" onClick={onClickAdd}>登録</button>
      {error}<br />
      合計時間:{totalTime} / 1000(h)  
      </div>
      }
    </>
  )
}

export default App
```

# おわりに
エラーに出会うことで、改めて基本事項をおさらいできるのはありがたいです。

# 参考

https://www.udemy.com/course/modern_javascipt_react_beginner/learn/lecture/40838780#notes

https://react.dev/learn/rendering-lists#keeping-list-items-in-order-with-key
長期インターンでの失敗談　春休み一人アドカレ6日目

## はじめに
前回の記事で長期インターンをやるメリットと通り方について自分の考えを述べましたが、今回はインターンを通してこうしておけばよかったという後悔を話します。
インターンを始めたばっかりの人やこれからインターンを始める人は、是非反面教師にしてください。


## こうしておけばよかったこと3選+α
### 1.焦らずもっと理解しながら進めるべきだった。
インターンが始まってすぐのとき、わからないことに時間をかけて大丈夫と言われていたのにも関わらず、焦って生成AIに投げたり他のコードを見ながら動かせるものを作ることを優先してしまいました。動く仕組みまで理解していたほうが結果としてそのプロジェクト単位でも理解に時間をかけたほうが早く進みましたし、現在の成長具合ももっと高かったと思います。

多少遅いと思われてもよいのでしっかりと理解しながら進めるべきでした。

### 2.休みを定期的に取るべきだった。
夏休みの間は順調だったのですが、授業が始まってから進み具合が遅くなってしまったのでそれを取り戻そうと躍起になって土日に作業して1日も休みがない状態が2、3ヶ月続いてしまいました。結果として長期休みなどでリバウンドのように二週間ほどやる気が起きずサボってしまうようなことが起こりましたし、体調も崩したりしてしまいました。

毎週1日は休むなど、定期的な休みをいれるべきだったとおもいます。


### 3.一つのことに集中するべきだった。
開発インターンに受かるか半信半疑だったので、メンターのインターンも同時期に受けていました。
ただそのインターンは研修として課題があり、かなり時間がかかるものでした。
インターンに受かって調子に乗り、あろうことか開発インターン中にその課題も行っていました。
そのせいで先に上げたようなコードを理解する時間や休みが取れませんでした。

少なくとも最初のインターンは一つのことに集中して掛け持ちなどはしないほうが良かったと私は感じています。

### おまけ
これはインターンではそこまで重要でないと感じているのでおまけとしました。
それはエンジニアの人以外とももっとコミュニケーションをとるべきだったということです。
社内の人経由で改修の要望が来たときなどにより円滑に聞き取りなどができたと感じています。
実際に就職するときはやはり部署限らず様々な人と接点をっつくっておこうと思いました。


## 反省を活かして
1つめの反省として今まで置いてきしまった分の理解度を上げるため、現在では暇なときにReactやNextのドキュメントを読んだりベストプラクティスに関する記事や動画をみてより細かい部分や仕組みについて理解することを心がけています。

また2つめの反省から遊びや旅行に行ってリフレッシュする時間を予定としてきちんと確保するようにしています。

3つめから今後は学びたいことを一気に集中しておこない、ある程度満足してから他の事を勉強をするようにしていくつもりです。
個人的備忘録：ITスクールのハッカソンに参加して学んだこと＆気づきを、自分なりに記事としてアウトプットしてみた

## はじめに
今年の1月から2カ月間、受講しているITスクールのハッカソンに参加しました。その中で多くのことを学んだので、自分の感想を交えながら記事としてまとめていきます。

:::note info
***ハッカソンでは、5～6人のチームを組み、限られた2カ月間でアプリ開発を行います。***
:::

技術的なスキルだけでなく、コミュニケーションやチーム開発の実践的な経験も得られる貴重な機会です。

今回の記事は主に個人的な感想になりますが、誰かの開発のヒントや励みになれば幸いです。

## そもそも、ハッカソンとは？
ハッカソンは、「ハック（Hack）」と「マラソン（Marathon）」を組み合わせた言葉で、限られた時間内にアイデアを形にする開発イベントです。

https://circu.co.jp/pro-sharing/mag/article/2486/

エンジニアやデザイナーなどがチームを組み、短期間でアプリやシステムを開発します。**技術力やチームワークが求められ、成果物が審査されることも多いです。**

また、新しい技術の習得や交流の場としても活用されています。

## 私にとって、ハッカソンは最高の趣味
私はIT技術が大好きで、夢中になると睡眠時間を忘れるほど没頭してしまいます。

***実際の仕事では調整業務や資料作成が中心だったため、プログラミングやインフラの設計・実装に取り組む時間はとても楽しいものです。***

:::note warn
**私にとって、ハッカソンの活動は最高の趣味になっています。**
:::

今回は、以前から使ってみたかったTerraformをメインのツールとして採用し、インフラのコード化に挑戦しました。

**Terraformについては、以下の記事を参考にしてみてください**

https://qiita.com/yutaroud/items/75915228d787f7b41fed

## うまくいったこと
時間的に余裕を持って、自分の担当する作業を進めることができました。**また、どのような仕組みを使って実装するかを事前にイメージし、計画的に取り組めたのも良かった点です。**

:::note
***特にコンテナ関連については、普段あまり触れる機会がなく、自信もありませんでした。***
:::

しかし、Udemyの動画で事前に学習したことで、スムーズにキャッチアップできました。おすすめの動画は以下になります。**セール中などに購入するのをおすすめします！**

https://www.udemy.com/course/ecsfargate/

## できなかったこと
他の分野、特にフロントエンド部分の理解が少し足りないと感じましたが、今回のハッカソンではその技術のキャッチアップが十分にできませんでした。

:::note alert
**また、最後の発表について、家庭の事情で間に合わなかったのはとても残念でした...。**
:::

***今後はスケジュール管理を徹底し、同じミスをしないよう気をつけたいと思います。***

さらに、コミュニケーションの難しさも痛感しました。専門用語（横文字）を使わずに、どのポジションのメンバーにも分かりやすく伝える工夫が必要だと感じました。

このような課題については、以下の記事にもまとめているので、参考にしてみてください。

https://qiita.com/free-honda/items/3192af32ef7473b31f86

**今回の反省点として、自己管理の徹底と生活リズムの改善を意識していこうと思います。**

特に、睡眠時間の確保と、寝る時間・起きる時間を固定することで、パフォーマンスを維持していきたいと考えています。

## 今回のハッカソンの反省点について

- フロントエンド技術のキャッチアップを強化し、開発全体の理解を深める。  
- スケジュール管理を徹底し、重要な発表や締め切りを確実に守る。  
- 専門用語を使わず、誰にでも伝わりやすいコミュニケーションを意識する。  
- 自己管理と生活リズムを整え、安定したパフォーマンスを維持する。  

## まとめ
ここまで読んでいただき、ありがとうございました。***今回のハッカソンでは、2カ月間にわたりとても楽しくチーム開発を行うことができました。チームの皆様には心から感謝申し上げます。***

:::note info
**最終発表には家庭の事情で参加できませんでしたが、皆様の支えがあり、無事に発表を終えることができて本当に感謝しています。**
:::

今回の経験を通じて、できたこと・できなかったこと、さまざまな反省点が見つかりました。次回のハッカソンでは、それらを意識してさらに成長できるよう頑張りたいと思います。

## 参考文献

https://biz.moneyforward.com/payroll/basic/67248/#:~:text=%E3%83%8F%E3%83%83%E3%82%AB%E3%82%BD%E3%83%B3%E3%81%A8%E3%81%AF%E3%80%81%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%82%84%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9E%E3%83%BC%E3%80%81%E3%83%87%E3%82%B6%E3%82%A4%E3%83%8A%E3%83%BC%E3%81%AA%E3%81%A9%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA,%E5%BD%B9%E7%AB%8B%E3%81%A4%E3%81%A8%E3%81%84%E3%82%8F%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%80%82

https://qiita.com/official-campaigns/hackathon/2024
freebsd-updateした環境でld-elf.soが"Undefined symbol"と怒る場合の対処 一例

# ld-elf.soに怒られた

## 症状  

freebsd-updateした環境で、一部の実行ファイルが動作しませんでした。  

ffmpegの場合。

> $ ffmpeg 
> ld-elf.so.1: /usr/local/lib/libvmaf.so.3: Undefined symbol "_ZTTNSt3__114basic_ifstreamIcNS_11char_traitsIcEEEE"


ccの場合。

> $ type cc
> /usr/bin/cc
> $ cc -v
> ld-elf.so.1: Undefined symbol "_ZTVNSt3__118basic_stringstreamIcNS_11char_traitsIcEENS_9allocatorIcEEEE" referenced from COPY relocation in /usr/bin/cc

ffmpegならともかく、/usr/bin/ccが動かないのはなかなかです。

## 対処  

わたしの場合、以下のファイルを参照できないようにしたら動作するようになりました。

> $ ll /lib/libc++.so*
> lrwxr-xr-x  1 root  wheel    11B Nov 24  2013 /lib/libc++.so@ -> libc++.so.1
> -rwxr-xr-x  1 root  wheel   868K Nov 24  2013 /lib/libc++.so.1*

ふ、古い・・・いかにも怪しいですね

~~~cmd
# mv /lib/libc++.so /lib/libc++.so.del
# mv /lib/libc++.so.1 /lib/libc++.so.1.del
~~~

## 結果

やりました。

> $ ffmpeg
> ffmpeg version 6.1.2 Copyright (c) 2000-2024 the FFmpeg developers
>  built with FreeBSD clang version 18.1.6 (https://github.com/llvm/llvm-project.git llvmorg-18.1.6-0-g1118c2e05e67)
> (以下略)
> $ cc -v
> FreeBSD clang version 18.1.6 (https://github.com/llvm/llvm-project.git llvmorg-18.1.6-0-g1118c2e05e67)
> Target: i386-unknown-freebsd13.4
> Thread model: posix
> InstalledDir: /usr/bin


## 説明

### 環境
2013年のライブラリが残っていたのは、わたしのPCが10.x->11.4へfreebsd-updateしたのち、長いことそのまま運用していたからなのです。(もしかしたら最初は9系だったかも・・・)
そろそろupgradeでもするかぁと12.4に上げたら、12.4もとっくにEOLになっていてpkg updateできず、13.4に上げた次第です。
(もちろん反省しております・・・)

### デバッグ
/usr/bin/ccの由来を実はわかってなかったのですが、FreeBSDの場合/usr/bin以下など基本的なファイルセットは"[base.txz](https://download.freebsd.org/ftp/releases/)"(以下にアーキテクチャ・バージョンごとに置いてある)から展開されるものなのだそうです。
そこで、base.txzを入手し、一時ディレクトリに展開後chrootした環境でcc -vしてみると動く。
一時展開したファイルと、"/" 以下のファイルをcmpで比較したら一部ファイル(ライブラリ含む)で差異があったので、ちょっと乱暴ですが"/" にetc以外を展開してみましたがそうするとcc -vはエラー終了します。(Undefined symbolを喰らいます)

なにか余計なファイルが邪魔していることはほぼ確定です。
そこでお邪魔虫を探すために、chrootして動く環境と、chrootしてない不動環境それぞれで
~~~cmd
# truss cc -v
~~~
を実行し、openしているライブラリの差分を確認すると、動かない方では余計なファイル(/lib/libc++.so)を触りに行ってることを確認しました。

動かない環境では、

> open("/lib/libc++.so.1",O_RDONLY|O_CLOEXEC|O_VERIFY,06) = 3 (0x3)

とOPEN成功していますが、chrootした動く環境には当該ファイルはなくて、

> open("/lib/libc++.so.1",O_RDONLY|O_CLOEXEC|O_VERIFY,06) ERR#2 'No such file or directory'

になってます。(ちなみに新しいlibc++.soは/usr/lib以下にあります)



お作法的にこの対応では色々まずいのだろうとは思いますが、ひとまず手っ取り早く動かすようにはできました。
initやsshdなど、重要プロセスでこのエラーくらわずよかったです。 /usr/sbinや/usr/bin以下はstaticなバイナリのほうが安全かもと思った次第・・・。
Jestで環境変数を読み込めない(React, TypeScript, supabase)


# 問題
Jestで環境変数を読み込めず、エラーになっていました。


# 解決方法
### viteプロジェクトで環境変数(.env)を読み込めるようにする

```vite.config.ts

import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
import tsconfigPaths from "vite-tsconfig-paths";
import envCompatible from "vite-plugin-env-compatible";

// defineConfig 関数を使うと、Viteの設定をオブジェクトとしてエクスポートする際に、型補完やエラーチェックが効く
export default defineConfig({
  plugins: [
// 中略
    // vite-plugin-env-compatibleプラグインを使用して、環境変数(.envで定義)をViteプロジェクトに適用するために使用される
    // Jestでの使用: Viteの環境変数をJestで使用できるようにする
    envCompatible({
      // プレフィックスの指定: 環境変数の前に付ける特定の文字列（この場合はVITE_）を指定
      // セキュリティ: ViteはデフォルトでVITE_プレフィックスが付いた環境変数のみをクライアントサイドのコードに公開
      // 意図しない環境変数がクライアントサイドに漏洩するのを防ぐ
      prefix: "VITE",

      // 環境変数をprocess.env形式で利用できるようにする 例: process.env.VITE_API_KEY として環境変数にアクセスできる
      // 環境変数を process.env にマウントすることで、Node.js 環境で使用されるオブジェクトにアクセスできるようにする
      // サーバーサイドのコードやテスト環境でも同じ環境変数を使用できる
      mountedPath: "process.env",
// 以下略
});
```

``` .env
// sample
VITE_SUPABASE_URL=https://sample.supabase.co
VITE_SUPABASE_ANON_KEY=testtesttest
```

``` .supabase.ts

import { createClient, SupabaseClient } from '@supabase/supabase-js'

//vite.config.tsで設定した方法で、.envから環境変数を取得
const supabaseUrl: string = process.env.VITE_SUPABASE_URL as string
const supabaseKey: string = process.env.VITE_SUPABASE_ANON_KEY as string

const supabase: SupabaseClient = createClient(supabaseUrl, supabaseKey)

export default supabase
```

### Jestから環境変数を読み込めるよう設定
```jest.config.ts

import type { Config } from "jest";

const config: Config = {
// 中略

// setupFilesは、テストコードがそれぞれ実行される前に実行される
// Jestは .env ファイルから環境変数を自動的に読み込むことができない
// setupFiles: ["dotenv/config"]を使用すると、Jestがテストを実行する前にdotenvパッケージを読み込み、.envファイルに定義された環境変数をprocess.envに設定
// テストコード内でprocess.envを使って環境変数にアクセスできるようになる
  setupFiles: ["dotenv/config"],

// 以下略
```

# 終わりに
振り返って改めてコードを確認したところ、Jestで環境変数を読み込む方法の理解ができました。
NeoBERTは「It don't [MASK] a thing if it ain't got that swing」の[MASK]に何を埋めてくるのか

Lola Le Breton, Quentin Fournier, Mariam El Mezouar, Sarath Chandar『[NeoBERT: A Next-Generation BERT](https://doi.org/10.48550/arXiv.2502.19587)』を横目に、[NeoBERT](https://huggingface.co/chandar-lab/NeoBERT)を使ってみることにした。Google Colaboratoryだと、こんな感じ。

```
!pip install -U transformers xformers torchvision
from transformers import AutoTokenizer,AutoModelForMaskedLM,FillMaskPipeline
tkz=AutoTokenizer.from_pretrained("chandar-lab/NeoBERT")
mdl=AutoModelForMaskedLM.from_pretrained("chandar-lab/NeoBERT",trust_remote_code=True)
fmp=FillMaskPipeline(tokenizer=tkz,model=mdl)
print(fmp("It don't [MASK] a thing if it ain't got that swing"))
```

「It don't [MASK] a thing if it ain't got that swing」の[MASK]に何を埋めてくるのか試したところ、私(安岡孝一)の手元では以下の結果が得られた。

> [{'score': 0.9794992804527283, 'token': 2812, 'token_str': 'mean', 'sequence': "it don ' t mean a thing if it ain ' t got that swing"}, {'score': 0.0026010603178292513, 'token': 2342, 'token_str': 'need', 'sequence': "it don ' t need a thing if it ain ' t got that swing"}, {'score': 0.002511243801563978, 'token': 3465, 'token_str': 'cost', 'sequence': "it don ' t cost a thing if it ain ' t got that swing"}, {'score': 0.002277001040056348, 'token': 17042, 'token_str': 'weigh', 'sequence': "it don ' t weigh a thing if it ain ' t got that swing"}, {'score': 0.002097407588735223, 'token': 2965, 'token_str': 'means', 'sequence': "it don ' t means a thing if it ain ' t got that swing"}]

「mean」が98%でダントツなあたり、この英文をNeoBERTは知っているのだろう。ただ、NeoBERTの[model.py](https://huggingface.co/chandar-lab/NeoBERT/blob/main/model.py)には、系列ラベリング(token classification)が見当たらない。https://github.com/chandar-lab/NeoBERT も、今のところリンクが繋がらない。いくら入出力幅4096トークンとは言っても、係り受け解析に使うには情報がなさすぎるのだけど、待てば何とかなるのかしら。
Raspberry Pi 5とDHT-11で温度・湿度を計測する

## 購入したセンサー

下記のキットに温湿度センサーとしてDHT-11が含まれており、それを利用しました。

https://www.amazon.co.jp/dp/B083SJQXCL?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1

## 1. DHT11センサーをRaspberry Piに接続する
この動画のとおりに接続で問題ありませんでした。上記購入先が提供しているビデオチュートリアルです。
ただし、私はRaspberry Pi 5を使用していたので、この動画のプログラムでは動きませんでした。Raspberry Pi 5用のプログラム作成方法については後述します。

https://docs.sunfounder.com/projects/davinci-kit/ja/latest/python_video/video_25_dht11.html

### 必要なもの

> 必要なコンポーネントは、Raspberry Pi、ジャンパーケーブル、DHT11センサー、10k抵抗です。

### DHT11センサーをRaspberry Piに接続する
ピン配置
- DHT11 の VCC ピンを Raspberry Pi の 3.3V に接続
- DHT11 の GND ピンを Raspberry Pi の GND に接続
- DHT11 のデータピン（DAT）を、Raspberry Pi の GPIO 21（BCM番号）など使用していないGPIOに接続

Raspberry Pi以外は上記の購入キットに含まれているはずです。
動画のとおりに接続したらブレッドボード側はOK。

## 2. DHT11用のdtoverlayを設定する

私はRaspberry Pi5を使用したのですが、Raspberry Pi 5は`PRI.GPIO`ライブラリが使えず、Raspberry Pi 4以前までのものと、やり方が少し違います。

下記を参考に進めました。

https://forums.raspberrypi.com/viewtopic.php?t=366269

### 設定ファイルを編集

1. ターミナルを開き、以下のコマンドを入力して `/boot/firmware/config.txt` を編集します。
    
    ```bash
    sudo nano /boot/firmware/config.txt
    ```
    
2. `[all]` セクションのすぐ下に、以下の1行を追加します。（GPIO 21 を使っている例）
    
    ```
    [all]
    dtoverlay=dht11,gpiopin=21
    ```
    
3. `Ctrl + X` → `Y` キーで保存して、エディタを終了します。
4. Raspberry Piを再起動
    
    ```bash
    sudo reboot
    ```
    

## 3. DHT11センサーが認識されているか確認

再起動後、次の手順でシステムがDHT11を認識しているか確認します。

1. ターミナルで以下を入力して、IIOデバイスディレクトリに移動
    
    ```bash
    cd /sys/bus/iio/devices
    ls
    ```
    
2. `iio:device0` のフォルダが表示される場合、DHT11が認識されています。さらに中身を確認します。
    
    ```bash
    cd iio:device0
    ls
    ```
    
    - `in_temp_input`（温度データ）
    - `in_humidityrelative_input`（湿度データ）
    
    といったファイルがあることがわかります。
    
3. 実際に数値が取得できるか試します。
    
    ```bash
    cat in_temp_input            # 温度データ（例: 20000）
    cat in_humidityrelative_input  # 湿度データ（例: 36000）
    ```
    
    これらの値が出力されれば、センサーが正常に動作している証拠です。
    

## 4. Pythonスクリプトで温度・湿度を取得

最後に、PythonからDHT11センサーの値を読み取るサンプルスクリプトを紹介します。

適当なPythonファイル（例: `read_dht11.py`）を作成し、以下のコードを貼り付けて保存します。
    
```python
import time

device0 = "/sys/bus/iio/devices/iio:device0"

# ファイルの先頭行を読み取って整数値を返す関数
def readFirstLine(filename):
    try:
        f = open(filename,"rt")
        value = int(f.readline())
        f.close()
        return True, value
    except ValueError:
        f.close()
        return False, -1
    except OSError:
        return False, 0

try:
    while True:
        # 温度を取得
        Flag, Temperature = readFirstLine(device0 + "/in_temp_input")
        print("Temperature:", end="")
        if Flag:
            print(Temperature // 1000, "℃", end="\t")
        else:
            print("N.A.", end="\t")

        # 湿度を取得
        Flag, Humidity = readFirstLine(device0 + "/in_humidityrelative_input")
        print("Humidity:", end="")
        if Flag:
            print(Humidity // 1000, "%")
        else:
            print("N.A.")

        time.sleep(2.0)
except KeyboardInterrupt:
    pass

```

スクリプトを実行します。
```bash
python3 readDHT11.py
```

正常に動作していれば、数秒おきに以下のように温度・湿度が表示されます。

```
Temperature:26 ℃   Humidity:32 %
Temperature:27 ℃   Humidity:31 %
...
```
SwiftUIで自前のタイトルバーをつくる

# はじめに
今回はSwiftUIをつかって自前のタイトルバーを作っていきます
### コード
```swift
ZStack {
    HStack {
        Button(action: {
            dismiss()
        }) {
            Image("arrow_back")
                .resizable()
                .foregroundStyle(Color.AccentColor)
                .frame(width: 24, height: 24)
            }
            .frame(width: 24, height: 24)
            .padding(.leading, 20)

         Spacer()
    }
    .frame(maxWidth: .infinity, alignment: .leading)
    Text("title")
        .font(.headline)
        .frame(maxWidth: .infinity, alignment: .center)
}
```
### 最後に
NavigationStackで遷移した時などに自動で表示してくれるものがあったり、それを非表示にする設定があったりはしますが、用意されてる分自由に使うには結局自前で実装したほうが使い勝手が良かったのでつくりました
どなたかのお役に立てれば幸いです
jQueryで実装する、スクロールに応じて表示されるトップへ戻るボタン

### HTML
```html
<div id="js-back-to-top" class="c-back-to-top">
    <div class="c-back-to-top__button">TOP</div>
</div>
```

### CSS
```scss
.c-back-to-top {
    display: none;
    position: fixed;
    bottom: 10px;
    right: 10px;
    z-index: 1000;
}

.c-back-to-top__button {
    width: 80px;
    height: 80px;
    border-radius: 100%;
    background-color: #fff;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 16px;
    cursor: pointer;
}
```

### JavaScript
```js
  const $backToTop = $("#js-back-to-top");

  $(window).scroll(function () {
    if($(this).scrollTop() > 80){
        $backToTop.fadeIn(300);
    } else {
        $backToTop.fadeOut(300);
    }
  });

  $backToTop.on("click" ,function () {
    $("html, body").animate({ scrollTop: 0 }, 500);
  });
```

```js
const $backToTop = $("#js-back-to-top");
```
・idが`js-back-to-top`の要素を取得して、変数`$backToTop`に格納する。
・変数の先頭に$を付けているのは、jQueryオブジェクトであることを明示するため。

```js
  $(window).scroll(function () {
```
・スクロールイベントを監視する。
・ユーザーがスクロールすると、中の処理（関数）が実行される。

```js
if($(this).scrollTop() > 80){
```
・`$(this)`は現在のイベントが発生した対象(ここではwindowオブジェクト)を指す。
・`scrollTop`メソッドは現在の位置（上から何ピクセルスクロールしたか）を取得する。
・`> 80` → 80px以上スクロールしたらボタンを表示する条件。

```js
$backToTop.fadeIn(300);
```
・300ms（0.3秒)かけて要素を表示するアニメーション。
・つまり、80px以上スクロールしたらボタンが表示される。
```js
  } else {
    $backToTop.fadeOut(300);
  }
```
・300ms（0.3秒）かけて要素を非表示にするアニメーション。
・`else`があるので、スクロール位置が80px未満でボタンが非表示になる。

```js
 $backToTop.on("click" ,function () {
    $("html, body").animate({ scrollTop: 0 }, 500);
  });
```
・`$backToTop`に対して、クリックイベントを設定。
・`$("html, body")`をセレクタに指定しているのは、ページ全体を対象にする必要があるため。ブラウザによってscrollTopを適用すべき対象が違うので`html`と`body`の2つを指定している。Webkit系（Chrome、Safari、Edge）ではbody、Firefoxではhtmlに適用される。
・ボタンをクリックするとTop位置まで500msのスピードでゆっくりと移動する。
VPC Share環境におけるEICエンドポイントのクォータ（制限）について

こんにちは、ちはらです。
今回は、AWS Resource Access ManagerでVPCを共有している環境におけるEC2 Instance Connect エンドポイント（以下EICE）のクォータについてまとめています。

### EC2 Instance Connect エンドポイントとは
EICEとは、踏み台サーバを使用したり、VPCがインターネットに直接接続したりする必要がなく、インターネットからインスタンスに安全に接続するためのエンドポイントサービスです。
主に以下のようなメリットが存在します。

- パブリックIPv4アドレスを設定することなく、インスタンスに接続が可能
- IGW経由のインターネット接続が不要
- IAMポリシーとアクセス許可でアクセス制限の設定が可能
- 基本的にコストがかからない（異なるAZ間のデータ転送にのみコストが発生）

### EICEクォータ
EICEには以下のクォータが設けられています。
いずれのクォータも引き上げは不可です。

- AWS アカウント ごとの AWS リージョン あたりの EC2 Instance Connect Endpoint の最大数：5
- VPC あたりの EC2 Instance Connect Endpoint の最大数：1
- サブネットあたりの EC2 Instance Connect Endpoint の最大数：1
- EC2 Instance Connect Endpoint あたりの同時接続の最大数：20

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/eice-quotas.html

今回の話の中で重要になってくるクォータが**VPC あたりの EC2 Instance Connect Endpoint の最大数**と**サブネットあたりの EC2 Instance Connect Endpoint の最大数**です。

### 実行環境

管理アカウントと利用者アカウントは同じAWS Organizationsに存在しており、
管理アカウントで作成したVPCをAWS RAMで利用者アカウントと共有している環境です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/e5f9b89d-83bf-4ab0-9ba0-7a3e66660714.png)

# VPC Share環境におけるEICEのクォータ
ドキュメントには1つのVPCやサブネットにつき1つのEICEしか作成ができないと記載されているので、
今回のようなVPC Share環境では1つのEICEしか作成できないというのが正しい挙動だといえます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/ae8fcc14-f61d-43a8-a8c7-2d3b33b31824.png)

しかし、コンソール上で操作を行うと管理アカウントにEICEが存在している状態でも利用者アカウントにもEICEが作成できてしまうというのが現状です。（2025.03.01時点）

以下に実際のキャプチャを示します。

【各アカウントID】
管理アカウント：XXXX-XXXX-3505
利用者アカウント：XXXX-XXXX-2336

①管理アカウントと利用者アカウントでサブネットが共有されていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/c4dda125-6073-4fd8-b38a-518e9d7d9c2a.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/36b47c42-07c1-43b8-a6d1-5ceeb93936d0.png)

②管理アカウント上でEICEを作成
　サブネットID：subnet-○○○bde
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/7b356314-9138-456f-b8d9-d11871377676.png)



③利用者アカウント上でEICEを作成
 サブネットID：subnet-○○○bde
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/80917d5e-e496-4cff-a6c1-452afd965960.png)


※別アカウントのEICEを表示することはできないので、別ブラウザで管理アカウントと利用者アカウントにログインし、それぞれのEICEを表示している画面も置いておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/ad3b3ee4-7ffc-496a-9e14-7df372b625a4.png)

各アカウントに1つずつのEICEは作成できてしまいますが、
2つ目のEICEはクォータのエラーが表示され、作成することはできません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3867728/27e5f910-0788-4c74-a27d-649533d0e63c.png)

このように、VPC Share環境において、1つのアカウントでEICEが作成されているからといって、他のアカウントで同じVPC・サブネット上にEICEが作成できないという訳ではないので注意が必要です。

# さいごに
私がドキュメントを確認した範囲では1つのVPC・サブネットに複数のEICEが作成できるケースは記載がなかったので、しばらくしたら今回のようなケースは発生しないようにアップデートされる可能性もあると思います。
ですが、現在は実際に複数のEICEが作成できることが確認できているので、EICEの作成に制限をかけたい場合は注意が必要です。
初めてのモダンUI：Chakra UIとReact Hook Formでブラッシュアップした学習記録アプリ

# はじめに
前回作成した学習記録アプリに新機能を追加し、大幅にブラッシュアップしました。開発中の気づきや学びについてまとめましたので、ぜひ最後までお読みください。

![画面収録 2025-03-02 18.40.55.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3775597/dab02618-4b1b-4e6a-b7c7-4ef9165929a5.gif)

# 実装した新機能
今回のバージョンで追加・改善した主な機能は以下の通りです：

* Chakra UIの導入によるUIの刷新
* React-Iconsを活用したデザイン性の向上
* React Hook Formによる洗練されたフォーム実装
* 登録済み学習記録の編集機能
* JESTでMockを活用した効率的なテスト実装

# 成長を感じた点
前回のアプリ開発と比較して最も成長を感じたのは、公式ドキュメントを積極的に活用できるようになった点です。特にReact Hook Formの実装時に壁にぶつかった際、公式ドキュメントと解説動画を丁寧に読み込むことで問題を解決できました。この経験が今回の開発における最大の学びとなりました。

また、テスト実装においても進化が見られました。以前はJESTを使用していたものの、Mockを活用していませんでしたが、今回はMockを取り入れることでテストの理解が格段に深まりました。

# 苦労した点と得られた気づき
開発過程で最も苦労したのは、やはりReact Hook Formの実装でした。AIに質問しても解決できず悩んでいたところ、JISOUのオンライン交流会で相談する機会があり、重要なアドバイスをいただきました。

> 新しい機能を実装する際は、まずその機能単体で検証することが大切だと教わりました。

<font color="red">**つまり、新機能実装する時は小さく開発する**</font>

これが非常に重要なポイントでした。私は既存の複雑なコードベースに直接新機能を組み込もうとしていたため、問題が複雑化していました。この経験から、段階的な開発アプローチと公式ドキュメントの重要性を強く実感することができました。

# おわりに
今回のアプリ開発を通じて、環境構築やCI/CDパイプラインの構築が自然にできるようになりました。今後もReactとTypeScriptの理解を深めていきたいと思います。
また、react-serverという新しいフレームワークやReact 19の安定版がリリースされたので、時間が許せばこれらの新機能も積極的に取り入れていきたいと考えています。
長文をお読みいただき、ありがとうございました！引き続きWebエンジニアになるべく精進していきます！

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。日本一のアウトプットコミュニティでキャリアアップしませんか？興味のある方は、ぜひホームページをご覧ください！
▼▼▼

https://projisou.jp
.length の罠！配列と文字列の違いに気をつけよう

Paizaの問題で「整数の文字数を出力せよ」と言われ、`.length` を使ったら、思った結果と違う値が出た…。実は `.length `は「配列」と「文字列」で意味が変わる！length の使い方を間違えるとこうなる！

<br>NGコード（間違えた例）
```js
const n = lines[0];  
for (let i = 1; i <= n; i++) {  
    console.log(lines[i].length);  
}
```
<br>❌ なぜ間違い？

`lines[i]` は 配列の要素 なので、`.length` を使うと「文字数」ではなく「配列の長さ」を返してしまう！

<br>正しい `.length` の使い方

OKコード（修正後）
```js
const n = Number(lines[0]);  
for (let i = 1; i <= n; i++) {  
    console.log(String(lines[i]).length);  
}
```
✅ 改善点
String(lines[i]) で確実に文字列化！
Number(n) で n を数値にして正しくループ！

<br>.length まとめ！

💡 配列の .length → 要素数 を返す！
💡 文字列の .length → 文字数 を返す！
💡 確実に文字列化するなら String(x) を使う！

.length を使うときは、データの型を確認するのが大切ですね！
[僕の失敗談と解決話！](https://paizabeginner.wordpress.com/2025/03/02/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc-length%e3%81%ae%e7%bd%a0%ef%bc%81%e2%86%92%e6%ad%a3%e3%81%97%e3%81%84%e6%96%87%e5%ad%97%e6%95%b0%e3%82%ab%e3%82%a6%e3%83%b3/)