OmniAICreator/Qiita-1.07M huggingface dataset:
【VSCode】スクロールをスムーズにする方法

`settings.json`に以下の記述を追記するとエディタが滑らかにスクロールするようになります。

```jsonc:settings.json
"editor.smoothScrolling": true
```

リストやターミナルも滑らかにスクロールするよう設定できます。

![スクリーンショット 2024-06-15 23.53.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/8eb307f1-925a-845b-7286-048c095baecc.png)

```jsonc:settings.json
{
  "workbench.list.smoothScrolling": true,
  "terminal.integrated.smoothScrolling": true
}
```
Azure上のADサーバをEntra Connectさせてみた


# はじめに

Azure上にADサーバを作ってみたので、記事にしました。
参考にした記事の紹介と、ハマった部分を紹介します。

# 手順

ADサーバの構築はこちらの記事を参考にさせていただきました。
かなり丁寧に解説してくださっています。
Azureの基礎がわかってとにかくADサーバ構築だけが知りたいという方は、VM作成後から参照するといいと思います。

https://qiita.com/carol0226/items/084fbbb3f31b646025f4

Connectもこちらの方の記事を参考にしました

https://qiita.com/carol0226/items/487874f07d2fe90f8e0c#-ad-ds-%E3%81%AE%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E5%90%8D%E3%82%92-microsoft-entra-%E3%83%86%E3%83%8A%E3%83%B3%E3%83%88%E5%90%8D%E3%81%AB%E5%90%88%E3%82%8F%E3%81%9B%E3%82%8B


# ハマったポイント

①Connectの要件
ドメイン名はAzureテナントと同じ「xxxx.onmicrosoft」にしておくととても簡単です。
私はConnectする際にドメイン名を合わせないと苦労することを知らず、一度削除してやり直しました。（泣）
実際にオンプレADとConnectさせることがある方は、ADサーバ側のドメインがすでに決まっていることが多いと思いますので
この方法は使えませんが、さくっと検証する場合はAzureテナントに合わせて作成するのがよいです。


②Connectエラー
何故かエラーがでて、中々Connectできずでした。
原因を探ると以下の記事と同様の症状だとわかりました
https://jpazureid.github.io/blog/azure-active-directory-connect/azure-ad-connect-2-3-20/

記事中にも紹介されていますが、下記のコマンドを使ってTLS1.2を強制することで解消しました。

https://learn.microsoft.com/ja-jp/entra/identity/hybrid/connect/reference-connect-tls-enforcement#powershell-script-to-enable-tls-12

# Connect完了後

AD上で作成したユーザがAzure portalのEntra ID上からも確認できるようになります。
AD上ユーザはEntra IDの画面からは大した操作はできないので、基本的にADにRDPして操作します。（パスワードリセットなど）

# 最後に

簡単ですが、Entra Connectをしてみた記事でした。
今後も試したことは記事にしてみようと思っています。
初めてNoSQLに触れて思ったこと

一年を振り返る Advent Calendar 2024の24日目です。もう少し頑張る。短い記事を淡々と。

これまでずっとOracleのRDBMSしか触ったことなかった人間ですが、人生で初めてNoSQLに触れてみて設計思想とか全然違ったのでメモ。

NoSQLの中で具体的に触ったのがDynamoDBでキーバリューDBに触れたので、その知見ベースの記事なります。

とりあえず最初に見たのはAWSさんのこの動画です。2年前の動画ですが、個人的には入りとしてめちゃくちゃわかりやすかった。

#### 今から理解する NoSQL Databases〜 ケーススタディと実践的データモデリング 〜(AWS-44)

https://youtu.be/LdMO5HVao7g?si=MS3roHGaq56Bkpxn

とりあえず思ったことを3つほどメモ。

## JOINがない
最初にまじかよと思いましたが、NoSQLでは基本的にJOINの機能が提供されないみたいです。なのでアプリケーション側で吸収してあげたり、そもそもテーブル設計のタイミングでちゃんと考えておかないといけないなぁ、というのが学びでした。

https://zenn.dev/ryokkkke/scraps/c13d07ab1e8b09
この記事のコメントにある以下の内容が自分もとてもしっくりきました。

- つまり、RDBは実行時に join するが、 NoSQL では設計時に join する、というイメージ。

データのとり方もうちょい理解するにあたってGSIとかLSIとかセカンダリインデックスもうちょいちゃんと理解しないとなぁと。

## テーブル設計は非正規化していく
上記に関連するところもありますが、DB設計するにあたってテーブルを非正規化していくという今までなかった行為をしないといけないのが新鮮でした。
テーブル設計の考え方、この記事が色々わかりやすく書いてくれてるなと思いました。

https://atmarkit.itmedia.co.jp/ait/articles/1103/25/news131_3.html

やっぱテーブル設計って大事だなぁと思いました。こういうの上手に設計できるように勉強していきたい。

## 排他制御が緩い
特性上一貫性を捨てて並列処理しやすいようにしているからだと思いますが、排他制御もアプリケーション側でゴリゴリ設計していかないといけないなぁという印象を持ちました。というか、ACID特性重視するのであればNoSQL使うべきじゃないんやろうなという印象です。

## まとめ
データベースも用途によって使い分けできるよう知見広げていきたいです。頑張って勉強していきます。
day13 『認知バイアス事典』

