OmniAICreator/Qiita-1.07M huggingface dataset:
Staticルート

**Staticルート（スタティックルート）**とは、ネットワーク機器（ルータやレイヤー3スイッチ）において、**手動で設定された固定的な経路情報**を指します。動的ルーティングプロトコルを使わず、管理者が明示的に宛先ネットワークとその経路を指定します。

---

### **Staticルートの特徴**
1. **手動設定**  
   管理者が特定の宛先ネットワークに対する経路を明示的に設定します。自動的に更新されないため、ネットワーク構成が変更された際には手動で修正が必要です。

2. **シンプルでリソース効率が高い**  
   - 動的ルーティングプロトコル（例：OSPFやBGP）に比べ、プロトコルの計算や通信が不要なため、ルータの負荷が少なくて済みます。  
   - 小規模ネットワークや、経路が明確で固定的な環境に適しています。

3. **信頼性**  
   手動設定なので、不必要なルートが広告される心配がありませんが、冗長性が低い場合は障害時に経路が切れるリスクがあります。

4. **運用負荷**  
   ネットワークが複雑になると、Staticルートの管理が煩雑になり、運用が難しくなります。

---

### **Staticルートの設定例**
**例1: Ciscoルータの場合**
```bash
ip route 192.168.1.0 255.255.255.0 10.0.0.1
```
- `192.168.1.0/24` への宛先ネットワークに対し、ネクストホップ（次にパケットを送る場所）を `10.0.0.1` に設定。

**例2: Linuxの場合**
```bash
sudo ip route add 192.168.1.0/24 via 10.0.0.1 dev eth0
```
- `192.168.1.0/24` 宛ての通信を、`10.0.0.1` を経由し、`eth0` インターフェースから送信。

---

### **Staticルートの用途**
1. **小規模ネットワーク**  
   固定的な通信経路がある場合に利用。

2. **バックアップ経路**  
   動的ルーティングの代替経路や、特定の通信のみ優先的に利用させる用途。

3. **特定の通信制御**  
   特定のトラフィックを特定の経路に流したい場合や、セキュリティのために経路を限定する際に活用。

---

### **Staticルートの注意点**
1. **冗長性が低い**  
   障害時に自動で他の経路へ切り替える機能がない（動的ルーティングと異なる点）。

2. **スケーラビリティ**  
   大規模なネットワークでは設定や運用が複雑になり、管理が困難。

3. **手動変更が必要**  
   ネットワーク構成が変わるたびに、設定を手動で更新する必要があります。

---

### **まとめ**
Staticルートは、ネットワーク構成が単純で安定している場合に有効です。ただし、柔軟性や自動化を求める場合は、動的ルーティングプロトコルと組み合わせて利用するのが一般的です。
ファクトリの属性を設定する際の注意

# 各クラスのファクトリを作成する際には一つのシンプルなファクトリを作成する
各クラスに対してそのクラスのインスタンスを作成することに必要な単純な属性セットを供給する一つのファクトリを持つことを推奨します。`ActiveRecord`オブジェクトを生成する際、バリデーションを通して必要とされる属性とデフォルトを持たない属性のみを提供することを意味します。継承によって作成された他のファクトリを作成し、各クラスに一般的なシナリオをカバーします

>It is recommended that you have one factory for each class that provides the simplest set of attributes necessary to create an instance of that class. If you're creating ActiveRecord objects, that means that you should only provide attributes that are required through validations and that do not have defaults. Other factories can be created through inheritance to cover common scenarios for each class.

同じ名前で複数のファクトリを定義を試みることはエラーを起こすだろう。
>Attempting to define multiple factories with the same name will raise an error.

https://thoughtbot.github.io/factory_bot/defining/best-practices.html

(ブロックなしの)静的な属性は`factory_bot 5`で利用不可になりました。このブログの投稿(リンク)で属性の削除の決定に関してご覧ください。
>Static attributes (without a block) are no longer available in factory_bot 5. You can read more about the decision to remove them in this blog post.

https://thoughtbot.github.io/factory_bot/defining/static-attributes.html
BGPフィルタメモ

**BGPフィルタの動作設定**について、概要と設定のポイントを以下にまとめます。

### **BGPフィルタの概要**
BGPフィルタは、ルータがBGP経路情報を受信・送信する際に、特定の条件に基づいて経路を許可または拒否する設定です。これにより、不要な経路の受信や誤った経路のアドバタイズを防ぎ、ネットワークの安定性とセキュリティを向上させます。

---

### **設定の主要項目**
BGPフィルタは以下のいくつかの方法で設定されます。

#### **1. Prefix List**
特定のIPプレフィックスを許可または拒否するリストを作成します。
- **適用場所**: 入力フィルタ (inbound) または出力フィルタ (outbound)
- **構文 (Cisco例)**:
  ```bash
  ip prefix-list ALLOW-ROUTES seq 10 permit 192.168.0.0/16
  ip prefix-list ALLOW-ROUTES seq 20 deny 0.0.0.0/0 le 32
  ```
  **説明**: 
  - `192.168.0.0/16` を許可
  - それ以外のルートを拒否

---

#### **2. Route Map**
フィルタ条件に応じて柔軟な動作を設定する場合に使用します。
- **適用場所**: BGPピアに適用可能
- **構文 (Cisco例)**:
  ```bash
  route-map FILTER-IN deny 10
    match ip address prefix-list DENY-LIST
  route-map FILTER-IN permit 20
  ```
  **説明**:
  - `DENY-LIST` に一致する経路を拒否
  - 他の経路は許可

---

#### **3. AS Path Access List**
ASパスに基づくフィルタリングを行います。
- **構文 (Cisco例)**:
  ```bash
  ip as-path access-list 1 permit ^$
  ip as-path access-list 2 deny .*$
  ```
  **説明**:
  - `^$` は直接接続している経路のみ許可
  - 他のすべての経路を拒否

---

#### **4. Community Filtering**
BGPコミュニティに基づいて経路をフィルタリングします。
- **構文 (Cisco例)**:
  ```bash
  ip community-list standard ALLOW_COMMUNITY permit 12345:1
  route-map COMMUNITY-FILTER permit 10
    match community ALLOW_COMMUNITY
  ```

---

### **設定手順の流れ**
1. **フィルタの条件を設計**: 対象となるプレフィックス、ASパス、コミュニティなどを決定。
2. **フィルタの作成**: Prefix List、AS Path Access List、または Route Map を設定。
3. **フィルタの適用**: 対象となるBGPピアに `inbound` または `outbound` フィルタとして適用。
   ```bash
   neighbor 192.168.1.1 prefix-list ALLOW-ROUTES in
   neighbor 192.168.1.1 route-map FILTER-OUT out
   ```

---

### **注意点**
- フィルタの順序が重要です。最初に一致したルールが適用されます。
- 不適切なフィルタ設定は、必要な経路の喪失やBGPセッションの問題を引き起こす可能性があります。
- 設定後は、`show ip bgp` コマンドなどで経路を確認してください。

必要に応じて、特定のシナリオに沿った具体的な設定例も提供できます！
Jenkinsにてgitのプライベートリポジトリクローンでハマったメモ

## リポジトリ
Jenkinsについて右も左もわからず、Udemyのとあるコースを履修していた中で起きたできごと。
プライベートリポジトリのクローンがどうしてもできずハマったので、メモ程度に紹介。

```
リポジトリ : Command "git ls-remote -h -- git@github.com:XXX/xxx.git HEAD" returned status code 128:
stdout:
stderr: No ED25519 host key is known for github.com and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
との接続に失敗しました。
```

![スクリーンショット 2025-01-23 16.45.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/239fad4d-958a-0c3c-52b6-7a3437dca812.png)

サーバ上で直接リポジトリのクローンはできた。
なので、登録した認証鍵情報に誤りがあることはなさそう。
```
vm:~$ git clone git@github.com:XXX/xxx.git
Cloning into 'xxx'...
remote: Enumerating objects: 78, done.
remote: Counting objects: 100% (78/78), done.
remote: Compressing objects: 100% (57/57), done.
remote: Total 78 (delta 32), reused 62 (delta 19), pack-reused 0 (from 0)
Receiving objects: 100% (78/78), 13.84 KiB | 13.84 MiB/s, done.
Resolving deltas: 100% (32/32), done.
azureuser@vm-otsuka01:~$ ll
drwxrwxr-x 4 user user 4096 Jan 23 07:58 xxx/

vm:~$ cat ~/.ssh/config 
Host  github.com
  HostName github.com
  IdentityFile ~/.ssh/jenkins_key
  User git
  port 22
```

いろいろググってみると、known_hostsにgithub.comの情報を書き込むことで対処ができそうとのことだった。

## やったこと
`/var/lib/jenkins/`に`.ssh/knowns_hosts`を作成
```
$ sudo mkdir -p /var/lib/jenkins/.ssh
$ sudo touch /var/lib/jenkins/.ssh/known_hosts
$ sudo chown jenkins:jenkins /var/lib/jenkins/.ssh/known_hosts
$ sudo chmod 600 /var/lib/jenkins/.ssh/known_hosts
```

github.comのSSHホストキーを取得して貼り付ける
```
$ ssh-keyscan -t rsa,ed25519 github.com | sudo tee -a /var/lib/jenkins/.ssh/known_hosts
```

