OmniAICreator/Qiita-1.07M huggingface dataset:
Difyを用いたGPT-4oのチャットボット

# はじめに
今回は、Difyを用いたGPT-4oのチャットボットを作成した。
Difyは独自のアプリケーションを作成できる、生成型AIツールの開発プラットフォームである。
特徴としては下記のような点が挙げられる。
・直感的なインターフェースによって、プログラミング知識がない方でも簡単にアプリケーションを作成できる。
・GPT-4やClaude 3などの最先端のAIモデルが統合されており、ノーコードで質の高いアプリ開発が可能である。

・Dify

https://dify.ai/jp

・参考文献

https://trends.codecamp.jp/blogs/media/about-dify


以下に、導入を示す。

# 導入
最初から作成をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/2bf738cc-73bf-fb95-8779-29ab710c008b.png)

どのタイプのアプリを作成しますか？の質問に対し、「ワークフロー」を選択
アプリに適当な名前を付ける
アプリの説明を入力(任意)
作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/2e99397c-fbc6-8790-dc7e-e89d1201e6e8.png)

開始を選択し、入力フィールドの＋を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/fe60fcf1-c8a7-8627-3a98-25d40963aedc.png)

変数名は、inputを入力
最大長は、48を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/bdc1e822-c779-756d-b542-ea18286b4a43.png)

開始ボタン横の＋を選択し、LLMを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/b4bc800e-b5c7-8b65-b206-b536c477b2e5.png)

モデルは、gpt-4oを選択（事前に設定済）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/183c7e01-d40c-01c9-94e8-9624d54f7927.png)

SYSTEM欄に下記の画像のように入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/23af15e5-2cb7-44a9-586e-6148fc8381ce.png)

【補足】
{を入力すると変数が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/3af60ab2-107f-ac55-628f-0757a8c4cd61.png)

LLMボタン横の＋を選択し、終了を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/2aa1041a-8e2a-f743-34b6-c61cc5bd70a0.png)

出力変数で、textを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/ce92c07c-0a87-9934-e1a5-8b3a391d52e8.png)

実行を選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/5bb1e37d-074c-5a3a-81cd-bde7d0eb4e22.png)



# 実行結果
入力のinputに質問を入力し、結果を得ることができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/203c00d9-6cd9-1d17-9cf0-9168283e31c8.png)
![スクリーンショット 2024-06-05 113203.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/bf636692-a8fa-ad6c-4b19-4915db07fec5.png)


公開するを選択する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/8da91b8d-a7d4-62cc-cb08-9d3809168834.png)

アプリを実行を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/fc6f68ad-bdc0-90fe-fb4f-f4e55ed2f523.png)

inputに質問を入力し、実行を選択すると、回答を得ることができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806967/c4b1a38c-6ccf-169e-d4da-161558b8704d.png)


# まとめ
今回は、Difyを用いたGPT-4oのチャットボットを作成した。
今後は特定の機能に特化した専門性の高いチャットボットを作成していきたいと考えている。
Azure Data Factory の メタデータ駆動のコピータスクにて Ingest Timestamp の Hive スタイルのパーティションの値を設定する方法

## 概要

Azure Data Factory の メタデータ駆動のコピータスクにて Ingest Timestamp の Hive スタイルのパーティションの値（例：`ngest_timestamp=2024-06-05 02%3A46%3A50`）を設定する方法を共有します。`MetadataDrivenCopyTask_xxx_BottomLevel`パイプラインにおける`FullLoadOneObject`アクティビティと'DeltaLoadOneObject'アクティビティにて、`cw_folderPath`パラメータの設定値を下記のように修正することで対応できます。

```text
@Concat(
    json(item().SinkObjectSettings).folderPath
    ,'/'
    ,'ingest_timestamp'
    ,'='
    ,formatDateTime(
        utcnow()
        ,'yyyy-MM-dd HH'
    ),
    '%3A'
    ,formatDateTime(
        utcnow()
        ,'mm'
    ),
    '%3A'
    ,formatDateTime(
        utcnow()
        ,'ss'
    )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a745609d-eed7-2093-a922-c492d53e15b3.png)

パイプライン実行後に`test01/ingest_timestamp=2024-06-05 02%3A46%3A50`のようなディレクトリにファイルが書き込まれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/99490a16-a76e-d249-00f8-8a46e1154fc5.png)


## 手順

### 1. Azure Data Factory にてメタデータ駆動のコピーアクティビティのパイプラインを構築

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/28a53fc3-e743-2ab0-bd3b-f8cd07ffbc25.png)

### 2. `MetadataDrivenCopyTask_xxx_BottomLevel`パイプラインを表示後に`FullLoadOneObject`アクティビティと'DeltaLoadOneObject'アクティビティにの`cw_folderPath`パラメータを修正

```json
@Concat(
    json(item().SinkObjectSettings).folderPath
    ,'/'
    ,'ingest_timestamp'
    ,'='
    ,formatDateTime(
        utcnow()
        ,'yyyy-MM-dd HH'
    ),
    '%3A'
    ,formatDateTime(
        utcnow()
        ,'mm'
    ),
    '%3A'
    ,formatDateTime(
        utcnow()
        ,'ss'
    )
)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a745609d-eed7-2093-a922-c492d53e15b3.png)

### 3. パイプラインを実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/b8b7330b-59e5-52de-c000-30ebe1ba9320.png)

### 4. Azure Storage にて Hive スタイルのパーティションのディレクトリ構成となっていることを確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/99490a16-a76e-d249-00f8-8a46e1154fc5.png)
ダイス台作ってみた

# はじめに
### 自己紹介
Taku_Taku_Takuと申します。
CTFと競プロしてます。（どちらも初心者）