## はじめに
　YouTubeを見ていたら、[心理学者が語る『頭がわるいとはどういうことなのか/「バカ」の研究』（GabalaboCH-ガバラボ）](https://www.youtube.com/watch?v=zunptLMypL8&list=LL&index=156&t=16s)で、シコッティ談 『誰もが騙されるバイアスに過剰に反応してしまう人』と、認知バイアスが強調されていました。
 
 ![認知バイアス事典 目次2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533414/5bb9440d-e62f-486f-c9aa-9950a80102ea.png)


  
## ポイント

### 第１部　論理学的

##### 二分法の誤謬
選択肢が、限られていると思い込んでしまう間違い。

##### ソリテス・パラドックス
定義が曖昧な語を用いることによって生じる間違い。

##### 多義の誤謬
同じ語が、異なる意味で用いられることで生じる間違い。

##### 循環論法
論証されるべき結論を、前提として用いる議論。

##### 滑りやすい坂論法
最初のステップが、その後の一連の悪い結果を必然的に起こしてしまう。よって、最初のステップを起こさないようにせよと主張する。

##### 早まった一般化
十分なデータが出揃う前に一般化を行う。

##### チェリー・ピッキング
都合の良い特定の証拠だけに注目し、それ以外の不都合な証拠を無視する。

##### ギャンブラーの誤謬
１回毎の試行が独立な時系列（表か裏か）の事象について、次回は前回とは異なる別のもの（今回表なら次回は裏）が出ると考える間違い。

##### 対人論法
問題の論点ではなく、論じている人の資質などを批判することで、相手の主張を退ける。

##### お前だって論法
相手の主張がその人の振る舞いと異なることを指摘し、論点をそらすことで相手を負かそうとする論法。

##### 藁人形論法
相手の主張を単純化したり、極端にするような操作をし、その歪めた主張に反論すること。

##### 希望的観測
好ましい結果が起こることを、好ましくない結果が起こることより期待すること。

##### 覆面男の誤謬
置き換えについての知識不足によって生じてしまう間違い。

##### 連言錯誤
「ＡかつＢ」と「Ａ」の選択肢があるとき、「Ａ」である確率より、「ＡかつＢ」である確率が高いと判断する間違い。

##### 前件否定
「もしＡならばＢである」に対して、「Ａではない」「したがってＢではない」に関する間違い。

##### 後件肯定
「もしＡならばＢである」に対して、「Ｂである」「したがってＡである」に関する間違い。

##### 四個概念の誤謬
三段論法の３つの概念に４つ目を加えることで生じる間違い。

##### 信念バイアス
導き出された結論が「信じられる」内容であったとき、その結論が、たとえ妥当ではない論証によって導き出されていても、その結論を信じてしまう。
信念のほうが論証による結論の正しさよりも重視される。

##### 信念の保守主義
情報が与えられても即座には信念を更新することができない。

##### 常識推論
人間が日常生活の中で行っている推論。？


---

### 認知科学的

（略）

---

### 社会心理学的

##### 単純接触効果
ある物事・人・刺激に繰り返し接すると、徐々にそれに対して好意的な感情を持つようになる。

##### 感情移入ギャップ
対象・人に対して、好意や怒りなどの感情を持っていると、感情を抜いて考えることが難しくなる。

##### ハロー効果
どこか優れている点を見つけると、その他も優れていると考える。

##### バーナム効果
ほとんどの人にあてはまるような性格についてのありがちな説明（例、占い）を、自分のことを言い当てているとして受け入れてしまう。

##### ステレオタイプ
血液型・性別・職業など、特定の集団かカテゴリに対して、個人の違いを無視して、１つの特徴でまとめてしまう。

##### モラル信任効果
社会的に意義のある活動をしている人が、少しくらい悪いことをしても世間は許すだろうと考える。

##### 基本的な帰属の誤り
他人の行動の原因について説明するとき、状況や環境の要因を軽視して、その人の能力や性格を重視しすぎる。

##### 内集団バイアス
自分の所属する集団やそのメンバを高く評価する。

##### 究極的な帰属の誤り
よそに厳しく身内に甘い。
自分が所属しない集団やそのメンバが成功したときは外的要因・状況を原因だとし、失敗したときは内的要因・才能や努力が原因だと考える。
逆に、
自分が所属する集団やそのメンバが成功したときは内的要因・才能や努力を原因だとし、失敗したときは外的要因・状況が原因だと考える。

##### 防衛的帰属仮説
良くないことが起こった時、加害者もしくは被害者で、自分に似た立場の方に自らを重ねて、反対の立場の人の責任を重く責める。

##### 心理的リアクタンス
自分の選択・行動の自由を制限されていると感じると、制限する者に対して反発し逆らう。

##### 現状維持バイアス
何かを変化させると現状をより良くなる可能性がある時でも、
損失の可能性を考慮して、現状を保持しようとする。

##### 公正世界仮説
良い行いには良いことが、悪い行いには悪いことが返ってくると思う。

##### システム正当化バイアス
現状の特定の社会システムが存在していること自体に価値を見出し、そのシステムを正当化し、維持しようとする。

##### チアリーダー効果
一人でいるときよりも、グループの中にいるときのほうが、人の顔は魅力的に見える。

##### 身元のわかる犠牲者効果
特定の個人の犠牲者には高い関心を示すが、人数や割合などの数値になると関心が低くなる。

##### 同調バイアス
他人の行動を参考にして、自分の行動を変える。

##### バンドワゴン効果
多くの人が同一の選択肢をとることで、その選択肢をとる人が更に増える。

##### ダニング=クルーガー効果
知識のない人ほど、自分には能力があると課題評価してしまう。
逆に、
知識が豊富で能力が高い人は、周囲も自分と同じ能力があると考え、自分を過小評価する。

##### 知恵の呪縛
自分が知っていることは他人も知っているだろうと思い込み、知識を持たない人の立場から考えることが難しくなる。

### バカな人？
これだけのバイアスを並べられて、それらに惑わされない人は確かに賢いと思いますが、バカの定義で使われるのは辛い・・・

## 書誌情報
- 書籍名：認知バイアス事典
- 著者：情報文化研究所
- 出版社：フォレスト出版
- ISBN：978-4-86680-123-0

## 参考
- ![シコッティ談 『誰もが騙されるバイアスに過剰に反応してしまう人』](https://www.youtube.com/watch?v=zunptLMypL8&list=LL&index=156&t=16s)
IBM Cloud Shellに定義された権限

# はじめに
こちらの記事は下記Advent Calendar 2024で紹介しているIBM Cloud権限設定における `IBM Cloud Shell` になります。

https://qiita.com/katahiro/items/274bec5ad4a9e2604dcf

# 共通権限は割愛
こちらの記事に記載しているように、プラットフォーム・アクセス、サービス・アクセスの権限でそれぞれどのようなものが共通して設定されているかを紹介させて頂きました。

https://qiita.com/katahiro/items/b5e367666fe984944d4b

こちらの記事では共通部分で出現する権限を除いた各サービス毎の権限設定を紹介します。

# IBM Cloud Shellで指定可能な権限のアクセス範囲
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/651598/ea6c6e7d-539b-73be-3fb2-8539b1a28efa.png)
- Region

## Regionの指定
IBM Cloud Shellの実行環境は現在ダラスとフランクフルトの2か所のみになります。実行環境としてどちらかでしか許さないケースがある場合、Regionを指定することで起動可能なCloud Shellを限定させることが可能です。

# IBM Cloud Shellに設定された権限
## プラットフォーム・アクセスの権限
※Admin : Administrator, KM : Key Manager, SCR : Service Configuration Reader
|権限|Viewer|Operator|Editor|Admin|KM|SCR|
|:---|:---:|:---:|:---:|:---:|:---:|:---:|
|cloudshell.config.read||||||〇|
|cloudshell.account-settings.update||||〇|||
|cloudshell.server.create||||〇|||
|cloudshell.server.manage-file||||〇|||
|cloudshell.server.preview-web||||〇|||

プラットフォーム・アクセスの権限指定では、Administrator権限を有する場合のみ利用可能となっています。
利用可能な機能を制限できるのはサービス・アクセス側の役割になります。

## サービス・アクセスの権限
|権限|クラウド・オペレーター|クラウド開発者|ファイル・マネージャー|
|:---|:---:|:---:|:---:|
|cloudshell.server.create|〇|〇|〇|
|cloudshell.server.manage-file|||〇|
|cloudshell.server.preview-web||〇||

通常Reader,Writer,Managerといった役割が構成されますが、Cloud Shellでは上記3つの役割のみが用意されています。
Cloud Shell自体はブラウザでアクセス可能な仮想Linux環境が立ち上がり、そこから利用するIBM Cloudアカウントに対して操作等を実施します。その関係で全ての役割にはサーバ起動権限が与えられます。

`クラウド・オペレーター`は上記Linux環境でコマンド実行のみを実施するケースを想定されています。
`クラウド開発者`は上記のLinux環境の特定のポートに対してブラウザでアクセスするWebプレビュー権限を持ちます。
`ファイル・マネージャー`はLinux環境とブラウザを通じてファイルのUpload/Downloadを実行する権限を持ちます。運用作業で実施した結果を取得といったことも可能です。

# さいごに
IBM Cloud Shellとして個別に設定されている権限は少なかったですが、サービス・アクセスで設定されている役割は他の権限と少し違う部分がありましたね。
IBM Cloud Shellで立ち上がるLinux環境はCLIが基本的に最新版になっており、ローカルPCだと時折プラグイン等Updateしないと使えないこともあるので、利用自体は重宝していたりします。
CLIの実行が何か情報収集に非常に有効にもかかわらず、誰かに話をする時にCLIのインストールが難しいというケースもあるので、そういう場合でもCloud Shellでの実行も案内したりします。

単純にCLIの実行以外にもWebプレビューやファイルの送受信といった機能もあるので、権限を設定してうまく利用して頂ければと思います。
ラッキーピエロ、更なる高みへ


以前このような記事を書きました。

https://qiita.com/yutowac/items/b8e3d7653d3dcad16faf

こちらの記事で、車でお店を回る最短ルートを求めましたが、実は計算が中々終わらないケースを発見し、巡る店舗とコースを少し工夫しました。

### その原因となった箇所がここ。
最短距離の計算、`NetworkX`の`shortest_path()`メソッドでした。
```python
import networkx as nx
nx.shortest_path_length(graph, current_node, start_node, weight='length')
```

`NetworkX`の公式ドキュメントを見ると、`method='dijkstra'`がデフォルトになっていて、この方法にはルート探索のループに入ってしまうカラクリがあります。

https://networkx.org/documentation/stable/reference/algorithms/generated/networkx.algorithms.shortest_paths.generic.shortest_path.html#networkx.algorithms.shortest_paths.generic.shortest_path


#### 改めて、パッケージの内容、理論はできるだけ良く理解しましょう！

## 代表的な計算方法
**dijkstra法** と **Bellman-Ford法** があります。

### dijkstra法
ダイクストラ法と読みます。
起点からの複数の頂点のうち最小距離の頂点を確定させ、そこを起点として複数の頂点から最小距離を選ぶということを全ての頂点を多るまで繰り返します。簡単に言うと一歩ずつ最短の方向を探すということです。

![Dijkstra_Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/bd1d2f0f-7f92-859c-8b01-23efb428c06d.gif)



### Bellman-Ford法
ベルマンフォード法は、負のエッジを持つグラフ内の2点間の最短経路の検索、負のサイクルの検出、グラフ内の最大フローの計算など、さまざまな問題を解決できます。辺の緩和を全頂点に対して複数回繰り返します。

![Bellman–Ford_algorithm_example.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/c8aa82f7-8bff-1ec0-32d0-26250095e0cb.gif)

## 2つのアルゴリズムの長所短所

**dijkstra法**

:::note
- 効率的
:::

:::note alert
- 負の閉路でループする
:::

**Bellman-Ford法**

:::note
- 汎用的
:::

:::note alert
- 計算に時間がかかる
:::

| 特徴 | Dijkstra法 | Bellman-Ford法 |
| --- | --- | --- |
| 負の重み対応 | 不可能 | 可能 |
| 負の閉路検出 | 不可能 | 可能 |
| 計算量 | O((V+E)logV) | O(V×E) |
| アルゴリズム | 貪欲法 | 全辺を順に緩和 |
| 実装の容易さ | やや複雑 | 簡単 |
| 使用場面 | 高速処理が必要な場合 | 負の重みや閉路がある場合 |

## 参考
アニメーションはWikipediaを参考にしました。

https://ja.wikipedia.org/wiki/%E3%83%80%E3%82%A4%E3%82%AF%E3%82%B9%E3%83%88%E3%83%A9%E6%B3%95

https://en.wikipedia.org/wiki/Bellman%E2%80%93Ford_algorithm
論文に載らないMS-DIAL Tips #1

この記事はtuat-sysbiolab advent calendarの12日目です。

# 開発の背景

MS-DIALは自分たちの研究室で開発しており、日常的に自分たちでも積極的に使用しています。そのため、必要な機能を随時追加しており、公式ドキュメントに記載されていない便利な機能も多く存在します。今回はその中の一つを紹介します。

# クロマトグラム表示

MS-DIALでは、ピークを選択するとその _m/z_ におけるEICが表示されます。ただし、TICを確認したい場合や、期待する化合物がピーク検出されていない場合に便利な特定の _m/z_ でのEIC確認機能があります。

画面上部のリボンタブから「View」→「EIC」を選択してください。するとダイアログが表示され、指定した _m/z_ におけるEICが表示されます。このとき、EICはメイン画面左で選択中のサンプルデータが対象になります。

![eicview.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3944004/68bed979-58c7-b24b-a44e-d754cd535075.png)


手順は以下の通りです：

1. _m/z_ とtoleranceの入力
2. 「Apply」ボタンをクリック
3. 入力したm/zにおけるEICの表示

以上の手順で表示することが可能です。複数のクロマトグラムを同時に表示することもできるので、標準品の強度の確認など役立ててください。

# スペクトルの表示

このクロマトグラム表示機能は以前から存在しましたが、約1年前のアップデートでスペクトル表示機能が追加されました。指定範囲のMSスペクトルの平均スペクトルを計算して表示できるようになりました。

クロマトグラム上で左クリックしながらドラッグして範囲を選択し、「+」ボタンをクリックすると選択範囲が青く表示されます。その状態でグラフ上を右クリックし、「Show MS Spectrum」をクリックすると、その範囲の平均スペクトルが表示されます。

![accumulate_spectrum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3944004/4168fb83-b8f5-3381-46e1-5cad703ef02a.png)

別の範囲を同様に選択して、「-」ボタンをクリックすることで、その範囲のスペクトルを差し引くこともできます。

また、「Show MS/MS Spectrum」でも同様の操作が可能なはずですが、驚くべきことに、この記事の執筆中にバグを発見しました。近日のリリースでの修正を予定しています。

表示したスペクトルはライブラリスペクトルとの比較ができ、mspフォーマットで保存可能です。そうして保存したmspファイルは解析の際のライブラリとして利用することが可能なので、インハウスのライブラリの作成に役立ちます。
また、スペクトル上でピーク範囲を選択すると、そのピークのm/zにおけるクロマトグラムも表示できます。

![ms_spectrum.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3944004/a5ff7050-b5f7-a01b-8914-42b4efcc983f.png)


# 終わりに

アドベントカレンダーの担当があと2回ほどあるので、次回も別の機能を紹介しようと思います。
PHPの文字列検索でよく使うpreg_match/str_contains/str_starts_withの処理速度調査


## 概要

パフォーマンスを意識するとどれを使えばいいのか調べてみた。


## 結論

通常なら`str_contains`

先頭から検索にマッチするなら`str_starts_with`

`preg_match`はおそらくパフォーマンスが多少落ちても`str_contains`では対応し切れない検索で使用する


## 環境

- MacBookPro M2 Max 12コア 96GB
- PHP 8.3.13 (cli)


## シンプル検索

```php
<?php
// テスト対象の文字列
$haystack = "This is a test string to measure the performance of string functions.";
$needle = "test";

// テスト回数
$iterations = 100000;

// パフォーマンス計測用関数
function measurePerformance(callable $function, $iterations)
{
    $start = microtime(true);
    for ($i = 0; $i < $iterations; $i++) {
        $function();
    }
    $end = microtime(true);
    return $end - $start;
}

// preg_match テスト
$pregMatchTime = measurePerformance(function () use ($haystack, $needle) {
    preg_match("/" . preg_quote($needle, "/") . "/", $haystack);
}, $iterations);

// str_contains テスト
$containsTime = measurePerformance(function () use ($haystack, $needle) {
    str_contains($haystack, $needle);
}, $iterations);

// str_starts_with テスト
$startsWithTime = measurePerformance(function () use ($haystack) {
    str_starts_with($haystack, "This");
}, $iterations);

// 結果を表示
echo "Performance Results:\n";
echo "preg_match:     {$pregMatchTime} seconds\n";
echo "str_contains:  {$containsTime} seconds\n";
echo "str_starts_with: {$startsWithTime} seconds\n";
```

### 結果

> Performance Results:
preg_match:     0.013596057891846 seconds
str_contains:  0.0050351619720459 seconds
str_starts_with: 0.0040431022644043 seconds

## リスト検索

```php
<?php
// ランダムな文字列リストを生成する関数
function generateRandomStrings($count, $length = 10) {
    $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
    $strings = [];
    for ($i = 0; $i < $count; $i++) {
        $strings[] = substr(str_shuffle(str_repeat($characters, $length)), 0, $length);
    }
    return $strings;
}

// テストデータの準備
$list = generateRandomStrings(10000, 20);
$needle = substr($list[array_rand($list)], 0, 5); // ランダムなリストの要素の一部を検索対象に設定

// パフォーマンス計測用関数
function measurePerformance(callable $function, $list)
{
    $start = microtime(true);
    foreach ($list as $item) {
        $function($item);
    }
    $end = microtime(true);
    return $end - $start;
}

// preg_match テスト
$pregMatchTime = measurePerformance(function ($item) use ($needle) {
    preg_match("/" . preg_quote($needle, "/") . "/", $item);
}, $list);

// str_contains テスト
$containsTime = measurePerformance(function ($item) use ($needle) {
    str_contains($item, $needle);
}, $list);

// str_starts_with テスト
$startsWithTime = measurePerformance(function ($item) {
    str_starts_with($item, "abc"); // "abc"は検索対象の固定値
}, $list);

// 結果を表示
echo "Performance Results:\n";
echo "preg_match:     {$pregMatchTime} seconds\n";
echo "str_contains:  {$containsTime} seconds\n";
echo "str_starts_with: {$startsWithTime} seconds\n";
```


### 結果

> Performance Results:
preg_match:     0.0013799667358398 seconds
str_contains:  0.00051212310791016 seconds
str_starts_with: 0.0003809928894043 seconds
Texで引用を書く

普通に詰まったので備忘録として書いておく

## 書き方

### 本文(引用が必要な部分)側

```tex
\cite{tag}
```

### 引用一覧(引用がまとめられてる)側

```tex
\begin{thebibliography}{9}
  \bibitem{tag} 
\end{thebibliography}
```

いつも忘れるのでメモ
演算子の順序とnullと三項演算子と私

~~intelliJさんはそもそも警告を出してくれていたんですが~~

```java
log.info("xxxx:" + obj != null ? obj.toString() : null);
```

書きたかったことはわかります。
おそらくなんらかの型の `obj` が `null` でないときだけ `xxxx: hoge` のようなログを出力し、 `null` であれば `xxxx: null` としたかったのでしょう。

***でも***

演算子の優先順位は `+ ` のほうが `? :` より高いです。
その結果

1. まっさきに "xxxx" + obj が演算される
1. `obj` が `null` でも `"xxxx:null` という文字列になる

ということで、この三項演算は意味をなしません。
なんなら `obj` のnullチェックとして機能していないので、最悪NullPointerが発生します。ていうか発生します。

## 全然関係ないですが

ググって出てくるJava演算子の優先順位、うそ混じってませんか？
そもそも優先順位に1〜15の番号降るのはいいとして、どちらが優先されるのか。ASCかDESCかはっきりしてもらいたい。
Datadog Agentによるメトリクス収集の仕組み

# はじめに
AWSでシステムを運用する場合、datadogを使用したモニタリングをする機会があると思います。
今回の記事では自分がdatadog agentを使用してインスタンスのメトリクスを収集しようとした時調べたことをまとめていこうと思います。

# メトリクス収集のアーキテクチャ
![スクリーンショット 2024-12-11 午後11.26.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/546781/96bfa8b6-1ead-3b3a-cb31-77f24b8a1f8e.png)

アーキテクチャは大きく分けると二つの領域で構成されます。

- AWS Cloud内のEC2インスタンス
- Datadog

それぞれの構成を見ていきましょう。

## EC2インスタンス内の構成
EC2インスタンス内には以下のリソースが存在します。

- アプリケーション
    - 今回モニタリングしたいアプリケーション
- システムメトリクス
    - CPU使用率
    - メモリ使用量
    - ディスク使用状況
    - ネットワークトラフィック
- Datadog Agent
    - メトリクス収集を行うエージェント

## Datadog内の構成
Datadog内では大きく三つのコンポーネントがメトリクス収集に関わってきます。

- Datadog Invoke API
    - メトリクスの受け口となるAPI
- Metric Storage
    - メトリクスを保存するストレージ層
- Monitoring Engine
    - メトリクスの評価とアラート生成を行うエンジン

## データ収集の流れ
では実際にデータ収集がどのように行われ、モニタリングができるようになるのかの処理の流れを見ていきます。

1. 初期収集
    - Datadog Agentは定期的にシステムメトリクスを収集する
        - デフォルト設定は10s
    - アプリケーション側からもカスタムメトリクスを収集することが可能
    - 収集されたメトリクスは一時的にエージェント内でバッファリングされる
1. データ転送
    - バッファリングされたメトリクスはhttpsでDatadog Invoke APIに送信される
1. データ処理
    - Invoke APIで受信したメトリクスはMetric Storageに保存される前に必要な前処理が行われる
1. モニタリング
    - Monitoring Engineが保存されたメトリクスを継続的に評価する
    - 設定された閾値に基づいてアラートが生成される

## まとめ
Datadog Agentを使用したメトリクス収集の仕組みはシンプルかつ効果的な監視体制を構築することができます。
Firebaseのリージョンは絶対に統一すべき



- **リージョンは統一すべき**。統一しないと遅延やコストが増加。
- 日本ユーザーが多いなら、リージョンを `asia-northeast1` に設定。
- 統一方法は簡単。以下のコード例で対応できます。


## なぜリージョンを統一すべき？

### 1. パフォーマンスの向上
異なるリージョン間で通信すると、物理的な距離やネットワークの影響で遅延が発生します。

例: 
- `us-central1`（アメリカ）と `asia-northeast1`（日本）の通信には **200ms** 程度の遅延。
- 同じリージョン内なら遅延は **数ms**。
- `us-central1`にfunction、`asia-northeast1`にdatabaseでやりとりして通知の送信とかやると余裕で3秒とか4秒遅延します。

### 2. コスト削減
リージョン間の通信には追加料金が発生する場合があります。同一リージョン内の通信は **無料**。

### 3. 信頼性の向上
リージョンが分散していると通信エラーが発生しやすくなります。同一リージョン内に統一することでシステム全体が安定。

---

## Firebase のリージョンを統一する方法

### 必要な設定

#### 1. Firebase Functions のリージョン設定
Functions を特定のリージョンにデプロイするには、`functions.region` を使用します。

以下のコードは、リージョンを `asia-northeast1` に設定した例です。

```javascript
const functions = require("firebase-functions");

// "asia-northeast1" にデプロイ
exports.myFunction = functions.region("asia-northeast1").https.onCall(async (data, context) => {
    // 関数の処理内容
    return { message: "Hello from asia-northeast1!" };
});
```
DBeaverのおすすめ使い方

## はじめに
【DBeaver】この機能便利だな〜と思ったものを紹介
導入方法などはたくさん記事があるのでこちらから👇

https://zenn.dev/kento_kodama/articles/2404a74f69f412

## 検索機能
### 行を検索
<!--
記事の主要な部分です。ここに思い思いの内容を書いていってください。

画像やGIFがあると分かりやすいです。
画像があるとUIが変わったとしても読者がアタリをつけて対応しやすくなります。

コードを記載する場合は必ずコードブロックを使いましょう。
バッククオート3つで囲んでください。
```python:表示名

    print('Hello World')
    
```
-->




#### 例）id = 1の行が見たい🥸
<!--
より詳細な内容を書いたり、事例を挙げたりするときに使います。
- 節の内容の列挙
- 節の補足事項
- 例外
-->
#### 1. 左上をクリック
![DBeaver_24_2_5_-_country.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/aab397a3-8be2-521f-7da7-a59200041592.png)

#### 2. 検索したいカラム名を入力
![1DBeaver_24_2_5_-_country.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/78b8bb37-0be4-cc9a-b865-2c496329a566.png)

#### 3. 検索したい値を入力
`Code = 'ABW'`と入力
![2Menubar_と_DBeaver_24_2_5_-_country_と_docker-compose_yml_—_MySQL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/e7edc80b-e76c-b105-758a-40d3cbed1511.png)

#### 4. 検索完了
![11DBeaver_24_2_5_-_country.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/4fad96f4-29db-ce55-60ca-0a1fb8ad13f3.png)

#### 5. 実行したSQLの確認
![１２DBeaver_24_2_5_-_country.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/0a178b8c-0288-31a7-e4dd-9d3996ca0e54.png)

#### 6. ダブルクリック後
![sqlCursor_と_DBeaver_24_2_5_-__Test_DB__country.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/2823e0f2-9ad1-b483-a620-7b5bbbe37e2d.png)

### ちょっとデータを確認したいときに✨おすすめ✨

## ER図
#### 例）テーブルがどう繋がっているか確認したい
#### 1. ER図をクリックするだけ
![Cursor_と_Menubar_と_DBeaver_24_2_5_-_world_と_docker-compose_yml_—_MySQL.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/53583a7f-564e-bd67-c318-328f2bb92a28.png)


## SQLエディタの自動補完が強い💪
![111DBeaver_24_2_5_-__Test_DB__Script-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933297/b20e244c-60ba-6839-9a3e-f588579719c2.png)


## 参考資料

https://qiita.com/ssc-syuinoue/items/5b819b4a9392ab241b73

## おわりに・まとめ
DBeaverは何でもできて便利なのでもっと調べていこうと思います！
なんでも出来すぎてわかりにくい説はあるかもしれない。。。
【競技プログラミング】AtCoder Beginner Contest 051_C問題

# 問題

https://atcoder.jp/contests/abc051/tasks/abc051_b

## 要約


1. 2つの整数 K と S が与えられる。

2. 3つの変数 X, Y, Z があり、それぞれ 0 以上 K 以下の整数値を取る。

3. X + Y + Z = S を満たす X, Y, Z の組み合わせの数を求める。

変数情報：
- K: 変数 X, Y, Z の取りうる最大値
- S: X, Y, Z の合計値
- X, Y, Z: 0 以上 K 以下の整数値を取る変数

この問題では、与えられた条件を満たす X, Y, Z の組み合わせの総数を求める必要があります。

# 既存投稿一覧ページへのリンク
[一覧ページ](https://qiita.com/o_chan_t/items/fc759695acfaef8df2cc)



# アプローチ

全探索を用いて、条件を満たす組み合わせの数をカウントする。
ただし、効率的な探索を行うために、不要な探索を省略する最適化を行う。
   
このコードは、問題の条件を満たす組み合わせを効率的に全探索するために設計されている。
X, Y, Zの3つの変数があり、それぞれ0からKまでの値を取り得るため、単純な全探索では O(K^3) の計算量になる。
しかし、X + Y + Z = S という条件があるため、Zの値は X と Y が決まれば自動的に決定されます。そこで、X と Y の2重ループで探索し、Z の値を計算することで、計算量を O(K^2) に抑えています。さらに、X + Y > S となった時点で内側のループを終了することで、不要な計算を省いています。


# 解法手順
1. 入力から K と S を受け取る。

2. カウンタ変数 count を 0 で初期化する。

3. 変数 X の値を 0 から K まで順に探索する。

4. 各 X に対して、Y の値を 0 から K まで順に探索する。

5. X + Y が S を超えた場合、それ以上 Y を増やしても条件を満たさないため、Y のループを終了する。

6. Z の値は S - (X + Y) で求められる。Z が 0 以上 K 以下であれば、条件を満たす組み合わせとしてカウントを 1 増やす。

7. すべての探索が終わったら、カウンタ変数 count の値を出力する。



# ACコード
```python:ac.py

def io_func():
    # 入力から K と S を受け取る
    K, S = map(int, input().split())
    return K, S

def solve(K, S):
    # カウンタ変数 count を 0 で初期化する
    count = 0

    # 変数 X の値を 0 から K まで順に探索する
    for X in range(K + 1):
        # 各 X に対して、Y の値を 0 から K まで順に探索する
        for Y in range(K + 1):
            # X + Y が S を超えた場合、Y のループを終了する
            if X + Y > S:
                break
            
            # Z の値を計算する
            Z = S - (X + Y)
            
            # Z が 0 以上 K 以下であれば、カウントを 1 増やす
            if 0 <= Z <= K:
                count += 1

    # カウンタ変数 count の値を返す
    return count

if __name__=="__main__":
    # メイン処理
    K, S = io_func()
    result = solve(K, S)
    print(result)

###
# 変数の意味:
# K: 整数の上限値
# S: X + Y + Z の合計値
# X, Y, Z: 0以上K以下の整数
# count: 条件を満たす組み合わせの数

# 1. io_func関数で標準入力から K と S を受け取る
# 2. solve関数で主な処理を行う
#    - 2重ループを使用して X と Y の値を全探索する
#    - 効率化のため、X + Y が S を超えた時点で内側のループを終了する
#    - Z の値を S - (X + Y) で計算し、0以上K以下であればカウントを増やす
# 3. 最終的なカウント結果を出力する


```

## 計算量
このコードの計算量は O(K^2) 。
外側のループが K+1 回、内側のループが最大で K+1 回実行されるため。
X + Y > S となった時点で内側のループを終了する余地あり。
【Rails】Object#withの使い方

# 紹介
Object#withが便利だったので紹介

こういうクラスを用意する
```rb
class Player
  attr_accessor :number

  def initialize(number:)
    self.number = number
  end

  def puts_number
    puts number
  end
end
```

このようなクラスで、`puts_number`メソッドだけ動作を確認したい時がある
前後に処理がある中で動作確認をするとき、動作確認後は値を戻したい場合にはこういうコードになる

```rb
player = Player.new(number: 2)

begin
  player.number = 3
  player.puts_number
ensure
  player.number = 2
end

player.puts_number
```

実行すると出力は
```
3
2
```
のようになる

これはこれでいいのだが、便利なメソッドがある

# それがこれ

```rb
player = Player.new(number: 2)

player.with(number: 3) do
  player.puts_number
end

player.puts_number
```

実行すると先ほどと同じく
```
3
2
```
となる

Object#withの内部実装もわかりやすい
```rb
  def with(**attributes)
    old_values = {}
    begin
      attributes.each do |key, value|
        old_values[key] = public_send(key)
        public_send("#{key}=", value)
      end
      yield
    ensure
      old_values.each do |key, old_value|
        public_send("#{key}=", old_value)
      end
    end
  end
```
https://github.com/rails/rails/pull/46681/commits/1884323574b35b3a2286850f3c98f677633728f1

最初のコードとほぼ同じ
これからはこれを使っていこう
Pyxelをインストールしよとしたらエラーが出て仮想環境が必要になった。 

pyxelをインストールしよとしたらエラーになった。
どっかのファイルに登録すれば動くのでしょうが今回はenveを使う。

## 環境

Ubuntu 24.04.1 LTS
Python 3.12.3


## 状況 

```
error: externally-managed-environment
```
ようは管理に登録されいません。というよな感じ。
エラーメッセージの下に解決方法が書いています。仮想環境（venv）を使いなさいとのこと。

``` 翻訳済み
解決方法
     仮想環境（venv）を作成し、その中でパッケージをインストールする
    システム管理者権限でパッケージをインストールする（管理者に依頼する場合など）
 
    仮想環境を使うと、Pythonのパッケージを管理しやすくなるため、このエラーを回避するのに有効です。
```

## インストール 
- "miura"は適当につける。
```
sudo apt install python3.12-venv

$python3 -m venv miura
```
- 仮想環境を割り当てる。
```
$source miura/bin/activate
(miura) $
```
- pipを行う。仮想環境ではpipとpyxelだけ入っている。これで動く。

```
(miura) $ pip3 install pyxel
Collecting pyxel
  Using cached pyxel-2.2.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (31 kB)
Using cached pyxel-2.2.8-cp38-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (3.0 MB)
Installing collected packages: pyxel
Successfully installed pyxel-2.2.8

(miura) $ pip3 list
Package Version
------- -------
pip     24.0
pyxel   2.2.8

```

- 次のコマンドで終わる。
```
(miura) $ deactivate
```

ー以上ー
一年を振り返るを振り返る。

一年を振り返る Advent Calendar 2024の25日目です。とりあえず宣言したので何とか走り切りました。

粗々な文章で内容も浅い感じでざっと書いてみましたが、25日も連続してブログ書くの好きじゃないと無理やな。

と言いつつ、粗くても一年振り返ってみて思ったのが、日々意識して取り組んでるとやっぱり学びがあるなぁというのはとても感じました。

そういう学んだことをちょっとでもブログにしたりアウトプットすることで、自分自身の知見も整理できたり、そもそも自分自身の振り返りになって何を学んだかを改めて理解することができるなと思いました。

また、自分の経験とか知見をちょっとでも世に出してみることで、誰かの何かのきっかけになれば結果的にとてもいいことだと思いました。

と言いつつ、きれいにマークダウン整えたり内容がっつり書いていくの、25日も連続して無理だったので、次ブログ書くときはもうちょっと丁寧にしっかり内容のあるブログを書いてみようと思います。

とりあえず人生初アドカレ25日完走でした。こんな雑記を見てくれた方、大変ありがとうございました。
【AWS】API Gateway + Lambda + WAFで、指定のIPアドレスからのアクセスのみを許可する

# 概要
API Gateway + Lambdaの構成にて、WAFを使ってIP制限を行う方法を紹介します。

構築までの手順は以下の記事で紹介しましたのでご参考ください。

https://qiita.com/Ryo-0131/items/f1a771570b7dc610a14d

### 経緯
ELB + EC2だとLoadBalancerのセキュリティグループのインバウンドルールを利用することで、指定したIPアドレスからのアクセスだけを許可して他はブロックすることが可能ですよね。
それをAPI Gateway + Lambdaでも実現しよう！という話です。

AWS WAFのIPセットを使って制限をかけます。

# 手順

## ①WAFでIP setsを作成する

まずはIPセットを作成します。
ホワイトリスト方式を利用するので「指定したIPのアクセスのみを許可する」という意味になります。

- WAF -> IP sets -> Create IP set
    - Region：リージョンを選択（②のWeb ACLと同じリージョンにすること）
    - IP addresses：対象アドレスを入力（CIDR方式・複数入力も可）

## ②WAFでWeb ACLsを作成する
- WAF -> Web ACLs -> Create web ACL
    - Name：任意に命名
    - Associated AWS resourcesにて「Add AWS resources」をクリック
        - Amazon API Gateway REST API -> 作成済みのAPI Gatewayを追加
    - Rulesにて「Add rules」をクリックし「Add my own rules and rule groups」を選択
        - ルールタイプ「IP set」を選択し、Ruleを任意に命名、上記①で作成したIP set名を選択
        - ActionはAllowを選択してルール追加
- 「Default web ACL action for requests that don't match any rules」
    - Blockに変更（これにより、このルールに合致しないアドレスはブロックする動作になる）

上記により、指定したIPアドレス以外のアクセスをブロックできるようになり、IP制限をかけることができました。

# 参考

https://qiita.com/kennyQiita/items/005da29e8e2ed2c2cc4e

https://www.sunnycloud.jp/column/20210601-01/
Next.js 15.1の主なアップグレード内容

# はじめに
Next.js15.1が出たので、気になった内容をまとめてみました。
間違いなどありましたら、コメントなどで教えてください。

https://nextjs.org/blog/next-15-1

# 各種コマンド

Next.jsの最新バージョンにアップグレードする際に、必要なコードの修正や設定変更を自動的に行います。手動で変更する手間を省く。
```
npx @next/codemod@canary upgrade latest
```

Next.jsプロジェクトで使われているnext、react、react-domを手動で最新バージョンに更新します。この場合、コードの修正は自分で行う必要があります。
```
npm install next@latest react@latest react-dom@latest
```

最新のバージョンで新規プロジェクトを作成
```
npx create-next-app@latest
```

# 主な更新内容
- **React 19を完全サポート**
- **エラーデバッグの改善**
- **after(安定)**
- **forbidden(403)/unauthorized(401) エラーページの追加 (Canary)**

# それぞれの詳細
主な変更内容についての詳細を書いていきます。

## React 19を完全サポート
React 19が、Pages RouterとApp Routerの両方で正式にサポートされました。
React 19についての詳しい情報は、以下が参考になります。

https://react.dev/blog/2024/12/05/react-19

https://zenn.dev/uhyo/books/react-19-new

## エラーデバッグの改善
Next.jsのエラーデバッグが改善され、ターミナル、ブラウザー、または接続されたデバッガーのいずれに問題が表示されても、問題の原因をすばやく特定できるようになりました。
これらの機能強化は、WebpackとTurbopack (現在は Next.js 15で安定) の両方に適用されます。
以下に、主な変更点が記載されています。
もっと詳しい内容については、追記したいと思います。

https://nextjs.org/blog/next-15-1#react-19-stable

## after APIの安定版がリリース
レスポンスがストリーミングを終了した後に処理するタスクをスケジューリングできるようにし、プライマリ・レスポンスをブロックすることなくセカンダリ・タスクを実行できるようにするAPIです。
そのafter APIが安定版としてリリースされました。
after APIの詳しい情報は、以下をご覧ください。

https://nextjs.org/docs/app/api-reference/functions/after

## forbidden(403)/unauthorized(401) エラーページの追加 (Canary)
実験的にですが、403, 401の場合に専用のエラーページを表示する機能が追加されました。
実装方法は、以下のようになります。

``` next.config.ts
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  experimental: {
    authInterrupts: true,
  },
};
 
export default nextConfig;
```

``` tsx
import { verifySession } from '@/app/lib/dal';
import { forbidden } from 'next/navigation';
 
export default async function AdminPage() {
  const session = await verifySession();
 
  // Check if the user has the 'admin' role
  if (session.role !== 'admin') {
    forbidden();
  }
 
  // Render the admin page for authorized users
  return <h1>Admin Page</h1>;
}
```

専用のエラーページは、今まで同様に「app」フォルダ配下にファイルを作成します。
``` app/forbidden.tsx
import Link from 'next/link';
 
export default function Forbidden() {
  return (
    <div>
      <h2>Forbidden</h2>
      <p>You are not authorized to access this resource.</p>
      <Link href="/">Return Home</Link>
    </div>
  );
}
```

``` app/unauthorized.tsx
import Link from 'next/link';
 
export default function Unauthorized() {
  return (
    <div>
      <h2>Unauthorized</h2>
      <p>Please log in to access this page.</p>
      <Link href="/login">Go to Login</Link>
    </div>
  );
}
```

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください！

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
ViperIDEを使ってみる①：とにかくアクセスしてみる

# ViperIDEとは

MicroPython界隈で話題になっていたViperIDEを使ってみた。

※ ちなみにちょっとだけ綴りが違うが "Viperidae" は「クサリヘビ科」のことだそうで、ヘビつながりで名前の由来となっているのかもしれない

Webブラウザで動作するMicroPyth, CircuitPython用のIDE。

以下の機能があるらしい。

* 軽量で使いやすい
  * Webブラウザで動くので（Chrome 系に限定されるらしい）、インストールは不要
  * PCでもスマートフォンでも動作
* 柔軟な接続性
  * USBシリアル接続
  * ワイヤレス/リモートオプションも利用可能
* 強力なPython開発サポート
  * リアルタイムコード分析: エラーや警告を即座に発見
  * REPLも使える
  * 基本的なコード補完
  * 実験用の MicroPython 仮想マシン
* 組込み管理ツール
  * ファイルエクスプローラーとエディター
  * パッケージ管理システム

# とにかくアクセスしてみる

Raspberry Pi OS の Chromium を使って以下のURLにアクセス。

```url
https://viper-ide.org/
```

以下のような ViperIDE の画面が表示される。

![スクリーンショット 2024-12-11 21.52.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/49a086b9-09b7-7990-0959-df5691170955.png)

最初から日本語表示に対応している。日本語はAIで訳したものを使っているとのこと。

とりあえず Pico W を USB ケーブルで PC に繋いで、右上の USB アイコンをクリックしてみる。"Board in FS mode" を選んで「接続」をクリックする。

![スクリーンショット 2024-12-11 21.55.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/bd04c34e-45a3-3748-1d26-3382fb9fbfc3.png)

左ペインに PICO W のファイルシステムの内容が表示され、下には REPL が繋がっている。

![スクリーンショット 2024-12-11 21.56.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/ccfe991d-7d73-be72-786f-a5ad47a5756f.png)

スクリプトを書いて、ファイルマネージャの上のほうにある ▶︎ をクリックするか F5 キーを押すと、REPL上で実行される。MicroPython のファイルシステムに書き込むには ↓ をクリックするか Ctrl-S キーを押す。

![スクリーンショット 2024-12-11 23.03.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/04a1b2bc-fec9-fb81-f50a-5c16523cde4d.png)

一度ファイル名を決めてしまうと変更できない模様。これはちょっと不便。
2024年 体の負担を減らして仕事をするため環境作り

この記事は カオナビ Advent Calendar 2024(シーズン2) 13日目です。

https://qiita.com/advent-calendar/2024/kaonavi

---

# はじめに

働き初めて10数年、気がついたらアラフォーと言われる年齢になってしまいました。

体にだいぶガタが来たと感じる日々です。

座り仕事ということもあり特に首・肩・腰へのダメージは無視できないものとなってきました。

体へのダメージを減らしつつ、1日(8h)仕事をするために色々環境を整えたので、去年末 〜 今年にやったことを振り返りたいです。

# やったこと達

## 椅子の変更

※これだけ去年末です

ゲーミングチェアを使っていましたが、思い切ってアーロンチェアに変更しました!!!!

1年ほど使っていますが、腰が痛いなーと思うことがほとんど無くなったなーと感じています!!:grin:

（定期的に20%OFFになるので買うならそのあたりがいいかなと思います）

## 分割キーボード

肩・腕を広げて作業すると聞いたのでMagic Keyboardから分割キーボードに変更しました。

JIS配列の分割キーボードが無かったので手を出していませんでしたが
こちらが発売されたので早速乗り換えました:grinning:

https://www.diatec.co.jp/shop/xacro/m10sp.php

慣れるまで1ヶ月近くかかりましたが、肩周りが痛くなるということは減ったような気がします。
馴染んでくると手放せない感じになってきました!!:tada: 

Magic Keyboardは指紋認証専用機として再利用していますが、場所を取るので指紋認証だけのデバイスがほしいですね:pensive:

## モニターアーム

モニターの位置を姿勢に合わせて調整するために導入しました。
自分の思うようにモニターの位置を変えられるので体の負担を減らすのにはいいのかなと感じてます。

モニター台はありましたが微調整ができなかったのであると便利だなーとは思っています:tada: 

## クラムシェル

MacBook + 外部モニターの2台構成から、クラムシェルに変更しました。

MacBookはほぼSlackアプリの表示専用となっていました。
Slackしか見ないならいっそのこと閉じてしまおうと思い、クラムシェル運用を開始しました。

モニターが1枚に統合されたことにより首の可動範囲が減ったのでかなり負担が減ったと感じています:tada:

外付けカメラは未だ持っていないので、リモート会議でカメラがONにできなくなりました:joy:
（変わりにチャットで頑張って反応します!!）

## Slackアプリの配置変更

クラムシェルにしてかなり首への負荷が減ったと感じていましたが、さらにSlackアプリの配置を少し変更しました。

元々はこのように左下にアプリを配置していました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206915/65796595-cd5a-2583-2166-75b062843746.png)

これをこのようにモニター中央（顔の正面）になるように変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206915/027752cb-dc74-f778-21b1-6727c75795f1.png)

