OmniAICreator/Qiita-1.07M huggingface dataset:
相互運用性

# 概要
他のソフトウェアないしは、システムとの対話能力である。
異なるシステム同士が情報のやり取りしたり、相互に同じプロトコルで接続しあったり。
SoSが異なるSoSと情報を共有する際にもこの性質が求められる。


# リスク
ただし問題点もある。
たとえば汚いデータ(要は不整合起きたままだったり、最新状態でないデータ)が、
もう片方のシステムに流れ出すと、汚染水のようにもう片方も浸食されてしまうリスク。
そのためにセキュリティ項目の完全性という非機能で、
データの正確さ・完全さを担保してあげることで、そのリスクを回避できると考えられる。
そこで重要なのが【不変オブジェクト】の思想である。
詳細については、別記事を参照してほしい。

# 背景
お互い情報を交換し合うことで、相手先で起こったアンチパターンや
サービスの質向上の成功事例などといったデータ利活用をするためにも、
他のシステムとの対話・情報交換は有力な手段である。

このことは、アナロジー思考で考えたら我々人間同士の情報交換でも同じ理屈が成り立つ。
自分一人・少人数の閉じた空間で学ぶよりも、積極的に外部との情報交換をする方が
文明は進化し、退化しにくいことは歴史でも物語っている。

したがって、この相互運用性が高いことによって嬉しいことは、
外部との交流にとってシステムの用途の選択肢を広げてくれて、
すでにある知見を有効活用することで開発期間やコストの削減に貢献することである。

# どうすれば
わかりやすくシンプルな接続が理想ではある。
たとえば業界標準の規格プロトコルに従った設計にしておくなどである。
ただし、このわかりやすさを犠牲にしてでも接続先のシステム独自の規格に合わす必要がある場面もある。

下図のような自分の準拠する規格とは異なる規格を持った相手とつなぎたいという時である。
この場合図のように直接繋ぐってのはあまりよろしくない設計、
OCP(オープンクローズド原則)に反したものである。(下図のような構図)
<img width="500" alt="相互運用.png (7.0 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/05/16/135213/9a3d2ca7-ac2f-40a9-8579-28de8c85274e.png">
なぜなら仮に相手先で規格を変えたりした場合に、こちら側までその影響を受けてしまう。

そこで接続先が自分のとこの規格と一致してないような場合、
もしくはこれから規格を変更することがほぼ確定していたりする場合には、
間に仲介を担ってくれるようなサブシステムの導入を検討することで、
OCPを守りつつ、接続したいシステムに問題(規格を変えるetc)が発生したとしても、
そのサブシステム内に影響範囲を閉じ込めるってことが可能になる。
要は、デザインパターンのAdapterパターンをシステムスケールの世界で適用てこと。
（下図を参照）

<img width="500" alt="スクリーンショット (132).png (82.4 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/05/16/135213/c302abd3-4162-4645-9ca0-40f678687dc6.png">

# まとめ
Adapterパターンはシンプルさは少し下がってしまうと感じる。
そこでわたしならこのように使い分けたアーキテクチャ方針を立てる。

接続したい相手先のシステムはほぼ高確率で自分のとこの規格と一緒にするって場合には、
こんなAdapterパターンは適用しない。
逆に、相手先では規格を変更することが前向きに検討されているのであれば
Adapterパターンの適用を検討しておく。

こういう風にしておけばAdapterがあるかないかで
「こことここのシステムは同じ標準規格に従ってるのね」
「ああ、ここには仲介人がいるってことだから異なる規格の相手と連携したいってことなのね」
という風に容易に判断もできることになるので、
結果的にシンプルなアーキテクチャで相互運用性を実現できると考えられる。
テスト容易性(検証容易性)

# 概要
テスト容易性とは、効果的に　効率的に検証を行える能力のこと。
効果的とは、より網羅的にMECEに隅々まで品質の検証ができていること。
効率的とは、より低コストで品質の検証ができていること。

# 背景
システムのサイズ感が大きくなればその分だけテストしなければいけない範囲は拡大する。
そのため、上記の効果的効率的が困難になってしまうというリスクが付きまとう。
そこでアーキテクチャ自体をテスト容易（正しさの評価検証が容易）な設計にすることが求められる。

# どうすれば
まずは検証の無駄を省くことが重要である。
<img width="300" alt="スクリーンショット (131).png (25.3 kB)" src="https://img.esa.io/uploads/production/attachments/5827/2023/05/16/135213/213e8f88-6b28-4f7e-bfba-66843173a1ff.png">

図のようにテスト対象のa、bがあった際に両方行うってことは、重複部分の検証が無駄に行われるということ。
したがって、テスト容易性のためには概念の重複があると検証コストの無駄遣い、
効率性の低下をその分招くということである。

さらに単一責務原則に従っていないとか、interface分離原則に従っていないものの
要素を後日再設計した際には、再度検証しなくてはいけないことになる。
また、テスト容易性はその特徴から構造がMECEでクリーンであれば容易になることから、
保守性との相関関係があることが容易に想像できる。

保守性が向上　⇒　テスト容易性も向上
テスト容易性が向上　⇒　保守性も向上(こちらの証明はまだ微妙なので後述)