# 目次
1. [使用物](Chapter0)
1. [なぜ作ろうと思ったか？](#Chapter1)
1. [作成工程](#Chapter2)
1. [完成品](#reference)

<a id="#Chapter0"></a>
# 使用物
CAD：Fusion360
スライサー：Flash Print 5
3Dプリンター：Adventurer 5M Pro
<a id="#Chapter1"></a>
# なぜ作ろうと思ったか？
A. TRPG（有名どころはクトゥルフ）にて、リソース（HP＆MP）を表示するのに、不便だったから。
（間違えてリソース表示用のダイスをロールする事案が多発）
あと、使うのが12面ダイスなせいでいい感じにはまるものが無い！！！

<a id="#Chapter2"></a>
# 作成工程
まず、インターネットで１２面ダイスの3Dデータを入手してきます。

https://booth.pm/ja/items/1701925

ここによさそうな無料の配布データがありました。

:::note info
利用規約的に、改変はセーフです
:::

中身はこんな感じのデータです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/167ea487-1a27-ef46-cad0-96b765967003.png)

これをうまいこと台の形状に編集し ... たものがこちらになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/eade6935-9255-899f-247c-c67809690a94.png)
<details><summary>苦労したポイント</summary>
CADを使うこと自体が久々で、サイコロと円柱部の重なった部分だけ切り取りとろうと悪戦苦闘してました。

さらに、１２面ダイスの性質上、高さが地面から1/2のところが一番大きく、そこに大きさを合わせなければいけない...ということに気づかず【１敗】
加えて、サイズ調整をミスり、【２敗】
計【３敗】しましたｗ

（まだまだ改良できそうなのは内緒です）
</details>



<a id="#reference"></a>
# 完成品
完成品はこちらになります。

![PXL_20240604_054253008.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/9d1517fa-67ff-6639-7783-de547b55af7c.jpeg)


すっぽりハマりました。多少なら揺らしてもダイスが動かないです。

しかし...

![PXL_20240604_054317878.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3805709/09817c34-9280-c773-8d8e-952f8eba13a6.jpeg)


反対向きにして、ダイス台を被せた方がサイコロが見やすい...というオチ

:::note info
実際に作ってみると、見えてくるものもあるんだねｗ
:::
Seleniumで動的サイトのスクレイピング

# 概要
ログインが必要なWEBサイトのスクレイピングとして，WEBブラウザの自動操作を行うSeleniumを用いる方法があります．
流れとしてはSeleniumでログインを突破し，取得したHTMLをBeautifulSoupで解析するといった感じです．
今回は検証として，Googleで「Python」と検索した時の検索結果を取得してみました．

# 実行環境
動作環境
- Python v.3.9.9
- Windows 11

Windows上で既にPythonを実行できる前提で進めます．

また，Seleniumのバージョンが4.6以上だと，ChromeDriverを手動でダウンロードしなくてもいいみたいです．
詳しくは下を読んでください．

https://www.selenium.dev/blog/2022/introducing-selenium-manager/

### 1. 仮想環境の構築
作業ディレクトリに移動して，下のコマンドを実行します．
```bash
$ python -m venv .venv
```
実行すると作業ディレクトリ直下に `.venv` といった名前のディレクトリが作成されます．

### 2. 仮想環境のアクティベート
```bash
$ .venv\scripts\activate
```
実行してうまくいくと，コマンドプロンプトの先頭が `C:\Users\x>` から `(.venv) C\Users\xxx>` になるはずです．

### 3. 必要なライブラリのインストール
`pip` のバージョンを更新し，seleniumとbs4をインストールしましょう
```bash
$ python -m pip install -U pip
$ python -m pip install selenium requests bs4
```

次のコマンドでインストールされたライブラリ一覧を確認できます
```bash
$ python -m pip list
```

# プログラムの実行
[こちらの記事](https://qiita.com/tomomi-kawashita/items/1a1e03d5ee590823b92e)から一部引用

下のPythonスクリプト (`scraping.py`) をコピペして実行．実行結果が `output` のようになれば成功！！（検索アルゴリズム的な問題で，完全には一致しないかもしれません）

```python:scraping.py
# ライブラリの読み込み
from time import sleep
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

# Web Driverの設定
driver = webdriver.Chrome()

# Googleのページを開く
driver.get("https://google.com")

# 検索ボックスの要素を指定
elm = driver.find_element(By.NAME, "q")

# 検索ボックスに「Python」を入力
elm.send_keys("Python")

# エンターキーを押す
elm.send_keys(Keys.ENTER)

sleep(1)

# 検索結果のHTMLを取得
html = driver.page_source.encode("utf-8")
soup = BeautifulSoup(html, "html.parser")

# ページタイトルを抽出して表示
# CSSセレクタで要素を指定
print(*soup.select(".LC20lb.MBeuO.DKV0Md"), sep="\n")

# Web Driverの終了
driver.quit()
```
```text:output
<h3 class="LC20lb MBeuO DKV0Md">python.jp: プログラミング言語 Python 総合情報サイト</h3>
<h3 class="LC20lb MBeuO DKV0Md">Welcome to Python.org</h3>
<h3 class="LC20lb MBeuO DKV0Md">初心者からPythonを実務で使えるためのスキル習得時間は？お勧めの勉強 ...</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonでできることとは？機械学習を使ったAI開発をはじめとした実例を ...</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonとは？3分で分かる人気の理由と基礎知識 - かっこ株式会社</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonでできること6選！仕事への活用方法から学習方法まで解説</h3>
<h3 class="LC20lb MBeuO DKV0Md">Python</h3>
<h3 class="LC20lb MBeuO DKV0Md">【入門】Pythonとは｜活用事例やメリット、できること、学習方法 ...</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonの開発環境を用意しよう！（Windows）</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonとは？プログラミング言語の用途を初心者向けに解説</h3>
<h3 class="LC20lb MBeuO DKV0Md">Python Release Python 3.12.3</h3>
<h3 class="LC20lb MBeuO DKV0Md">O'Reilly Japan - Pythonクイックリファレンス 第4版</h3>
<h3 class="LC20lb MBeuO DKV0Md">Pythonとは？開発に役立つ使い方、トレンド記事やtips</h3>
<h3 class="LC20lb MBeuO DKV0Md">新・Python入門編 | プログラミング学習サイト【paiza ...</h3>
```

# まとめ
動的サイトのスクレイピングを行う方法として，SeleniumとBeautifulSoupを組み合わせた手法を試しました．
ちなみに今回のケースは，クエリパラメータを設定して`https://google.com?q=Python`にリクエストを送ることで静的サイトのスクレイピングと同様に行えます．
毎日ABC day13【c++】ABC333 A-C問題解説【ACコード付き】

# AtCoder Beginner Contest 333

https://atcoder.jp/contests/abc333

## A - Three Threes
与えられた整数 $N$ を $N$ 個繋いで出力する。

```cpp
int N;

int main()
{
	cin >> N;
	for (int i = 1; i <= N; i++) cout << N;
	cout << endl;
	return 0;
}
```
## B - Pentagon
正五角形の頂点のペアが二つ与えられる。それぞれを結んだ線分の長さが等しいか判定せよ、という問題。

2点のペアの長さは、頂点の番号の差分が同じペアでは必ず同じになるので、ft_diff()関数で差分を求め、比較している。

```cpp
string S, T;

int	ft_diff(char a, char b)
{
	int ans = 0;
	if (a > b) ans = a - b;
	else ans = b - a;
	if (ans >= 3) ans = 5 - ans;
	return ans;
}

int main()
{
	cin >> S >> T;
	if (ft_diff(S[0], S[1]) == ft_diff(T[0], T[1])) cout << "Yes" << endl;
	else cout << "No" << endl;
	return 0;
}
```
## C - Repunit Trio
十進法ですべての桁の数字が 
1 である整数をレピュニットと呼びます。レピュニットを小さい順に並べると $
1,11,111,…$ となる。
3 つのレピュニットの和として表せる整数のうち$ 
N $番目に小さいものを求めよ、という問題。

和の小さい順に並べた時に、どのように３つのレピュニット数が遷移するか、規則性を見つけられるかがミソ。

```cpp
int N;
long long dp[19];

int main()
{
	cin >> N;
	dp[1] = 1;
	for (int i = 2; i < 18; i++) dp[i] = 10 * dp[i - 1] + 1;
	int i = 1;
	int j = 1;
	int k = 1;
	for (int l = 2; l <= N; l++)
	{
		if (i == j && j == k)
		{
			i = 1;
			j = 1;
			k++;
		}
		else if (i < j) i++;
		else
		{
			j++;
			i = 1;
		}
	}
	long long ans = dp[i] + dp[j] + dp[k];
	cout << ans << endl;
	return 0;
}
```
Azure OpenAIのGPT-4oを実行してみた。

# はじめに
Azure OpenAIは、マイクロソフトが提供するクラウドベースのAI言語モデルサービスです。このサービスでは、GPT-4oをはじめとする最先端の言語モデルを利用することができます。GPT-4oは、従来のGPT-3.5モデルよりも高度な言語理解と生成能力を持っており、様々なタスクに活用できます。

このコードの目的は、Azure OpenAI APIを使ってGPT-4oモデルを活用し、対話形式のレスポンスを生成することを示すことです。具体的には、ユーザーからの質問に対して、GPT-4oモデルが適切な回答を生成する様子を確認することができます。これにより、Azure OpenAIサービスの活用方法の一例を理解することができます。



# 開発環境
- Azure OpenAI
- Python 3.11
    - Azure OpenAI APIとの通信に使用します。
    - python-dotenv 環境変数の管理に便利です。 
- IDE
    - 今回はcursorを使用しています。 

# 導入
Azureにログインします。
Azure Open AIサービスを開きます。
新しいリソースグループを作成します。
今回[GPT-4o]を使いたいため地域を[East US]にしておきます。
リソースグループ名は任意で入力します。
インスタンスNameを一意にする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/94d59f88-0055-2292-60d8-464b81d34541.png)

次の「Network」と「Tag」はそのまま。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/f4d92363-9325-e434-ec43-160193879975.png)

ここでCREATEを押したらリソースグループの作成は完了します。それを作成したらリソースグループのリストから先程作ったリソースグループを選択し、リソース管理の方からのKEYとEndpointを取得します。KEYはどれか１つでだいじょうぶです。これは後程利用します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/d545b6dc-f6d5-167b-0bdb-e1cc226c8d83.png)



次に、左のリストからOverviewを選択し、次の画面で
Azure OpenAi Studioに入いります。

左側のメニューからデプロイを選択します。
そこで新しいモデルをデプロイを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/bac5e66a-5c13-3cbc-fd8e-e1584c5ac41e.png)