地味な変更ですがほぼ正面を向いてSlackでやり取りをできるようになったため、結構効果を感じています:grinning:

## 休憩する or 帰る

体がやばそうだな、と思ったら大人しく休憩を取るようにしています。
軽くヨガをやったりしています:muscle:

それでもダメそうならもう退勤ボタンを押して休憩です:sleeping:

# まとめ

以上、2023年末 〜 2024年で揃えたものでした。
だいぶ体へのダメージは減らせてきているのではないかと思っています。

しかしまだ十分ではないと思っていますので、来年は昇降デスクとマウスを狙っています！
OSSライセンスと向き合わないといけない

一年を振り返る Advent Calendar 2024の13日目です。頑張る。

転職して製造業で働いているせいか、再輸出規制とか米国輸出管理法(EAR)とかいう単語が日々の業務で付きまとうようになりました。

例えば、海外で製造されたOSSのライブラリを日本で利用して商品を構築して、その商品を海外に輸出すると再輸出扱いになっちゃうみたいな。

あとは特許調査とかもあったりします。独立項とか請求項とか。知らん単語が多くて大変です。

というわけで、そういう話に関連してちゃんとOSSについて学んでおかないといけないなというので、これくらいは理解しておかないとなぁというメモ。

某書籍を読んでみましたが、個人的にとほほのライセンス入門がわかりやすい。