これは品質特性のトレードオフ文献[システム品質属性の実装 |マイクロソフト学習 (microsoft.com)](https://learn.microsoft.com/en-us/previous-versions/bb402962(v=msdn.10)?redirectedfrom=MSDN)にも記載があるとおりである。

また、モジュール間の依存関係が強いほどテストはしにくい。
テストしにくい箇所があるとそこがボトルネックになりかねないし、
モジュールが大きい単位のままだと検証した際に問題発生したらどこに問題があるのか？
判別が難しいため、以下の２つが必要条件としてあることが望ましい。

・小さい単位での検証ができる仕組み　つまりカプセル化
・極力依存関係を疎にしておくこと　
つまりオープンクローズドにしておくことがテスト効率性を下げないポイントである。

# テスト容易⇒保守性高いの証明
検証がしやすいということは、時間もコストも網羅性も優れてるってことなので、
いまのアーキテクチャに問題がある場合、テストの容易性が徐々に下がっていくはず。
それをメトリクス解析ツールで常に計測しておくことで、
【テスト容易性が下がってる　⇒　保守性が下がってきている】という事実として観測ができる。
【テスト容易性が下がってる　⇒　保守性が下がってきている】てことと
【保守性が向上　⇒　テスト容易性向上】てことから、
テスト容易性が高い　⇒　保守性高い　を証明できることになる。

# まとめ
以上のことから、UAFでMECEに則って作成しておくことは、
変更容易性の高いアーキテクチャを実現するだけでなく、低コストで検証しやすいことも
同時に実現できるということである。
これは逆に言えば、テスト容易性がしにくくなってきている
変更する際にやたら時間がかかっているなどといったメトリクスデータが取れた場合には、
いまのアーキテクチャが徐々に劣化し始めてきているサインでもあるということ。
なので、早急に構造の見直し具体的には
・重複概念が発生していないか？
・カプセル化は正常にされているか？　　などの再検討が求められる。
ASRでAzure VMの災害対策をする

### Azure PortalからAzure VMのASRを設定する

Azure Site Recovery（ASR）の構築方法はAzure Portal、PowerShell、REST APIがサポートされています。今回はAzure Portalから設定します。
サポートリージョンなどサポートされる構成については[Microsoftドキュメント](https://learn.microsoft.com/Ja-jp/azure/site-recovery/azure-to-azure-support-matrix?WT.mc_id=itopstalk-blog-thmaure#replicated-machine-operating-systems)よりご確認ください。

以下のメニューから設定を開始します。
![ASR1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/8dbeefab-a187-1cd7-6e37-b01571bab9cc.png)

ターゲットリソースはAzureが自動で構成してくれますが、自身で設定を追加することもできます。
![ASR2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/9556c06d-d368-6338-32a7-93816b23f8f1.png)

フェイルオーバーの選択肢としては2パターンあります。ソースVMが生きている場合、データの損失を防ぐためASRにVMsをシャットダウンさせフェイルオーバーさせることができます。ソースVMにアクセスできない場合は最新の復旧ポイントから復旧します。

### フェイルオーバーをテストする

実際にフェイルオーバーを確認してみます。リカバリーポイントを選択してテストフェイルオーバーを開始すると、ターゲットサイトで実際にVMが構成され立ち上がってくることが確認できます。
![ASR4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/4dc9f27c-562a-5279-a6af-e0ae8f364326.png)
![ASR5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3322105/83c8f579-7462-8135-b687-a44313091049.png)


今回は1台だけなので災害対策の画面から直接フェイルオーバーをテストしましたが、複雑な構成では[Recovery Plan](https://learn.microsoft.com/Ja-jp/azure/site-recovery/recovery-plan-overview?WT.mc_id=itopstalk-blog-thmaure)設定しておくことでアプリの依存関係を考慮した復旧計画を定義できます。

### 参考
- [How to set up Disaster Recovery for Azure IaaS VMs](https://techcommunity.microsoft.com/t5/itops-talk-blog/how-to-set-up-disaster-recovery-for-azure-iaas-vms/ba-p/1153807?WT.mc_id=twitter-social-thmaure)
- [Azure から Azure へのディザスター リカバリー アーキテクチャ](https://learn.microsoft.com/Ja-jp/azure/site-recovery/azure-to-azure-architecture?WT.mc_id=itopstalk-blog-thmaure)
Streamlit を使って論文執筆支援アプリを作った

## はじめに
テンプレに沿って論文執筆できるような、執筆支援アプリがあったら嬉しいなと思ったので作りました。

## やりたいこと
論文構成のテンプレを準備し、それに沿って執筆できるようにする。執筆箇所について、入力データのダウンロード、アップロード、マークダウンへのエクスポート機能などの機能を持たせる。

## 環境
python = 3.10

## パッケージ
pip install streamlit（利用したのは1.22.0）

## 実行
streamlit run app.py

# コード格納先
https://github.com/MySweetEden/ScienceResearchWriting

# アプリ
https://mysweeteden-scienceresearchwriting-app-zjmvqo.streamlit.app

## 振り返り
土日の晩だけで開発を終えたかったので、GUI で操作できるものを簡単に作って共有できそうな Streamlit を選択しました。良い判断だったと思います。ウェブ技術の操作性を利用できる点が良かったです。かけた時間は全部合わせて７～８時間くらいだと思います。

# おわりに
急いで実装したのでかなり汚いです。ダウンロードしたデータをメモ帳で開くと大変汚いので閲覧注意です、見ないでください。
若干挙動が怪しい箇所もありますがお許しください。気が向いたら修正します。

# 参考
https://camp.trainocate.co.jp/magazine/streamlit-web/
ガチ転職、まきを動きます。

こんばんは、お久しぶりの投稿です。
早速ですが4月28日、会社辞めましたｧﾝ！！

4月頭に流行り病に感染し、明けてからの仕事の引き継ぎラッシュが思いの外多すぎて1ヶ月も空いてしまった。（言い訳）
俺、やばいくらいたくさん役割あったんだなあ。

意外と職場の人達にけっこう慕われていたらしくて、GWは4グループの派閥から送別会に呼ばれ、ポートフォリオ用のホームページを作りながら満喫した次第であります。
が、ある企業に就職したくて覚悟を決めて退職したので、全力でプログラミングやっていくZE🌟


…ということで、どこまでやってたかなーって思って見てみると『はやたす』さんの100問演習パックを購入したところで止まっていた。勿体ねえ…

よっしゃやるべやるべ！！
ってところで「問題を見る」　→「？」→「？？？」

1、2の…ポカン！
俺は『Pythonの基礎』をきれいさっぱりわすれて…
新たに『ドわすれ』をおぼえた！！

やばいやばいやばい！！！
何もかも忘れてるやんけ！！！！！
こーれむしろ逆に分かってよかった説ある。

…ということで今回は『Progate　4周目の世界線』をやって思い出しつつ復習やっていこうと思う。
けっこう危機的状況だけど落ち着け、まだ慌てる時間じゃない。

やっていくぞい！！！！！


----------------------------------------------------------------------

ひとまずPythonコース３まで完了。
忘れている部分が多かったけど、やっている内に感覚というか「これ確かこうだったんじゃね？」って思い出した部分も多くなっていたと思う。
明日残りのPythonコースをやって次の日に一通り復習しようと思う。
Webアプリの設計④


## はじめに

前の記事から、「自己研鑽＋ポートフォリオ+趣味」という位置づけでWebアプリを作り始めました。

https://qiita.com/kajiyai/items/f66ba5d9659ef87c3247

「自己研鑽＋ポートフォリオ+趣味」

自分のフェーズに合致したとてもいい記事があったので、こちらの記事を参考に進めています。

https://qiita.com/takahirocook/items/3cfa6585e74effafe5da

## キーワード

設計書, 設計, 設計プロセス, 外部設計

## 目次

1. 全体
2. 外部設計
    1. 画面設計
        1. レイアウト図
3. おわりに

## 全体

各フェーズのざっくりとした自分の理解です

1. 企画
    1. どんなものを作るか決める
        1. ユーザーゴール
            1. サービスを使う人のゴール
        2. ビジネスゴール
            1. サービスを作る人のゴール
2. 要件定義
    1. 機能要件
        1. 最低限の機能
    2. 非機能要件
        1. +αの機能
3. 外部設計**←イマココ**
    1. 方式設計
        1. 使用するサーバー,言語,フレームワーク,DBなどの環境整備を行う
    2. 機能設計
        1. 実装する機能の洗い出し
            1. DB設計, バッチ処理等もここで設計する
    3. 画面設計
        1. 画面遷移図の作成
            1. トリガー, 流れを図示する
4. 内部設計
    1. データ設計
        1. 概念設計
            1. 概念図
        2. 論理設計
            1. ER図
        3. 物理設計
            1. テーブルの図
    2. モジュール設計
        1. モジュールの分割を行う
    3. プログラム設計
        1. 設計内容を具体的に落とし込む
5. 開発
    1. goooooooooooooooooooooo
6. テスト
    1. 単体テスト
        1. モジュール内のテスト
    2. 結合テスト
        1. モジュール間のテスト

## レイアウト図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3092463/931694d8-c624-330f-8418-fe91f2217ccb.png)


仮のフレームを作ってみました。

日本語がうまく変換されなくて少し手こずりましたが、作りやすかったです。

https://whimsical.com/

## おわりに

今回はレイアウト図を途中まで描いたところで力尽きました。

次回は内部設計をする前に、設計のために色々触ってみる、という事を暫くしてみようと思います。

具体的には、認証やページネーションや画像のアバター等のライブラリを試してみたりしようと思います。

ではまた。
Next.js 13（app dir）と microCMS で Jamstack なブログを作ってみた

# はじめに
この記事では、Next.js 13 から Next.js を勉強し始めた私が、Next.js 13（app dir）と microCMS で Jamstack なブログを作成する方法をメモとして残します。（似たような内容の記事は沢山ありますが、Next.js 13（app dir）に対応したものは2023/05/15時点で未だ少ないため、これからブログを作成する人の参考になればと思います。）

# 実際に作成したブログにメモを残してみました
https://tech.shinaps.jp/articles/n6783yx-1
プログラムによる制御

# 概要
API3ではシンプルなカウンターを作成する。

# 動作確認
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">プログラムによる制御 <a href="https://t.co/STyOpOApB1">pic.twitter.com/STyOpOApB1</a></p>&mdash; いまむら　たくま (@Imamuuu5) <a href="https://twitter.com/Imamuuu5/status/1658119986726961153?ref_src=twsrc%5Etfw">May 15, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
# ソースコード

**java**
**API3.java**

```java
package app28;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/api3")
public class API3 extends HttpServlet {

    private int count;  // カウンター

    // GET 処理（GET メソッドで HTTP リクエストが送られてくるたびに実行される）
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // レスポンスの設定（毎回この設定）
        response.setHeader("Cache-Control", "no-cache");    // キャッシュを利用しない
        response.setHeader("Pragma", "no-cache");           // キャッシュを利用しない（下位互換性用）
        response.setDateHeader("Expires", 0);               // キャッシュ有効期限0
        response.setCharacterEncoding("UTF-8");             // レスポンス文字コード UTF-8 設定
        response.setContentType("application/json");        // レスポンスタイプ application/json 設定

        count++;    // カウントを1増やす

        // レスポンスを {"count": <count>} で返却 <count> はカウント変数の中身を表す
        // レスポンスボディ作成処理
        PrintWriter out = response.getWriter();             // レスポンス書き込み用 PrintWriter 取得
        out.println("{\"count\": " + count + "}");          // レスポンス書き込み {"count": <count>}
        out.flush();                                        // フラッシュ処理（強制送信のようなもの）
        out.close();                                        // PrintWriterのクローズ（これ以降書き込めない）
    }

}

```
# 説明

実行アドレスのパスの設定

@WebServlet("/api3")
実行アドレス
**http://localhost:8080/App28/api3**

 int 変数 counter を用意し、API3が呼ばれる度にカウンターを1増やし、データを送信するという処理になっている。

Servletのポイントとして、 インスタンス変数（クラス直下の変数） はアクセスの度に 初期化されない という特性がある。

1人目がアクセスした場合結果は 1 が返却され、次に別の人間がアクセスした場合結果は 2 が返却される。

サーバが止まるまで、最後のデータが保存されるため、何度も使いまわしたいデータなどは**インスタンス変数**としてクラス直下に作るようにする。

インスタンス変数とは、オブジェクト指向プログラミング言語で、個々のインスタンスごとに固有の変数。クラス定義で単にメンバ変数、フィールド、データメンバなどという場合はこれを指す。
shellってなに

## シェル (shell) とは
オペレーティングシステムのカーネルとユーザーの間のインターフェースを提供するコマンドラインインターフェース (CLI) のこと

シェルは、ユーザーがコマンドを入力すると、それを解釈してオペレーティングシステムに指示を送信する役割を持つ

ファイルの作成や削除、プログラムの実行などの一般的なタスクの実行もできる
複数のコマンドを一度に実行することも可能

・UNIXやLinuxなど
→BashやZshなど
・Windows
→CmdやPowerShellなど

プログラミングにおいて、シェルは、シェルスクリプトとしてプログラムを書くこともできるシェルスクリプトは、シェルが解釈できるスクリプトファイルであり、ファイルの作成や削除、プログラムの実行などを自動化するために使用される
【Docker】DockerfileでCOPYの際に権限や所有者を変更する方法


## 権限の変更
以下のように記述することで変更できます。
```Dockerfile:Dockerfile
COPY --chmod=755 /sample-file /sample-file 
```

## 所有者の変更
以下のように記述することで変更できます。
```Dockerfile:Dockerfile
COPY --chown=ユーザー名:グループ名 /sample-file /sample-file 
```
【SQL】値のセットの検索条件でselectする

SQLで値のセットの条件指定でselectする書き方を、何度も調べているので、メモします。
例： insert_dateが'20220101' かつ insert_user_idが'1'のデータと、
insert_dateが'20220102' かつ insert_user_idが'2'のデータを取得する。
（insert_dateが'20220101' かつ insert_user_idが'2' のデータは不要）

以下のように、指定したいカラム名をかっこでくくって、値のセットもかっこでくくって指定すると、取得できます。

```sql
select * from data_sample 
where (insert_date, insert_user_id) in (('20220101', 1), ('20220102', 2));
```
【phpmyadmin】インポート時に「#2006 - MySQL server has gone away」エラーが表示された場合の原因と解決方法

# 概要
- phpmyadminでsql.ZIPをインポートした時に、以下のエラーが表示されました。
- 本記事はこのエラーの解決方法を記載します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/2e49ebaf-7acd-263d-7546-e68082257863.png)

```
エラー
静的解析:

解析中に 1 個のエラーが見つかりました。

式がありません。 (near "ON" at position 25)
SQL クエリ: コピー 編集 編集

SET FOREIGN_KEY_CHECKS = ON;

MySQL のメッセージ: ドキュメント

#2006 - MySQL server has gone away
```

# 原因：MySQLサーバーパケットの最大サイズ
-  MySQLサーバーの`max_allowed_packet`設定値（パケットの最大サイズ）が不足している場合、MySQLサーバーが接続を中断してしまう場合があります。自分の場合もインポートしたZIPの半分くらいまでテーブルが作成されている状態で、途中で終わってしまったぽかったです。
-  `SET FOREIGN_KEY_CHECKS = ON;`を実行しようとしたら、MySQLサーバーに接続できなかった、というメッセージの意味であって、`SET FOREIGN_KEY_CHECKS = ON;`と`#2006 - MySQL server has gone away`は直接関係があるわけではなさそうです。
-  他には、データベースの設定が正しくない場合やネットワークで問題が生じている場合に表示されることがあるらしいです。


# 解決方法：`max_allowed_packet`を変更する
-  MySQLサーバーの`max_allowed_packet`設定値も変更する必要があります。
-  `my.cnf`ファイルで以下を追加すればOKです(設定次第では`mysqld.cnf`の可能性もあります)。

```my.cnf
[mysqld]
max_allowed_packet=512M
```

-  自分の場合は、Dockerコンテナでmysqlを起動していたので、`docker-compose.yml`で起動する際に自動適用できるように`my.cnf`ファイルをマウントする形にしました。インポートし直すとするたびにこの設定を加えるような運用だと面倒ですので。
-5- 作っているゲームが行き詰ってきた(自己反省メモ)

# 　よくわからなくなってきた！

私が今行き詰っているのはUIです。
開発が進むにつれて、規模が大きく、扱う情報が多くなっていきます。
それを束ねる知識が必要なのでは？私にはそれがないのでは？と考え、思考の沼にはまりました。

コンポーネント指向とオブジェクト指向の違い。
UIでの設計モデル。

自分が書いているやり方が正解なのかもわからない。
それを見てもらう環境もない。

効率が悪いと思っている今のやり方で、時間をかけてそれを成すしかないのかもしれませんが。
私は一度効率が悪いと思うと作業を続けたくなくなる人間です。
一旦開発から離れ、遠回りでもいいので別の学習を進めることにしました。

## 　目標の再確認と足元の見直し

そもそもの私の目標はゲーム会社に就職すること。(その本質は入社後にあるが)
そのために、自分はどんな活動を行っていかなければならないのか。
今このゲームを作り上げることのメリットはあるのか。
短い時間の中で確実に着実に成長していかなければならない。

自分の実力を把握し、高望みな夢ばかり見るのではなく、必須な知識を地道に習得していくことが大切である。

## 　C++とUEとオブジェクト指向と

この３つを学び１つゲームを完成させる。
ポートフォリオのため。
そこに自分の強みになる要素を加える。

私はゲーム開発より開発時の設計を考えるのが好きなので、そっちに力をいれて学習していきたい。


以上。
学歴無意味な元東大ヒキニートのITサバイバル日記 第0話

# 元東大ヒキニートのITサバイバル日記
>「学歴なんて意味ない。」「東大卒でもダメな奴はいる。」

　正にそんな事を言われる環境で、脱ヒキニートのために社会の荒波に揉まれて早1年。
　最低賃金でサービス残業ならまだマシ、無給に週80時間労働の漆黒ITサバイバル日記を書くことにしました。

　ホワイトとは何かを考えさせられる毎日でした。というか現在進行形です。
　そんな肉体労働の日々も、日記に変えてお小遣いにならないかなと思いました。
　
　やる気が出たら書きます。
　日記といっても、こうすればよかった等の後悔というより、ゴリゴリの技術寄り記事を書く予定ですが。
【学習】Ruby on Rails チュートリアル 第7版 - 第5章 レイアウトを作成する

5/15 22:15 開始

*Bootstrap
 Twitter社によるオープンソースのWebデザインフレームワーク

*クラスとidの主な違い
 クラス:ページ内で何度でも使える
 id:ページ内で一度しか使えない

*レスポンシブウェブデザイン (英: responsive web design、 RWD)
 デスクトップ版のウェブページを閲覧者の画面サイズまたはウェブブラウザに応じて表示できるようにする

*Sass
：スタイルシートを記述するための言語
5.1まで終了

5/15 23:15 終了


5/16 8:15 開始

*アセットパイプライン
：CSSや画像などの静的コンテンツの作成と管理を大幅に強化する。以下の3つの主要な機能がある。
∟アセットディレクトリ:静的ファイルを目的別に分類する、標準的な3つのディレクトリ
 app/assets: 現在のアプリケーション固有のアセット
 lib/assets: あなたの開発チームによって作成されたライブラリ用のアセット
 vendor/assets: サードパーティのアセット（デフォルトでは存在しない）

∟マニフェストファイル：アセットディレクトリに配置した静的ファイル（アセット）をどのように1つのファイルにまとめるのかをRailsに指示する。※実際にアセットをまとめる処理を行うのはSprocketsというgem。

∟プリプロセッサエンジン：必要なアセットをディレクトリに配置してまとめた後、さまざまなプリプロセッサエンジンを実行して結合することで、ブラウザに配信できるようにする。ファイル名の拡張子で判断する。※プリプロセス（前処理）
.erbであればERB用のプリプロセスが実行されて、HTMLに変換されるイメージ....?


5.3.2まで終了

5/16 9:10 終了

5/16 18:45 開始

*統合テスト（Integration Test）
 一連の作業をテスト
↓統合テストを自動で実施するファイル(site_layout_test.rb)を作成。
rails generate integration_test site_layout

以下の一連をテストする。
1.ルートURL（Homeページ）にGETリクエストを送る。
2.正しいページテンプレートが描画されているかどうか確かめる。
3.Home、Help、About、Contactの各ページへのリンクが正しく動くか確かめる。

1.get root_path
2.assert_template 'static_pages/home'
3.assert_select "a[href=?]", root_path, count: 2 など

3.の補足

"a[href=?]"
 →aタグとhref属性をオプションで指定して調べる。
?
 →root_pathが入る
count: 2 
 →埋め込んだリンクの数

↓がヒットする。
<a href="/">xxxx</a>

さらに↓をオプションに加えれば...
text: "Home"

↓がヒットする。(きっと)
<a href="/">Home</a>

5章 終了!

5/16 20:00
JSON形式のデータ

# 画面
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">JSON形式のデータ <a href="https://t.co/ZQXfgn0PY7">pic.twitter.com/ZQXfgn0PY7</a></p>&mdash; いまむら　たくま (@Imamuuu5) <a href="https://twitter.com/Imamuuu5/status/1658116071298039814?ref_src=twsrc%5Etfw">May 15, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# java

## API2.java

```java
package app28;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet("/api2")
public class API2 extends HttpServlet {

    // GET 処理（GET メソッドで HTTP リクエストが送られてくるたびに実行される）
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        // レスポンスの設定（毎回この設定）
        response.setHeader("Cache-Control", "no-cache");    // キャッシュを利用しない
        response.setHeader("Pragma", "no-cache");           // キャッシュを利用しない（下位互換性用）
        response.setDateHeader("Expires", 0);               // キャッシュ有効期限0
        response.setCharacterEncoding("UTF-8");             // レスポンス文字コード UTF-8 設定
        response.setContentType("application/json");        // レスポンスタイプ application/json 設定

        // レスポンスを {"name": "太郎", "age": 20} で返却
        // レスポンスボディ作成処理
        PrintWriter out = response.getWriter();             // レスポンス書き込み用 PrintWriter 取得
        out.println("{\"name\": \"太郎\", \"age\": 20}");   // レスポンス書き込み {"name": "太郎", "age": 20}
        out.flush();                                        // フラッシュ処理（強制送信のようなもの）
        out.close();                                        // PrintWriterのクローズ（これ以降書き込めない）
    }

}

```

パスの設定である WebServlet アノテーションが
以下の設定に変わっている。

``` @WebServlet("/api2") ```
これにより
http://localhost:8080/App28/api2
というアドレスにアクセスした際、実行されるプログラムがAPI2になるよう設定される。

RESTful API では **JSON（JavaScript Object Notation）** 形式のデータを送信する。

今回は2種類のデータをJSON形式にまとめ送信している。
``` {"name": "太郎", "age": 20} ```

1つ目が name という項目名で 「太郎」という文字列。
2つ目が age という項目名で「20」という数値を設定した。

複数の項目を設定したい場合、「,（カンマ）」で区切ることで設定できる。
また、**文字列のデータは「"（ダブルクオーテーション）」で囲む必要があるが、int や boolean 等の値は囲まなくて良い。**
k近傍法（k-NN）メモ

# なんぞそれ？
k近傍法(K-Nearest Neighbor Algorithm)とは、機械学習の**教師あり分類アルゴリズム**の1つです。
KNNによる分類の特徴は、未知のデータに着目した際にそのデータの近隣情報に基づき、分類結果を予測することです。
K近傍法では、データ空間のユークリッド距離(またはマンハッタン距離)で最も近い点を探索する「**最近傍探索問題**」に基づき分類が実行されます。

# 長所と短所
### メリット
+ **実装が容易**
  このアルゴリズムの単純さと正確さが手伝い、新米のデータサイエンティストが最初に学ぶ分類子の1つになっているほどだとか。

+ **適応が容易**
　このアルゴリズムでは、すべてのトレーニングデータがメモリーに保存されるため、新しいトレーニングサンプルが追加された場合に新しいデータを考慮した調整が行われます。

+ **ハイパーパラメーターが少ない**
 KNNでは**k値と距離メトリックのみ**が必要です。これは他の機械学習アルゴリズムと比較して少ないです。


### デメリット
+ **拡張に適していない**
 KNNは**遅延アルゴリズム**であるため、他の分類子と比較して**多くのメモリとストレージを消費**します。 
そのため、時間と費用の両方の観点でコストがかかる可能性があります。
 メモリとストレージが増えるとビジネスコストが増加し、データ量が増えると計算時間が長くなります。
 計算の非効率性に対処するために、Ball-Treeなどのさまざまなデータ構造が作成されていますが、ビジネス上の問題によっては、別の分類子が理想的な場合もあります。

+ **次元の呪い**
 KNNアルゴリズムは、次元の呪いの犠牲になる傾向があります。つまりは高次元のデータ入力では十分に機能しないことを意味します。 
これは、**ピーキング現象**とも呼ばれ、アルゴリズムが最適な数の特徴量に達した後に、特にサンプルサイズが小さい場合、追加の特徴量によって分類エラーの量が増加します。

+ **オーバーフィットする傾向**
 **次元の呪い**のために、KNNでは、オーバーフィットしやすいという傾向もあります。 
これが起こるのを回避するために、特徴量選択と次元削減の手法が活用されていますが、kの値もモデルの動作に影響を与える可能性があります。 
kの値を小さくすると、データをオーバーフィットする可能性があります。
一方、kの値を大きくすると、より広い範囲（近傍）で値が平均化されるため、予測値が**平滑化**される傾向があります。 
かといって、kの値が大きすぎるとデータをアンダーフィットする可能性が出てきます。

# KNNの計算
### 距離メトリック
##### ユークリッド距離（p=2)
これは最も一般的に使用される距離指標であり、実数値ベクトルに制限されます。 
この式を使用して、照会ポイントと測定対象の他のポイントの間の直線を測定します。
$$d(x,y)=(\sum_{i=1}^{n}|x_i - y_i|^2)^\frac{1}{2} =\sqrt{\sum_{i=1}^{n}(x_i - y_i)^2} $$

##### マンハッタン距離（p=1）
これも一般的な距離指標で、2点間の絶対値を測定します。 
一般的にグリッドで視覚化されるため、タクシー距離または市街地ブロック距離とも呼ばれ、市街地の道路を通ってある住所から別の住所に移動する経路を示します。
$$d(x,y)=(\sum_{i=1}^{n}|x_i - y_i|^1)^\frac{1}{1} =\sum_{i=1}^{n}|x_i - y_i| $$


##### ミンコフスキー距離 **~~ミノフスキー粒子~~**
この距離指標は、ユークリッド距離メトリックとマンハッタン距離メトリックを一般化した形式です。 次の式のパラメータpを使用して、他の距離メトリックを作成できます。 pが2に等しい場合、この数式はユークリッド距離を表し、pが1に等しい場合、この数式はマンハッタン距離を表します。
$$d(x,y)=(\sum_{i=1}^{n}|x_i - y_i|^p)^\frac{1}{p}$$

### kの定義
k-NNアルゴリズムのk値は、特定の照会ポイントの分類を決定するためにチェックされる**近傍の数**を定義します。 
例えば、k=1の場合、インスタンスは最も近い1つの近傍と同じクラスに割り当てられます。 

kを定義する際には、その値によって**オーバー・フィット**や**アンダー・フィット**につながる可能性があるため、バランスに注意する必要があります。

kの値を小さくすると、分散は大きくなりますがバイアスは小さくなります。逆にkの値を大きくすると、バイアスは大きくなりますが分散は小さくなります。 

多くの外れ値やノイズを持つデータでは、kの値を大きくすることでより良好な結果を得られる可能性があるため、入力データを十分に考慮してkを選択する必要があります。 

全体的には、分類において同順位が発生することを回避するために、**kには奇数を指定**することをお勧めします。
また、**交差検証戦術**は、データ・セットに最適なkを選択するのに役立ちます。

# あとがき
今回はk近傍法について何となくまとめてみました。
何日か後に見たら全部頭から抜けてる気がしますねぇ…。

記Q&K
GitHub Actions 上で .github/workflows 上のファイルを git push すると remote rejected エラー

# エラー内容

```
! [remote rejected] main -> main (refusing to allow a GitHub App to create or update workflow `.github/workflows/foo.bar` without `workflows` permission)
```

# 問題のコード

```bash:GitHubActions内で
  git config --local user.email $GHA_EMAIL
  git config --local user.name $GHA_NAME
  git add .github/workflows/foo.bar
  git commit -m 'Update'
  git push
```

# やったこと

## Workflow Permission の変更

Read and write にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49525/dd492f74-3293-eb95-78bc-cbb9a884b199.png)

## PAT の権限変更 (Workflow)

そもそも Actions 内では secrets.GITHUB_TOKEN を利用しているので意味ない気もするが、念のため。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/49525/af5bd5d6-91a2-c821-bf8b-2ee525bc1a8c.png)

https://github.com/settings/tokens

## .github/workflows 内に Push しないようにする

ここが盲点だった。
純粋にリポジトリルートに Push させるようにしたらエラーが出なくなり、Push に成功した。
変数宣言機能による違い

| タイプ     |       再宣言 |    再代入    |   スコープ     | 初期化 (ホイスティング)     |
|:-----------------|------------------:|:------------------:|:------------------:|:------------------:|
| let             |              × |        〇        |        ブロック        |        ×        |
| const           |             × |        ×       |        ブロック        |            × |
| var            |              〇 |        〇        |        関数        |       undefined        |



**「再宣言」varは再宣言できるが、letは再宣言できない**
let a = 0;
let a = 0;
コンソール結果↓
Uncaught SyntaxError: Identifier 'a' has already been declared

var b = 0;
var b= 0;
コンソール結果↓
0
#

**「再代入」letは再代入できるが、constは再代入できない**

let c = 0;
c = 1;
コンソール結果↓
1

const d = 0;
d = 1;
コンソール結果↓
main.js:22 Uncaught TypeError: Assignment to constant variable.

#

**「ブロックスコープ」　letはスコープの条件が適応されるがvarはスコープの条件は無視される**

{
  let e = 0;
}
コンソール結果↓
VM70:1 Uncaught ReferenceError: e is not defined


{
  var e = 0;
}
コンソール結果↓
0

#
**「ホイスティング」letは宣言前に値を取得するとエラーになるがvarは undefined となる**

console.log(h);
let h = 0;
コンソール結果↓
main.js:45 Uncaught ReferenceError: Cannot access 'h' before initialization

console.log(g);
var g = 0;

#
【学習】ハブ・スイッチについて

# はじめに
[前回の投稿](https://qiita.com/dr_rk/items/ff969a95f1db1a1095b7)で、LANとWANについて学習を進める中で、自分で図を描いてみました。
(こんな感じの⇩)
![WS_000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3319937/01848ecc-6c26-ceff-25f2-8f3e046e29fb.jpeg)

今回はこの図にもある**スイッチ**と、よく比較される**ハブ**についてまとめてみました。


# ハブ(リピータハブ)
通信ネットワークの集線装置の一種。
OSI参照モデルの第1層(物理層)でネットワークを接続する。

特徴として、下図のように**接続しているすべてのコンピュータに電気信号を送る**ことが挙げられる。
(PC1からPC4にデータを送信する場合を想定⇩)
![2_000000.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3319937/faebd218-e918-74b8-5fae-2c960f866c1c.jpeg)
リピータハブはあくまで電気信号の中継が役割なので、接続されているすべてのコンピュータにそのまま電気信号を送る。
受信側は自分宛のデータであれば受け取り(PC4)、自分宛でなければ無視する(PC2,PC3)。
また、上記のようにPC1からPC4にデータを送信している間、他の端末同士が通信を行うことはできない。

リピータハブは、学校で校内放送で個人を呼び出す場合に例えられる。
(自分が呼び出されたのでなければ無視する感じ)

# スイッチ(スイッチングハブ)
リピータハブと同じく通信ネットワークの集線装置の一種であるが、
**宛先のコンピュータのみに電気信号を送る**点が大きく異なる。

先ほどの図のようにPC1からPC4へデータを送信する場合、データはPC4に向けてのみ送信される。
また、同時にPC2⇔PC3間のデータ送受信も可能である。
![2_000001.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3319937/534ee2a7-db4c-608e-8f68-fb9acfcd41fd.jpeg)
スイッチングハブは通常OSI参照モデルの第2層(データリンク層)で動作する。
リクエストを受けると、リクエスト内容から送信先のMACアドレスで送信先を特定してリクエストを送信する。

リピータハブと比べると、通信回線を不要なデータが流れないためネットワーク全体の性能を向上させることに繋がる。
最近ではスイッチングハブを導入するケースがほとんどとなり、リピータハブの需要は減少している。


.

[次回]
本当はルーターについても、もっと深ぼりたかったのですが、
長くなりそうなため別の投稿にまとめたいと思います。
Azure DevOps にて Markdown 形式のファイルにてリンク先にうまくいかないことへの対応方法～ドットの入力が不足編～

## 概要

Visual Studio Code にて設定したリンク先の項（例：`## 1. 本題`）へのMarkdown 形式でのリンク（例：`[link_test](./markdown_link_test.md#1-本題)`）が、 Azure DevOps では想定通りに動作しませんでした。ドットを追記（`[link_test](./markdown_link_test.md#1.-本題)`）することで、想定通りとなりました。Visual Studio Code と Azure DevOps で仕様が異なるようで、注意が必要です。

## 事象

Visual Studio Code にてリンクを作成した場合には、サジェストにてドットがないリンクが提示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bec546cf-2b45-66f9-55ec-9c49964af1a2.png)

Visual Studio Code では、想定通りのリンク先に移動しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/82f108a8-3668-a800-cac9-3a494cbf21e4.png)

Azure DevOps 上で同じ動作を行うと、想定の項に移動しませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/440ea5e5-f13d-a799-0ce1-3af73a104483.png)