今回はモデルを「GPT-4o」にしています。デプロイ名も同じものにして作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/52c777ab-1c56-b40a-ef13-67ad7d7be7af.png)


# コードの作成

先ほど取得した「KEY」と「Endpoint」を利用して「.env」ファイルを作成します。


~~~.env
AZURE_OPENAI_ENDPOINT=<YOUR_ENDPOINT>
AZURE_OPENAI_API_KEY=<YOUR_APIKEY>
~~~

次にプログラムを作成します。ここで「load_dotenv()」関数を利用して先ほど作成した「.env」ファイルから機密情報を取得しています。modelのところを先ほど作成したデプロイ名にします。

~~~.py
import os
from openai import AzureOpenAI
from dotenv import load_dotenv

load_dotenv()

client = AzureOpenAI(
  azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
  api_key=os.getenv("AZURE_OPENAI_API_KEY"),
  api_version="2024-02-01"
)

response = client.chat.completions.create(
    model="gpt-4o", # model = "deployment_name".
    messages=[
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "user", "content": "Does Azure OpenAI support customer managed keys?"},
        {"role": "assistant", "content": "Yes, customer managed keys are supported by Azure OpenAI."},
        {"role": "user", "content": "Do other Azure AI services support this too?"}
    ]
)

print(response.choices[0].message.content)
~~~

# 実行結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806972/835d68d9-e61f-3d20-3508-502c17ec331c.png)


お疲れ様でした。
Docker環境でのmerge時のエラーの解決方法




## はじめに
Docker環境でGitを使用する際、マージコンフリクトが発生したときに指定されたエディタが見つからない場合があります。
この記事では、そのエラーメッセージの対処方法と、DockerfileにGitのデフォルトエディタ設定を組み込む方法を紹介します。

## エラーメッセージ
まず、Gitマージ時に以下のようなエラーメッセージが表示されることがあります。

```
root@local-board:/var/www/html# git merge develop
Auto-merging hogehoge.ts
Auto-merging fogefoge.txt
Auto-merging higehige.php
hint: Waiting for your editor to close the file... error: cannot run editor: No such file or directory
error: unable to start editor 'editor'
Not committing merge; use 'git commit' to complete the merge.
```

このエラーメッセージは、Gitがエディタを開こうとした際に、指定されたエディタが見つからないことを示しています。

## 解決策
この問題を解決するために、Gitが使用するエディタをVSCodeに設定します。以下のコマンドを使用して設定します。

```sh
git config --global core.editor "code --wait"
```

しかし、Dockerを再構築するたびにこの設定を行うのは手間がかかるため、Dockerfileに組み込むことにしました。

## Dockerfileの編集
以下は、Gitのデフォルトエディタ設定をDockerfileに組み込む方法です。今回はPHPとApacheのイメージを使用しています。

```Dockerfile
#例
FROM php:8.3-apache

#その他必要な設定

# Gitのエディタを設定
RUN git config --global core.editor "code --wait"
```

## 注意点
- **VSCodeがインストールされていない場合**: `code --wait`はVSCodeのコマンドであり、通常のPHP-Apacheイメージには含まれていません。この設定はホストマシン上でVSCodeがインストールされていることを前提としています。
- **ホストマシン上での設定推奨**: Dockerコンテナ内でVSCodeを直接使用するシナリオは一般的ではありません。通常はホストマシン上でVSCodeを使用し、Gitの操作もホストマシン上で行います。

## まとめ
Docker環境でGitのデフォルトエディタを設定する方法を紹介しました。
Dockerfileに設定を組み込むことで、再構築時の手間を省くことができます。
これにより、開発効率を向上させることができるでしょう。
学習過程メモ｜サーブレット（servlet）についてオプション的な役割だと思ってたけど、実際はメインディッシュだった

# 【今日書くこと】
サーブレットについてふわっと理解してきたので、その辺り

## 1. ざっくり概要

### そもそもサーブレットとは

語源：serve（サーブする）＋let（〜させる）

- 大まかには、サーバーサイドで実行されるプログラム
- Java Servlet APIの一部
- サーブレットコンテナと呼ばれるサーバー環境で実行される

→つまり、クライアントのリクエストに応答する小さなサーバー

※Java Servletについて
JSPと組み合わせて使う場合、データの入出力処理を担当する


### サーブレットコンテナ（webコンテナ）の話

- サーブレットを実行するためのソフトウェア

※処理の流れ
→HTTPリクエストを受け取る
→受け取ったHTTPリクエストを解析する
→サーブレットやJSPなどのJavaコンポーネントを実行する
→生成されたHTTPリクエストをクライアントに送信する

※サーブレットコンテナを含みJSPやHTTPサーバーとしての機能も含むものはwebコンテナと呼ぶ／Apache Tomcatはwebコンテナの一つ


### ついでに、JSPとは

- サーブレット技術の延長
- HTML内にJavaコードを埋め込める
- JavaEEの一部
- 一般的にサーブレットと組み合わせて使う


### あと、web.xml

- Java EEのウェブアプリケーションデプロイメントディスクリプタ
- サーブレットやフィルターなどの設定やマッピングを定義
- web.xmlファイル内でサーブレットの定義、サーブレットのURLパターンとマッピング、サーブレットの初期パラメータの設定が行われる

```web.xml
< web-app>
    < servlet>
        < servlet-name>Sample</servlet-name>
        < servlet-class>com.example.Sample</servlet-class>
    </servlet>

    < servlet-mapping>
        < servlet-name>Sample‹/servlet-name>
        ‹url-pattern>/sample</url-pattern>
    </ servlet-mapping>
</web-app>
```

【解説】
web.xmlでSampleというサーブレットを定義→/sampleというURLパターンにマッピング

これによって、クライアントが/sampleパスにリクエストを送信するとSampleが呼び出される


## 2. 実践／具体例

前提：
- サーブレットはServletインターフェイスを実装する
- GenericServletかHttpServletクラスを継承する
- HttpServletクラスを継承する場合、doGet(), doPost(), doPut(), doDelete()メソッドに分岐させられる
We can't find the field ‘Is US Based’ (API Name includes ‘Is_US_Based__c’) associated with the Data Stream ‘Lead’.


# We can't find the field ‘Is US Based’ (API Name includes ‘Is_US_Based__c’) associated with the Data Stream ‘Lead’.

+ [Unable to verify step on Create a Data Stream unit](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007cli8y)


新しいプレイグランドを使ったとのこと

+ [Unable to verify step in 'Create a Data Stream'](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007clmiMSAQ)
+ [Error when verifying Data Stream and Formula Field despite creating it in playground org.](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epEKOSA2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/681a64c0-19c9-e55b-97d1-998aa5386661.png)


+ [数式フィールドを追加してマップする](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007eqKk6SAE)

:::note
私にとって役に立った答えは、 別のグループのDan Bowldsからのものでした。 

「忘れるところでした。最初の画像のステップ 3 で間違えたことの 1 つは、フィールド「米国に拠点を置いている」を、リードではなく連絡先の未マッピング セクションに誤ってマッピングしたことです。」
:::


+ [am stuck on Create a Formula Field and getting a error and trying to fix it](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Kh24p)

:::note
Please check this article. 


https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epEKOSA2
:::
モーダルのお話

## HTMLとCSSだけでモーダルが作れるようになったらしい。
フロントエンドになってはや数年、自作やらプラグインやらで対応してきた私には「本当ですか…？（疑い）」という気持ち。
実際に打って自分で見て試すことにしました。


https://codesandbox.io/embed/hirsty-shaw-4f7q47?fontsize=14&hidenavigation=1&theme=dark


…動く！ えっすごい
背景を固定したいだとか、そういうのも実装したいとなるとJSが必要ですが、
基本形はHTML + CSS で十分対応できます。
モーダルをスクロールしてるのに、下のページがスクロールされて困る場合は、
`[popover]`に対して `overscroll-behavior` を設定すれば、そのモーダル内のものだけスクロールができるように調節できます。モーダルがないところにカーソルを置いてスクロールすると背景がスクロールされます、固定化がされるわけではないです。

`popover` の値を変更すると閉じるボタン以外で閉じられないようにすることもできるし、背景もちゃんと設定できます。