https://www.tohoho-web.com/ex/license.html

というわけで上記サイトから部分的に抜粋。詳細はちゃんと調べます。

## MITライセンス
Massachusetts Institute of Technology License の略。
著作権および許諾表示を記載すれば、非営利、商用を問わず、使用、改変、複製、再頒布が可能です。

## BSDライセンス
Berkeley Software Distribution License の略。
四条項版、三条項版、二条項版があります。非営利、商用を問わず、使用、改変、複製、再頒布が可能です。

## Apacheライセンス
Apacheのライセンス。ライセンス明記することで商用でも使用・改変・複製・再配布が可能です。

## MPL (Mozilla Public License)
利用しただけのコードは独自のライセンスを適用することができますが、改造した場合は、改造物もMPLライセンスとして公開する必要があります。

## GPLライセンス
GNU General Public License。無償で利用・改造・再配布できますが、GPLのモジュールをライブラリとして呼び出すだけでも、呼び出したソースコード自体も GPL ライセンスとする必要があり、成果物の配布先に開発コードを公開する必要があります。これを コピーレフト とも呼びます。利用しただけでソース公開の義務が生じることから「GPLに感染する」ともいわれています。

## まとめ
OSSって難しい。こういうの真面目にちゃんと勉強しないとな。。。頑張ろう。
Denaベースターズの佐野選手の成績を打球方向や結果から考察する