画面を更新してみるとエラーが消えました。
![スクリーンショット 2025-01-23 17.27.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/aa47e1d4-bd71-ed34-43e1-15c3f23c0204.png)

## クローンはできたがジョブが最後まで実行されない
Jenkinsユーザが固有の認証情報を持つ必要があるらしく、別のエラーが発生
```
git@github.com: Permission denied (publickey).
```

`/var/lib/jenkins/.ssh`にjenkinsユーザ用の認証鍵を配置し、
その情報をgithubにアップロードすることでエラーは解消
（若干解せないのでもう少しエラーについて調べたいところ。。。）

```
$ sudo -u jenkins ssh-keygen -t ed25519 -C "jenkins@XXX"
$ sudo cat /var/lib/jenkins/.ssh/id_ed25519.pub ### githubにはりつ
```

![スクリーンショット 2025-01-23 17.59.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610268/72360b9b-d39a-1ef7-ca30-c6411a8302fe.png)
Google Colab上でGUIを作ってみる

## はじめに
今までGoogle Colabを使ってディープラーニングについていろいろと試してきました。
推論の結果などはテキスト形式でColab上に表示するだけでしたが、GUIで表示できた方が便利そうという安直な思い付きでその方法について調べてみました。その備忘録について記載します。

## Gradioとは
WebアプリケーションのUIを簡単に作成することができるPythonのライブラリのようです。
以下の本家のサイトにもWebインタフェースを使って機械学習モデルをデモすることができるツールと記載があり、Google Colabとも相性がよさそうです。

https://www.gradio.app/

## 早速使ってみる
使い方はかなり簡単で、本家にも記載されている通り、
gradio.Interface()でWebベースのGUIを作成（骨格を作成）し、
gradio.Interface.launch()でデモを実施するためにWebサーバを起動するとのことです。

またwith gradio.Blocks()でもカスタマイズしたWebベースのGUIを作成することができます。

```Python
import gradio as gr

def greet(name):
    return "Hello " + name + "!"

demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch()
```

ディープラーニングの推論で得られた上位3つの結果を表示したかったので、
出力用にテキストボックスを3つ用意しました（もっとよいやり方はありそうですが。。。）

```Python
import numpy as np

def mod_predict(inp):
    x = np.array(inp)
    x = np.expand_dims(np.array(x, dtype=np.float32) / 255., 0)
    pred = model.predict(x)
    argpred = np.argsort(pred[0])[::-1]
    strlist=[]
    for i in range(3):
        strlist.append(classes[argpred[i]]  + ": " + str(pred[0, argpred[i]]))
    return strlist[0], strlist[1], strlist[2]
```
降順に並べた推論結果の上位3つをリストにappendしています。

```Python
import gradio as gr

with gr.Blocks(css=".gradio-container {background-color: skyblue}") as demo:
    # UI
    input = gr.Image(type="pil")
    output = outputs=[gr.Textbox(label="No1:"), gr.Textbox(label="No2:"), gr.Textbox(label="No3:")]
    submit_btn = gr.Button("Submit")

    submit_btn.click(fn=mod_predict, inputs=input, outputs=output)

demo.launch(debug=True)
```
デフォルトのままだと少し味気ないので、skyblueの背景にしてみました。
demo.launchの引数のdebug=TrueはGUI実行時にエラーが発生したときにデバッグ用にログを出力するオプションです。

## 作成できた
gradioを実行すると以下のようなメッセージが表示されます。

**Colab notebook detected. This cell will run indefinitely so that you can see errors and logs. To turn off, set debug=False in launch().
  Running on public URL: https://XXXXXXXXXXXXXXXXXX**

このリンクは72時間で有効期限が切れるとのことです。このURLにアクセスするとWeb UIが表示されます。

![gradioui.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/befca16e-a2ce-770c-9534-3fd6695980f2.png)


## 注意点
Google Colabでは**gradio**はインストールされていないので、以下のコマンドで
インストールして使用してください。

```Python
!pip install gradio
```
初心者でも簡単！ChatGPTを自分仕様にするカスタムGPTの作り方

## はじめに
最近、ChatGPTを使った作業効率化が注目されていますが、その中でも「GPTs（カスタムGPT）」を作成することで、さらに特化したタスクに最適化されたAIアシスタントを作成できます。  
この記事では、ChatGPTのカスタムGPTを作る方法を初心者にも分かりやすく解説します。

---

## 1. GPTsとは？
**GPTs**は、ChatGPTのカスタマイズされたバージョンのことです。これにより、特定のタスクや目的に特化したAIアシスタントを簡単に作成できます。

例えば、以下のような用途があります：
- 特定分野のアドバイザー（例：プログラミングサポート）
- ドキュメントや記事作成の補助
- カスタマーサポート
- チーム内でのナレッジ共有

---

## 2. GPTsを作成する準備
カスタムGPTを作成するには、以下の準備が必要です。

### 必要なもの
1. **ChatGPT Plusアカウント**  
   GPTsの作成は無料で可能ですが、ChatGPT Plusアカウントを利用すると、より高度な機能や最新モデルを使用できます。

2. **目的とターゲットの明確化**  
   作成したいGPTが解決する課題を具体的に考えましょう。例：
   - 技術記事を書くアシスタント
   - カスタマーサポート用ボット

---

## 3. GPTsの作り方：手順解説
以下は、実際にGPTを作成する手順です。

### ステップ1：ChatGPTの「Explore GPTs」ページにアクセス
1. ChatGPTの画面右上の **「Explore GPTs」** ボタンをクリックします。  
2. 「Explore GPTs」ページでは、他の人が作成したカスタムGPTを閲覧したり、自分のGPTを作成できます。

### ステップ2：新しいGPTを作成する
1. **「Create a new GPT」ボタン** をクリックします。  
2. 作成画面が開くので、以下を入力します：
   - **名前**: 作成するGPTの名前を設定します。例：「プログラミング記事アシスタント」。
   - **説明文**: このGPTの機能を簡単に説明します。例：「初心者向けの技術記事をスムーズに作成するお手伝いをします」。
   - **アイコン**: アイコンをカスタマイズして、視覚的に分かりやすくします。

### ステップ3：指示（カスタムインストラクション）の設定
次に、GPTに何をさせたいかを明確に指示します。  
**ポイント**：
- 具体的かつ簡潔に書く。
- 利用シーンを想定して設計する。

**例：Qiita記事作成アシスタントの指示**
```plaintext
あなたはQiita記事作成を支援するアドバイザーです。初心者向けに分かりやすく、SEOを考慮した技術記事の執筆を手助けしてください。Markdown形式で提案を行い、具体的な例を挙げて説明を簡潔にします。
```

### ステップ4：カスタムデータの追加（オプション）
カスタムデータをアップロードすることで、特定のデータに基づいてGPTをトレーニングできます。ただし、現時点ではこの機能は限られています。

---

## 4. 実際に作ったGPTをテスト
作成したGPTを実際にテストしてみましょう。  
- **入力例**: 「JavaScriptの配列操作に関する記事を作成して」
- **期待される出力例**:
  ```markdown
  # JavaScriptの配列操作入門
  配列はJavaScriptで頻繁に使われるデータ構造の一つです。本記事では、配列操作の基本を初心者向けに解説します。
  ...
  ```

問題がある場合は、カスタムインストラクションを微調整してください。

---

## 5. 公開と活用方法
完成したGPTは以下の方法で活用できます：
- **公開**: 他のユーザーが使えるように公開設定にする。
- **プライベート使用**: 自分専用のアシスタントとして利用。
- **共有**: チームメンバーや友人と共有して活用。

---

## 6. 作成時のコツ
- **具体的な指示を書く**: 「広く浅く」より「特化して深く」を意識しましょう。
- **小さく試して改善する**: 作成後、少しずつ指示を調整して改善してください。
- **Markdownの活用**: 提案内容をMarkdown形式で書くと記事作成が効率化します。

---

## 7. まとめ
カスタムGPTは、個人やチームの作業を効率化する強力なツールです。この記事の手順を参考に、自分だけのGPTを作成してみてください！
ReactをDocker desktop for windowsで動かすと遅くない？

Reactで開発しているときに，
・buildのnpmインストールの時間かかりすぎ
・ホットリロード(ファイル編集後の反映)が全然ホットじゃない，むしろ冷めてるやん
みたいな経験のある方に向けた記事になります．

これはReactに限らずNext.js環境で開発を進めようとしていると出会う障壁みたいです．
どうやらwindowsとLinuxのOS間でのファイルの読み書きが死ぬほど遅いらしい．

WSL2でdockerを動かしていても，windows配下のファイルをlinux配下にマウントして読み取りに行くだけで遅い．
じゃあそもそもdocker自体をfor windowsで動かしているとさらに...ってなっているみたいです．
(解釈が間違っているとあれなのでソースは貼っておきます)

改善策としては
ubuntu上にdocker engineを入れて動かす．
ファイルを
\\wsl.localhost\Ubuntu\mntではなく
\\wsl.localhost\Ubuntu\homeに置く
だそうです．

以下の記事を参考にしてみてください．

https://zenn.dev/thyt_lab/articles/fee07c278fcaa8