本気でこれからはこれでモーダルを実装してもいいのでは…？という感じです。
ただ、最近主要ブラウザで使えるようになっただけであり、
古いものだと対応していないので使う案件等は選ぶ必要があります。

しかし、JS必須だったときよりも導入もしやすく時間もその分減っているので、
技術の進歩（？）って目覚ましいな〜と思います。

## 参考

https://developer.mozilla.org/ja/docs/Web/HTML/Global_attributes/popover
https://developer.mozilla.org/ja/docs/Web/CSS/overscroll-behavior
https://www.gaji.jp/blog/2024/02/16/18434/
Leafletで後から操作を無効化する方法

Googleで「leaflet 操作 無効化」等で検索しても、さくっと見つからなかったので自分用メモを兼ねて。

# はじめに
Leafletは、JavaScriptで地図APIを呼び出すための高機能なライブラリである。基本的には、ユーザーが地図を自由に移動できるよう作られているが、場合によっては、地図を固定したい（操作を禁止したい）場合もあるだろう。

移動させないことを前提として、地図を読み込みたいならば、例えば以下の記事のように、`L.map`へオプションを渡せば解決する。

https://qiita.com/ynunokawa/items/8da1f422a754a54d8707

しかし、特定の条件を踏んだ時にのみ、操作を禁止するという場合はどのようにすればよいのだろうか。

# 結論

`const mymap=L.map("your_map_div_id")`とした上で、以下の関数を呼び出すと良い。

```js:index.js
function map_control_disable(){
    //ドラッグやズーム等、すべてを禁止する
    mymap.dragging.disable();
    mymap.touchZoom.disable();
    mymap.scrollWheelZoom.disable();
    mymap.doubleClickZoom.disable();
    mymap.boxZoom.disable();
    mymap.tapHold.disable();
    mymap.keyboard.disable();
    mymap.zoomControl.disable();
}
```
　

以上。

　


# 参考文献

https://leafletjs.com/

https://waq3-travelog.com/how-to-use-leaflet-and-gsi-map-vol2/
Jupyter Lab で lgb.train を実行すると処理が終わらない問題

某Udemy の講座で Jupyter Lab で lgb.train を実行すると処理が終わらない問題が解決したので記載

Jupyter Lab で重い処理を実行するとカーネルが再起動する（らしい）。
その際、実行中のステータス（*）は表示されたままになり、「見かけはbusyだが実際はアイドル状態」という問題が発生している。

GoogleColabで同じコードを実行した際の警告文が解決につながった。
警告文は「ちょっとbin数多すぎんよ」的な内容だったので、ビニング処理を行った。

具体的にはこんな感じ![GPRe5GlbUAAXU-K.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3761212/d0021690-3797-6c14-ad03-6d5882cede31.png)

結果、GoogleColabでは警告文が表示されなくなり、Jupyter Lab でも無事実行できた。

もっとスマートな解決法とかもっと綺麗なコードの書き方とか、この記事に足りないものは星の数ほどあると思うので、適宜修正していく予定。
SQLAlchemyでSQLクエリをログに表示する方法

## 背景
SQLAlchemyを使用する際に、SQLクエリをログに表示したい

現状のログ
```
2024-06-05 10:47:42.877 | INFO     | backend.interface.api.healthz:healthz:19 - Database connection successful
2024-06-05 10:47:42.878 | INFO     | uvicorn.protocols.http.httptools_impl:send:481 - 127.0.0.1:53438 - "GET /healthz HTTP/1.1" 200
```

対象のコード
```
@router.get("/healthz")
async def healthz(session: AsyncSession = Depends(get_session)) -> JSONResponse:
    try:
        async with session.begin():
            # データベース接続確認クエリ
            result = await session.execute(text("SELECT 1"))
            _ = result.fetchone()
        logger.info("Database connection successful")
        return JSONResponse(
            status_code=200, content={"status": "ok", "database": "connected"}
        )
    except Exception as e:
        logger.exception(f"Health check failed: {str(e)}")
        return JSONResponse(
            status_code=500,
            content={"status": "error", "database": "disconnected", "error": str(e)},
        )
```

## やったこと
SQLAlchemyのエンジン作成時に、echoオプションを有効にするだけで、SQLクエリのログ出力が可能
```
Engine = create_async_engine(DATABASE_URL)
```
↓
```
Engine = create_async_engine(DATABASE_URL, echo=True)
```

## 動作確認
`echo=True`オプションを有効にしたことで、以下のようにSQLクエリがログに表示された
```
2024-06-05 10:53:26,686 INFO sqlalchemy.engine.Engine SELECT DATABASE()
2024-06-05 10:53:26,686 INFO sqlalchemy.engine.Engine [raw sql] ()
2024-06-05 10:53:26,688 INFO sqlalchemy.engine.Engine SELECT @@sql_mode
2024-06-05 10:53:26,688 INFO sqlalchemy.engine.Engine [raw sql] ()
2024-06-05 10:53:26,688 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names
2024-06-05 10:53:26,688 INFO sqlalchemy.engine.Engine [raw sql] ()
2024-06-05 10:53:26,689 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2024-06-05 10:53:26,690 INFO sqlalchemy.engine.Engine SELECT 1
2024-06-05 10:53:26,690 INFO sqlalchemy.engine.Engine [generated in 0.00021s] ()
2024-06-05 10:53:26,691 INFO sqlalchemy.engine.Engine COMMIT
2024-06-05 10:53:26.691 | INFO     | backend.interface.api.healthz:healthz:19 - Database connection successful
2024-06-05 10:53:26.692 | INFO     | uvicorn.protocols.http.httptools_impl:send:481 - 127.0.0.1:53455 - "GET /healthz HTTP/1.1" 200
```

## まとめ
SQLAlchemyでSQLクエリをログに表示する方法は非常に簡単だった。create_async_engine関数に`echo=True`オプションを追加するだけ。
これでデータベースとのやり取りを詳細に把握できるため、アプリケーションのパフォーマンス向上や問題解決が容易になる。
RNでお手軽i18n