## 対応方法

ドットを追記してリンク先に移動すると、想定通りの動作となりました。

```markdown
[link_test](./markdown_link_test.md#1.-本題)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/9b07eb3d-bb4f-2b16-b129-aeae65c81a91.png)
Stateパターンについて調べたのでFlutterでサンプルを作ってみた

# Stateパターンについて軽く

クラス内のとある状態によって同じクラスでも振る舞いが変わることが多々ある。
それをそのままクラス内で表現しようとすると、
この条件の時にはこう、こっちの時はこう、とIf分岐だらけになってしまうので、
状態ごとにクラス化しシンプルなコードとするパターン。

# サンプルとして何を作ったか

赤、青どちらの色で出力するかのボタンを用意して、
色の出しわけを状態としてStateパターンで実装する。

# クラス図

```mermaid
classDiagram
  class OutputState {
    <<abstract>>
    +getColor()
    +getText()
  }
  class StateRed {
    +getColor()
    +getText()
  }
  class StateBlue {
    +getColor()
    +getText()
  }
  class MyApp {
  }
  class MyHomePage {
  }
  class _MyHomePageState {
  }

  OutputState <|.. StateRed
  OutputState <|.. StateBlue

  MyHomePage <-- MyApp
  _MyHomePageState <-- MyHomePage
  StateRed <-- _MyHomePageState
  StateBlue <-- _MyHomePageState