## はじめに

佐野選手（左打者）の打球方向や結果（ホームラン、三振、四球）を通じて、打率3割以上を記録した2020～2022年シーズンと3割未満だった2023～2024年シーズンを比較しました。本記事では、結果のデータからわかる傾向と考察を紹介します。

## 成績データ

![スクリーンショット 2024-12-11 22.42.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933685/b3287606-8c2c-2b2c-61e0-2c12491dd813.png)
![スクリーンショット 2024-12-11 22.18.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3933685/03740aa7-9a5d-c4b7-6935-62a5d227bbb1.png)


## 打球方向別割合

| 打球方向 | 3割以上 | 3割未満 | 差異（%） |
|----------|---------|---------|-----------|
| 左方向   | 23.7%   | 20.5%   | -3.2      |
| 中方向   | 36.1%   | 32.8%   | -3.3      |
| 右方向   | 40.2%   | 46.7%   | +6.5      |

- **左方向・中方向の割合が減少**  
  3割以上のシーズンでは左方向と中方向の打球が多く、センターを中心に反対方向へのコンタクトの質が高かったと推測されます。
- **右方向の割合が増加**  
  3割未満のシーズンでは右方向への打球が増加。引張りの打球が多かった。

## ホームランの比較

| 項目               | 3割以上 | 3割未満 | 差異（%） |
|--------------------|---------|---------|-----------|
| ホームラン（外野）| 4.0%    | 2.0%    | -2.0      |