要 [react-native-localize](https://github.com/zoontek/react-native-localize)

## コード

### ライブラリ部分

i18n.js

```javascript
import { getLocales } from 'react-native-localize';

import EN from './en.json';
import JA from './ja.json';

export class i18n {
    static intance = null

    lng = ""
    fallbackLng = { 'en': EN, 'ja': JA }
    langdata = {}

    constructor(props) {
        this.init()
    }

    init() {
        this.lng = getLocales()[0].languageCode;
        this.langdata = this.fallbackLng[this.lng] || EN
        console.log("" + this.langdata["lang"])
    }

    getText(key) {
        let t = ""
        let value = this.langdata
        try {
            const keys = key.split('.')
            // console.log("" + Object.keys(keys))
            for (const k of keys) {
                if (value[k] !== undefined) {
                    value = value[k]
                } else {
                    return undefined
                }
            }
            if (typeof value == 'string')
                return value
        } catch (e) {
        }
        console.log("" + key + " is not found.")
        return t
    }

    static getInstance() {
        if (i18n.instance == null) {
            i18n.instance = new i18n()
        }
        return i18n.instance;
    }

    static t(key, ...args) {
        const cls = i18n.getInstance()
        // console.log("t key:" + key)
        s = cls.getText(key)
        if (!s) return ""
        return s.replace(/\{(\w+)\}/g, (match, variable) => {
            const value = args[Number(variable) - 1];
            return value !== undefined ? value : match;
        })
    }
}
```

ja.json
```json
{
    "lang": "日本語",
    "appversion": {
        "button": {
            "title": "{1}のバージョン情報"
        }
    }
}
```

en.json
```json
{
    "lang": "English",
    "appversion": {
        "button": {
            "title": "{1} version"
        }
    }
}
```

definition.js
```javascript
export const APP_NAME = "sample app"
export const APPVERSION_BUTTON_TITLE = "appversion.button.title"
```

# 使用

```javascript

import { i18n } from "../translation/i18n"
import * as D from "../definitions"

...snip...

    const btn_app_version = i18n.t(D.APPVERSION_BUTTON_TITLE, D.APP_NAME)
```

btn_app_versionが以下になる
- sample appのバージョン情報
- sample app version


# その他
- JSON管理なので、ファイル追加して、`fallbackLng`に追加するだけで容易に多言語対応出来る
- スマホの言語が欲しいだけなので`react-native-localize`も使用せず、native moduleで取ってきても良いかもしれない
基本情報技術者の壁

# 難しいことばかり...
---
現在基本情報の学習を進めています。
コンピュータの構成、ソフトウェア関連、基礎理論の学習を主に行っています。
そんな中で初心者の私が難しいと感じたものを3つ紹介します。

---
### 1.**基数変換**

---<font color="green">基数変換とは</font>---
エンジニアおなじみの2進数や、普段利用している10進数などの進数を変換すること。
仕組みを理解するうえで「**桁の重み**」に苦労しました。
慣れてしまえば楽に計算ができるかもしれませんが、初心者が躓きやすいかもしれません。

詳しくは下記のリンクを参照ください。
[桁の重み](https://qiita.com/Upatissa/items/7aa6588b322c4f7605f2)

---
### 2.**シフト演算**
---<font color="Blue">シフト演算とは</font>---
左右にビットをずらして乗算や除算の演算を行うこと。[ビットをずらす＝シフトする]
ただずらすだけではなく2の何乗倍する、1/2何乗倍するなどをします。
またシフト演算には2種類あるため、種類によって計算式も変わるため注意が必要です。

詳しくは下記のリンクを参照ください。
[シフト演算の仕組み](https://qiita.com/Upatissa/items/a83dcb92f124c22d0565)

---
### 3.**情報の表現**
---<font color="Red">情報の表現とは</font>---
皆様も聞いたことがある「〇〇キロバイト」「〇〇ギガバイト」も、コンピュータでは
最小単位が存在します。それが「**ビット**]です。
8ビット＝1バイト　になります。(例外も存在します。)

試験の中では「32ビットの表現ビットパターンの個数は24ビットの何倍か」のような
問題が出てきたりします。
計算式は以下の通りです。

##### 32ビットで表現できるビットパターンは2 32乗個。 24ビットで表現できるビットパターンは2 24乗個。 2 32乗 ÷2 24乗＝2 8乗＝256倍。

---

全くの初心者の私にとっては難しいことばかりで同じ境遇の方は躓くのではないか、と思います。
今後も学習を行う中で初心者が躓きそうなものを更新していこうと思います。

[参考文献:栢木先生の基本情報技術者教室](https://www.amazon.co.jp/%E4%BB%A4%E5%92%8C05%E5%B9%B4-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%EF%BC%86%E3%82%AF%E3%83%AC%E3%83%90%E3%83%BC%E6%96%B9%E5%BC%8F%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E6%A0%A2%E6%9C%A8%E5%85%88%E7%94%9F%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E6%95%99%E5%AE%A4-%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93-%E6%A0%A2%E6%9C%A8/dp/4297131307)
【paizaラーニング】レベルアップ問題集 素数メニュー 「素因数分解」 PHP　

### 問題

https://paiza.jp/works/mondai/prime_number_primer/prime_number_primer__prime_factorization?language_uid=c

### 解答

素因数分解の条件式`$i * $i <= $num`の必要性

##### 1.処理時間の短縮

`num` の平方根よりも大きい数は、`num` の素因数になり得ません。なぜなら、平方根よりも大きい数の積は常に `num` より大きくなるからです。

例えば、`num = 15` の場合、平方根は約 `3.87` です。つまり、4 以上のすべての数は `15` の素因数候補から除外できます。

この条件式を導入することで、無駄なループ処理を大幅に削減でき、処理時間を短縮することができます。

##### 2.探索範囲の絞り込み

`i * i <= num` という条件は、`i` が `num` の最大限素因候補となり得る値を明確に示しています。

例えば、`num = 20` の場合、この条件式は `i <= 4` となり、`i` として検討すべき値は `1, 2, 3, 4` のみに絞られます。

このように、`i * i <= num` 条件式は、探索範囲を効率的に絞り込む効果がある。

```php
<?php
    function primeFactors($num) {
        $factors = array();
        // 2で限界まで割る
        while ($num % 2 == 0) {
            $factors[] = 2;
            $num /=2;
        }
        // 素因数分解
        for($i = 3; $i * $i <= $num; $i += 2) {
            while ($num % $i == 0) {
                $factors[] = $i;
                $num /= $i;
            }
        }
        if($num > 2) {
            $factors[] = $num;
        }
        return $factors;
    }
    
    $n = trim(fgets(STDIN));
    $factors = primeFactors($n);
    foreach ($factors as $v) {
        echo $v."\n";
    } 
    
?>
```
メールの仕分けルール原案作りをGPTに手伝ってもらう


# はじめに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/194b76e7-6e6e-0e16-ee8d-a65f0113579f.png)

先日、Outlook の仕分けルールが壊れてしまい作り直す羽目になりました:innocent:
せっかくだから (?) GPT にルール作成を手伝ってもらおうってことで、プロンプトを作ってみました。

# プロンプト

試行錯誤して自分にあったプロンプトを準備しました。

```
下記のメールアドレスを整理してください。

# 整理の制約
* Nは10とします。
* 会社の業種で整理してください。
* 担当者の個人アドレスと配信専用のアドレスに分類してください。
* 担当者の個人アドレスは「@」を含むドメインアドレスの部分だけリスト化してください。
* 配信専用のアドレスはメールアドレスをリスト化してください。
* 全く同じ複数の項目は1項目のみ出力してください。
* リストの記号は省略してください。
* リストの項目数は最大Nとし、Nごとにリストを分割してください。

# メールアドレス
```

この後にメーラーのプレビュー表示などからメールアドレスを適当にコピペします。例えば、Desktop 版の Outlook の場合、プレビュー表示されている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3695440/3be5b8ba-1a93-ca11-56df-257d1d529986.png)
の Google の部分で右クリックしてコピーを選択すると、

```
Google <no-reply@accounts.google.com>
```

が得られるので、それをそのままコピーします。

```
# メールアドレス
Google <no-reply@accounts.google.com>
```

これを仕分けしたいメールについて繰り返し、ある程度たまったらプロンプトを実行し、分類されたメールアドレスで仕分けルールを作成し、仕分けを実行します。あぶれたメールをさらに分類し、繰り返します。

# 説明

分類は、以下の考えに基づきます。

* 見逃さないことを第一に仕分けます
* ダイレクトメールとそうでないメールで仕分けます
* 配信専用アドレスをドメインで分類すると、同じドメインの必要なメールも仕分けされてしまうため、メールアドレスすべてを指定し、ダイレクトメールフォルダへ仕分け、無視します
* 担当者個人アドレスを同じダイレクトメールに仕分けると、必要なメールも仕分けされてしまうため、ドメインを指定し、ダイレクトメール個人フォルダへ仕分け、確認します
* 仕分けの追加や解除が必要になった場合を考慮し、業種で分類します
* そのままコピペしやすいように記号を加えません
* Outlookの場合、1つのルールに大量のアドレスを指定するとルールが壊れやすい・フリーズするといったバグに遭遇した経験があるため、最大Nでルールを分けて作成します

# おわりに

MS-Copilot の導入が未だですが、仕分けのルール作りもメールを指定するだけで作成してくれるようになれば嬉しいですね。それまでのつなぎとして使用したいと思います。
The MySQL server is running with the --read-only option so it cannot execute this statement (SQL: insert into...

# はじめに
AWS RDSのMySQL5.6 -> 8.0への移行をするために、お勉強がてらBlueGreenDeploymentを利用してみました。
Blue：MySQL 5.7
Green：MySQL 8.0
で構築し、テスト用に構築したEC2からMySQL8.0へ接続して動作確認したところ
データの取得はできるがデータの更新でエラーが発生
Greenは読み取り専用になっているらしい

# 解決
Green用にRDSのパラメータグループを作成し
**read_only**の項目を
**{TrueIfReplica} -> 0**
に変更することでエラー解消

## 手順
作成したパラメータグループを選択
![スクリーンショット 2024-06-05 9.57.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535832/70407c73-9ec5-6e3f-31c7-96a7bcb6cbe3.png)

read_onlyの項目を確認するとレプリカの場合はTrueとなっている
![スクリーンショット 2024-06-05 9.57.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535832/cb477640-84db-7bdd-0995-ac6ce5e88ed4.png)

read_onlyを0に修正
![スクリーンショット 2024-06-05 9.59.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535832/f80d1297-6871-96b7-53b8-58126e3432d6.png)
【paizaラーニング】レベルアップ問題集 素数メニュー 「素数大学」 PHP　

### 問題

https://paiza.jp/works/mondai/prime_number_primer/problem_index?language_uid=php&a8=yYl6pYdB0crXXk52cVUFDBUF7BkorNs61VUN2kFD7DqB0clYWQlcs7ly.7.2i24rRDj7F_lERYl6vs00000022930001

### 解答
　1. 最初に取りうる値の最大値を定義します。
　2. 素数判定の関数を定義。
　3. 定義した最大値の大きさの素数判定表を作成。
　4. それに基づいて合格判定の出力。
```php
<?php
    // 最大値の定義
    define("MAX", 6000001);
    
    function sieve($x) {
        $is_prime = array_fill(0, $x + 1, true);
        $is_prime[0] = $is_prime[1] = false;
        // エラトステネスの篩で素数判定
        for($i = 2; $i * $i <= $x; $i++) {
            if($is_prime[$i]) {
                for($j = $i * $i; $j <= $x; $j += $i) {
                    $is_prime[$j] = false;
                }
            }
        }
        return $is_prime;
    }
    
    $primelist = sieve(MAX);
    // 判定表のもと、出力
    $n = trim(fgets(STDIN));
    for($i = 0; $i < $n; $i++ ) {
        $num = trim(fgets(STDIN));
        echo ($num <= MAX && $primelist[$num]) ? "pass" : "failure";
        echo "\n";
    }
?>
```
Mac Node.js 1万件の情報が入ったcsvを出力するスクリプトを作ってみる

## 概要

Macのローカルでjsのスクリプトを動かして1万件の情報が入ったcsvを出力してみる。

## 方法

1. MacのローカルにNode.jsを導入（筆者はVoltaを使ってNode.jsを管理している。Node.jsのバージョンは20.11.1を使用）
1. 任意のディレクトリを作成
1. 下記コマンドを実行して初期化

    ```shell
    npm init
    ```

1. 下記コマンドを実行してcsv-writerパッケージをインストール

    ```shell
    npm install csv-writer
    ```

1. 下記コマンドを実行してスクリプトファイルを作成

    ```shell
    touch generate_csv.js
    ```

1. 作成したスクリプトファイルに下記の記載を実施

    ```generate_csv.js
    const createCsvWriter = require('csv-writer').createObjectCsvWriter;
    const path = require('path');

    const csvWriter = createCsvWriter({
        path: path.join(__dirname, 'users.csv'),
        header: [
            {id: 'name', title: 'Name'},
            {id: 'email', title: 'Email'},
        ]
    });

    const data = [];

    for (let i = 1; i <= 10000; i++) {
        data.push({
            name: `user_${i}`,
            email: `user_${i}@example.com`,
        });
    }

    csvWriter.writeRecords(data)
        .then(() => {
            console.log('The CSV file was written successfully');
        });
    ```

1. 下記を実行してスクリプトを実行

    ```shell
    node generate_csv.js
    ```

1. カレントディレクトリにusers.csvというファイルが出力される
AzureVM（仮想マシン）の起動、シャットダウン、割り当て解除が簡単に自動化できるようになった

# ある日の出来事
私の部署ではAzureのVMを日常的に開発やテストでよく使っているのですが、節約のために自動シャットダウンを設定していました。
そんなある日、ユーザー様へのデモ環境として***業務時間中は仮想マシンをずっと起動しておきたい***という問い合わせが来ました。

以前からAzureには自動シャットダウンの機能が備わっていたのですが、自動起動の機能は標準ではサポートされておらず、Azure Automationや古い方法ですとタスクマネージャーを使って、VMの自動起動を実現する必要がありました。

ただ、ふと今回改めて調べてみると[Microsoftの記事](https://learn.microsoft.com/ja-jp/shows/it-ops-talk/auto-shutdown-and-auto-start-an-azure-vm)に自動起動のことが書かれておりました。
試しに利用してみるとこれがとても***便利***で***簡単***だったので、簡単にですが記事にまとめてみようと思った次第です。

## 仮想マシンの自動起動の実装
今回の目玉である仮想マシンの自動起動の方法を記載します。
というより、自動停止も自動割り当て解除（Deallocate）も一緒の流れなので、自動起動さえできれば他も同じ要領で出来ます。

作成の流れは以下の通りです。
### 1. 自動化タスクを追加する
1. AzurePortalで自動起動したい仮想マシンのページに遷移する
2. 左ペインから、オートメージョン>「タスク（プレビュー）」をクリックする
3. 「タスクの追加」をクリックする
<img alt = "タスクの新規追加" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612369/96bf4e21-eb2b-3bb8-921a-74cc61a982dd.png" width = "90%">

### 2. テンプレートを選択する
1. 「Start Virtual Machine」を選択する
2. 「次：認証>」をクリックする
<img alt = "タスクの新規追加" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612369/3848c9c3-6d42-70f7-b9d4-2f3801a49059.png" width = "90%">

### 3. 認証情報の設定
1. Azure VM(azurevm)の「作成」をクリックする
2. 右ペインに接続画面が表示されるため、「サインイン」をクリックする
3. サインイン情報を入力の上、「次へ」をクリックする
<img alt = "タスクの新規追加" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612369/f7dc0e15-3a3f-42d5-b5b4-59c318b47a39.png" width = "90%">


同様に「Office 365 Outlook(office365)」に対しても認証情報を設定する。
すべてが終わったら画面下部の「次：構成>」をクリックする

### 4. 構成の設定（自動起動の頻度や時間はここで設定します）
1. 構成内容を入力する
   - タスク名：自由に設定する（わかりやすい名前が良いと思います）
   - Start Time：最初の起動日時を設定する
   - Timezone：Tokyo Standard Time（デフォルトだとUTCとなっており日本時刻とは9時間の差異が発生します）
   - Interval：自由設定（Frequencyと合わせてタスクを実行する頻度を設定します）
   - Frequency：下記から選択する（Intervalと合わせてタスクを実行する頻度を設定します）
       - Month
       - Week
       - Day
       - Hour
       - Minute
       - Seconds
   - Notify Me：通知メールを送るかを設定します
   - Enter email：Notify MyをONにした場合、通知先のメールアドレスを入力します
2. 「次：確認および作成>」をクリックする

***画像は毎日日本時間の9:00に起動するように設定しています***
<img alt = "タスクの新規追加" src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612369/7115b53d-d54f-8e96-0e00-ad90752f12c2.png" width = "90%">

#### 【補足】平日のみ自動起動したい場合
曜日指定の機能はないため、以下のように週１回起動するタスクを5個用意することで実現できます。
- 毎週月曜日の9時に起動
- 毎週火曜日の9時に起動
　　　 ・・・
- 毎週金曜日の9時に起動

## 5. 作成
1. 確認および作成で画面下部の「作成」をクリックする

## 6. 確認
今回作成されたタスクが無事登録されていれば問題ありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1612369/254c4e78-445a-7afe-cacf-b415675cf81d.png)

# 所感
Azureの仮想マシンはCPUやメモリといったリソースを解放（割り当ての解除）することで、節約することが出来ます。
そのため、普段誰も使わないような夜間などは停止させると、Azureの利用料を抑えることができます。

皆さんもAzureの仮想マシンを使う際は、このような機能を使って節約してみてください。
GMT version4とversion5のコマンドを解読するための解説

## はじめに

GMTのversion4、version5のプログラムの改修を余儀なくされた人に向けている。  
新しく作成する場合は、GMT version6またはpygmtで作成したほうが当然によい。  
GMTコマンドはほとんどの場合Shell Scriptで作成されていると思われるが、多くは可読性が悪い。コメントがない場合や変数が分散していたり、100行前の変数を使用していたりと、めちゃくちゃなことが多い。

以下はリファレンスである。

GMT5.4.5

https://docs.generic-mapping-tools.org/5.4/

GMT4.5.18

https://docs.generic-mapping-tools.org/4/

## GMTコマンドの種類

2種類ある。
1つ目は、データの補間やデータの形式を変換するコマンド。
2つ目はそれら生データや変換を行ったデータをグラフやある地図座標系上にプロットするためのPostScriptのコマンドを出力するコマンドである。

## 用紙という考え方

GMTはPostScriptのコマンドを標準出力することで図示している。最終的にプリントアウトをすることを想定されて設計がなされている。PostScript自体には描画範囲という概念はないが、GMTには用紙の大きさという概念がある。用紙から外れた部分は描画がなされないという特徴がある。例えば、A4サイズで設定した場合はA4から外れた部分はコマンドを実行しても除かれる。また、PostScriptの中身を知る必要はないが、PostScriptの描画の設計が反映されているようなオプションの書き方なされていることが多い。

## -K,-O,-Pオプションについて

GMTのオプションの中身は呪文のようなものがほとんどで意味がすぐに分かるものはほとんどない。まずはこのオプションたちを把握するとよい。

### -Pオプション

GMTは出力した内容をPostScriptが扱える印刷機で印刷することを考えている。
-Pオプションはプリントする方向を決めるオプションである。
Landscape(風景、長辺が左右)、Portrait(肖像、長辺が上下)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/998887/ff129372-fb56-9818-a954-aaa086839627.png)

デフォルトはLandscapeで、-PオプションをつけるとPortraitになる。Landscapeがデフォルトなのは、地図はたいてい横長であることが理由。
Landscapeの原点は右下でX方向は上下、Y方向は左右。
Portraitの原点は左下でX方向は左右、Y方向は上下。
印刷すればどちらでも問題はないかと思われるが、現代では画面上で見る、png等に変換しPC上で見ることが多く、Landscapeでは不都合なことが多い。基本的にはソースコードでは-Pオプションをつけていることが多い。
GMT6では当然Portraitのみになっている。

## -K,-Oオプション

GMTコマンドは１回で終わることはなく複数回に分けておこなわれることが多い。

PostScriptファイルというかGMTの出力は、  

1.	ヘッダー部分(初期化と定義)
2.	本体
3.	ページ印刷

と構成されているので、最初のコマンドや中間のコマンドや最後のコマンドでつけくわてほしい部分が異なる。
-Kオプションではページ印刷部分を記載しない。-Oオプションではヘッダー部分を記載しない。
したがって以下のような使い方になる。

### コマンド1回で終わる場合

```bash
~ > psfile
```

### コマンド2回で終わる場合

```bash
~ -K > psfile
~ -O >> psfile
```

### コマンド3回以上の場合

```bash
~ -K > psfile
~ -O -K >> psfile
~ -O -K >> psfile
~ -O >> psfile
```

## 原点位置

地図やグラフの枠線を用紙に描画する際の基準である。左下が基準である。  
デフォルトは(2.5c,2.5c)である。(cはcmのこと。)  
コマンドを解釈する際は今の原点はどこにあるか、枠線の縦と横の長さは何か等を考えながら実施する必要がある。  
原点の位置を前のコマンドからずらすことも可能である。
-X,-Yオプションで原点を変えることができる。  
Shell Scriptには今の原点はどこにあるかをコメントで記載することが望ましい。  

## Shell Scriptの解読方法

まず出力図があればそれを見て、コマンドがどの出力に対応するのか確認する。  
-X,-Yオプションがあれば別の地図やグラフの作成に移ったことがわかる。  
-J,-Rオプションの記入が-JMや-Rである場合は、その前のコマンドで地図座標や範囲の設定がなされているとこがわかる。

## おわりに

まだ書きかけなので、適宜追記します。
Azure Firewallを停止・起動する方法

# はじめに
業務で使用しているAzure Firewallがある日動かなくなりました。
VMからFirewallにpingを飛ばしても応答が返ってこず、、、。

結局、どういう状態になっているか分からず、対策も打てなかったので、
やむを得ずFirewallを停止→起動することで問題を解消しました。

本記事では、Firewallに何らかの問題が発生し、私のように停止・起動する以外に手を打てない状況になった方々に向けて、
Firewallの停止・起動方法を記載したいと思います。

# 使用するPCの環境
今回使用するPCの情報を下記に記載いたします。

OS：Windows 11
PowerShellのバージョン：5.1
Azure PowerShellモジュールのバージョン：10.4.1

# 方法
Azure Firewallの停止・起動はAzure PowerShellで行います。
（Azure Portal上では出来ないんです。。。）

端末のPowerShellに、Azure PowerShellモジュールをインストールしていない場合は、
以下のコマンドを実行してモジュールをインストールします。
```
Install-Module -Name Az -Repository PSGallery -Force
```

## Azure Firewallを停止
以下のコマンドを実行してFirewallを停止します。
　当該Firewallリソースに対してDeallocate()メソッドを実行します。

```stop_firewall.ps1
# Azureへのログイン
Connect-AzAccount

# Firewallを停止
$azfw = Get-AzFirewall -Name "<Azure Firewallのリソース名>" -ResourceGroupName "<Azure Firewallが所属するリソースグループ名>"
$azfw.Deallocate()
Set-AzFirewall -AzureFirewall $azfw
```

正常に実行されると、以下のような出力結果が表示されます。
　対象Firewallの情報（リソースグループ、リソース名、リージョン）が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485934/036db94c-50e4-bd45-b466-18fa83ef397e.png)

Azure Portal上で対象Firewallを確認すると、下図のように、
停止状態ではパブリックIPやプライベートIPが未割り当ての状態になります。
　このとき、プロビジョニング状態がSucceededとなっていることを確認しておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485934/5281af5e-ab87-96e4-e3ab-9a0a1601b9bf.png)