https://www.aska-ltd.jp/jp/blog/197
Hello！令和８年度に転職を目指して

令和８年度の転職を目指し、昨日よりプログラミング学習等をスタートした30歳行政マン

まずは１月末までUdemyで入門(https://www.udemy.com/course/web-application-development/?couponCode=KEEPLEARNING)
勉強の上、独学かスクールで勉強をするか検討中
（公務員のため、リスキリング助成を受けられず、、、）

人生を歩み始めた我が子に癒されつつ、まずは１年強粘ります:point_up_2:
【第54回_Beginner限定コンペ】PCゲームの勝敗予測に参加してみた

## はじめに
この記事を目にした方ならkaggleやsignateなどプラットフォームについて聞いたことがある、参加したことがあるかもしれません。KaggleとSIGNATEは、データサイエンスや機械学習に特化した競技プラットフォームです。

Kaggleはグローバルに展開され、多彩な企業や研究機関が提供するデータセットと課題を通じて、データ分析スキルを競う場を提供します。

一方、SIGNATEは日本発のプラットフォームで、国内企業や団体が提供する課題を中心に、実務に近い分析やAIモデル開発に挑戦できます。

どちらもランキングや賞金があり、学びやキャリアアップに最適です。初心者からプロまで幅広い層に対応しています。

Begginerコンペというのとゲームの勝敗というのにひかれて初めて参加してみました。

### PCゲームの勝敗予測：内容
学習用データ、評価用データ、サブミッション用ファイルの３つが与えられます。
データの中身はこんな感じです
![スクリーンショット 2025-01-09 005519.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676395/e592cf6d-d2e5-7baf-d024-80497a385034.png)
### 特徴量エンジニアリング
自分はこのゲームを知っていて一時期結構やりこんでいました。これはleague of legendsという5v5のゲームで相手の拠点を先に壊した方が勝利というゲームです。このゲームについては結構詳しく知っていたので調べに行く必要はありませんでした。

データ欠損やダミーかする必要のあるデータはなかったためこのゲームで重要な
kill-deathキルデス差そして、戦闘が起きた時にチームの連携力という点でkill*assistというのも作りました。
またこのゲームはfirstBloodに追加のお金が入るようになっており普通のkillより多くお金がもらえるためキルデス差に＋１した値を追加しました。
## モデルの選択
様々な手法を試してみてクロスバリデーションで予測を実行し、特に精度の高かった”SVM””lightBGM”"rondomforest"をアンサンブルしました。
まだ今回のコンペが終わっていないためコードは後悔しませんが終わり次第公開します。
## 終わり![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3676395/c2b20cde-b1f5-e472-0446-eb2ac03b3d06.png)
今のところ12位という結果なので自分はこのゲームの知識背景がある分１桁順位で終われるよう引き続き頑張っていきたいと思います。
mkdirではできない所有者と権限を指定してディレクトリを作成するコマンド

Linuxでは普段mkdirコマンドでディレクトリの作成をしていましたが
作成 ⇒ 所有者調整 ⇒ 権限調整 をするのが面倒でした。

```bash
$ mkdir test_dir
$ chown test_user:test_group test_dir
$ chomod 775 test_dir
```

`&&`で繋げてディレクトリ作成するのもいいのですが、
もう少し良い方法がないか調べたところどうやら`install`コマンドとオプションを利用することで、一発で所有者と権限を指定してディレクトリ作成出来るようです。

## 【install】指定したファイルをファイルシステム内の特定の場所にインストールする
insatllコマンドはcpコマンドと似ており、パーミッションなども指定することが出来ます。
```bash
install test01_file test02_file
```
上の場合test01_fileがコピー元でtest02_fileがコピー先になります。
オプションなしで実行するとパーミッションは755(rwxr-xr-x)に設定されてファイルがコピーされます。

| オプション | 説明 | 
|:--------:|:------------|
| -d    |指定したパスにディレクトリを作成 |
| -m   |コピーするファイルやディレクトリのパーミッション（例: 755）を指定
| -o   |新しく作成するファイルの所有者を指定|
| -g   |新しく作成するファイルのグループを指定|
| -p   |タイムスタンプを保持（元のファイルのアクセスおよび変更時刻をそのままコピー）|
| -v   |詳細モードで実行し、作業の進行状況を表示|
| -T   |コピー元のファイルをそのままディレクトリとして扱わない|
| --backup  |バックアップファイルを作成|
| --help  |ヘルプ情報を表示|
| --version  |コマンドのバージョン情報を表示|

これらのオプションを組み合わせて所有者と権限を指定してディレクトリを作成します。
```bash
install -d -m 755 -o test-user -g test-group /path/to/new/test_dir
```
これで権限が775で所有者がtest_user、所有者グループtest-groupのディレクトリが/path/to/new/directoryで作成されます。
【2025年01月版】ライセンスが明確でないWindows機のライセンスを確認する方法メモ

# はじめに

ミニPC買ったけどライセンス情報を確認したいな、のメモ

# 確認方法

## コマンドで確認

コマンドプロンプトで以下のコマンドを実行する。

```
slmgr -dli
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/5369737e-8808-6e2f-b7da-5ce71d0ce0fa.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/7ef18bad-556d-46e4-d938-5677b2055a38.png)

## アプリケーションで確認

以下のインストールを行って確認する。

- [ShowKeyPlus](https://apps.microsoft.com/detail/9pkvzcprx9nv)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/7a9b8094-04c4-c799-2c18-8f1fdfc00fa6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/519cb64a-25c9-093e-215e-2dfb44c8eb76.png)

# Windowsのバージョン

ファイル名を指定して実行から `winver`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143127/46c3ed45-9fcb-7acd-94cc-284814d7a59d.png)


# さいごに

かんたんでしたね
初心者向け！とりあえず見た目がかっこいいNeovimの設定

前回ターミナルを半透明化してかっこよくしたので、今回はコマンドラインエディタの見た目をかっこよくしていきます。

![スクリーンショット 2025-01-22 17.42.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639915/3aaf27f0-b95b-03c5-daca-3961ab6526e5.png)



## Neovimのインストール
NeovimのインストールはMacの人であればbrewを使うことで簡単にインストールすることが可能です。
実はbrewってlinux系にも導入できまして、公式にインストール方法が載っています。
なので、特にこだわりがないなら、wsl組もbrewを使うのはありかと。

https://brew.sh/ja/

`brew`を使って簡単にインストールすることはできるのですが、少しだけコツがあります。
以下のコマンドでインストールを行ってもらえると、今後のカスタマイズがスムーズに行くかと思います。

```
brew install utf8proc --HEAD && brew install neovim --HEAD
```

Neovimは機能性と拡張性を追求する先進的なコマンドラインエディタというコンセプトのため、拡張機能も最新版のNeovimをターゲットにしていることが多々あります。なので、`--HEAD`を指定することによって最新のバージョンをインストールさせています。

絶対に安定版がいいという方は`brew install neovim`でも大丈夫ですが、拡張機能のインストールの際に依存関係でエラーが出たりするので注意してください。

インストール後は`nvim`コマンドで起動することができますが、`vi`や`vim`に`alias`をかけてもいいかもしれません。



## LazyVim
Neovimの初期設定でおすすめなのが、こちらの`LazyVim`です。
LazyVimは初期設定とプラグインのテンプレートセットを含む、Vimのプラグインマネージャーになります。

https://www.lazyvim.org/

インストールは公式に書いてある手順を踏むだけなので簡単です。とりあえずシリーズなのでLazyVimの詳しい使い方は省きますが、プラグインのアップデートは`:Lazy`でメニューを出して、`U`を入力すればOKです。

![スクリーンショット 2025-01-23 10.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639915/afa17dda-b10c-ea81-2539-388a029a2fd3.png)



## NerdFont
NerdFontはアイコンフォントセットで、これを導入しないと一部装飾が文字化け表記になってしまい、かっこよくありません。
難しいことはないので、導入していきましょう！

https://github.com/ryanoasis/nerd-fonts/blob/master/readme_ja.md

上記からお好きなものをDLしてください！と、言いたいところですが、NerdFontを含む日本語対応フォントを探してインストールする必要があります。`NerdFont 日本語`とかで検索するといろいろ見つかると思うので、お好みのものを導入してみましょう。

とりあえずって感じで、Macの人は`brew install font-sauce-code-pro-nerd-font` で簡単にインストールすることもできます。
インストールできたら、iTerm2の設定から「Profiles」「Text」に入り、フォントを選択しましょう。

![スクリーンショット 2025-01-22 19.20.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3639915/01a0127f-eff3-2a6f-b696-f50619f3ac5a.png)

wsl環境の人はWindows側にフォントをインストールする必要があるので若干面倒です。
以下のリンク先からDLしてください。

https://github.com/ryanoasis/nerd-fonts/tree/master/patched-fonts/SourceCodePro

DLができたら右クリックでオプションメニューを表示させて、「その他のオプションを表示」「インストール」でフォントの追加ができると思います。
(インストールには管理者権限が必要となるので注意してください)

インストールできたら、PowerShell側の設定でフォントを選択します。



## おわりに
とりあえず見た目をかっこよくするという目的ではありましたが、コマンドモードがPopup表示になるなど、初心者にも使いやすいVimになったかと思います。
次回は`Fish Shell`を使ってかっこいいシェル環境の構築をやる予定です。
git stashを効率的に活用！fzfで選択的に適用する便利な関数を紹介


# 👍️ いいねのお願い
励みになるので、いいねをお願いします。 

# ✍️ はじめに
Gitを使って開発を進めていると、git stashを使って一時的に変更を退避させる場面が頻繁にあります。  
しかし、git stash listで一覧を確認した後、特定のstashを適用するには手動で名前を指定する必要があり、少し手間に感じることも。  
そんな煩わしさを解消するために、fzfを活用して、git stashのリストから選択して適用する便利な関数をご紹介します。

## こんな事ありませんか？
`git stash`しすぎて毎回どの番号かわからない。。 

`git stash list`するとこんな感じ

![スクリーンショット 2025-01-23 16.50.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907333/cdb39a55-d469-cabe-1be8-d4a7e99a89c0.png)

毎回`git stash list`してから、`git stash apply stash@{2}`する必要がある。。。

この動作をまとめられたらな。。。

# ✅ 実際の動作イメージ
`gsla`とターミナルで打ち込む

![スクリーンショット 2025-01-23 16.53.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3907333/ca2ce1a0-13d8-57b5-0126-1c6c91c3d844.png)

ここで好きなものを選択すれば、選択したものが自動で`git stash apply`される＼(^o^)／


# 🚀 やり方
以下を`.zshrc`へ追加
### git stashリストをfzfでインタラクティブに選択し、選択したstashを適用するシェル関数
```zsh
# git stashしたリストの中から選択し、applyする関数
function git_stash_list_apply() {
    # stash list を取得して選択
    local selected_stash=$(git stash list | fzf --height=15 --prompt="Select a stash to apply: ")

    # 選択されなかった場合は終了
    if [[ -z "$selected_stash" ]]; then
        echo "No stash selected. Aborting."
        return 1
    fi

    # 選択された stash 名を抽出 (例: 'stash@{0}')
    local stash_name=$(echo "$selected_stash" | sed -E 's/^(stash@\{[0-9]+\}):.*/\1/')

    # stash apply を実行
    git stash apply "$stash_name"
}
```

### 簡単に呼び出せるようにaliasを設定
```zsh
alias gsla='git_stash_list_apply'
```

# 📝 まとめ
これを使うと、stashの番号が何だっけ問題が簡単に解決できます！
ぜひ使ってみてください！👋
uv=0.5.22からエラーが出るようになった

# uv=0.5.22からエラーが出るようになった

## 以前の手順
```
.template_sam:
  image: public.ecr.aws/sam/build-python3.11
  before_script:
    - *use_aws_credentials
    - python -V
    - sam --version
    - pip install --upgrade pip
    - pip install uv
    - uv sync
    - source .venv/bin/activate
```

```
$ pip install uv
Collecting uv
  Downloading uv-0.5.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (11 kB)
Downloading uv-0.5.22-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (16.1 MB)
   ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 16.1/16.1 MB 110.1 MB/s eta 0:00:00
Installing collected packages: uv
Successfully installed uv-0.5.22
$ uv sync
error: Failed to inspect Python interpreter from search path at `/usr/bin/python`
  Caused by: Can't use Python at `/usr/bin/python`
  Caused by: Python executable does not support `-I` flag. Please use Python 3.8 or newer.
```

指定されたパス /usr/bin/python に存在する Python インタプリタを正しく検出または確認できなかったことを示しています。

# Python 仮想環境（venv）を有効化してから、`uv sync`する

```.gitlab-ci.yml
.template_sam:
  variables:
    PYTHON_VERSION: 3.11
    UV_VERSION: 0.5.22
    UV_LINK_MODE: copy
    SAM_CLI_TELEMETRY: 0 # AWS SAM セッションのテレメトリの無効化
  image: public.ecr.aws/sam/build-python$PYTHON_VERSION
  before_script:
    - *use_aws_credentials
    - python -V
    - sam --version
    - pip install --upgrade pip
    - pip install uv==$UV_VERSION
    - uv venv
    - source .venv/bin/activate
    - uv sync
```
AWS APIGateway プライベートなエンドポイントをテストする

# APIGatewayプライベートなエンドポイントをテストする

直接叩けないので、許可されてるVPCエンドポイントにあるEC2などを経由して、ローカルからテスト（APIを呼びたい）したい

## プライベートなAPIエンドポイント

![スクリーンショット 2025-01-23 16.02.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44351/abcc3e21-bde1-6216-eae7-af8f54d3efee.png)

## リソースポリシーでAPIエンドポイント叩けるVPCエンドポイントが制限されている

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": "*",
      "Action": "execute-api:Invoke",
      "Resource": "arn:aws:execute-api:ap-northeast-1:999999999999:xxxxxxxxxx/*",
      "Condition": {
        "StringEquals": {
          "aws:sourceVpce": [
            "vpce-00000000000000000"
          ]
        }
      }
    }
  ]
}
```

`999999999999`:アカウント ID

`xxxxxxxxxx`:API ID

`vpce-00000000000000000`:VPCエンドポイント

## 許可されてるVPCエンドポイントにあるEC2などを経由して、ローカルからテスト（APIを呼びたい）

`https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/STAGE/users`

`STAGE`:ステージ名



- ①EC2インスタンスにssh(22)とhttps(443)できるようにしておく
`AAA.BBB.CCC.DDD`:EC2インスタンスのパブリックIP

- ②sshポートフォワード

```
ssh -L 33443:xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com:443 ec2-user@AAA.BBB.CCC.DDD -i ~/.ssh/EC2インスタンス.pem
```

127.0.0.1:33443 >>>>> AAA.BBB.CCC.DDD:443

これで127.0.0.1:33443をEC2インスタンス(AAA.BBB.CCC.DDD)の443にフォワードする

- ③curlでAPIを叩く

```
curl --resolve xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com:33443:127.0.0.1 https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com:33443/STAGE/users
```

curl --resolve オプションは、特定のホスト名に対して特定の IP アドレスを解決させるために使用します。
これにより、DNS ではなく指定した IP アドレスを使って通信を行うことができます。
/etc/hostsに書く手間が省ける

ちなみに`xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com`でアクセスしないとSSL 証明書の検証エラーになる

```
% curl https://localhost:33443
curl: (60) SSL: no alternative certificate subject name matches target hostname 'localhost'
More details here: https://curl.se/docs/sslcerts.html

curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the webpage mentioned above.
```
Web素人がVueのtutorialをやってみる その5 (Step12/15 ～ end)

# 概要
[前回](https://qiita.com/tak_y07/items/8a5a09a7e388d074e9ac)から引き続きVueのチュートリアルをやっていきます。

# Step12
親コンポーネントが子に値を渡す方法について

### propsオプション
propsオプションを子で宣言して親から値を渡すことができる

```Child.vue
<script>
export default {
  props: {
    msg: String
  }
}
</script>

<template>
  <h2>{{ msg + 'Cv1' || 'No props passed yet' }}</h2>
</template>
```

```App.Vue
<script>
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      value: 'Pv1 '
    }
  }
}
</script>

<template>
  <ChildComp :msg="value + 'Pv2 '" />
</template>
```

結果
![{57192CD8-14F5-4DE1-9EE5-EE9E45496EAB}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/f6737a38-c4ca-c7a3-143b-eac4e449dbff.png)
親の宣言 ➡ 親(から子)の呼び出し ➡ 子の描画
の順で値が流れていることを確認。


# Step13
子コンポーネントが親にイベントを渡す方法について

`emits`と`this.$emit()`で親にイベントを渡す

```Child.vue
<script>
export default {
  emits: ['response'],
  created() {
    // 第一引数がイベント名, 第二引数以降は任意の渡したい値
    this.$emit('response', 'hello from child',' and goodbye')
  }
}
</script>

<template>
  <h2>Child component</h2>
</template>
```

```App.vue
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      childMsg: 'No child msg yet'
    }
  }
}
</script>

<template>
  <ChildComp @response="(msg,msg2) => childMsg = msg + msg2" />
  <p>{{ childMsg }}</p>
</template>
```
結果
![{82FD3868-E228-42C2-AD1D-75284EC76980}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/c485ce8c-d2eb-ce86-1675-7ecca8537fd4.png)



# Step14
スロットについて

親から子に要素を渡す仕組み
子の`<slot>`タグに親の`<子コンポーネント名>`の中の要素が渡る
渡していない場合は`<slot>`タグの中が表示される

```Child.vue
<slot>Fallback content</slot>
```

```App.vue
<script>
import ChildComp from './ChildComp.vue'

export default {
  components: {
    ChildComp
  },
  data() {
    return {
      msg: 'from parent'
    }
  }
}
</script>

<template>
  <ChildComp>Message: {{ msg }}</ChildComp>
</template>
```
結果
![{DC6E2DFF-5B73-4D71-A18A-5EBFCA7F774F}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/5fd5a66d-7294-cbe4-8a75-ce02ccb64fde.png)
ほんとは色々複雑なテンプレを渡すんだろうけど割愛...

# Step15
チュートリアル完了！
![{E9D34883-067A-4403-8F48-08E87DEC144A}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759711/a78d8e55-92a1-1e24-85ac-e1ed8bcfaab0.png)

このステップでは[チュートリアル以降のステップ](https://ja.vuejs.org/tutorial/#step-15)が示されています。

...

どうにか完了しました！
私の次のステップとしては[先達](https://zenn.dev/comm_vue_nuxt/articles/start-to-learn-vue-2024#%F0%9F%A4%94-vue.js-%E3%81%A3%E3%81%A6%E4%BD%95%E3%81%8B%E3%82%89%E5%8B%89%E5%BC%B7%E3%81%99%E3%82%8C%E3%81%B0%E8%89%AF%E3%81%84%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F)に倣って
- 公式ドキュメント流し見
- 実装例に挑戦
- なんか簡単なアプリ作る

で進めていこうと思います！

# お勉強にAIを使ってみて

チュートリアルの説明は結構あっさりしているので、途中からAIが補足に大活躍でした。
キリがないので全カットしましたがウラでめっちゃ質問しています。
VueのみならずHTML/CSS/JS の知識も補えたので使ってよかったと思います。
とはいえ公式ドキュメントの重要性もPowerBIを使ったときの経験で身に染みているので、
前述の通りここを掘り下げるところから始めたいと思います。

**Hello Vue!**
文字コード判別と変換

英数字のみのテキストファイルに、Win10メモ帳で漢字を追記すると、
メモ帳での保存時にUTF8が選択されるから、昔ながらのANSI/SJISを前提とした
アプリだとエラーが出るんだと。
久しぶりのWin32、以下のように修正してやりました。
MultiByteToWideChar()/WideCharToMultiByte()はBOMを削除しないので、ファイルから読み込んだバイナリーデータを変換する場合には、BOMのバイト分ずらす必要がありました。
```
#include <mlang.h>
...
  IMultiLanguage2* mlang = NULL;
  DetectEncodingInfo detectEnc{};
  HRESULT hres=CoCreateInstance(CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER, IID_IMultiLanguage2, (void**)&mlang);
  {
    int encCount=1;
    DWORD size_i;
    char txtdata[MAX_BUFFERBLOCK];
    
    HANDLE h=CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    ReadFile(h, txtdata, MAX_BUFFERBLOCK, &size_i, NULL);
    CloseHandle(h);
    hres=mlang->DetectInputCodepage(MLDETECTCP_NONE, 0, txtdata, (INT *)&size_i, &detectEnc, &encCount);
    }
  }
  mlang->Release();
  
  if(detectEnc.nCodePage==65001){ // UTF8
    char b_filename[MAX_PATH]{};
    strcpy(b_filename, filename);
    PathRenameExtension(b_filename, ".ini_UTF8");
    MoveFileEx(filename, b_filename, MOVEFILE_REPLACE_EXISTING);

    HANDLE h;
    DWORD srcsize, medsize, dstsize, rwsize;
    unsigned char *mtxt=NULL, *mtxt_a=NULL;
    wchar_t *wtxt=NULL;
    bool wBOM=false;
    {
      h=CreateFile(b_filename, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
      srcsize=GetFileSize(hFile, NULL);
      mtxt=(unsigned char *)malloc(srcsize);
      ReadFile(h, (char *)mtxt, srcsize, &rwsize, NULL);
      CloseHandle(h);

      if((mtxt[0]==0xef)&&(mtxt[1]==0xbb)&&(mtxt[2]==0xbf)) wBOM=true;

      if(wBOM==true){
        mtxt_a=&mtxt[3];
        srcsize=rwsize-3;
      }else{
        mtxt_a=&mtxt[0];
        srcsize=rwsize;
      }

      medsize=MultiByteToWideChar(CP_UTF8, 0, (LPCCH)mtxt_a, srcsize, NULL, 0);
      wtxt=(wchar_t *)malloc(medsize*sizeof(wchar_t));
      MultiByteToWideChar(CP_UTF8, 0, (LPCCH)mtxt_a, srcsize, wtxt, medsize);

      dstsize=WideCharToMultiByte(CP_ACP, 0, wtxt, medsize, NULL, 0, NULL, NULL);
      mtxt=(unsigned char *)realloc(mtxt, dstsize*sizeof(unsigned char));
      WideCharToMultiByte(CP_ACP, 0, wtxt, medsize, (LPSTR)mtxt, dstsize, NULL, NULL);

      h=CreateFile(filename, GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL);
      WriteFile(hFile, (char *)(mtxt), dstsize, &rwsize, NULL);
      CloseHandle(h);
    }
    if(mtxt!=NULL) free(mtxt);
    if(wtxt!=NULL) free(wtxt);
```
Javaで「テキストフィールドの余白の設定と枠線の変更」の動作を確認してみた。

# 概要

Javaで「テキストフィールドの余白の設定と枠線の変更」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/tutorial/jtextfield/index6.html

# 実装

以下のファイルを作成しました。

```JSample6_1.java
import javax.swing.JFrame;
import javax.swing.JTextField;
import javax.swing.JPanel;
import java.awt.Container;
import java.awt.BorderLayout;
import java.awt.Insets;

class JSample6_1 extends JFrame{
  public static void main(String args[]){
    JSample6_1 frame = new JSample6_1("MyTitle");
    frame.setVisible(true);
  }

  JSample6_1(String title){
    setTitle(title);
    setBounds(100, 100, 600, 400);
    setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    JTextField text1 = new JTextField("Hello", 40);
    JTextField text2 = new JTextField("Hello", 40);
    text2.setMargin(new Insets(10, 10, 10, 10));

    JPanel p = new JPanel();
    p.add(text1);
    p.add(text2);

    Container contentPane = getContentPane();
    contentPane.add(p, BorderLayout.CENTER);
  }
}
```

以下のコマンドを実行しました。

```
$ javac JSample6_1.java 
$ java JSample6_1
```

実行結果は以下の通りです。

![Screenshot from 2025-01-23 16-01-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3192024/be7e5f7e-9e0e-6202-875e-eb171ca09917.png)

# まとめ

何かの役に立てばと。
blastengineのメールエラーWebhookをAWS Lambda + Rubyで処理する


[blastengine](https://blastengine.jp/)はエンジニアフレンドリーなメール送信サービスになります。APIまたはSMTPを使って、簡単にメール送信を行えます。

blastengineではエラーメールに対するWebhook通知をサポートしています。この記事では、その扱い方とデータについてAWS Lambda + Rubyによる処理を通じて解説します。

## 設定

Webhook設定はblastengineの管理画面で行います。設定の中にあるWebhookをクリックします。

![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/059adabd-6159-2cd4-12d3-9d98c075b1c2.jpeg)

設定は主に2つです。

- エンドポイントURL
Webhookを受け取るURLです
- 通知イベント
Webhookを受け取るイベントです

エンドポイントURLにはPOSTメソッドで呼ばれます。Content-Typeはapplication/jsonになります。通知イベントは以下の3つが用意されています。

- ドロップ
エラー停止リスト内にあるメールアドレス宛に送信しようとした場合のエラーです
- ハードエラー
ホストがない、ユーザーがいないといった恒久的なエラーです
- ソフトエラー
メールボックスがいっぱいなど一時的なエラーです

## 注意点

2024年11月現在、Webhookはトランザクションメール（即時配信メール）に対してのみ有効です。バルクメール（一括配信）やSMTPリレーは未対応です。

## データを受け取ってみる

では実際にデータを受け取ってみます。今回はRubyで以下のようなコードを書きました。

```ruby
require 'json'

def lambda_handler(event:, context:)
    data = JSON.parse(event['body'])
    puts data['events'][0]['event']['detail']['error_message'] # 宛先のメールアドレスがありません
    { statusCode: 200, body: JSON.generate('ok') }
end
```

以下はドロップの例です。 `error_message` にエラー内容が入ります。

```json
{
	"events": [
		{
			"event": {
				"type": "DROP",
				"datetime": "2023-01-26T16:17:54+09:00",
				"detail": {
					"mailaddress": "user@drop.example.com",
					"subject": "Test subject",
					"error_code": "554(errors)",
					"error_message": "エラー停止リストに含まれる宛先であるため、配信がドロップされました",
					"delivery_id": 1128
				}
			}
		}
	]
}
```

以下はハードエラーの場合です。ホストがない、ユーザーが存在しないなど恒久的に発生する場合のエラーです。

```json
{
	"events": [
		{
			"event": {
				"type": "HARDERROR",
				"datetime": "2023-01-26T16:22:43+09:00",
				"detail": {
					"mailaddress": "user@harderror.example.com",
					"subject": "Test subject",
					"error_code": "550",
					"error_message": "宛先のメールアドレスがありません",
					"delivery_id": 1129
				}
			}
		}
	]
}
```

## まとめ

データが受け取れれば、後はSlackへ通知したり、データベースと連携するなどが容易になります。配信先リストを自動クリーニングするのにも使えるでしょう。

一例としてZapier経由でSlackへ通知するデモを[blastengineのwebhook機能でメール送信が失敗したらzapier経由でSlackに通知できるようにした。 - Qiita](https://qiita.com/hirosatooooo/items/21573f79fbb8599090d1)にて紹介しています。ご覧ください。

[エンジニア向けメール配信システム「ブラストエンジン（blastengine）」](https://blastengine.jp/)
いにしえのCPUで円周率を１万桁計算するプログラムを作ってみた


# 概要
- いにしえの 8bit CPU NS製 SC/MP-III に関する記事です。
- C言語で書かれたSC/MP-III CPUエミュレータ上で、円周率を計算してみました
- ソースコードは公開です。
  https://github.com/iruka-git/SCMP3_Calc_Pi

# 計算方法の概要
- ごく普通にマチンの公式を用いています。
- arctan()の計算はマクローリン級数を固定小数点の多倍長演算で計算していきます
- C言語で記述した、Linux上で動作するソースも同梱しています。(SC/MP-IIIでは動きません)
- それをSC/MP-IIIのCPUに落とし込んだものが本題です。



# SC/MP-III は SC/MP-IIとどこが違うの？
- SC/MP-IIIは EレジスタとAレジスタを連結して16bitレジスタとして使えるようになりました。
- ポインタオフセットが0x80(-128)だったときに、オフセット値をEレジスタの内容に読み替える処理は、無くなりました。
- 6800/6502系のゼロページアドレッシングに近い、FFxxページの256バイトを直接参照するダイレクトアドレッシングが出来るようになりました。
- ポインタ P1 がスタックポインタになり、16bit 絶対番地指定のJSR命令やJMP命令 が追加されました。
- 乗除算用にTレジスタ(16bit)が追加され、16bitの乗算/除算命令がそれぞれ追加されています。

# 独自言語Asmpp3 を公開（同梱）しています。
- C言語風の記述、どちらかというとFORTHに近いかも。
- サブルーチン関数は定義できます。
- 変数や戻り値などの型はありません。
- 関数引数はありません。暗黙的にはレジスタ(A,E,EA,P2,P3など)をそのまま使います
- asm の表現と混在できます。

# SC/MP-IIIのどこがだめ？
- SC/MP-III エミュレータとか、独自言語を入れてみて、だめだったことを記述します。

- 比較命令(cmp) がない。減算で代用。（できるか！A regが毎回壊れる。）
- 大小比較の結果の取得や分岐が大変面倒。条件分岐命令が A regの内容でしか分岐できない。しかも条件分岐命令は BZ、BNZ、BP (Aregが正) の３個のみ。
- さらに 16bitレジスタ EA の値を大小比較しようとすると、もっと面倒なことに・・・
- キャリーフラグを含む加減算命令が（SC/MP-IIにはあったのに）抜かれている。
- 多倍長演算を行うには限りなく不利。

- まあ、それ以外は、可もなく不可もなく、16bit同士の乗除算命令がある8bitレガシーCPUは珍しいんですけどね。・・・

# 円周率1万桁の計算時間
- 軽く見積もったところ55時間という結果が出ました。

- ウェィトを設けないエミュレータ上では3分で計算できています。

- 最適化をいくつか実施すれば数分の１に短縮できるかも。
- （収束した級数は最初にずっとゼロが続いているので、除算をスキップできる）
- （除数が8bitに収まっている条件ではCPUのDIV命令を使って多倍長除算を構成できる可能性）


# 参考
- http://www.st.rim.or.jp/~nkomatsu/miscproc/INS8070.html
-
blastengineのメールエラーWebhookをAWS Lambda + Pythonで処理する


[blastengine](https://blastengine.jp/)はエンジニアフレンドリーなメール送信サービスになります。APIまたはSMTPを使って、簡単にメール送信を行えます。

blastengineではエラーメールに対するWebhook通知をサポートしています。この記事では、その扱い方とデータについてAWS Lambda + Pythonによる処理を通じて解説します。

## 設定

Webhook設定はblastengineの管理画面で行います。設定の中にあるWebhookをクリックします。

![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/059adabd-6159-2cd4-12d3-9d98c075b1c2.jpeg)

設定は主に2つです。

- エンドポイントURL
Webhookを受け取るURLです
- 通知イベント
Webhookを受け取るイベントです

エンドポイントURLにはPOSTメソッドで呼ばれます。Content-Typeはapplication/jsonになります。通知イベントは以下の3つが用意されています。

- ドロップ
エラー停止リスト内にあるメールアドレス宛に送信しようとした場合のエラーです
- ハードエラー
ホストがない、ユーザーがいないといった恒久的なエラーです
- ソフトエラー
メールボックスがいっぱいなど一時的なエラーです

## 注意点

2024年11月現在、Webhookはトランザクションメール（即時配信メール）に対してのみ有効です。バルクメール（一括配信）やSMTPリレーは未対応です。

## データを受け取ってみる

では実際にデータを受け取ってみます。今回はPythonで以下のようなコードを書きました。

```python
import json

def lambda_handler(event, context):
    data = json.loads(event['body'])
    events = data.get('events', [])
    event = events[0].get('event', {})
    print(event['detail']['error_message']) # 宛先のメールアドレスがありません

    return {
        'statusCode': 200,
        'body': json.dumps('ok')
    }
```

以下はドロップの例です。 `error_message` にエラー内容が入ります。

```json
{
	"events": [
		{
			"event": {
				"type": "DROP",
				"datetime": "2023-01-26T16:17:54+09:00",
				"detail": {
					"mailaddress": "user@drop.example.com",
					"subject": "Test subject",
					"error_code": "554(errors)",
					"error_message": "エラー停止リストに含まれる宛先であるため、配信がドロップされました",
					"delivery_id": 1128
				}
			}
		}
	]
}
```

以下はハードエラーの場合です。ホストがない、ユーザーが存在しないなど恒久的に発生する場合のエラーです。

```json
{
	"events": [
		{
			"event": {
				"type": "HARDERROR",
				"datetime": "2023-01-26T16:22:43+09:00",
				"detail": {
					"mailaddress": "user@harderror.example.com",
					"subject": "Test subject",
					"error_code": "550",
					"error_message": "宛先のメールアドレスがありません",
					"delivery_id": 1129
				}
			}
		}
	]
}
```

## まとめ

データが受け取れれば、後はSlackへ通知したり、データベースと連携するなどが容易になります。配信先リストを自動クリーニングするのにも使えるでしょう。

一例としてZapier経由でSlackへ通知するデモを[blastengineのwebhook機能でメール送信が失敗したらzapier経由でSlackに通知できるようにした。 - Qiita](https://qiita.com/hirosatooooo/items/21573f79fbb8599090d1)にて紹介しています。ご覧ください。

[エンジニア向けメール配信システム「ブラストエンジン（blastengine）」](https://blastengine.jp/)
【Ruby】今日書いたコードの振り返り(CSVライブラリ)#13

# はじめに
こんにちは！アメリカで独学でソフトウェアエンジニアを目指している者です。
本日は Ruby の Array クラスの演習をしていたところ、標準ライブラリの CSV を使う機会があったので、使い方を忘れないうちに備忘録として記事にまとめようと思いました。

## 問題内容
1. users.csv が以下のような形式で与えられます。（ヘッダ行あり）
```csv
name,age
Alice,30
Bob,25
Carol,35
```
2. これを読み込んで、[{name: "Alice", age: 30}, {name: "Bob", age: 25}, ...] のような配列として扱ってください。
3. 配列を age 昇順（年齢が小さい順）にソートし、結果を出力してみましょう。

## 解答例
Chatgpt o1にて出力しました。あくまでも解答例です

```ruby
require 'csv'

users = []

CSV.foreach("users.csv", headers: true) do |row|
  users << {
    name: row["name"],
    age:  row["age"].to_i
  }
end

# ageの昇順にソート
sorted_users = users.sort_by { |u| u[:age] }

puts "ソート結果:"
sorted_users.each do |user|
  puts "#{user[:name]} (#{user[:age]})"
end

```
`users.csv`のファイル内容は以下の通りとします。
```csv:users.csv
name,age
Alice,30
Bob,25
Carol,35
```

### 解説
1. `CSV.foreach("users.csv", headers: true) do |row|`
* `CSV.foreach`: CSVライブラリの特異メソッド`foreach`を使用しています。
* `headers: true`: オプションで`true`にすると最初の行はヘッダー(列名)として扱われます。なおデフォルトは`false`です
* `row`: CSV::Row オブジェクトで、ハッシュに似た操作が可能です。ただし、厳密にはハッシュではありません。
2. `users << {name: row["name"], age: row["age"].to_i }`
* `row["name"]`: CSVファイルの「name」列に入っている文字列データを取得します。
* `row["age"]`: CSVファイルの「age」列に入っている文字列データを取得します。


## まとめ
今回、Ruby の標準ライブラリである CSV を使ってファイルを読み込み、配列に格納する方法を学びました。演習として CSV::Row を用いる形を初めて知ったのですが、実務でもデータの取り込みで頻出する処理だと思うので、とても良い学習になりました。
AWS Marketplaceに年間前払いがあるって知ってますか？

どうも！[株式会社ShowcaseGig](https://www.showcase-gig.com/)でSREとして働いている [@atsusics](https://x.com/atsusics) です

最近はAWSを中心としたコスト削減を進めていて、新しいコスト削減策がないかなと思いながら日々コストエクスプローラーを眺めています

今回はあまり話題にならないAWSコスト削減方法を紹介します

# コスト削減策 ~AWS Marketplace編~
皆さんは[AWS Marketplace](https://aws.amazon.com/jp/mp/marketplace-service/overview/)を利用していますか？

一番よく聞くのは、AMI (Amazon Machine Image) を利用して、必要なソフトウェアをすぐに EC2 インスタンス上で起動するような使い方かなと思います。弊社でもNetgate pfSenseを利用しています

そこで、料金表を見ていると赤枠で囲った部分が初めて目に入りました
今まで従量課金で払っていてあまり気にしていなかったので、年間前払いに気づいていなかったようです

![20250123.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261535/09ddb230-65c0-e297-d111-1d736e40cf8d.png)

公式ドキュメントを確認
https://docs.aws.amazon.com/ja_jp/marketplace/latest/buyerguide/buyer-ami-subscriptions.html

Netgate pfSenseの場合は年間前払いにするだけで20％offになるので、継続的に利用する場合はお得ですね！

# 最後に
参考程度にいくつか年間前払いの割引率を調査しました

| 製品名 | 割引率 |
|:-:|:-:|
| Netgate pfSense Plus Firewall/VPN/Router   |  20% |
| Fortinet FortiGate Next-Generation Firewall  | 69%  |
| Cisco Secure Firewall ASA Virtual  |  62% |
| F5 BIG-IP Virtual Edition  |  44% |

本番ワークロードで利用している場合だと、割と馬鹿にできない金額コスト削減できるかと思います

もしAWS Marketplaceを利用している方がいたら、一度検討してもらえればと思います！
MAMP 7.2.0 (Mac/ARM) htmlファイルでphpを実行

これまで（6.9.0とか）は.htaccessに
````
AddType application/x-httpd-php .php .phtml .html .htm
````
で動いていましたが
````
AddHandler php-fastcgi .html .htm
````
で動きました。

.htaccessでリダイレクトしていると「500 Internal Server Error」になったので、設定ファイル
/Applications/MAMP/conf/apache/httpd.conf
内以下のコメントアウトを解除しmod_rewriteを有効にしましょう。

````
LoadModule rewrite_module modules/mod_rewrite.so
````

ありがとうございました。
UFWを活用してOpenVPN経由の通信のみ許可する方法

今回はUFWの設定により、OpenVPN接続している端末において、OpenVPNサーバを経由した通信のみ許可する方法について書いていきます。つまり、VPNがリンクダウンした時に、通信が外へ漏れないようにする方法です。早速設定に写っていきます。

:::note
この記事は[こちら](https://manacra.com/openvpn-ufw/)でも紹介しています。
:::

## 設定方法

まず、UFWを有効化する前に必ずSSH接続を許可するようにします。この設定をしないと、外部から接続不能になってしまいます。

```
$ sudo ufw allow in on enp3s0 from 192.168.1.0/24 port 22 proto tcp
$ sudo ufw allow out on enp3s0 to 192.168.1.0/24 port 22 proto tcp
```

ローカルネットワークのサブネットは各環境に合わせて適宜修正してください。

次にデフォルトポリシーをIncomingとOutgoing共に禁止するように変更します。

```
$ sudo ufw default deny incoming
$ sudo ufw default deny outgoing
```

そしてOpenVPNインターフェースにおける全ての通信を許可します。

```
$ sudo ufw allow in on tun0
$ sudo ufw allow out on tun0
```

最後に物理インターフェースにおけるOpenVPN通信のみを許可します。

```
$ sudo ufw allow out on enp3s0 to any port 1194
$ sudo ufw allow in on enp3s0 from any port 1194
```

これで設定が一通り終わりました。あとはUFWを有効化して完了です。

```
$ sudo ufw enable
```

設定を確認してみます。

```
$ sudo ufw status verbose
```

適切に設定されていることを確認できたら成功です。

## まとめ

このようにUFWをうまく使いこなすことで、安全な通信を実現できます。セキュアなサーバを構築するのに役立つと幸いです。今回は以上です。
【langchain v0.3】ChatOpenAIの使い方メモ（構造化出力、tool_call）

# 概要
langchain v0.3のChatOpenAIの構造化出力、tool_callのやり方をよく忘れるので自分用にまとめました。

# 準備

```sh
pip install langchain langchain-openai
```

環境変数OPENAI_API_KEYを指定します。もしくはプロジェクトのルートに`.env`を作成しOPENAI_API_KEYを指定します。

# 構造化出力

pydanticのBaseModelまたはTypedDictをmodel.with_structured_outputに渡せばよいです（[参考](https://python.langchain.com/docs/how_to/structured_output/)）

## Pydantic

pydantic.Fieldは変数の説明を加えたいときに使います。変数名のみで意味が明確であれば不要です。

```Python
from pydantic import BaseModel, Field
from langchain_openai import ChatOpenAI

class AnswerWithConfidence(BaseModel):
    answer: str = Field(description="回答")
    answer_is_based_on_reference: bool = Field(description="参考文献に基づいて正確な回答を作成できたかどうか。参考文献が情報不足の場合などはFalseとする。")

model = ChatOpenAI(model="gpt-4o-mini")
model_with_structured_output = model.with_structured_output(AnswerWithConfidence)

output = model_with_structured_output.invoke("質問: この世界で５０番目の山の高さは？、参考文献: この世界で５０番目に高い山は富士山です。")
print(output.answer)
print(output.answer_is_based_on_reference)
```

```
富士山の高さは3,776メートルです。
True
```

## TypedDict
pydantic.BaseModelの代わりにTypedDictを使うこともできます。
Annotatedは変数の説明を加えたいときに使います。変数名のみで意味が明確であれば不要です。

```Python
from langchain_openai import ChatOpenAI
from typing import TypedDict, Annotated

class AnswerWithConfidence(TypedDict):
    answer: Annotated[str, ..., "回答"]
    answer_is_based_on_reference: Annotated[bool, ..., "参考文献に基づいて正確な回答を作成できたかどうか。参考文献が情報不足の場合などはFalseとする。"]

model = ChatOpenAI(model="gpt-4o-mini")
model_with_structured_output = model.with_structured_output(AnswerWithConfidence)

output = model_with_structured_output.invoke("質問: この世界で５０番目の山の高さは？、参考文献: この世界で５０番目に高い山は富士山です。")
print(output["answer"])
print(output["answer_is_based_on_reference"])
```

```
富士山の高さは3,776メートルです。
True
```

# tool_call
tool_callはtoolを定義して、model.with_toolsに渡します（[参考](https://python.langchain.com/docs/how_to/tool_calling/)）。
toolの定義はpydanticかTypedDictか`@tool`デコレータを使います。
ここではデコレータを使います。

```Python
from typing import Literal
import sys
from langchain_core.tools import tool
from langchain_core.messages import HumanMessage

@tool
def weather_tool(weather: Literal["sunny", "cloudy", "rainy"]) -> None:
    """Describe the weather"""
    print(f"The weather is {weather}")


model_with_tools = model.bind_tools([weather_tool])

message = HumanMessage(
    content=[
        {"type": "text", "text": "天気をランダムに教えて"},
    ],
)
response = model_with_tools.invoke([message])
print(response.tool_calls)

function_name = response.tool_calls[0]["name"]
function_args = response.tool_calls[0]["args"]

module = sys.modules[__name__]  # 現在のモジュールを取得
getattr(module, function_name)(function_args)
```

```
[{'name': 'weather_tool', 'args': {'weather': 'sunny'}, 'id': 'call_6ffI1FLNwPrTWfyXIBVnCgLB', 'type': 'tool_call'}]
The weather is sunny
```

デコレータでツール化された関数は引数の辞書を受け取る仕様になっているので、`**function_args`ではなく`function_args`を与えていることに注意してください。
New Relic アップデート(2024年12月)

2024年12月のNew Relic のアップデートをまとめて紹介です！AWS CloudWatchのメトリクスやログの転送をこれまで以上に簡単にセットアップできるようになりました！！

## [Cloud Integration] AWSのデータ統合のセットアップが効率化
これまで、AWS CloudWatchのメトリクスや複数個所に点在するログは、個別に転送設定を行う必要がありましたが、一つのCloudFormation テンプレートを使用して、複数の転送設定を数分でセットアップできるようになりました。
![update202412-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485441/92aa2cbd-1b21-0f48-c88c-aa114012b6b3.png)

アップデートの詳細につきましては以下Qiita記事が参考になります。

https://qiita.com/nr-mito/items/c4e528840294ef9e3a6b

## [Browser] Core Web VitalsのINPでより詳細な計測が可能に
Browser エージェント v1.267.0からCore Web VitalsのINPのより詳細なデータを取得できるようになりました。ユーザー操作から次の描写が完了するまでの応答性でどこにボトルネックがあるか、より正確に把握して改善できるようになります。
![update202412-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485441/2c347047-6a70-3677-980a-f2281a365ccf.png)

Core Web VitalsのINPについては以下サイトの記事が参考になります。

https://web.dev/articles/inp

## [Security] OSS脆弱性スキャナFOSSAとの連携で脆弱性管理を更に容易
OSS脆弱性スキャナFOSSAと連携し、検知した脆弱性をNew Relicの脆弱性管理に統合可能になりました。ビルド時とランタイムの脆弱性を１箇所に統合し、最初に対応すべき脆弱性の優先順位付けした上で脆弱性を更に容易に管理できるようになります。
![update202412-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3485441/3e38f0a5-9bf1-552c-6a33-41965a344c78.png)

アップデートの詳細はこちらのブログでご確認ください。
↓↓↓↓↓↓

https://newrelic.com/jp/blog/nerdlog/new-relic-update-202412

- **2024年12月アップデート**
  - Cloud Integration: AWSのデータ統合のセットアップが効率化
  - Browser: Core Web VitalsのINPでより詳細な計測が可能に
  - Security: OSS脆弱性スキャナFOSSAとの連携で脆弱性管理を更に容易
AWS関連のメモ

## 日本のAWS導入における経済効果

https://aws.amazon.com/jp/about-aws/whats-new/2024/01/aws-commits-2trillion-yen-investment-into-japan-ai-and-digital-transformation-from-2023-to-2027/

>AWS が日本にもたらす経済効果に関するレポートによると、今回の投資計画は**日本の国内総生産（GDP）に 5 兆 5,700 億円**貢献し、国内企業で**年間平均 30,500 人以上の雇用**を支える見込み

2023年の日本のGDPが約600兆円なので、GDP増加に1%寄与する予想。
年平均で3万人の雇用増加は、AWS関連という広い範囲ではもっとありそう。

Amazon Web Services, Inc.がAWSの経済効果に関するレポートを出して、細かい数字も出て興味深い。

https://d1.awsstatic.com/ja_JP/PR/economic-impact-study-report.pdf

## AWS プレミアティア サービスパートナー
 日本では2024年6月時点で15社

https://aws.amazon.com/jp/blogs/psa/tag/premier-tier-services/

>AWS プレミアティアサービスパートナーは、最も経験豊富なパートナーで、それぞれの地理的市場、垂直市場、または水平市場のリーダーとして認知されています。このパートナーは、複数のパートナープログラムの検証に関する深い技術的な専門知識を持ち、数多くのお客様と大規模に協力してきた実績を持ちます。

1. アイレット
   https://www.iret.co.jp/news/20240318_2.html
1. CTC
   https://www.ctc-g.co.jp/company/release/20220331-01418.html
1. SCSK
   https://www.scsk.jp/sp/usize/service/aws.html
1. NHNテコラス
   https://aws.amazon.com/jp/blogs/psa/aws-premier-nhntechorus/
1. NTTデータ
   https://dc.jp.nttdata.com/cloud/index/awssolutions.html
1. クラスメソッド
   https://classmethod.jp/aws/certification/
1. サーバーワークス
   https://www.serverworks.co.jp/point/
1. TIS
   https://www.tis.jp/service_solution/aws/
1. NEC
   https://jpn.nec.com/cloud/service/aws/index.html
1. NRI(野村総合研究所)
   https://atlax.nri.co.jp/news/20220928_2/
1. 株式会社日立システムズ
   https://aws.amazon.com/jp/blogs/psa/aws-premier-hitachisystems/
1. 富士ソフト
   https://aws.amazon.com/jp/blogs/psa/fsi-premier-apn/
1. 富士通株式会社
   https://aws.amazon.com/jp/blogs/psa/aws-premier-fujitsulimited/
1. 株式会社TOKAIコミュニケーションズ
   https://aws.amazon.com/jp/blogs/psa/aws-premier-tokai/
1. 株式会社ＢｅｅＸ
   https://aws.amazon.com/jp/blogs/psa/aws-premier-beex/

## 日本国内の協業契約企業
 日本では2024年2月時点で8社

1. 日本電気株式会社（NEC） 2020年10月
   https://jpn.nec.com/press/202011/20201113_01.html
1. クラスメソッド 2021年10月
  https://classmethod.jp/news/20211004-sca/
1. NTT データ 2021年12月
  https://www.nttdata.com/global/ja/news/release/2021/121600/
1. 富士通 2022年5月
  https://pr.fujitsu.com/jp/news/2022/05/18.html
1. サーバーワークス 2023年4月
  https://www.serverworks.co.jp/news/20230414_aws_sca.html
1. SCSK株式会社 2023年10月
  https://www.scsk.jp/news/2023/pdf/20231023.pdf
1. 日立 2024年3月
  https://www.hitachi.co.jp/New/cnews/month/2024/03/0311.html
1. NHNテコラス 2024年1月
  https://nhn-techorus.com/c-chorus/sca/
Qiita Advent Calendar 2024受賞者発表！ご参加してくださった皆様本当にありがとうございました！

# 今回のイベントを終えて...
まずは、[Qiita Advent Calendar 2024](https://increments.connpass.com/event/336093/)のイベント、
[Markdown AIのサーバーAI機能を使ってWebサイトを作ってみよう](https://qiita.com/advent-calendar/2024/markdownai) にご参加いただいた皆様、**本当にありがとうございました。**

本当に多くの方々にご参加いただき、「Markdown AI」を活用したハイクオリティなツールや、個性が光るオリジナリティ溢れる作品、さらには「なるほど！」と驚かされるようなユニークな使用方法を生み出してくださり、運営としても大きな刺激を受けました。公式の立場から見ても、参考になる素晴らしい記事が多数あ、非常に充実したイベントとなりました。

イベントの受賞者については、Qiita公式ブログにて発表されていますので、ぜひご覧ください。
**また、この記事では惜しくも受賞には至らなかったものの、特に素晴らしい内容の記事も併せてご紹介させていただきます。**

**【Qiita Advent Calendar 2024 プレゼントカレンダー 結果発表！】**

https://blog.qiita.com/adventcalendar-2024-presents-winners/

# 受賞者の発表

## 最優秀賞
**タイトル：** 

https://qiita.com/shikuno_dev/items/8986c605dbb1edf58a05

**制作者：** @shikuno_dev 様

**コメント：**
UIや機能面において、制作していただいたツールのクオリティが非常に高く、その技術力を評価して最優秀賞に選出させていただきました。
さらに、技術力の高さだけでなく、複数のテンプレートが用意されている点や直感的に操作できる親切な設計など、ユーザー目線に立った工夫が随所に見られる点も大きな評価ポイントとなりました。

## Creative賞
**タイトル：** 

https://qiita.com/shuji4649/items/dcf8dd7ae9705be9758e

**制作者：** @shuji4649 様

**コメント：**
ツールがとても実用的かつ明確で、プログラマーの方々が日常の中で自然に取り入れられるツールとして、完成度の高さを感じました。
また、直感的な操作性と機能のシンプルさが相まって、幅広い層のユーザーにとって使いやすい設計となっている点も素晴らしかったです。

## Fanny賞
**タイトル：** 

https://qiita.com/hayuse/items/24d3a59011ace883a542

**制作者：** @hayuse 様

**コメント：**
記事内容もユニークで、ツール自体も優れたデザインと演出が際立つコンテンツでした。
シンプルなツールながら、視覚的な美しさと使いやすさを兼ね備えていて、Markdown AIの可能性を十分に引き出し、新たな活用方法を提示してくれた点が大変印象的だったので、Fanny賞に選出させていただきました。

# 惜しくも賞を逃した方々
**タイトル：** 

https://qiita.com/Sakai_path/items/785233d50b5b562dce4a

**制作者：** @Sakai_path 様

**コメント：**
ゲームの構造やコードはシンプルながら、AIMの練習などに活用できる実用性の高いツールとなっており、好印象を受けました。さらに、スマートフォンやタブレットでも快適に遊べるよう、タッチイベントの実装などの工夫が施されている点も評価のポイントとなりました。
このツールの様にアイディア次第で、シンプルながら実用的なツールが今後も出てきて欲しいと思える内容でした。

---

**タイトル：** 

https://qiita.com/gomagoma000/items/9a99afff661536743f22

**制作者：** @gomagoma000 様

**コメント：**
謝罪メッセージを自動生成するというユニークなコンセプトが光る作品でした。
さらに、入力項目として「何についての謝罪」「相手の立場」「謝罪の深刻度」「トーン」などが用意されており、様々な場面に対応できる拡張性の高さも魅力です。日常生活からビジネスシーンまで、幅広い用途で活用できる実用的なツールとなっていました。

---

**タイトル：** 

https://qiita.com/yu_uk/items/9ef8ca6aeb50eb15236d

**制作者：** @yu_uk 様

**コメント：**
実際に触ってみてのインパクトがとても大きいツールでした。
まず、サイトのデザインが2000年代初期を思わせる雰囲気で、懐かしさを感じました。また、プロンプトが優秀で入力した内容に合わせて違和感の無いギャル語で絵文字も沢山使われていて、笑みが溢れるツールでした。

# 最後に
改めて、イベントへご参加いただいた皆様に、**心より感謝申し上げます。**
今回のイベントを通じて、参加者の皆様が繰り返しツールを活用し、**試行錯誤を重ねながらアイデアを形にしていく過程**を拝見できたことは、非常に意義深いものでした。

イベントを通じて、「Markdown AIをもっと活用したい！」という熱意や挑戦する姿勢 に触れることができ、**私たちも多くの学びと刺激を得ることができました。**

このイベントが、皆様にとっても新たな発見や成長のきっかけとなっていれば幸いです。

最後に、改めましてご参加いただいた皆様、本当にありがとうございました！