```

# コード

[GitHub](https://github.com/kenta4327/flutter_state) に完全版があります。

```dart:output_state.dart
import 'dart:ui';

abstract class OutputState {
  Color getColor();
  String getText();
}
```

```dart:state_red.dart
import 'dart:ui';

import 'package:flutter_state/utils/output_state.dart';

class StateRed implements OutputState {
  @override
  Color getColor() {
    return const Color(0xFFC62828);
  }

  @override
  String getText() {
    return '赤色だよ';
  }
}
```

```dart:state_blue.dart
import 'dart:ui';

import 'package:flutter_state/utils/output_state.dart';

class StateBlue implements OutputState {
  @override
  Color getColor() {
    return const Color(0xFF536DFE);
  }

  @override
  String getText() {
    return '青色だよ';
  }
}
```

```dart:main.dart
  :
  : // 割愛
  :
class _MyHomePageState extends State<MyHomePage> {
  final _textController = TextEditingController();
  String _outputText = '';
  Color _outputColor = const Color(0xFFC62828);
  OutputState? _outputState;

  @override
  void initState() {
    super.initState();

    _outputState = StateRed();
  }

  @override
  void dispose() {
    _textController.dispose();
    super.dispose();
  }

  void _changeRed() {
    _outputState = StateRed();
    setState(() {
      _outputColor = _outputState!.getColor();
      _outputText = _outputState!.getText();
    });
  }