## Azure Firewallを起動
以下のコマンドを実行してFirewallを起動します。
　当該Firewallリソースに対してAllocate()メソッドを実行します。
　　Allocate()メソッドの引数には以下を指定します。
　　　Firewall配置先Vnet
　　　Firewallに割り当てるパブリックIPリソース（配列で指定）

 ```start_firewall.ps1
 # Azureへのログイン
Connect-AzAccount

# Firewallを起動
$azfw = Get-AzFirewall -Name "<Azure Firewallのリソース名>" -ResourceGroupName "<Azure Firewallが所属するリソースグループ名>"
$vnet = Get-AzVirtualNetwork -ResourceGroupName "<Firewall配置先VNetが所属するリソースグループ名>" -Name "<Firewall配置先VNetのリソース名>"
$publicip1 = Get-AzPublicIpAddress -Name "<Azure Firewallに割り当てるパブリックIPのリソース名>" -ResourceGroupName "<パブリックIPリソースが所属するリソースグループ名>"
$azfw.Allocate($vnet,@($publicip1))

Set-AzFirewall -AzureFirewall $azfw
 ```

Deallocate()メソッド実行時と同様、正常に実行されると
Firewallリソースの情報が出力結果に表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485934/3331d5f3-d4f7-70df-bb4f-4e89a8e18e08.png)