- **ホームラン数が減少**  
  3割以上のシーズンでは外野本塁打（左越本、中越本、右越本）が多く、長打力が大きな武器となっていました。一方、3割未満のシーズンでは本塁打率が減少していることがわかります。

## 三振と四球の比較

| 項目 | 3割以上 | 3割未満 | 差異（%） |
|------|---------|---------|-----------|
| 三振  | 11.5%   | 10.9%   | -0.6      |
| 四球  | 8.6%    | 6.3%    | -2.3      |

- **三振が増加**  
  3割以上のシーズンでは三振の割合が増加しています。ホームランが増えていることから長打を狙った結果だと予想しました。
- **四球が減少**  
  3割以上のシーズンでは四球率が高く、選球眼の良さが際立っていました。これにより出塁率の向上に寄与していたと考えられます。

## 考察

### 1. ホームランと三振の関係

3割以上のシーズンでホームラン数が多い一方、三振も一定割合で発生していました。このことから、長打を狙う打撃スタイルが明確であり、その結果として三振も増加していた可能性があります。

### 2. 長打力による四球の増加

長打力が投手に与えるプレッシャーは大きく、結果的に四球の割合が増加する傾向がありました。特に、3割以上のシーズンでは長打を恐れた投手が慎重な配球を行い、四球率が高まっていたと考えられます。

### 3. 逆方向の打球増加と打率の上昇

3割以上のシーズンでは左方向（逆方向）への打球割合が増加しました。最後までボールを見極めてコンタクトできていたと考えられます。