  void _changeBlue() {
    _outputState = StateBlue();
    setState(() {
      _outputColor = _outputState!.getColor();
      _outputText = _outputState!.getText();
    });
  }
  :
  : // 割愛
  :
```

以上
Railsで遷移元のコントローラーとアクションを取得する時No Route Matchエラーが発生

遷移元のコントローラーとアクションを取得する↓

<b>実装コード：</b>
```
  def prev_action
    actions = route_details_for(request.referer)
    return actions[:controller], actions[:action]
  end
```
Getメソッドの場合は、問題なく取れましたが、Getメソッド以外の場合
「 Rails.application.routes.recognize_path」で過去のルートを取得すると、No Route Matchエラーが発生されます。

<b>原因：</b>
```
  path = request.referer
　Rails.application.routes.recognize_path(path）
```

recognize_pathにパラメータとしてpathだけ渡すとメソッドはdefault「GET」になり、No Route matchエラーが発生されます。

参考：
https://api.rubyonrails.org/v4.2.0/classes/ActionDispatch/Routing/RouteSet.html#method-i-recognize_path


<b>解決方法：</b>
  Rails.application.routes.recognize_pathを呼び出すときPathかつメソッドもパラメータとして渡せば問題なくPreviousのコントローラーとアクションが取れます。
  例：
  Rails.application.routes.recognize_path(url, method: method)


<b>修正後コード</b>

```
  def get_prev_action
    actions = prev_action
    puts "Previous controller : #{actions[:controller]}, Previous action : actions[:action]"
  end

  def prev_action
    methods = [:get, :post, :put, :patch, :delete]
    method = methods[0]
    retry_count ||= 0
    route_details = nil
    begin
      route_details = Rails.application.routes.recognize_path(request.referer, method: method)
    rescue ActionController::RoutingError => e
        puts "Routing Error = #{e}"
        method = methods[retry_count]
        retry unless (retry_count += 1) == 5
    else
      return route_details
    end
  end
```
PKIとは

# はじめに
毎週1本様々な技術に関する記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiixta.com/7_inai_)

# PKIとは
PKI（Public Key Infrastructure）とは、`公開鍵暗号技術を利用して認証やデータの暗号化などのセキュリティ機能を提供するための仕組み`です。

PKIでは、信頼できる第三者機関（Certification Authority）が、公開鍵に対応する電子証明書（Digital Certificate）を発行します。電子証明書には、公開鍵の所有者や有効期限、認証局の署名などが記載されています。ユーザーは、この __電子証明書を用いて、デバイスや通信相手の正当性を確認する__ ことができます。

- 共通鍵方式
通常の暗号化方式では、送信者と受信者が同じ秘密鍵を共有してデータを暗号化・復号化する必要があります。しかし、PKIでは、公開鍵と呼ばれる暗号化キーと秘密鍵と呼ばれる復号化キーのペアを使用します。公開鍵は誰でも入手できるように公開され、秘密鍵は本人だけが保持するようにします。

# PKIで 本人確認 × 完全性 × 盗聴防止
PKIはセキュリティ面で非常に重要な役割を果たしますが、特に「本人確認、完全性、盗聴防止」の3要素に効果を発揮します。
- 本人確認
前述した通り、信頼できる第三者機関（認証局）が、公開鍵に対応する電子証明書を発行することで、本人確認を行います。
- 完全性
ハッシュ関数を使用し、送受信の前後で値の変化がないことを確認することで、完全性を保証できます。
- 盗聴防止
暗号化されたデータを復号するには、受信者の秘密鍵が必要となるため、第三者が盗聴することはできません。

# 終わりに
IoTにおいても、PKIは重要な役割を果たしています。
IoTデバイスは、多数のセンサーやアクチュエーターを備えており、それらがインターネットを介して相互に通信するため、__セキュリティリスク__ が高まっています。PKIを導入することで、IoTデバイス同士の通信やIoTデバイスとクラウドサーバーとの通信において、本人確認や完全性、盗聴防止が実現できます。これにより、IoTシステム全体のセキュリティレベルが向上し、セキュリティリスクを低減することができます。


最後までお付き合いくださりありがとうございました。
Railsのcallbackについて

# Callbackのafter_destroyで他モデルのデータを操作できたのでメモします。

今回Userモデルにdepartment（部署）モデルが紐づいております。


```user.rb
belongs_to :department,       optional: true
```

```department.rb
has_many :users
```

アソシエーションは上記です。
optional: trueは外部キーのnilを許可するものです。

今回直面したエラーは部署テーブルを一つ削除をすると、
その削除された部署idを持つuserの詳細画面等を表示しようとすると
無い部署idからデータを持ってこようとする為エラーが起こってしまいます。

そこで今回使用するのが　callbackというものです。

## callbackとは
・オブジェクトの生成・更新・削除のタイミングで呼び出されるメソッド
・トリガとなるイベント（create, saveなど）の前後に登録可能
・トリガに対してメソッドを共通化できて便利

## 　after_destroyを使用する
今回はdepartment.rbに下記を追記します。

```department.rb
has_many :users

# コールバック（部署が削除後にメソッドを発動）
  after_destroy :user_has_a_value?

   private

# 部署が削除された時にその部署IDを持っているユーザーがいたら
  # そのユーザーのdepartment_idをnilに変更する。
  def user_has_a_value?
    self.destroy
    if User.where(department_id: self.id).exists?
      user = User.where(department_id: self.id)
      user.update(department_id: nil)
    end
  end

```

解説すると部署が削除されたタイミングでafter_destroyが発火します。
after_destroyではuser_has_a_value?というメソッド使っています。
user_has_a_value?は部署が削除された時にその部署を持っているuserがいないかを全て探し、
存在すればそのuser達のdepartment_idをnilに更新しています。

user.rbでdepartmentに対してoptional: trueを記述している為、
department_idが空でもエラーにはなりません。

これで問題解決となります。

利用可能なコールバックは沢山ありますので興味がある方は調べてみてください。

わかりずらい説明で申し訳ございません。
最後まで見てくれた方は有難うございます。
【Javascript】for...inとfor...ofの違い

## for...in
+ オブジェクトのプロパティを列挙するためのループ処理。
+ 対象のオブジェクトが持つメソッド以外にも、外部から追加したプロトタイプも列挙する。

```javascript
const tom = {
  name: 'Tom',
  age: 23
}
const like = {
  food: 'potato',
  animal: 'cat'
}

Object.setPrototypeOf(tom, like)

for(let key in tom) {
  console.log(`${key}: ${tom[key]}`)
}
```
tomのプロトタイプにlikeのメソッドを設定すると、ループ処理で呼び出される。
```:コンソール
name: Tom
age: 23
food: potato
animal: cat
```


## for...of
+ イテラルオブジェクトの値を列挙するループ処理。
+ 配列やMap、Set、文字列、NodeListなどの反復可能オブジェクトから要素を取り出すために使用される。
+ オブジェクトのプロパティは列挙されない。

```javascript
const array = [1, 2, 3];

for(let val of array) {
  console.log(val)
}
```
```コンソール
1
2
3
```
Valid Anagramをpythonで解き方を詳しく説明してみる

# Valid Anagram

https://leetcode.com/problems/valid-anagram/

上記の問題になります。

簡潔に言えばsを並び替えてtはできるのか？という問題です。
# 解説

最初に考えることはs,tは同じ長さかということです。
文字列sをどのように並び替えたらtができるのかを考える前に長さが異なればｓからｔを作ることが不可能です。
そのため先に
```python
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False
```
そして、ここから考えていきます。
文字列sはアルファベットしかありません。ここから24種類のアルファベットがsの中にいくつ出てきているかをカウントする、同時にｔをカウントする。その種類と数が一致するとTrueを返すように作ればいいじゃないのか？と考えることができます。

ここからハッシュマップを作っていきます。

ハッシュマップはここから詳しくわかります。

https://qiita.com/ztrehagem/items/32407b3bae8fb92d4baf

https://qiita.com/kenta1984/items/5b61ecc4b96a30a32601

![無題のプレゼンテーション.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1493403/a54cb062-6453-564f-887b-01fdeced6b48.png)
このように出てきたアルファベットをカウントしていきます。
このようにしてハッシュマップを作っていきます。
以下は実装です。

```python
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        if len(s) != len(t):
            return False
        dict_s, dict_t = {},{}
        for i in range(len(dict_s)):
            dict_s[s[i]] = 1 + dict_s.get(s[i],0)
            dict_t[t[i]] = 1 + dict_t.get(t[i],0)
        return dict_s == dict_t
```
# ポイント

dictのget関数

https://docs.python.org/ja/3/library/stdtypes.html#dict.get
[AWS Q&A 365][Batch]AWSのよくある問題の毎日5選 #57

# 1. AWS BatchにおけるGPUジョブとは何ですか？
回答：AWS BatchにおけるGPUジョブとは、グラフィックス処理ユニット（GPU）を使用して計算を行うジョブのことを指します。これらのジョブは、機械学習や科学的シミュレーションなどの高性能コンピューティングを必要とするタスクに通常使用されます。

# 2. EKSリソース上でGPUベースのジョブを作成するにはどうすればよいですか？
回答：EKSリソース上でGPUベースのジョブを作成するには、ジョブ定義でGPUリソースの要件を指定する必要があります。ジョブ定義のコンテナのプロパティに「resourceRequirements」フィールドを追加し、「nvidia.com/gpu」というリソースタイプと必要なGPUの数を指定することで行えます。

# 3. AWS BatchでGPUジョブを実行する際の考慮事項は何ですか？
回答：AWS BatchでGPUジョブを実行する際には、GPUリソースの利用可能性、メモリとvCPUの要件、スケジューリングポリシーなどの要素を考慮する必要があります。また、ジョブ定義が正しいリソース要件を指定しており、計算環境に必要なGPUリソースがあることも確認する必要があります。

# 4. AWS BatchでGPUの機能をテストする方法はありますか？
回答：AWS BatchでGPUの機能をテストするには、GPUベンチマークやその他のGPUに負荷をかけるタスクを実行するテストジョブを作成することができます。その後、ジョブのログとメトリクスを監視して、GPUリソースが正しく利用されていることを確認します。

# 5. Amazon EKS上でGPUベースのKubernetesクラスタを作成するプロセスは何ですか？
回答：Amazon EKS上でGPUベースのKubernetesクラスタを作成するには、まず必要なGPUリソースを指定する計算環境を作成する必要があります。その後、ジョブキューを作成し、計算環境をそれに関連付けます。最後に、GPUリソースの要件を指定するジョブ定義を作成し、ジョブをキューに提出します。
[AWS Q&A 365][Batch]Daily Five Common Questions #57

# 1. What are GPU jobs in AWS Batch? 
Answer: GPU jobs in AWS Batch refer to the jobs that use graphics processing units (GPUs) for computation. These jobs are typically used for tasks that require high-performance computing, such as machine learning and scientific simulations. 

# 2. How can I create a GPU-based job on EKS resources? 
Answer: To create a GPU-based job on EKS resources, you need to specify the GPU resource requirements in the job definition. You can do this by adding the "resourceRequirements" field to the container properties in the job definition, and specifying the "nvidia.com/gpu" resource type with the number of GPUs required. 

# 3. What are the considerations for running GPU jobs on AWS Batch? 
Answer: When running GPU jobs on AWS Batch, you need to consider factors such as GPU resource availability, memory and vCPU requirements, and scheduling policies. You also need to ensure that your job definition specifies the correct resource requirements and that your compute environment has the necessary GPU resources. 

# 4. How can I test GPU functionality in AWS Batch? 
Answer: To test GPU functionality in AWS Batch, you can create a test job that runs a GPU benchmark or other GPU-intensive task. You can then monitor the job logs and metrics to ensure that the GPU resources are being utilized correctly. 

# 5. What is the process for creating a GPU-based Kubernetes cluster on Amazon EKS? 
Answer: To create a GPU-based Kubernetes cluster on Amazon EKS, you need to first create a compute environment that specifies the GPU resources required. You can then create a job queue and attach the compute environment to it. Finally, you can create a job definition that specifies the GPU resource requirements and submit a job to the queue.
Base DB(DBCS)検証用設定集

OracleDBの仕様確認のための環境をOCI BaseDB上で作りたい、というときのTips。本番環境ではお勧めできない設定ばかりなのであくまで検証用途での利用を想定しています。

# oracleユーザーで10分たったらタイムアウトをやめさせる
/etc/profileの編集

```
[oracle@dbhost ~]$ ls -l /etc/profile
-rw-r--r-- 1 root root 1880 Feb  9 02:54 /etc/profile
[root@dbhost ~]# cp -p /etc/profile /etc/profile_org
[root@dbhost ~]# vi /etc/profile
```

最後の行の以下の箇所を編集
```
# Interactive Session Timeout must be configured
#TMOUT=600
TMOUT=0
```
TMOUTが0（タイムアウトなし）になっていたら成功
```
[oracle@dbhost ~]$ echo $TMOUT
0
```

他のユーザーでもタイムアウトなしになっています

# .bashrcに好みのalias追加

```
alias talert='tail -10f /u01/app/oracle/diag/rdbms/${ORACLE_UNQNAME}/${ORACLE_SID}/trace/alert_${ORACLE_SID}.log'
alias sqlsys='sqlplus / as sysdba'
alias sqlsysp='sqlplus sys/AAbbcc12345##@dbhost.sub050801XXXXX.tjkvcn01.oraclevcn.com:1521/pdb01.dbhost.sub050801XXXXX.tjkvcn01.oraclevcn.com as sysdba'
```

# pdb上にテストユーザー作成

```
SQL> create user test identified by AAbbcc12345##;
--dbaがあればconnectとresourceはなくてもOK
SQL> grant connect,resource,dba to test;
SQL> ALTER USER test quota unlimited on USERS;
SQL> ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;
```

# gloginの設定

$ORACLE_HOME/sqlplus/admin/glogin.sql
```
SET NUMWIDTH 13
SET LINESIZE 200
SET LONG 40000
SET LONGCHUNKSIZE 40000
SET PAGESIZE 50000
SET SERVEROUTPUT ON
SET TIMING ON
SET TIME ON
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY/MM/DD HH24:MI:SS' ;
SET SQLPROMPT "_USER'@'_CONNECT_IDENTIFIER> "
```

# aliasの設定
PT5_PDB1はtnsnames.oraでPDB接続サービスを指定した接続文字列
```
alias sqlsys='sqlplus sys/AAbbcc12345## as sysdba'
alias sqlsysp='sqlplus sys/AAbbcc12345##@PT5_PDB1 as sysdba'
alias sqltest='sqlplus TEST/AAbbcc12345##@PT5_PDB1'
```
POPとIMAPの違い

# 学習前
メール受信といえばPOPだな～。
IMAPもメール受信のプロトコル！！！？？？

# POPとIMAPの違い
POPはPCにメールをダウンロードし、内容を見る。
IMAPはメールサーバ上で内容を見る。

# 感想
ネットワークに繋がってなくてもメールが見れるのは、
POPでPCにデータがあるからか～。なるほど。

Gmailとかはどの端末でも同期されているから、IMAPか～。なるほど。
lambda Node.js18でbcryptモジュールを使おうとしてドハマリした

# 概要

- ランタイムNode.js18のlambda関数にてbcryptモジュールを使って文字列をハッシュ化しようと試み、めっちゃハマったので経緯をまとめておく。

# ご注意

- 本記事を呼んでも解決方法は記載していません。

# 結論

- 下記の方法でbcryptjsモジュールを使うことで解決した。

https://qiita.com/miriwo/items/9a1662b957fc3afbfcf4

# 反省

- bcryptアルゴリズムを使ったハッシュ化の方法が途中までbcryptモジュールを使うものだけだと思っていた。
- bcryptjsモジュールも使用可能なことを知らなかった。
- ちょっと詰まったら複数の方法があるかもしれないと疑うことをしよう。

# 経緯

1. jsでbcryptアルゴリズムを使ってハッシュ化する場合にbcryptモジュールを使うことを知る。
1. モジュール追加する必要があったため、ローカルのMacでNode.jsバージョンを18に設定、`$ npm init` → `$ npm install bcrypt`を実行、インストール後、package.jsonが入っているディレクトリをzip化し、レイヤーに登録した。
1. lambda関数を作成し、下記のようなimport文を記載した。

    ```index.mjs
    import bcrypt from "bcrypt";
    ```

1. 先に作成したレイヤーを当該の関数に登録した。
1. 当該の関数を実行してみた。
1. 下記のようなエラーがでた。

    ```
    "errorType": "Error",
    "errorMessage": "/opt/nodejs/node_modules/bcrypt/lib/binding/napi-v3/bcrypt_lib.node: invalid ELF header",
    "code": "ERR_DLOPEN_FAILED",
    ```

1. エラーを調べてみると、「bcryptモジュールのバイナリファイルがlambda（AmazonLinux2）と互換のない」ことが原因らしい事がわかった。
1. どうやらAmazonLinux2にて`npm install bcrypt`を実行する必要があるらしい。
1. ぱっと思い浮かんだのがEC2だったのでとりあえずAmazonLinux2のインスタンスを立ち上げてVoltaを入れてNode.js18を入れようとした。
1. Voltaの導入には成功したがVoltaのコマンドが存在しない。（おそらくパスを通してなかったから。）
1. 仕方ないので下記の公式の方法に則ってnvmでNode.js18をインストールする。
    - [https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html](https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html)
1. `$ node -v`を実行すると下記のようなエラーが出る。

    ```
    node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by node)
    node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node)
    ```

1. 衝撃の事実発覚、「AmazonLinux2でNode.js18がサポートされていない」

    ![チュートリアル__Amazon_EC2_インスタンスでの_Node_js_のセットアップ_-_AWS_SDK_for_JavaScript.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/0088681a-fc92-4882-9cb1-069d90344a74.png)

1. ここで気がつけばよかったが、なぜかDockerでAmazonLinux2のコンテナを立ててNode.js18を入れてしまう。

    ```
    docker pull amazonlinux:2.0.20230504.1
    docker run -itd amazonlinux:2.0.20230504.1 /bin/bash
    docker container exec -it コンテナ名 /bin/bash
    ```

1. 案の定`$ node -v`を実行すると下記のようなエラーが出た。AmazonLinux2のDockerイメージ使ってるんだから当たり前、、、。

    ```
    node: /lib64/libm.so.6: version `GLIBC_2.27' not found (required by node)
    node: /lib64/libc.so.6: version `GLIBC_2.28' not found (required by node)
    ```

1. bcryptjsモジュールの存在に気が付きそちらを使うことに、、、。という流れだった。
SQL 超入門

この記事はSQLを知らない人向けに書いてます

<p>alphavantage APIとか使って、以下のような株アプリを作ってる</p>

https://stonehills.tokyo/financer/
<!-- /wp:heading -->


# リレーショナル・データベースとは

リレーショナル・データベースでは、表形式のデータに対し、ＩＤとなる列を決め、IDの値を指定してアクセスする仕組みです。

↓社員情報のテーブルです。この社員IDのような列を「主キー」と呼びます。以降では社員情報をデータベースに格納する方法を説明します。

|  社員ID  |  社員名  | 所属部署 |
| ---- | ---- |---- |
| 0001	| 田中　ABC	| 人事部| 
| 0002	| 山田　CDE	| 営業部| 
| 0003	| 佐藤　XYZ	| 情シス部| 
| 0004	| 鈴木　ABC	| 人事部| 
| 0005	| 佐藤　CDE	| 営業部| 

# テーブルを作る
まず最初にテーブルを作ります。その名も “CREATE TABLE”。先頭で、各レコードを一意に特定できるID情報を主キーに設定します。

MySQL)
```
CREATE TABLE shain_table
(shain_no int NOT NULL PRIMARY KEY,
 shain_name varchar(30),
 busho varchar(20));