また、Azure Portalでは、下図のように起動状態ではパブリックIPやプライベートIPが割り当てられた状態になります。
　プロビジョニング状態がSucceededとなっていることを確認しましょう。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2485934/ee4bd1f4-9906-be43-12e9-a8b24ae0f5aa.png)

# 参考資料
・Azure Firewallの停止・起動方法（中段に記載）
https://learn.microsoft.com/ja-jp/azure/firewall/firewall-faq
VScodeでも文字の縮小のショートカットを変更する

VS code や Cursorで文字の拡大縮小だけど、
ZoomInは[command]+[Shift]+[;]　= command + なのに
ZoomOutは[command]+[NumPadSubtract] と テンキーの-に割り当てられてて
MacBook単体で使ってると積む。。。

適度に環境変わるから（・・）、焦らないように備忘録。

### ショートカットの変更方法

VScodeだと、左下のギアアイコン
Cursorだと、右上のギアアイコン
から[Keyboard Shortcuts]を選択
(このショートカットもIDEによって変わるからカオス・・・)

検索にzoomといれる

View:Zoom Outの行をクリックして、左に出てくるペンをクリック
[command]を押して[-]を押したらリターンキーを押して確定

ついでに、View:Reset Zoomも設定しておく
[shift] [command] [-]でいいだろう
CSSが適用されない事象について

## 記事を書こうと考えた背景について
* JavaScriptでTODOアプリを作成する前にhtmlとcssで画面の全体像を作成していて書いたcssが想定通りに表示されなかった為