### 4. 打球方向と打率の相関

高打率を記録するためには、逆方向や中方向への打球割合が高いことが重要であることがデータから示唆されます。逆に引張りの割合が高いと打率低下に繋がる可能性が高いです。

## まとめ

- 3割以上のシーズンでは、ホームランや四球の割合が高く、長打を狙う積極的な打撃スタイルが見られました。また、左方向・中方向への打球が多く、反対方向へのコンタクトの質が高かったことが高打率に寄与したと考えられます。
- 3割未満のシーズンでは、三振が増加し、右方向への打球割合が増加しました。これにより、引張りの打球を狙う結果が多く、打率低下の要因となったと考えられます。
- **今後の改善点**  
  最後までボールを見極めて逆方向への打球をを増やすことで、打率向上が期待できるでしょう。また、長打力を発揮することで四球率の向上を図ることも重要な戦略となります。

この記事では、データ分析を基に佐野選手の成績を掘り下げました。データが示す傾向は明確であり、次シーズンに向けた課題と改善点が見えてきました。あなたの考察や意見もぜひコメントでお聞かせください！
w3m使ってみた

# 0 概要
げんしけんアドカレ12/14の記事です。
プラモデル云々と言っていたけども、作る時間を確保できませんでした。かわりに最近あった面白いことを書きます。
Manjaro Linuxの計算機でw3mを使ってみた話です。

# 1 w3mって？
テキストベースwwwブラウザです。
図1のようなかんじ。
```plantuml
@startuml
<style>
root {
  Padding 0
  Margin 0
}
footer {
  FontColor black
  FontSize 17
}
</style>
footer 図１ w3mこんなかんじ
title <img:https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989098/5a1885ef-df8f-527e-9355-b12e02fca3e7.png>
@enduml
```


# 2 インストール
ManjaroはArchベースなので、パッケージマネージャはpacmanを使います。
```
sudo pacman -S w3m
```
ですんなり入りました。Ubuntu環境でも試したところ、aptで問題無くインストールできました。
# 3 使い勝手
おもしろい。ただ、画像の表示はちょっと不自由かも。
# 3.1 画像表示
Manjaroでは画像は表示されました。しかし、Ubuntuだと表示されませんでした。
Gnome Terminalだと画像が出ず、XTermだと出るとか聞いたが検証してないです。
あと、画像を表示するとレイアウトが崩れたりします。
# 3.2 キーバインド
デフォルトだと慣れないキーバインドでした。皆さんも使いなれたVimのキーバインドが良いですよね。
ゴリラさんの記事[2]のをコピペしてみました。ちょっと使いやすくなった。

# 4 おわりに
GUIが当たり前の時代に生きてきたからか、CUIっていいよねえ。
良いCUIライフを。

# 5 参考
[1] w3m HomePage


 https://w3m.sourceforge.net/index.ja.html

[2] ゴリラ."VimでWorld Wide Web"

https://qiita.com/gorilla0513/items/11be5413405792337558
作業時のコマンドを自動化しよう

# はじめに
VSCodeでディレクトリ開いたとき、`npm run dev`して、開発サーバー立てて、zsh開いて、、、
って毎回同じコマンド打つの面倒なので`tasks.json`を使って自動化しようと思います。

**ディレクトリ(フロントエンド)をVSCodeで開くだけ**で、以下のコマンドを実行します
1. フロントサーバー起動 (`npm run dev`) 
2. バックエンドサーバー起動 (`bun dev`)
3. zsh 起動

# tasks.jsonとは
>tasks.json は、Visual Studio Code（VS Code）で カスタムタスクを設定するためのJSONファイル です。このファイルを使うことで、プロジェクト内でよく使うコマンドやツール（例えばビルド、テスト、デプロイなど）を簡単に実行できるようになります。

From the grate GPT...

# 作業
## `tasks.json`の作成
`.vscode/tasks.json`を作成します。
このとき、`.git/info/exclude`に入れておくと`.gitignore`に記述せずにgit追跡から除外できるので便利です。
(チーム開発の場合、あまりレポジトリに個人の設定ファイルを含めたくない)

## タスクの定義
`tasks.json`に以下を書き込みます

```json
{
    "version": "2.0.0",
    "tasks": [
    
    # 1️⃣ ⭐フロントサーバーを起動
    
      {
        "label": "front run",
        "type": "shell",
        "command": "npm run dev",
        "group": "none",
        "presentation": {
          "reveal": "always",
          "panel": "new"
        }
      },

      # 2️⃣ 🔥 バックエンドサーバーを起動
      
      {
        "label": "server run",
        "type": "shell",
        "command": "cd ../server && bun dev",
        "group": "none",
        "presentation": {
          "reveal": "always",
          "panel": "new"
        }
      },

      # 3️⃣ 🐋 zshを起動
      {
        "label": "shell run",
        "type": "shell",
        "command": "/bin/zsh",
        "group": "none",
        "presentation": {
          "reveal": "always",
          "panel": "new"
        }
      },

      # 4️⃣ 🍏 ↑をまとめて起動
      
      {
        "label": "tasks",
        "type": "shell",
        "dependsOn": [
          "front run",
          "server run",
          "shell run"
        ],
        "runOptions": {
          "runOn": "folderOpen"
        }
      }
    ]
  }
```
* 1️⃣: `npm run dev`で現在のディレクトリでフロントエンドサーバーを起動しています
* 2️⃣: サーバーディレクトリへ移動してから`bun dev`でバックエンドサーバーを起動しています
* 3️⃣: macの場合、`/bin/zsh`でzsh(ターミナル)を起動しています
* 4️⃣: 最後に、これらを`tasks`という名前でまとめています

## 自動起動の有効化
`ctrl + shift + P`でパレットを開き、`Tasks: Run Task`を選択し、先程作成した`tasks`を実行すると、開発サーバーが立ち上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3531484/76b953b2-fbcc-f993-522f-f45e66e8579c.png)

# おわりに
Raycastの`Run Script Command`を使って、コマンドでVSCode開いて、サーバーのローカルホストも開けるようにカスタマイズするともっと便利になるよ

# 引用
- [【VSCode】開発環境を自動で立ち上げる](https://zenn.dev/kazuwombat/articles/d9512aebbbae07)
- [自分専用の.gitignore(相当)を使おう | 株式会社ソリューションウェア](https://solutionware.jp/2020/12/11/%E8%87%AA%E5%88%86%E5%B0%82%E7%94%A8%E3%81%AE-gitignore%E7%9B%B8%E5%BD%93%E3%82%92%E4%BD%BF%E3%81%8A%E3%81%86/)
Elixirで作る「DDJ-FLX4のジョグ対応ブロックくずし」　その３　ジョグの入力イベントを作る

`Elixirで作る「DDJ-FLX4のジョグ対応ブロックくずし」　その２　ゲームの画面の枠を作る`の続きです

https://qiita.com/t-yamanashi/items/e1d4299cc18310f79c57

# ジョグの入力イベントを作る

- PortMidi.openでDDJ-FLX4を開く
- PortMidi.listenでDDJ-FLX4の信号受付する
- PortMidi.closeでDDJ-FLX4を閉じる
- midi_inでDDJ-FLX4の信号を受信する

```diff_elixir:
defmodule DdjBlock do
  @moduledoc """
  Documentation for `DdjBlock`.
  """
  alias Rayex.Structs.Rectangle
  use Rayex

  def main() do
+   {_, input} = PortMidi.open(:input, "DDJ-FLX4 MIDI 1")
+   PortMidi.listen(input, self())
+   midi_in(input)
+   PortMidi.close(:input, input)
    init_window(800, 800, "DdjBlock")
    main_loop(true)
  end

  defp main_loop(true) do
    begin_drawing()
    draw()
    end_drawing()

    Process.sleep(100)
    main_loop(!window_should_close())
  end

  defp main_loop(_), do: nil

  defp draw() do
    rectangle = %Rectangle{x: 100.0, y: 100.0, width: 100.0, height: 50.0}
    draw_rectangle_lines_ex(rectangle, 1, %{r: 0, g: 255, b: 0, a: 255})
  end

+  def midi_in(_input) do
+   receive do
+     v ->
+       IO.inspect(v)
+   end
  end
end
```

```sh
$ mix ddj
```

下記のエラーになりました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/f1bafba8-1bc3-cfe3-9722-e274d62b8e0e.png)

# 起動ができないから別の方法を考える

理由はわからないがmix tasksと相性悪いかも…
と言うことで

起動スクリプトを作成
```sh:ddj.sh
#!/bin/sh
mix run --eval "DdjBlock.main"
```

実行権限を与える
```sh
$ chmod +x ddj.sh 
```

実行
```sh
$ ./ddj.sh
```

ジョグを回したら
`{#PID<0.227.0>, [{{144, 54, 127}, 3179}]}`が受信し
その後に画面が開いた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/d3d2ed0d-d894-725a-585b-1f3d334bb6f8.png)

# midi_inを連続で受信可能にする
midi_in(input)関数を下記に書き換える

```diff_elixir:lib/ddj_block.ex
# 省略
  def midi_in(input) do
    receive do
      v ->
        IO.inspect(v)
      midi_in(input)
    end
# 省略
```

実行すると画面は表示しないがコンソールを観察すると

ジョグを右周りに回すと
`{#PID<0.241.0>, [{{176, 33, 65}, 384476}]}`