```

Oracle)
```
CREATE TABLE shain_table
(shain_no number NOT NULL PRIMARY KEY,
 shain_name varchar2(30),
 busho varchar2(20));
```

# データを登録する
テーブルにデータを登録します。 INSERT文を使います

```
insert into shain_table values( 1, '田中 ABC','人事部');
insert into shain_table values( 2, '山田 CDE','人事部');
insert into shain_table values( 3, '佐藤 XYZ','情シス部');
```

# SELECT する
SELECT 文でデータを取得します。

```
select * from shain_table;
```

```
| shain_no | shain_name | busho   |
|        1 | 田中 ABC   | 人事部   |
|        2 | 山田 CDE   | 人事部   |
|        3 | 佐藤 XYZ   | 情シス部|
3 rows in set (0.000 sec)
```

検索条件を指定する場合
```
select * from shain_table where shain_no =3;
```

```
| shain_no | shain_name | busho  |
|        3 | 佐藤 XYZ   | 情シス部 |
1 row in set (0.000 sec)
```

エクセルのような、表形式のデータを扱うのですが、列の数は固定なんですよね
【合格体験記】AWS認定SAA-C03版に合格しました！

この度AWS認定ソリューションアーキテクトアソシエイトC03版に合格できたので、受けようと思ったきっかけと合格までの経緯を書いていこうと思います。
![FwHsJ6TaQAEZWmb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882765/b76aaafc-51ca-e65d-fd4b-89cb84346aed.jpeg)

# 結果
合格点が720/1000点なのに対して、736点でしたので割とギリギリです。
![FwHsJySaEAAzXMq.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2882765/465faf83-e097-bf9e-a7f8-7c0c839b8f29.jpeg)


# 受ける前の自身のスキル

- エンジニア歴３年目
- 普段の業務でLinuxは頻繁に使っている
- クラウド経験なし
- TCP/IPの基本知識はある
- 基本情報技術者持ってる

# 受けようと思ったきっかけ

私は普段、組み込み・IoTソフト開発に携わっています。言語はPythonをメインに使っています。IoTとなるとハード内のソフトだけでなくインフラ周りの知識もいると感じており、私自身今後強くしていかなければならない分野と考えていました。

インフラといえば、今はクラウド化がトレンド。そんな中AWSは他のAzureやGCPと比較しても採用率の高いパブリッククラウドということで、まずはAWSの知識をつけようということで受験しました！

# 前提知識について

ちなみにクラウドプラクティショナーは受けずにいきなりソリューションアーキテクト受けましたが、ちゃんと合格できました。

前提として、ITの基本的な知識、具体的には基本情報技術者の知識くらいは必要と思います。問題にはTCP/IPやセキュリティの知識が必要だったり、RAIDに関しての問題も出るからです！

# 勉強期間
３月の下旬頃からスタートして、５月中旬に取得することができました。
ですので、大体２ヶ月弱です。インプット期間が約一ヶ月、アウトプット期間が約一ヶ月の半々くらいでした。

# 使用教材

使用した教材は次の３つです！

[【SAA-C03版】これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座](https://www.udemy.com/share/101WKk3@HUm2PqcQkMRNilNeqVy47c5kUgLusKtu49f6eZvRER-_1dqHgb_-fDIc2Htv4uAQzA==/)

[【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）](https://www.udemy.com/share/101rfM3@wieseXvaWDrSpiOH25_nVhKtpSlmNZOhFrhuhUVk_q_7pTywUZPI_9u82qUrdr4aVQ==/)

[Ping-t](https://ping-t.com/)

これらの教材を選んだ理由は、単純に**評判が高くみんな使っていたから**です笑

# 勉強の進め方（アウトプット大事！）
全体的な進め方は以下のとおりです。
1. Udemyの動画講座(めちゃくちゃ長い）を見る。
1. 動画を見ながらハンズオンをやってみる。
1. 動画内容をNotionにまとめる。
1. その後章の終わり毎のクイズをやる。
1. 終了したら模擬試験を解く。
1. サービス分野別のPing-tの問題を解く。
1. 5.6を繰り返す。できてないところ・苦手な分野は**Notion**に追記していく。

基本的に一回動画見たり、ハンズオンやっても定着しないので、アウトプットを繰り返すこと（**模擬試験を解きまくる**）が一番重要だと思います！

もう一度言います。一番重要なのは「**アウトプットを繰り返す**」です！これはAWS認定だけでなく、すべての資格勉強（もちろん業務でも）に共通することだと思います。

## Udemyの問題集
上記のUdemyの模擬試験は発展編はやりませんでした。発展編は高難易度ということで、出るかわからない問題に時間を費やしたくなかったからです。

ですが、それ以外の模試（これだけでOK２つ＋模擬試験問題集４つ）はすべて２回分は解きました。２回やっても合格率７２％未満は３回目もやりました。

# 今後の展望

勉強を通して、AWSの魅力を知ることができました。AWSはIT技術のほぼすべてを網羅していると言ってもいいくらい、様々なサービスが展開されているので、これを極めていきたいと感じました！

ですので、他の認定資格も受けていこうと思います！そして、実務経験も積んでいきたいですね！
Web Intelligenceでカレンダーツールから選択した日付の形式が不正に変換されてしまう

**SAP BusinessObjects Business Intelligence Platform 4.3 Support Package 01**
（以下、BO4.3SP01と略）に関連する製品不具合の情報です。

BO4.3SP01上でWebIレポートを作成する際に、Web Intelligenceでカレンダーツールから選択した日付の形式が不正に変換され、値が正しく反映されない、という不具合事象が発生しました。
SAP公式サポートに問い合わせた結果、原因と対処方法が判明し、実際に不具合事象の解消に至りました。
SAPの公式ドキュメントは基本的に英語が多いので、当該SAP Noteの日本語訳を掲載させていただきます。
同様の事象が起こった場合の参考にしていただければ幸いです。
***
**（SAP Note 原文リンク）**

[3215245](https://launchpad.support.sap.com/#/notes/3215245 "SAP Note 3215245") - The date value picked from Calendar is not working well in Web Intelligence when Preferred Viewing Locale is set to use browser and browser locale is Japanese.
***
**3215245
：Web Intelligenceで、カレンダーツールから選択した日付の値が不正になる
  （優先表示ロケールはブラウザのロケールを使用する設定、かつブラウザのロケールは日本語を設定）**

※本ドキュメントのリリース日付：2022/06/20


**現象**
   Web Intelligenceで、カレンダーツールから選択した日付の値が正しく反映されなくなります。優先表示ロケールはブラウザのロケールを使用する設定になっており、ブラウザのロケールは日本語です。
    Web Intelligenceのクエリフィルタで、日付型オブジェクトを追加し、カレンダーツールから値を選択する場合の制御で、値の形式がYYYY/MM/DDのように正しく表示されず、MM/DD/YYYYとなってしまいます。
    また、クエリパネルで再度クエリ定義を確認すると、渡された値が不正でおかしくなっています。

**関連キーワード**
    BI Webi, BOE, wid, format, time, datetime, yyyy/m/d, m/d/yyyy, region

**原因と前提条件**

**環境：**
SAP BusinessObjects Business Intelligence Platform 4.3 Support Package 01
Web Intelligence

**再現手順：**
    1. Webブラウザを開き、言語を日本語に変更して、Webブラウザを再起動します。
    2. BIラウンチパッドにログオンし、[優先表示ロケール]が
       　'ブラウザのロケールを使用'　として設定されていることを確認します。
    3. Web Intelligenceアプリケーションを起動し、新しいWebIレポートを作成します。
    4. クエリパネルを開き、「結果オブジェクト」と「クエリフィルタ」の両方に
       　日付項目のオブジェクトを追加します。
    5. 「クエリフィルタ」にて、カレンダーツールから日付の値をピックアップします。
       　例として、2022年6月7日をピックアップします。
    6. 日本語ロケールでの表示方式である、 2022/6/7 (YYYY/MM/DD) の形式ではなく、
       　6/7/2022 (MM/DD/YYYY) の形式で表示されることに注意してください。
    7. クエリーを実行し、再度クエリーを編集します。
    8. クエリフィルタの日付の値が、2006/7/20という不正な値になっていることを
       　確認します。


**原因：**
    本問題は、BI 4.3 SP01レベルの潜在的な不具合です。

:::note info
**解決方法１**
**BO4.3 SP02 Patch03以上**のパッチを適用することで問題が解消されます。
:::

:::note info
**解決方法２**
パッチ適用ができない場合、**BO4.3 SP01**レベルのままでの回避策として、
　　優先表示ロケールを手動で固定値　Japanese(日本語)　に設定する
という方法も、問題解決のために有効です。
:::

**補足手順：**
＜優先表示ロケールの設定＞
BI ラウンチパッドの基本設定で、以下の手順によりWeb Intelligence の優先表示ロケール言語を選択できます。

（１）BI ラウンチパッドのツールバーで [基本設定] をクリックし、
　　　[基本設定] ダイアログボックスを表示します。
（２）[基本設定] リストで [ロケールおよびタイムゾーン] をクリックし、
　　　使用可能なオプションを表示します。
（３）[優先表示ロケール] 一覧から優先表示ロケールを選択します。
（４）Web Intelligence をクリックし、Web Intelligence オプションを表示します。
（５）優先表示ロケールを使用してデータを書式設定する場合、
　　　[ドキュメントの表示] の[データの書式設定に現在の優先表示ロケールを使用] 
　　　をクリックします。
（６）[保存して終了] をクリックします。
NextJSでLangchainをAzure版のOpenAIで利用する際の設定方法

## TL;DR

NextJS(つまりJavascript）で、Langchainを使ってAzure版OpenAIを利用したかったのですが、なかなか情報がなかったので簡単にまとめておきます。
（同じところで困っている人がいれば・・）

## LangchainからAzureのOpenAIの利用時に設定の必要がある情報
環境変数に以下の4つの値を設定する必要がある（OpenAIの場合はKeyだけでいいのに・・・）
```sh:.env
# インスタンス名（最初に環境作る時に自分で決めた名前）
AZURE_OPENAI_API_INSTANCE_NAME=xxxxxx
# API_KEY（Azureのコンソールから2つ参照可能）
AZURE_OPENAI_API_KEY=xxxxxx
# 以下の画面で確認できる
AZURE_OPENAI_API_DEPLOYMENT_NAME=xxxx
# 現時点では以下の記述でOK。コンソール画面からは情報がなく、Playgroundで取得したサンプルコードから拝借した。
AZURE_OPENAI_API_VERSION=2023-03-15-preview
```

InstanceNameとDevelopmentNameがどこから持ってこればよいかわかりにくかったのでAzureコンソールの画面をスクショを添付しておく
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/1b9472f0-8d5e-44a8-d1c1-b4911da0cba6.png)


## サンプルコード
NextJSの場合、ルートディレクトリに.envを作成し、上記の情報を書けば自動で読み込まれる。
以下のコードで実際に動作確認することができた。
（サーバサイドで動かす必要があるため、/apiの下にコードを配置する必要がある点に注意！


```typescript:chatgpt
import { OpenAI } from "langchain";
import { ChatOpenAI } from "langchain/chat_models/openai";
import { OpenAIChat } from "langchain/llms/openai";
import { HumanChatMessage, SystemChatMessage } from "langchain/schema";