cssが適用されなかったときのコードと実行結果
htmlファイル
```
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
	<title>Snake Game</title>
	<link rel="stylesheet" href="style.css">
</head>
<body>
	<div class="input-area">
	<input type="text"name="todo" placeholder="TODOを入力"/>
	<button>
	  追加
	</button>
	</div>
	<div>
        <p>未完了のTODO</p>
        <ul>
            <div>
            <li><p>TODOです</p>
                <button>完了</button>
                <button>削除</button>
            </li> 
            </div>   
        </ul>
    </div>
    <div>
        <p>完了のTODO</p>
        <ul>
            <div>
            <li><p>TODOでした</p>
                <button>戻す</button>
            </li> 
            </div>   
        </ul>
    </div>
	<script src="./JavascriptTodo/index.js"></script>
</body>
</html>
```
cssファイル
```
 body {
    font-family: sans-serif;
};
 .input-area{
    background-color: aqua;
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/53351390-2066-4e36-e552-28f0ad55a702.png)

cssが適用されなかった原因

**{}の後に;をつけていたことによる文法ミス**

正しくCSSが適用された時のコードと実行結果

※htmlファイルは上記と同じものを使用

CSSファイル
```
 body {
    font-family: sans-serif;
}
 .input-area{
    background-color: aqua;
}
```
実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/e61e4097-1915-c7c8-b4cd-ff6793b2b979.png)
メモ
**bodyの{}の後の；を削除した**　

## 想定通りに実行されないときの考え方のフローについて

* 正しい文法で書かれているか
* 1行ずつコメントアウトして想定通り動かないもしくはエラーが出るところを突き止める
* 問題の場所を突き止めたらエラーの解決に向けて検索・コードの修正をする
KonnectのDev Portalの認証にEntra ID(AzureAD)を利用する

API GatewayのKong GatewayのSaaS版である[Konnect](https://docs.konghq.com/konnect/)では開発者向けAPIポータル（Dev Portal）の認証にOpenID Connect(OIDC)をサポートしている。
ここではEntra ID(旧AzureAD)と連携させて、どれくらい簡単に設定できるかを確認する。
なお、公式ドキュメントは[こちら](https://docs.konghq.com/konnect/dev-portal/access-and-approval/azure/)になる。

## 準備
### Azure側の設定
#### アプリケーションの作成 
最初にAzureにアプリケーションの作成を行う。
参考にしたのは[こちら](https://learn.microsoft.com/ja-jp/power-apps/developer/data-platform/walkthrough-register-app-azure-active-directory)。
Azureにログインし、Entra IDから`アプリの登録`->`新規登録`をクリック。
![20240521114831.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/a90e6150-b09d-66eb-35f4-4f1e3c58c427.png)

以下を入力して登録ボタンを押す。
- 名前: `konnect`
- サポートされているアカウントの種類: `この組織ディレクトリのみに含まれるアカウント`
- リダイレクトURI: `Web`, `https://<Dev PortalのURL>/login`

![20240521132751.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/96ca649f-8d47-0877-1bfc-a8af631e0532.png)

Konnectの`Client ID`がアプリケーションの`アプリケーションID`に相当するため、作成後にアプリケーションIDを控えておく。

#### アプリケーションの設定
作成したアプリケーションをクリックし、`証明書またはシークレットの追加`->`+ 新しいクライアントシークレット`->`追加`の順にクリックする。
![20240521120142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/f9e90474-ad1d-1c9a-fd22-a76a4bf4f5e9.png)

作成したクライアントシークレットの`値`がKonnectの`Client Secret`に対応するため、作成後にそれらの値を控えておく。作成直後しか`値`は取得できないので、見逃した場合は再作成する。

左サイドバーの`概要`からアプリケーションの概要画面に戻り、`エンドポイント`から`OpenID Connect メタデータ ドキュメント`に表示されているURLをコピーしブラウザで開く。
ブラウザで開くとJSON形式の出力が確認できるので、`issuer`の項目(`https://login..../v2.0`)をコピーし控えておく。

![20240521120622.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/af62397f-50bb-66fe-0f66-463695b2ab92.png)


#### グループ要求の設定
Azureの左サイドバーの`トークン構成`->`+ グループ要求の追加`からグループ要求を追加する。
全てのチェックボックスにチェックを入れて、ID、アクセス、SAMLはそれぞれ`グループID`を選択して`追加`をクリックする。
![20240521131912.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/485dd1a8-a216-9485-6c4a-17042a2b77d4.png)

次に`+ オプションの要求の追加`をクリックして以下選択して`追加`をクリックする。
- トークンの種類: `ID`
- 要求: `email`
- Graph email のアクセス許可: チェックする

![20240521132032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/064dd43d-1e15-281e-578d-597abe87da48.png)

以上でAzure側の設定は終了となる。

### Konnect側の設定
Dev Portalの[`Settings`->`Identity`](https://cloud.konghq.com/portal/portal-settings#identity)からOIDCの横の`Configure Provider`をクリックし、以下を入力してSaveする。
- Provider URL: `IssuerのURL`
- Client ID: `アプリケーションID`
- Cilent Secret: `シークレットIDの値`

![20240521133706.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/72a32d8f-3f2e-092d-b6b2-f4018d697630.png)


## 動作確認
Dev Portalにアクセスする。
アクセスすると、以下のようにSSOログインのボタンが表示されるようになる。
![20240521133910.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/fd73345e-0052-9ecb-6bfb-03036c0b3c2f.png)

`Continue with SSO`をクリックしてEntraIDのアカウントでログインすると以下のようにDevPortalの画面が表示される。
![20240605092316.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/a6ec7b51-7b6f-3504-dead-aa3d8ac4d4eb.png)

ということで、特に苦労することなく簡単にOIDC連携を設定することが出来た。
robloxでassistant その104

# 概要
robloxでassistantやってみた。
練習問題やってみた。

# 練習問題
時間を表示せよ。

# 手順
- ReplicatedFirstに、LocalScriptを追加。
- スクリプトを書く。
```

local Players = game:GetService("Players")
local Player = Players.LocalPlayer
local PlayerGui = Player:WaitForChild("PlayerGui")
local Gui = Instance.new("ScreenGui")
Gui.Parent = PlayerGui
local Frame = Instance.new("Frame")
Frame.AnchorPoint = Vector2.new(0.5, 0.5)
Frame.Position = UDim2.new(0.5, 0, 0.3, 0)
Frame.Parent = Gui
local Label = Instance.new("TextLabel")
Label.Text = os.date("%H:%M")
Label.TextSize = 100
Label.Parent = Frame


```


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a26f8a77-7006-487a-19e0-91789c30c7d0.png)


以上。
【Java】継承を覚える

スーパークラスを継承したサブクラスが通常のクラスと比べて何が違うのか、覚えるための自分用メモです。

# 継承とは？
既存のクラスのフィールドとメソッドを引き継いで、新しいクラスを定義することです。

# サンプルプログラム

例えば、以下のクラスを```SubClass1```クラスに継承するとします。
```java:SuperClass.java
public class SuperClass {
    private String name;
    public SuperClass(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}
```
その場合、以下のように記述します（親クラスに引数なしのコンストラクタが無い場合、```super()```でコンストラクタを呼び出す必要あり）。
```java:SubClass1.java
public class SubClass1 extends SuperClass {
    public SubClass1(String name) {
        super(name);
    }
}
```
親の```SuperClass```クラスをスーパークラス、子の```SubClass1```クラスをサブクラスといいます。

## 継承したサブクラスをインスタンス化する
継承したサブクラスをインスタンス化する記述は、通常のインスタンス化と変わりません（スーパークラス型でインスタンス化も可能）。
```java:Main.java
public class Main {
    public static void main(String[] args) {
        SuperClass superClass = new SubClass1("名前1");
    }
}
```
## 継承したメソッドを呼び出す
継承したメソッドは、サブクラスに記述が無くても呼び出すことができます。
```java:Main.java
public class Main {
    public static void main(String[] args) {
        SuperClass superClass = new SubClass1("名前1");
        print(superClass);
    }
    static void print(SuperClass superClass) {
        System.out.println(superClass.getName());
    }
}
```
**実行結果**
名前1