ジョグを左周りに回すと
`{#PID<0.241.0>, [{{176, 33, 63}, 526377}]}`

この結果からソース改良

```diff_elixir:lib/ddj_block.ex
# 省略
  def midi_in(input) do
    receive do
      {^input, [{{176, 33, 65}, _}]} ->
        IO.inspect("右")
        midi_in(input)
      {^input, [{{176, 33, 63}, _}]} ->
        IO.inspect("左")
        midi_in(input)
      _ ->
        midi_in(input)
    end
  end
# 省略
```

実行しジョグを回すと下記になる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/48344acf-ad18-d2ad-6390-4d3b8880428e.png)

# 問題点画面が表示できない
この問題は次回考える

:::note alert
早速壁にぶち当たる、このままだと企画倒れする
:::

つづく

https://qiita.com/t-yamanashi/items/e817a9d8fbd9792c16b5
マークダウン記法の中でもhtmlライクに修飾できるのか

原神を再開しました（DL長っ）こんにちは。
# n番煎じだけど試したこと

Qiitaにおけるマークダウン記法でのフォントサイズの変更のテストです
マークダウン記法の中でもhtml的にいじれば文字の修飾ができるのか？
実際にQiitaで試してみた
```sample.html
表示ここから
こんにちは（ノーマル）
<span style="font-size: 200%">こんにちは（spanで修飾）</span>
<div style="font-size: 200%">こんにちは（divで修飾）</div>
表示ここまで
```
↓
表示ここから
こんにちは（ノーマル）
<span style="font-size: 200%">こんにちは（spanで修飾）</span>
<div style="font-size: 200%">こんにちは（divで修飾）</div>
表示ここまで

:::note info
文字修飾は反映されず、divタグの段落の意の改行のみが反映される
（逆にdivタグの意が反映されたことにはびっくり）
:::
:::note warn
補足
:::

**各見出しとサイズの比較**
# こんにちは（見出し1）
## こんにちは（見出し2）
### こんにちは（見出し3）
#### こんにちは（見出し4）
##### こんにちは（見出し5）
###### こんにちは（見出し6）※見出しは最小6まで
#### こんにちは（見出し4）
こんにちは（ノーマル）

:::note info
見出し4とノーマルのフォントサイズはほぼ同一、フォントサイズ最小は見出し6
:::

# まとめ
やっぱり、マークダウン記法の中ではhtmlライクに文字を修飾できない
以上、ありがとうございました
【React】パスパラメータとクエリパラメータの違いとReactでの使い方

# はじめに
Reactで個人開発をしている中で、useParamsを使いパスパラメータによる内容の出し分けを実装しようとしたところ、***パスパラメータ***と***クエリパラメータ***の違いを正しく理解できておらずエラーに悩まされました。今回はその違いを整理しつつ、正しい実装方法を共有します。

:::note warn
***この記事は<font color="Red">個人的なアウトプット</font>を目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです***。
:::

# パスパラメータとクエリパラメータ
## パスパラメータ
```
https://qiita.com/masafumi1073
```
URL構造の一部として利用されます。情報が特定のリソースに紐付いている場合に適しています。例: /users/:id
ここでは`masafumi1073`がユーザーID。
## クエリパラメータ
```
https://qiita.com/search?keyword=react
```
URLの後に?で始まる形式で、追加条件やオプション情報を渡す際に使います。例: /search?keyword=react
ここでは`id=7`がクエリパラメータ。

「情報がリソースに属する場合はパスパラメータ」、「条件やフィルターの場合はクエリパラメータ」を使います。

# 私が間違えていたこと
当初、パスパラメータを使うべき場面で、クエリパラメータを指定してしまい正しく動作しませんでした。

## 誤ったコード
```react
const Menu = ({ pageId }) => {
  const pathname = useLocation().pathname;
  const { id } = useParams();
  const pageUrl = pathname === `/home/?id=${id}`; // パスパラメータとクエリパラメータの混同

  return id && (
    <Box onClick={onclickAnswer}>
      <Center>
        <MdOutlineQuestionAnswer size="30px" color="#f9a8d4" />
      </Center>
      <Text color="#f9a8d4">Home</Text>
    </Box>
  );
};

```

https://qiita.com/shuhei_m/items/ce8a5c168b7f2864b08c

## 修正後のコード
`useParams`を使いパスパラメータ/home/:idを取得する形に変更しました。

```react
const Menu = ({ pageId }) => {
  const { id } = useParams();

  return id && (
    <Box onClick={onclickAnswer}>
      <Center>
        <MdOutlineQuestionAnswer size="30px" color="#f9a8d4" />
      </Center>
      <Text color="#f9a8d4">Home</Text>
    </Box>
  );
};

```
今回の教訓は「URL構造を正しく理解し、適切なパラメータを選択する」ことです。ReactのuseParamsはパスパラメータ専用であり、クエリパラメータはuseLocationを使う必要があります。

# 終わりに
URL構造を正しく理解することは、Reactでのルーティング実装において重要なポイントだと思います。今回の教訓を活かして、適切なパラメータ選択をしていきたいと思います。

# 参考
『パスパラメータとクエリパラメータの違い』Zenn

https://zenn.dev/eri_agri/articles/859a3362db8386

『パスパラメータとクエリパラメータ』Zenn

https://zenn.dev/y__adler/articles/7a73cdf4c1987a

『[React] React Router 後編』 Qiita

https://qiita.com/aaaasahi_17/items/775bbb96358c1fee99dc

useParams

https://www.commte.co.jp/learn-nextjs/useParams

reactでURLパラメータから値を取得する方法　Qiita

https://qiita.com/shuhei_m/items/ce8a5c168b7f2864b08c
LangChainでElasticsearchStoreをベクトルストアとして使う

# はじめに

Elasticsearchはベクトル検索をサポートしてるためLangChainからベクトルストアとして取り扱うことができます。特に難しいことはないのですが動作する例で紹介します。

# サンプルコード

ElasticsearchStoreを使うとドキュメントストアとしてElasticsearchを利用することができます。利用には以下のパッケージをimportしてください。

 - [elasticsearch](https://elasticsearch-py.readthedocs.io/en/v8.16.0/)
 - [langchain-elasticsearch](https://python.langchain.com/docs/integrations/vectorstores/elasticsearch/)

```
pip install elasticsearch
pip install langchain-elasticsearch
```

以下、LangChainのRetrieverとしてElasticsearchを扱い、ドキュメントをベクトル検索するサンプルコードです。

```python
from elasticsearch import Elasticsearch
from langchain_elasticsearch import ElasticsearchStore, DenseVectorStrategy

# 接続情報を環境変数から取得
from dotenv import load_dotenv
import os
load_dotenv()
ES_CLOUD_ID = os.getenv('ES_CLOUD_ID')
ES_API_KEY = os.getenv('ES_API_KEY')

# Elasticsearchのインデックス名、モデルID等を指定
INDEX_NAME = "datasets-wikimedia_wikipedia-20231101.ja"
MODEL_ID = '.multilingual-e5-small_linux-x86_64'
VECTOR_QUERY_FIELD="text_semantic.inference.chunks.embeddings" # ベクトル検索するフィールド
QUERY_FIELD = "text" # BM25で検索するフィールド

# Elasticsearchに接続
es_client = Elasticsearch(
    cloud_id=ES_CLOUD_ID,
    api_key=ES_API_KEY,
    request_timeout=60,
)

# Modelを指定してDenseVectorStrategyを作成（ハイブリッド検索を有効化）
strategy = DenseVectorStrategy(model_id=MODEL_ID, hybrid=True)

# ElasticsearchStoreを作成
store = ElasticsearchStore(
    es_connection=es_client,
    index_name=INDEX_NAME,
    vector_query_field=VECTOR_QUERY_FIELD,
    query_field=QUERY_FIELD,
    strategy=strategy,
)

# クエリを発行
query = "日本の首都はどこですか？"
retriever = store.as_retriever()
docs = retriever.invoke(query)
```

コード内のコメントの通りなので特に追加する説明もないですね。。`store.as_retriever()`でChainとして扱えるRetrieverが取得できるので、LCELに組み込んで使えます。またDenseVectorStrategyでhybrid=Trueとしているので、ベクトル検索とキーワード検索のハイブリッド検索を実行するようになっています。

ただし、見て分かる通りElasticsearchStoreを使う場合、クエリーのカスタマイズができません。本当にベクトル検索だけできれば良い、ということなら便利かもしれませんが、クエリーをチューニングしてパフォーマンスや関連度を向上させたい場合などは、通常のElasticsearchクライアントから普通にsearch()メソッドを使ったり、あるいはよりおすすめの方法としてはsearch_template()を使ったりした方が、自由にクエリーを組み立てられます。元も子もないのですが。

Search Templateについては以下の記事も参照してください。

https://qiita.com/daixque/items/064493e289dbe24530e8

# おわりに

LangChainのElasticsearchStoreの使い方について紹介しました。既存のChainに組み込まれているRetrieverをElasticsearchStoreと別のもので条件によって切り替えたい、などの時は便利に使えるかもしれません。

単にElasticsearchをドキュメントストアとしてRAGを構築したい、という場合は無理やりChainに組み込まず、独自でElasticsearchへのクエリーを書いてそれをコンテキストとしてLLMに渡す、などでも問題ないと思いますので、必要に応じて使い分けてください。