export default async function handler(req, res) {
  if (req.method === "GET") {
    const chat = new ChatOpenAI();
    const response = await chat.call([
        new HumanChatMessage("名古屋の歴史について教えてください"),  
    ]);
    console.log(response);
    res.status(200).json({ message: responseB });
  }
}

```

## 動作確認

以下のURLにアクセスすると、Azureからのリクエストが取得できる。
http://localhost:3000/api/chatgpt

```json
{
"message": {
    "text": "名古屋の歴史は古く、約2000年前から人が暮らしていたとされています。特に、平安時代には官道などの交通網が整備され、交通の要所として発展していきました。\n\n戦国時代には、織田信長が名古屋城を築城し、名古屋を拠点とする軍団を率いて多くの戦いを勝ち抜いたことが知られています。\n\n江戸時代には、徳川家康が東海道五十三次のうちの一つとして名古屋宿を設置して発展を促し、また、藩政時代には尾張藩のお家騒動もありました。\n\n明治時代には、名古屋市が建設され、産業の発展が進み、近代的な都市へと変貌を遂げていきました。\n\n現代においても、名古屋は自動車産業の中心地として知られ、また、食文化や観光資源も豊富であることから、多くの人々に愛されています。"
    }
}
```


## まとめ

Langchainを利用すると、ものすごく簡単にOpenAIのサービスにアクセスすることができた