OmniAICreator/Qiita-1.07M huggingface dataset:
Azure App Service をルートドメインで構築してみた

Azure App Service をルートドメインで構築した事がなかったので、試してみました。

## 検証環境構築

```bash:bash
prefix=mnrapptest
region=japaneast
domain=example.com

az group create \
  --name ${prefix}-rg \
  --location $region

az appservice plan create \
  --name ${prefix}-plan \
  --resource-group ${prefix}-rg \
  --is-linux \
  --sku B1

az webapp create \
  --name ${prefix} \
  --resource-group ${prefix}-rg \
  --plan ${prefix}-plan \
  --runtime "PHP|8.0" \
  --https-only true

az webapp config set \
  --name ${prefix} \
  --resource-group ${prefix}-rg \
  --always-on true \
  --ftps-state Disabled
```

## 「カスタムドメインの追加」で表示される下記レコードをDNSに追加

![appservice-rootdomain-01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675885/78adee91-bc9b-bed0-4461-b8a6d2330bbf.png)

## AppService にカスタムドメインとマネージド証明書を登録

```bash:bash
az webapp config hostname add \
  --webapp-name ${prefix} \
  --resource-group ${prefix}-rg \
  --hostname $domain

az webapp config ssl create \
  --resource-group ${prefix}-rg \
  --name ${prefix} \
  --hostname $domain

az webapp config ssl bind \
  --certificate-thumbprint $(az webapp config ssl show \
  --resource-group ${prefix}-rg \
  --certificate-name $domain \
  --query thumbprint \
  --output tsv) \
  --resource-group ${prefix}-rg \
  --name ${prefix} \
  --ssl-type SNI
```

## 参考

https://learn.microsoft.com/ja-jp/azure/app-service/app-service-web-tutorial-custom-domain?tabs=root%2Cazurecli
LangChainでChatGPTのWebみたいに返信を徐々に表示する

<iframe width="560" height="315" src="https://www.youtube.com/embed/hAFXgg1oun4" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

ChatGPT の API を呼び出すと結果がまとめて返ってくるけど、ChatGPT の WebUI のように１文字１文字徐々に表示することもできます。LangChain を使った場合のコードはこちら。

```py:chat.py
from typing import Any, Dict, List
from langchain.chat_models import ChatOpenAI
from langchain.callbacks.base import BaseCallbackHandler
from langchain.schema import (
    LLMResult,
    HumanMessage,
)
import openai
import os


openai.api_key = os.environ.get("OPENAI_API_KEY", "")


class MyCustomCallbackHandler(BaseCallbackHandler):
    def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any) -> None:
        print("START")

    def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
        print("\nEND")

    def on_llm_new_token(self, token: str, **kwargs: Any) -> None:
        print(token, end="", flush=True)

    def on_llm_error(self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any) -> None:
        pass


chat = ChatOpenAI(streaming=True, callbacks=[MyCustomCallbackHandler()], temperature=0)
chat([HumanMessage(content="炭酸ソーダについての詞を書いてください。")])
```

`streaming=True` と `callbacks=[MyCustomCallbackHandler()]` を指定し、 `BaseCallbackHandler` を継承したクラスを定義してください。
Shotcutで動画画面を左右反転する

手順は大きく分けて２つ
・上下反転
・180度回転

操作手順
1-1. フィルタの「+」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/8b405bd1-d78c-3409-4f87-5e6219806152.png)

1-2. 「上下反転」フィルタをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/d20f69bf-d986-2f85-2d7b-b01b400af3b5.png)

1-3. 以下は「上下反転」フィルタ適用後の画面です。パラメータはありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/b68b64ce-ce0b-47d7-7e40-cf7135d78c3a.png)

2-1. フィルタの「+」、「サイズ・位置・回転」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/285d5b90-4fc2-8c16-0292-974545d9bfa9.png)

2-2. 回転に180度を設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/f90a7081-c2b5-2694-1db8-7e50f3b11c4c.png)

2-3. 回転後の画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/988592/70999196-1777-ed82-b8a0-f895fa1f2d70.png)
杉浦光夫 解析入門 I p6 例題5　

まず、$s$は暗に「上限(supremum)」の意味なので、$s^2=2$ (あるいは、$s^2$は、2より小さいが2に非常に近い数)が（暗に）想定されています。 

ただ、それはそれでおいておき以下の恒等式を考えます。

$s^2 + \frac{1}{2}(2-s^2) = 2 - \frac{1}{2}(2-s^2)$

この左辺は、$s^2$に非常に小さい数を加えたいという「心」をあらわしたものですが、数式的には「恒等式」です。　$s^2 + (2-s^2) = 2$  ですので、この両辺から$\frac{1}{2}(2-s^2)$ を引いたものです。

$(s+\frac{1}{4s}(2-s^2))^2 - \\{ \frac{1}{4s} (2-s^2) \\}^2 = 2 - \frac{1}{2}(2-s^2)$

これは、上の右辺は触らずに、左辺を「平方完成」したものです。

この場合、平方完成には２つの方法があると言えるでしょう。つまり、$s^2 + a$ の平方完成を考える際、$s^2 + a = (s+\frac{a}{2s})^2 - \frac{a^2}{4s^2}$ とするケースと $s^2 + a = (s+\sqrt{a})^2 - 2s\sqrt{a}$ とするケースです。ここでは、まずは、前者のケースを考えました。上式、左辺第２項を右辺に移項して、

$(s+\frac{1}{4s}(2-s^2))^2  = 2 - \[\frac{1}{2}(2-s^2) - \\{\frac{1}{4s}(2-s^2)\\}^2 \] $

(1) 右辺を見て、$\frac{1}{2}(2-s^2) > \\{\frac{1}{4s}(2-s^2)\\}^2$ ならば、$(s+\frac{1}{4s}(2-s^2))^2 < 2$ が成り立ちます。
$\frac{1}{m}$ は、小さければ小さいほどいいのですが、ここでは、「どれだけ小さければいいのか？」という疑問に対する答えが得られます。つまり、$\frac{1}{4s}(2-s^2) > \frac{1}{m}$  を満たす　$\frac{1}{m}$ であれば、それを $c$ とおけば、$(s+c)^2 < 2$ が得られます。

(2)$\frac{1}{2}(2-s^2) \leq \\{\frac{1}{4s}(2-s^2)\\}^2$ （☆）ならば以下を考える。
$s^2 + \frac{1}{2}(2-s^2) = 2 - \frac{1}{2}(2-s^2)$
$(s+\sqrt{\frac{1}{2}(2-s^2)})^2 - 2s\sqrt{\frac{1}{2}(2-s^2)} = 2 - \frac{1}{2}(2-s^2)$
$(s+\sqrt{\frac{1}{2}(2-s^2)})^2  = 2 - \\{\frac{1}{2}(2-s^2) - 2s\sqrt{\frac{1}{2}(2-s^2)} \\} \leq 2$
なぜなら、☆ ⇒ $2s\sqrt{\frac{1}{2}(2-s^2)} \leq \frac{1}{2}(2-s^2)$ 
つまり、$\frac{1}{2}(2-s^2) > \frac{1}{n^2}$  を満たす　$\frac{1}{n}$　を $c$ とおけば、$(s+c)^2 < 2$

結局、Min$(\frac{1}{m}, \frac{1}{n}) =c$ とすれば、$(s+c)^2 < 2$
vbsの作法 その74

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
htaで、mdbにinsertせよ。

# サンプルコード

```

<html>
<head>
	<title>mdb sql run</title>
	<HTA:APPLICATION SHOWINTASKABAR="no" WINDOWSSTATE="maximize" />
</head>
<body bgcolor="#ffddCC">
	<h1> mdb sql up</h1>
	<p>
		url: <input type="text" id="a" size="50" value="https://qiita.com/"><br>
	</p>
	<p>
		titel: <input type="text" id="b" size="50" value="tetle"><br>
	</p>
	<p>
		body: <input type="text" id="c" size="100" value="body"><br>
	</p>
	<p>
		itime: <input type="text" id="d" size="20" value="4"><br>
	</p>
	<p>
		<input id="Button1" type="button" value="　挿入　" />
	</p>
<script language="vbscript">
Sub Button1_onClick
	Dim SQL
	With CreateObject("ADODB.Connection")
		.Open "Provider=MSDASQL;Driver={Microsoft Access Driver (*.mdb)};DBQ=db1.mdb"
		SQL = "INSERT INTO b_date(url,title,body,itime) VALUES('" & a.value & "','" & b.value & "','" & c.value & "','" & d.value & "');"
		.Execute(SQL)
		.Close
		msgbox "ok"
	End With
End Sub
d.value = date()
</script>
</body>
</html>




```

以上。
vbsの作法 その73

# 概要
vbsの作法、調べてみた。
練習問題、やってみた。

# 練習問題
クローラーを実装せよ。

# 方針

与えられたurlを取得してlinkを取得して、htmlを取得して、titleを表示する。

# サンプルコード

```


Function crawler1(url)
	SamAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
	Set objHTTP = CreateObject("Microsoft.XMLHTTP")
	objHTTP.Open "GET", url, False
	objHTTP.SetRequestHeader "User-Agent", SamAgent
	objHTTP.Send
	Set objStream = CreateObject("ADODB.Stream")
	objStream.Type = 1
	objStream.Open
	objStream.Write objHTTP.responseBody
	objStream.Position = 0
	objStream.Type = 2
	objStream.Charset = "utf-8"
	http_source = objStream.ReadText
	objStream.Close
	'MsgBox http_source
	Set re = New RegExp
	re.Ignorecase = False
	re.Global = True
	re.Pattern = "title.*?/title"
	Set Matches = re.Execute(http_source)
	For Each Match in Matches
		'msgbox Match.Value
		title = Replace(Match.Value, "title>", "")
		title = Replace(title, "</title", "")
		msgbox title
	Next
	'msgbox "ok"
	Set re = Nothing
	Set objHTTP = Nothing
	Set objStream = Nothing
End Function

Function crawler0(url)
	SamAgent = "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
	Set objHTTP = CreateObject("Microsoft.XMLHTTP")
	objHTTP.Open "GET", url, False
	objHTTP.SetRequestHeader "User-Agent", SamAgent
	objHTTP.Send
	Set objStream = CreateObject("ADODB.Stream")
	objStream.Type = 1
	objStream.Open
	objStream.Write objHTTP.responseBody
	objStream.Position = 0
	objStream.Type = 2
	objStream.Charset = "utf-8"
	http_source = objStream.ReadText
	objStream.Close
	'MsgBox http_source
	Set re = New RegExp
	re.Ignorecase = False
	re.Global = True
	re.Pattern = "a href=""https://qiita.com(/.+?)"" "
	Set Matches = re.Execute(http_source)
	'For Each Match in Matches
	'	msgbox Match.Value
	'Next
	for i = 0 To 2
		'msgbox Matches(i).Value
		url = Replace(Matches(i).Value, """", "")
		url = Replace(url, "a href=", "")
		'msgbox url
		crawler1(url)
	next
	'msgbox "ok"
	Set re = Nothing
	Set objHTTP = Nothing
	Set objStream = Nothing
End Function

crawler0("https://qiita.com/")




```


以上。
【Unity】任意の処理 / タイミングでUIに対して操作をする方法

# 皆さん、こんな経験ありませんか？
・EventSystemで定義したボタン以外でも、UI操作を行いたい
・キーコンフィグ等で、動的にボタンを変えたい
・言語設定に応じて、UIに対する決定ボタンを変えたい(日本だと○、海外だと✖みたいな感じ)

# 今回実装する事
・デフォルトだと、EventSystemのインスペクターで指定したボタンでしか
　UIに対して決定処理できませんが
　スクリプトを通じてどのボタン/キーからでも決定処理できるようにします

# 実際に試した環境
・Unity 2021.3.0 LTS
・Visual Studio2017

:::note alert
この処理は旧式のInputManagerでのみ動作します
新システムであるInputSystemでは、デフォルトで変更可能になっておりAPIも提供されています
:::

:::note alert
この処理はPC向けのゲームのコントローラー操作を対象にしています
また、この処理では従来のInputManager同様に決定ボタンを押した後
次はどのボタンにカーソルを合わせるかについては独自に実装する必要があります
:::

# 実装方法
①新規にScriptを作成します(別に名前は何でもいいです)
②標準のStart関数とUpdate関数を消して、usingに以下の項目を追加します
```C#:InputManager_SubmitButton_Change
using UnityEngine.EventSystems;
using UnityEngine.UI;
using System; //もしかしたらいらないかも
```
③継承を変更します
```C#:InputManager_SubmitButton_Change
public class InputManager_SubmitButton_Change : MonoBehaviour //←ここのMonoBehaviourを変える
{

}
```
↓
```C#:InputManager_SubmitButton_Change
public class InputManager_SubmitButton_Change : StandaloneInputModule
{

}
```
④必要な変数を追加します
```C#:InputManager_SubmitButton_Change
    [SerializeField]
    EventSystem eventSystem; //イベントシステム用
    public GameObject SelectedButton; //現在選択されているボタン
```
⑤初期化関数を設定します
```C#:InputManager_SubmitButton_Change
    protected override void OnEnable()
    {
        base.OnEnable();
    }

    public void Start()
    {
        base.Start();
        EventSystem ev = EventSystem.current;
        ev.firstSelectedGameObject = SelectedButton;
    }
```
⑥任意の処理で決定処理を行う処理を書きます
```C#:InputManager_SubmitButton_Change
    public void Update()
    {
            if (//ここに決定させたい時に使うものを記載)
            {
                if (eventSystem.currentSelectedGameObject == null)
                {
                    return; //現在選択中のボタンが無い場合は終了
                }
                var baseEventData = GetBaseEventData();
                ExecuteEvents.Execute(eventSystem.currentSelectedGameObject, baseEventData, ExecuteEvents.submitHandler); //この処理によって現在選択中のUIオブジェクトに対して決定コマンドが送信されます
            }
    }
```
⑦スクリプトを保存し、Unityに戻ります
⑧インスペクター上で、`SelectedButton変数`に最初にカーソルを合わせるボタンをセットします
⑨インスペクター上で、`eventSystem変数`にイベントシステムのゲームオブジェクトをセットします
⑩動作確認を行います

以上です！
快適なUnityライフをお楽しみください！！
axios-auth-refreshでアクセストークンのリフレッシュを行う

# はじめに
先日、SPAのWebアプリを開発している最中に、アクセストークンの有効期限は短く保ちつつ、リフレッシュトークンを用いてアクセストークンの再取得を行うことでユーザービリティを向上させる対応を行いました。
しかし、この処理を自前で実装しようとすると、複数同時リクエストの考慮が必要だったり、フラグでトークン取得中か否かを判定しなきゃいけないで結構面倒でした。

そんな時に便利だった[axios-auth-refresh](https://github.com/Flyrell/axios-auth-refresh)を紹介します。

# axios-auth-refreshとは
axios-auth-refreshは、このトークンの自動リフレッシュを簡単に実装するためのヘルパーライブラリです。
トークンが有効期限切れであることを検知すると、自動的にトークンをリフレッシュしてからリクエストを再試行することができます。

# 使い方

使い方は簡単で[axiosのintercepters](https://axios-http.com/docs/interceptors)みたいな感じでトークン再取得処理を渡すだけです。

```typescript
import axios from 'axios';
import createAuthRefreshInterceptor from 'axios-auth-refresh';

// リフレッシュトークンの取得と設定を行うメソッド
async function const refreshAuthLogic = () =>
    axios.post('https://www.example.com/auth/token/refresh').then((tokenRefreshResponse) => {
        localStorage.setItem('token', tokenRefreshResponse.data.token);
        failedRequest.response.config.headers['Authorization'] = 'Bearer ' + tokenRefreshResponse.data.token;
        return Promise.resolve();
    });

// interceptorに設定する
createAuthRefreshInterceptor(axios, refreshAuthLogic);

```
これでトークンの有効期限が切れている場合は`refreshAuthLogic`が実行され、トークンを再取得した後に新しいトークンで元のリクエストを再度投げてくれます。

## 参考

- [axios-auth-refresh](https://github.com/Flyrell/axios-auth-refresh)
- [Interceptors](https://axios-http.com/docs/interceptors)
GooleColaboratoryでpyファイルを実行する

# 結論
実行したいpyファイルをアップロードしてからpythonコマンドで実行できます。

# 手順

1. Colaboratoryの左メニューにあるファイルアイコンをクリックします。
  ![py実行01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/0ff27485-2105-e24b-e561-1eabb1e233ca.png)
1. 実行したいpyファイルをエクスプローラーなどからドラッグしてファイル構成の部分にドロップします。
  ![py実行02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/829c7b37-dc74-5fbb-8cc9-7eb553b625b8.png)
1. 確認のダイアログが出た場合は「OK」をクリックします。
1. ドラッグしたファイルがドロップされていることを確認後、以下のコマンドをColabのセルに記述します。
    ```
    !python <実行するpyファイル名>
    ```
    hello.pyの場合
    ![py実行03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/df5f09a6-6b51-7bdb-2fab-a195fe922c8e.png)
1. 実行します。
1. 実行できていることを確認します。
    ![py実行04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3071987/e2a1b7b6-8c2f-2f88-e7b4-fa85aaebb178.png)

# 注意事項
:::note warn
アップロードしたファイルはランタイムの接続が解除されると削除されてしまいます。アップロードするファイルは必ずバックアップを取っておきましょう。
:::

以上です。
DeviceScriptでRaspberry Pi Pico WのLチカを試してみる

# DeviceScript
Microsoft公式のTypeScriptでIoTできちゃうやつとのこと。
デバイスには固有のランタイムをあらかじめ書き込んでおき、DeviceScriptで書いたコードをビルドして配信する仕組みのようです。

以下さくっとRaspberry Pi Pico WでLチカまでの流れを書いていきます。

https://microsoft.github.io/devicescript/

https://github.com/microsoft/devicescript



# 実行環境
私の実行環境です。

* OS: Windows10 Pro v22H2
* Node.js: v18.16.0
* VS Code: v1.78.2



# 環境構築
VS Code拡張のDeviceScriptを使って進めていきます。
なのでVS CodeとNode.jsが必要です。
（ちなみにCLIもあってそっちならNode.jsだけでOK）

以下を一通りインストールします。

* Node.js v18以上
* VS Code
* [VS Code拡張のDeviceScript](https://marketplace.visualstudio.com/items?itemName=devicescript.devicescript-vscode)


https://microsoft.github.io/devicescript/getting-started/vscode

https://marketplace.visualstudio.com/items?itemName=devicescript.devicescript-vscode



# DeviceScriptプロジェクト作成
* VS Codeにてコマンドパレット（Ctrl + Shift + P） > DeviceScript: Create New Project...
	* ディレクトリ構成や依存パッケージ等自動的にセットアップされます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207109/13b3cbcd-d41d-e04b-b910-b4407e78c8c0.png)



# Raspberry Pi Pico Wへのランタイム書き込み
* BOOTボタンを押しながらRaspberry Pi Pico WをPCへ接続
* コマンドパレット（Ctrl + Shift + P） > DeviceScript: Connect... > Flash Firmware > Raspberry Pi Pico W > yes
	* ターミナルへ以下のようなログが出力されます

```
using drive X:/
fetch https://github.com/microsoft/devicescript-pico/releases/latest/download/devicescript-rp2040w-pico_w.uf2
saved .devicescript/cache/devicescript-rp2040w-pico_w.uf2 976896 bytes
cp .devicescript/cache/devicescript-rp2040w-pico_w.uf2 X:/
OK
```



# とりあえずソース実行
* サイドバーよりDeviceScriptサイドパネルを表示
* コマンドパレット（Ctrl + Shift + P） > DeviceScript: Connect... > Serial
	* サイドパネルUIのDevicesにRaspberry Pi Pico Wが追加される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207109/40370769-63dd-4a46-1313-6eac20a06985.png)

* main.tsを開き、パネル右上の三角アイコンより`DeviceScript: Run`を押す
	* ちなみにコマンドパレットにも同じコマンドがありますが、私の環境だと何故かそっちは動きませんでした

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207109/6b2e762a-1115-192a-c8cd-d6d54c49c43c.png)

* ターミナルが開かれ、1秒おきに`:)`が表示される
* なんか右側にUIも表示される
	* STOPボタンおすと止まる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207109/85438846-e6fa-c521-a5ff-fd1edc26a683.png)



# Lチカ
* Raspberry Pi Pico WのGP1とGNDにLEDを接続
	* 必要に応じて抵抗も
    	* 私は↓の図のように挿しました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207109/1c7a0e67-b34f-6eab-d045-696ab771ed11.png)


* サンプルコードを`main.ts`へコピペ
	* サンプルコード：https://microsoft.github.io/devicescript/getting-started/samples/blinky
* もう一度パネル右上の三角アイコンより`DeviceScript: Run`を押す
    * 1秒おきにLEDが点滅する
* 右側のUIの下の方に`lightBulb`というボタンが追加されてる
	* そのボタンからもLEDを制御できる

<blockquote class="twitter-tweet"><p lang="es" dir="ltr">fmfm... <a href="https://twitter.com/hashtag/DeviceScript?src=hash&amp;ref_src=twsrc%5Etfw">#DeviceScript</a> <a href="https://t.co/ZhQqMaT3dH">pic.twitter.com/ZhQqMaT3dH</a></p>&mdash; 田中みそ (@miso_develop) <a href="https://twitter.com/miso_develop/status/1662131118395772928?ref_src=twsrc%5Etfw">May 26, 2023</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> 

以上さくっと。
[AWS Q&A 365][SNS]AWSのよくある問題の毎日5選 #67

# 1. Amazon SNSのA2Aメッセージングとは何ですか？
Amazon SNSのA2Aメッセージングとは、SNSをメッセージングサービスとして使用して2つ以上のアプリケーション間でメッセージを送信するプロセスを指します。

# 2. Amazon SNSがサポートするA2Aメッセージングの異なるタイプは何ですか？
Amazon SNSは、Kinesis Data Firehose配信ストリームへのファンアウト、Lambda関数へのファンアウト、Amazon SQSキューへのファンアウト、HTTP/Sエンドポイントへのファンアウトを含む、異なるタイプのA2Aメッセージングをサポートしています。

# 3. A2AメッセージングでのKinesis Data Firehose配信ストリームへのファンアウトはどのように動作しますか？
Kinesis Data Firehose配信ストリームへのファンアウトでは、SNSトピックに公開されたメッセージがKinesis Data Firehose配信ストリームに配信されます。そこから、データは変換されて他のシステム、例えばAmazon S3、Amazon Redshift、またはElasticsearchにロードされます。

# 4. A2Aメッセージングでのモバイルプッシュ通知の送信プロセスは何ですか？
A2Aメッセージングでは、モバイルアプリを設定し、プッシュ通知のためのプラットフォームエンドポイントを作成し、モバイルプッシュAPIアクションを使用して通知を送信することで、モバイルプッシュ通知を送信することができます。

# 5. Amazon SNSのA2Aメッセージングのベストプラクティスは何ですか？
Amazon SNSのA2Aメッセージングのベストプラクティスには、メッセージが必要な受信者にのみ送信されることを確認し、適切なメッセージ形式を使用し、メッセージの配信とエラーレートを監視することが含まれます。また、機密データを保護するために暗号化とアクセス制御対策を使用することも推奨されます。
[AWS Q&A 365][SNS]Daily Five Common Questions #67

# 1. What is A2A messaging in Amazon SNS? 
A2A messaging in Amazon SNS refers to the process of sending messages between two or more applications using SNS as a messaging service. 

# 2. What are the different types of A2A messaging supported by Amazon SNS? 
Amazon SNS supports different types of A2A messaging, including fanout to Kinesis Data Firehose delivery streams, fanout to Lambda functions, fanout to Amazon SQS queues, and fanout to HTTP/S endpoints. 

# 3. How does fanout to Kinesis Data Firehose delivery streams work in A2A messaging? 
In fanout to Kinesis Data Firehose delivery streams, messages published to an SNS topic are delivered to a Kinesis Data Firehose delivery stream. From there, the data can be transformed and loaded into other systems such as Amazon S3, Amazon Redshift, or Elasticsearch. 

# 4. What is the process for sending mobile push notifications in A2A messaging? 
In A2A messaging, mobile push notifications can be sent by setting up a mobile app, creating a platform endpoint for push notifications, and sending notifications using the mobile push API actions. 

# 5. What are the best practices for A2A messaging in Amazon SNS? 
Some best practices for A2A messaging in Amazon SNS include ensuring that messages are sent only to the required recipients, using appropriate message formats, and monitoring message delivery and error rates. It is also recommended to use encryption and access control measures to protect sensitive data.
jQuery Validation Pluginをyarnで導入する

jQuery-validation-pluginをyarnで導入している記事が見つからなかったので書いてみます。

# インストール
名前の通りjQueryが必要なのでとにかく追加（既に導入済みの方はスキップ）

```
$ yarn add jquery
```

次に本命のpluginを追加
```
$ yarn add jquery-validation
```
<br>

この2つをimportします
それぞれファイルの下に記述を追加してください！

```app/javascript/packs/application.js
import "jquery";
import "jquery-validation";
```


```config/webpack/environment.js
const webpack = require('webpack')
environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)
```

### これで導入完了です👍

## Formとjsファイル作成

```sample.html.erb
<%= form_with model: @sample, id: sampleForm do |f| %>
  <%= f.label :title %>
  <%= f.text_field :title %>
<% end %>
```

```app/javascript/packs/sample_validation.js
$(function () {
  $("#sampleForm").validate( {
    rules: {
      "sample[title]": {
        required: true
      }
    }
  });
});
```

jsファイルをimportします！
```app/javascript/packs/application.js
import "./sample_validation"
```

## 動作確認&エラー
やっと動作を確認してみます...が
`$(...).validate is not a function`
のエラーがコンソールに出てしまい、動作してくれません。

原因はimportしたjQueryと`jquery-validation`の中で使われているjQueryが別のものとして認識されてしまっていることにあります。

## 解決策
上記の解決策として、`expose-loader`を導入します。
`expose-loader`を使うと、jQueryをグローバル変数にしてくれるので問題を解決できます！
```
$ yarn add expose-loader@1
```

```app/javascript/packs/application.js
import "jquery"; // 削除
import $ from "expose-loader?exposes[]=$&exposes[]=jQuery!jquery"; // 追加
import "jquery-validation";
import "./sample_validation";
```
これに伴い、environment.jsの以下の部分を削除します。（わざわざ追加してもらったのにすみません😅）
```config/webpack/environment.js
const webpack = require('webpack')
environment.plugins.prepend(
  'Provide',
  new webpack.ProvidePlugin({
    $: 'jquery/src/jquery',
    jQuery: 'jquery/src/jquery'
  })
)
```

# 完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3231090/b44ccf55-4a66-6f28-3f72-51cbe5f6914e.png)
お疲れ様でした！
Bootstrapも使うとより良い感じに実装できるので調べてみてください！

## 余談
ここまでの実装だと、一部の機能（ファイルのバリデーションなど）が使えないので、下の2つもimportをおすすめめします
```app/javascript/packs/application.js
import 'jquery-validation/dist/additional-methods' // 追加機能
import 'jquery-validation/dist/localization/messages_ja' //日本語化
```
<br>

## 参考記事
https://ja.stackoverflow.com/questions/83510/webpack-%E3%81%A7%E3%81%AE-jquery-%E3%81%AE-%E5%A4%89%E6%95%B0%E3%81%AE%E6%89%B1%E3%81%84%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6
Vimの基本操作をまとめてみた

## Vimについて
Vimとはコマンドラインベースで動作するテキストエディタです。
キーボードのみで操作を行えるので、マウスにてを伸ばすことなく作業を行うことができます。
また、Vimを使いこなせるようになることでファイルの編集などを高速に行えるようになります。

## モード
Vimには４つのモードがあり、これらのモードを使い分けながらコマンドを実行していくことになります。
モードは下記のようなものになります。
|  モード名  |  実行できること  |
| ---- | ---- |
|  ノーマルモード	  |  カーソル移動、削除など  |
|  インサートモード  |  文字入力、ペースト、単語削除など  |
|  コマンドモード  |  コマンド実行、保存、終了など  |
|  ビジュアルモード	  |  範囲指定など  |

Vimを起動するとノーマルモードから始まるため、基本はノーマルモードを基準として各モードに切り替えることになります。

## Vimの基本操作
Vimの代表的な基本操作を紹介します。

### モード変更
|  vimコマンド  |  動作  |
| ---- | ---- |
|  esc  |  ノーマルモード  |
|  i  |  インサートモード  |
|  a  |  次䛾文字からインサートモード  |
|  o  |  選択行の下に空白を入れ、インサートモード  |
|  O(shift+o)   |  選択行に空白を入れ、インサートモード  |
|  :  |  コマンドモード  |
|  v  |  ビジュアルモード  |

### カーソル移動
|  vimコマンド  |  動作  |
| ---- | ---- |
|  k  |  上に移動  |
|  j  |  下に移動  |
|  ｈ  |  左に移動  |
|  l  |  右に移動  |
|  w  |  単語移動  |
|  b  |  単語移動（逆順）  |
|  ＄  |  行末へ移動  |
|  ０  |  行頭へ移動  |
|  gg  |  ファイルの先頭へ移動  |
|  G  |  	ファイルの末尾へ移動  |

### カーソル移動以外の移動
|  vimコマンド  |  動作  |
| ---- | ---- |
|  :set number  |  行番号を表示  |
|  :10    |  10行目に移動(数字の数だけ移動)  |
|  $(shift+4)   |  行末に移動  |
|  0   |  先頭に移動  |
|  ^    |  インデントの先頭に移動  |
|  {   |  段落ごとに上に移動  |
|  ｝   |  段落ごとに下に移動  |
|  [[   |  セクションごとに上に移動  |
|  ]]   |  セクションごとに下に移動  |
|  「:1」or「gg」   |  ファイル䛾先頭に移動  |
|  G   |  ファイルの最後に移動  |
|  Control+o   |  移動前に戻る  |
|  /{pattern} ex) /test   |  検索  |
|  n   |  次の検索結果に移動  |
|  N (shift+n)   |  前の検索結果に移動  |
|  >   |  右にインデントを移動  |
|  <   |  左にインデントを移動 |

## 置換
|  vimコマンド  |  動作  |
| ---- | ---- |
|  R  |  置換  |
|  dw    |  単語削除（置換より使用すること多め）  |
|  :%s/{検索文字列}/{置換文字列}/g  |  一括置換  |
|  :%s/{検索文字列}/{置換文字列}/gc  |  確認しながら置換  |

### 削除
|  vimコマンド  |  動作  |
| ---- | ---- |
|  u(ノーマルモード）   |  Undo（行った操作の取り消し）  |
|  Control+r(ノーマルモード）  |  Undoを取り消し |
|  x(ノーマルモード）   |  1文字削除  |
|  dd(ノーマルモード）   |  行の削除 （コピー可能）  |
|  dw(ノーマルモード）   |  単語の削除  |
|  2dd(ノーマルモード）   |  2行削除(数字の数だけ削除を実行)  |

### コピペ
|  vimコマンド  |  動作  |
| ---- | ---- |
|  yy(ノーマルモード）   |  一行コピー  |
|  p(ノーマルモード）  |  下にペースト |
|  P(ノーマルモード）   |  現在行にペースト  |
|  2yy(ノーマルモード）   |  2行コピー(数字の数だけコピーを実行)  |
|  dw(ノーマルモード）   |  単語の削除  |
|  2dd(ノーマルモード）   |  2行削除(数字の数だけ削除を実行)  |
| .(ノーマルモード）   |  直前に行った動作をリピート  |
| v(ビジュアルモード)移動してからy(yank)    |  直前に行った動作をリピート  |

## コマンド実行
|  vimコマンド  |  動作  |
| ---- | ---- |
|  「:」or「/」(コマンドモード）   |  コマンドモード  |
|  !{コマンド}(コマンドモード）   |  コマンド実行  |
|  !!(コマンドモード）   |  カーソル指定コピー  |

### 検索
|  vimコマンド  |  動作  |
| ---- | ---- |
|  /｛検索文字列｝   |  検索  |
|  :noh   |  検索のハイライト消す  |

### 保存、終了
|  vimコマンド  |  動作  |
| ---- | ---- |
|  :q   |  編集終了  |
|  :q!   |  保存せずに編集終了  |
|  :w   |  保存  |
|  :wファイル名   |  ファイル名をつけて保存 |

## まとめ
Vimの基本的な説明とコマンド操作について簡単に紹介させていただきました。
読んで頂いてる方の助けとなれば幸いです。
PythonでPDFから抽出したテキストをPDFのページごとに対応したExcelシートへ書き込む

# 前提条件
* Windows10
* Python3
* openpyxlライブラリ
* PyMuPDFライブラリ
* Tkinterライブラリ

サンプルのPDFファイルは下記のウィキペディアトップページをPDFとしてローカルに保存したものを使用します。
https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8

openpyxlライブラリの公式ドキュメントは以下です。
https://openpyxl.readthedocs.io/en/stable/

PyMuPDFライブラリの公式ドキュメントは以下です。
https://pymupdf.readthedocs.io/en/latest/

Tkinterライブラリの公式ドキュメントは以下です。
https://docs.python.org/ja/3/library/tkinter.html

# 目的
PyMuPDFライブラリを利用して、ローカルにあるPDFからテキストを抽出する。抽出したテキストはPDFのページごとにExcelのシートとしてopenpyxlライブラリを利用して書き込み、Excelファイルとして保存する。

# 環境構築
```
pip install openpyxl pymupdf  
```

# サンプル
```pdf2excelsheet.py
# -*- coding: utf-8 -*-

import fitz # pymupdfライブラリ
import openpyxl as px #openpyxlライブラリ
import os
from tkinter import filedialog #thinterライブラリ


typ = [('pdfファイル','*.pdf')] 
dir = './'
pdf = filedialog.askopenfilename(filetypes = typ, initialdir = dir)
doc = fitz.open(pdf)

# PDFテキストを格納するリスト
item_list = []

# PDFから1ページずつテキストを取得
for page in range(len(doc)):
    textblocks = doc[page].get_text('blocks')
    for textblock in textblocks:
        if textblock[4].isspace() == False:
            tmp = textblock[4].encode('shift_jis','ignore')
            text = tmp.decode('shift_jis')
            item_list.append([page,text])

# PDFファイルを閉じる                
doc.close()

# 新しいエクセルを作成
wb = px.Workbook()

# エクセルの1行目として使用
headers = ['No', 'ページ', '内容']

# シート作成用
i = 0
# シートごとの要素数
j = 0

# エクセルにPDFのテキストデータを出力
for y, row in enumerate(item_list):
    # PDFのページごとにエクセルシートを作成
    if item_list[y][0] == i:
        ws = wb.create_sheet(title = str(i))
        ws.column_dimensions['C'].width = 100
        j = y
        i = i + 1
        for k, header in enumerate(headers):
            ws.cell(row = 1, column = k+1, value = headers[k])
    ws.cell(row = y-j+2, column = 1, value = y-j+1)
    for x, cell in enumerate(row):
        ws.cell(row = y-j+2, column = x+2, value = item_list[y][x])

#　Sheet1の削除
wb.remove(wb.worksheets[0])
excel = os.path.splitext(pdf)[0] + '_page_excel.xlsx'
# エクセルファイルの保存
wb.save(excel)
# エクセルファイルを閉じる
wb.close()
```
# 参考資料
https://www.amazon.co.jp/Python%E3%81%A7%E6%96%87%E6%9B%B8%E5%87%A6%E7%90%86%E2%80%95%E8%B3%87%E6%96%99%E3%81%AEPDF%E5%8C%96%E3%80%81%E6%96%87%E5%AD%97%E8%AA%8D%E8%AD%98%E3%80%81%E6%A4%9C%E7%B4%A2%E3%80%81%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%95%E3%81%BE%E3%81%96%E3%81%BE%E3%81%AA%E4%BD%9C-%E5%8C%97%E5%B1%B1-%E6%B4%8B%E5%B9%B8/dp/4877834974?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=K018UDE4Y69J&keywords=python+pdf&qid=1686010977&sprefix=%E4%BA%BA%E5%8F%A3%2Caps%2C2758&sr=8-1&linkCode=ll1&tag=qiitajinbei23-22&linkId=6fd240817b25e70d26c80bf24d192ed7&language=ja_JP&ref_=as_li_ss_tl

https://fastclassinfo.com/entry/python_pdf_to_excel/

# 関連資料
https://qiita.com/jinbei230525/items/fc01e8cd4469302f5e1c

https://qiita.com/jinbei230525/items/f192d35be3d3a2c29f73

# きっかけ
ネットで探すと、Excelの1枚目のシートにPDFの内容を全て書き込む例は見つけたけれども、PDFのページとExcelのシートが1対1対応してる例が見つけられなかったので、このプログラムを書いてみた。
苦労したところはページごとの要素数を記録し、それを活用して2枚目以降のシートの2行目から抽出したデータを書き込むところでした。
fullstackエンジニアを目指して

roadmap.sh のウェブサイトに掲載されている「2023年版ロードマップ」というものがあるらしい。

![full-stack_page-0001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3458029/78b7fb94-cdf9-ec66-c0e7-136d5ec7fa84.jpeg)

バックエンドエンジニアとして３，４年ほど業務を行ってるがほんとにしらないことが多くて日々勉強です。

投稿頻度は低めですが、fullstackのロードマップを順に追っていきながら記事を投稿していこうと思います。
Lodashライブラリの .get関数入門

JavaScriptの便利なライブラリ、**Lodash**の一部、「**.get関数**」について説明します。

## Lodashとは？

まず始めに、Lodashについて簡単に説明します。

LodashはJavaScriptの便利なツールボックスのようなもので、色々な便利な関数を提供しています。これを使うことで、より簡潔で、効率的なコードを書くことが可能になります。

## .get関数とは？

今回の主役、**.get関数**について説明します。この関数は、指定したオブジェクトから特定の値を取り出すためのものです。

以下のようなオブジェクトがあるとしましょう。

```javascript
let person = {
  name: {
    first: "Taro",
    last: "Yamada"
  }
}
```

ここで、"Taro"という値を取り出したい場合、Lodashを使わずに直接アクセスすると次のようになります。

```javascript
let firstName = person.name.first; 
```

しかし、この方法だと`name`が存在しない場合にエラーが発生します。これを避けるために、_.get関数を使います。

```javascript
let firstName = _.get(person, 'name.first');
```

もし`name`が存在しなくても、このコードはエラーを出さずに`undefined`を返します。これが_.get関数の便利な点です。

## まとめ

JavaScriptを書いていると、深い階層のデータにアクセスする必要があります。しかし、直接アクセスすると存在しないプロパティにアクセスしようとしたときにエラーが出てしまいます。Lodashの_.get関数を使えば、そのようなエラーを避けつつ、簡潔にコードを書くことができます。

Lodashライブラリの_.get関数は、JavaScriptで安全にオブジェクトのプロパティにアクセスするための強力なツールです。
初心者向け：詳細処理の書き方のコツ

# 1. はじめに
初めて詳細処理を書く際、初心者の方には戸惑いや苦労があるかもしれません。
本記事では、初心者の方々がわかりやすく詳細処理を書くためのコツや考え方について解説します。

# 2. 詳細処理とは
詳細処理とは、プログラムの実装において、処理の内容や手順を具体的に記述するものです。
詳細処理は、開発者同士のコミュニケーションやバグの特定・修正などにも役立ちます。

# 3. 詳細処理の書き方のコツ
詳細処理をわかりやすく書くためのコツをいくつか紹介します。

- 入力情報や出力結果を具体的に記述する
- 処理の手順や条件分岐を明確に表現する
- インデントを使って処理の階層構造を視覚的に表現する

# 4. Excelを使った詳細処理の書き方
Excelを使った詳細処理の書き方の一例を示します。
しかし、以下の例は改善の余地がありますので、注意点を確認しましょう。
```
ログイン処理
1 ユーザーの情報を取る
2 ユーザデータを見つける
3 一致するかチェック
4 ログイン成功のメッセージを表示
```

問題点と改善点
- 処理の詳細が不足している
>各ステップの詳細が明確に表現されていません。具体的には、入力情報の具体的な内容やデータのやり取り方法、条件の判定方法などが欠落しています。詳細処理は、開発者が実際に実装するためのガイドラインとなるべきです。

- 条件分岐やエラーハンドリングが欠けている
>処理の中には、ユーザ名とパスワードの一致をチェックするステップがありますが、一致しない場合やエラーが発生した場合の処理が明示されていません。詳細処理では、成功と失敗、異常ケースなどのシナリオを網羅的に考慮する必要があります。

- データの内容が不明確
>例では「ユーザの情報を取る」というステップがありますが、具体的な情報の取得方法や保存先などが明示されていません。詳細処理では、データのやり取り方法や使用するデータベースなど、具体的な情報を記述することが重要です。

- インデントがない
>Excelの方眼紙のようにインデントを使って処理の階層構造を表現することが推奨されています。例ではインデントが省かれており、処理の関係性や階層が分かりにくくなっています。

上記の問題点を解消するために、詳細処理の書き方について以下のように改善することができます。

```
ログイン処理
1 ユーザーからの入力を受け取る
	入力：
		ユーザ名：キーボードからの文字列入力
		パスワード：キーボードからの文字列入力

2 ユーザ名に該当するユーザデータを取得
	ユーザデータ：データベースに保存されているユーザ名とパスワードの組み合わせ

	2-1 ユーザが存在する場合

		2-1-1 一致している場合
			2-1-1-1 ログイン成功のメッセージを表示
				表示メッセージ：「ログイン成功！」

		2-1-2 一致していない場合
			2-1-2-1 ログイン失敗のメッセージを表示
				表示メッセージ：「パスワードが違います。」

	2-2 ユーザが存在しない場合

		2-2-1 ユーザが存在しない旨のメッセージを表示
			表示メッセージ：「ユーザが存在しません」
```
改善後の例では、詳細な処理内容や条件分岐、エラーハンドリングの考慮が行われており、データの内容も明確に示されています。また、インデントを使って処理の階層構造を視覚的に表現しています。

# 5. 他の方法も検討しよう
詳細処理の書き方は現場によって異なる場合があります。
Excel以外のツールやテキストエディタを使用する場合もありますので、他の方法も柔軟に検討しましょう。

# 6. まとめ
詳細処理をわかりやすく書くためには、具体的な情報や条件、インデントなどを意識しましょう。
Excelを使った書き方の一例を紹介しましたが、現場によって書き方は異なる場合もあることを覚えておきましょう。

初心者の方々が詳細処理をスムーズに理解し、正確に記述できるようになることを願っています。
GamePlayEffectでUAttributeSetのパラメータの取り扱いメモ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/be0df01d-47a7-18dd-21b5-43cc449983cc.png)

Blueprint作成を行い親クラスを「GameplayEffect」にしたGPE_Xxxxxを作成する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/51b71a73-188f-ef39-5530-6dbd7e3cfd93.png)

変更したいUAttributeSetのパラメータ情報を設定する


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249684/ee3cdecb-e8c9-48d0-112d-badb2ed85247.png)

パラメータ更新、取得

https://dev.epicgames.com/community/snippets/0dD/unreal-engine-gameplayeffect-uattributeset
Dockerを用いたNext.jsの環境構築

dockerを使用したNext.jsの環境構築方法
下記の記事を参考にコードを書いています。https://qiita.com/higemegane1992/items/defd193f4c8752ca9996

```zsh
vi Dockerfile
```
```docker:Dockerfile
FROM node:20.2.0

WORKDIR /usr/src/app

#RUN npm install -g npm@latest && npm install create-next-app
RUN npm install -g npm@9.7.1 && npm install create-next-app
```

```zsh
vi docker-compose.yml
```

```docker-compose.yml
version: "3.9"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/usr/src/app
    ports:
      - "3000:3000"
    command: bash -c "npm run dev"
```

```zsh
docker-compose build
```

```zsh
docker-compose run --rm app npx create-next-app tmp --ts\
&& mv tmp/* . && mv tmp/.* . && rm -r tmp
```

```zsh 
docker compose up
```

```bash
#!/bin/bash

echo "enter new app name"
read newAppName # ここで読み込み待ち
echo ${newAppName}

#新規アプリ名フォルダに移動
mkdir ${newAppName}
cd ${newAppName}

#Dockerfileセットアップ
touch Dockerfile

echo "FROM node:20.2.0 \n
WORKDIR /usr/src/app \n
RUN npm install -g npm@9.7.1 && npm install create-next-app \n
" > Dockerfile

#docker-compose.ymlセットアップ
touch docker-compose.yml

echo "version: \"3.9\"
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/usr/src/app
    ports:
      - \"3000:3000\"
    command: bash -c \"npm run dev\"
" > docker-compose.yml

#docker イメージ作成
docker-compose build

#next.js 新規アプリ作成
docker-compose run --rm app npx create-next-app tmp --ts\
&& mv tmp/* . && mv tmp/.* . && rm -r tmp

#dockerコンテナ起動
docker compose up

exit 0
```
【Next.js】SSRでPOSTパラメータを取得する方法

# 結論から言うと

SSRで前画面からPOSTされたパラメータを受け取る方法について、最初は馬鹿正直に

```typescript
export const getServerSideProps: async (context: GetServerSidePropsContext) => {
    // 注：この方法じゃGETパラメータは取れるけどPOSTパラメータは取れません
    const query = context.query;
    const param = query.param;
    ...
}
```

とかやって取れるのかと思ってたんだけど全然取得できず、どうやって取るのかなーと色々試行錯誤していた。で、色々ググったところ、[こちらのissue](https://github.com/vercel/next.js/discussions/12152#discussioncomment-50914)にたどり着いた。タイトルの方法に関しては、ここで公開されている内容にほぼ完ぺきな回答がある。一部抜粋して転記させていただくと、以下の通りである。これでPOSTパラメータが取れる。

```javascript
...
	const streamPromise = new Promise( ( resolve, reject ) => {
		let postBody = '';

		req.on( 'data', ( data ) => {
			// convert Buffer to string
			postBody += data.toString();
		} );

		req.on( 'end', () => {
			const postData = qs.parse( postBody );
			resolve(postData);
		} );
	} );
...
		const {
			username,
			password,
		} = await streamPromise;
		props.username = username;
		props.password = password;
```

この例では `username` と `password` というパラメータをPOSTしてもらって、それを `getServerSideProps` の中で取り出している。

# 若干修正

が、上の実装例にはちょっと難があって、というのも
1. 処理が共通化されていないため、POSTパラメータを必要とする全ての `getServerSideProps` に同じ処理を書く必要がある
2. 型の定義がないのでTypescriptにそのままコピペすると `const {username, password} = await streamPromise;` の部分は警告が出る
3. というかそもそも`qs.parse` (`querystring.parse`) は[Node.js v14以降でdeprecatedである](https://nodejs.org/dist/latest-v14.x/docs/api/querystring.html#querystring_querystring_parse_str_sep_eq_options)

といった点で修正が必要だった。まあ1点目はこの処理取り出して別のところに移せばいいのでそんな難しい話ではないのだが、3点目とそれに絡んで2点目（型をどうするか）でちょっと悩んだ。ググってみた感じ、`querystring` の代替えとしては `URLSearchParams` を使うのが一般的らしい。というわけで上の処理を取り出して個人的に共通化してみたのが以下。

```typescript
import type { IncomingMessage } from "http";
import { URLSearchParams } from "url";
export default async function parsePostParam(req:IncomingMessage): Promise<URLSearchParams> {
    return new Promise<URLSearchParams>( ( resolve, reject ) => {
        let postBody = '';
    
        req.on( 'data', ( data ) => {
            // convert Buffer to string
            postBody += data.toString();
        } );
    
        req.on( 'end', () => {
            const postData = new URLSearchParams(postBody);
            resolve(postData);
        } );
    } );
} 
```

ほとんど上と同じである。違うのは引数と戻り値の型を決め打ちしていること。引数は `IncomingMessage` で、これは `GetServerSidePropsContext.req` をそのまま渡すことを想定している。戻り値は `Promise<URLSearchParams>` になっているので、呼び出し元からは `await` 付けて呼んで `URLSearchParams` を返してもらって使う。ちなみに呼び出し側からは以下のように呼び出して使う。

```typescript
export const getServerSideProps: async (context: GetServerSidePropsContext) => {
    const urlSearchParams = await parsePostParam(context.req);
    const p1 = urlSearchParams.get('p1'); // POSTパラメータ名 "p1" の値を取り出す
    ...
}
```

ただ、戻りの型を `URLSearchParams` にしちゃってるのでパラメータの取り出しには `get` を使う必要があるのが若干イケてない気はする。`querystring.parse` の戻り値と同じで `params.name` みたいにアクセスできるほうがなんかしっくりくる。ような気はする。これをいい感じにその辺をまとめてるクラスみたいのをラップしてあげればその辺解決しそうだな、と思ったけど、面倒くさいのと実質これで動いてるからいいやと思うことにした。
なお元のコードも↑の修正例も、例外処理は一切入ってないのでその辺は各自良しなに、という感じで。。

以上
【Shell】ログインシェルの確認方法


## Linux

Linuxの場合には次のコマンドで確認できます。

```terminal
$ grep $USER /etc/passwd

```

また`SHELL`環境変数　にデフォルトでログインシェルのフルパスが設定されています。

```terminal
$ echo $SHELL
/bin/bash
```

## Mac

Macの場合には次のコマンドで確認できます。

```terminal
$ dscl localhost -read Local/Default/Users/$USER UserShell
```
ROS2 Eloquent でのQoS調整時の備忘録

# 背景
ROS2業務の最後に、QoS設定を調整して通信状態を安定化させようとした際の備忘録

# 環境

ROS2 Eloquent

# DDS変更

基本は以下

https://docs.ros.org/en/eloquent/Installation/DDS-Implementations/Working-with-Eclipse-CycloneDDS.html

単純に、install して、export したら変更可能だった

1. install 
    
    ```bash
    sudo apt install ros-eloquent-rmw-cyclonedds-cpp
    ```
  

2. export

    ```bash
    export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
    ```

## エラー発生時の対処法

- Defaultで入っていると思って export だけしてみると、インストールされてねーよ
    - install するのみ
- KeepAllは、プロセス間通信では使えない。以下のようなエラーが出る
    
    > Interprocess communication is not allowed with keep all history qos policy
    > 
- Type がサポートされていない？
    
    > [ERROR] [node]: could not create publisher: type support handle implementation 'rosidl_typesupport_cpp' (0x7f539f74a0) does not match valid type supports ('rosidl_typesupport_opensplice_cpp' (0x7f1c0ab118), 'rosidl_typesupport_opensplice_c' (0x7f863506d0)), at /tmp/binarydeb/ros-eloquent-rmw-opensplice-cpp-0.8.1/src/rmw_publisher.cpp:101, at /tmp/binarydeb/ros-eloquent-rcl-0.8.5/src/rcl/publisher.c:173
    > 
    
    こんな感じのが出るときは、ビルドからやり直すと上手くいくっぽい

https://github.com/ros2/rmw_fastrtps/issues/541

切り替えが簡単に出来るものは、apt-installですぐわかる。

apt install で補完かけると以下のように出る。shared はfastrtps の共通部分っぽい
ros-eloquent-rmw
ros-eloquent-rmw-connext-cpp
ros-eloquent-rmw-connext-shared-cpp
ros-eloquent-rmw-cyclonedds-cpp
ros-eloquent-rmw-cyclonedds-cpp-dbgsym
ros-eloquent-rmw-dbgsym
ros-eloquent-rmw-fastrtps-cpp
ros-eloquent-rmw-fastrtps-cpp-dbgsym
ros-eloquent-rmw-fastrtps-dynamic-cpp
ros-eloquent-rmw-fastrtps-dynamic-cpp-d
ros-eloquent-rmw-fastrtps-shared-cpp
ros-eloquent-rmw-fastrtps-shared-cpp-db
ros-eloquent-rmw-implementation
ros-eloquent-rmw-implementation-cmake
ros-eloquent-rmw-implementation-dbgsym
ros-eloquent-rmw-opensplice-cpp
ros-eloquent-rmw-opensplice-cpp-dbgsym


## Dynamic Binding

DDS を通信単位で変えることは現状できないけれど、研究してるっぽい。Eloquentじゃ古すぎて恩恵受けられないけど

https://ieeexplore.ieee.org/document/8607261

# QoS 設定

設定例は、以下

https://docs.ros2.org/eloquent/api/rclcpp/classrclcpp_1_1Node.html#ad1dfc9d04d67ab93353e04a7df72bc9a

QoS Class は以下

https://docs.ros2.org/eloquent/api/rclcpp/classrclcpp_1_1QoS.html

Default設定やEnum値は以下を確認
/opt/ros/eloquent/include/rmw/types.h

https://github.com/ros2/rmw/blob/master/rmw/include/rmw/types.h

/opt/ros/eloquent/include/rmw/qos_profiles.h

https://github.com/ros2/rmw/blob/master/rmw/include/rmw/qos_profiles.h

# 所感

QoS/DDS 調整する為にも、ノード単位の処理時間、通信遅延（Callback の開始時刻で代用？）、通信漏れ確認用Serial等を Performance 測定用に突っ込んでおいた方がいいですね。
でもって、現状は DDS はシステム全体で共通なので、全体、もしくは重要な通信品質に注目して調整が必要

# あとがき
ROS2 に関わって、Jetson もなかなかに面白いなぁと思ったけど
Jetson 以外の選択肢も拡充されていて、開発環境的に Jetson って使いやすいんだろうか？という疑問があった
Visual Studio のような開発環境もなんかあったのかもしれないけれど・・結局デバッグが超苦痛だった・・

さて、次は Azure へ旅立とう :laughing:
本日の微分方程式（22日目）

前回の内容はこちら

https://qiita.com/Schwarzschi1d/items/9a294bff7006187c5cfc


## 問題
$n\neq 0,1$ とするとき，次の微分方程式は **ベルヌーイの微分方程式** と呼ばれる．

```math
\begin{align}\tag{1}
\dfrac{\mathrm{d}y}{\mathrm{d}x}+P(x)y=Q(x)y^n.
\end{align}
```

以下の手順に従い，ベルヌーイの微分方程式は，適切な置換により**一般線形微分方程式に帰着できる** ことを確認せよ．

**STEP1**. 両辺を $y^n$ で割る
**STEP2**. $y^{1-n}=u$ とおき，**STEP1**で得られた式を， $x$ に関する $u$ の微分方程式に書き換える． 


【参考】 一階線形微分方程式

```math
\begin{align}\tag{2}
\dfrac{\mathrm{d}y}{\mathrm{d}x}+P(x)y=Q(x).
\end{align}
```

## ポイント
- $y^{1-n}=u$ とおいたわけですから，$u$ も $x$ の関数であることに注意しまししょう．
- ベルヌーイの微分方程式については，ヨビノリさんの動画もご参照ください．

https://www.youtube.com/watch?v=TaVimHlrN4U&list=PLDJfzGjtVLHnmhT1AhMx7bSt0ZOGbIP3c&index=5

## 解説

誘導通り変形していきます．

---
**STEP1** 両辺を $y^n$ で割る

$y^n\neq 0$ のとき，式(1)の両辺を $y^n$ で割ったものは以下の通りです．

```math
\begin{align}\tag{3}
y^{-n}\dfrac{\mathrm{d}y}{\mathrm{d}x}+P(x)y^{1-n}=Q(x).
\end{align}
```

**STEP2**. $y^{1-n}=u$ とおき，**STEP1**で得られた式を， $x$ に関する $u$ の微分方程式に書き換える． 

式(3) を眺めてみると， 左辺第一項 $y^{-n}\dfrac{\mathrm{d}y}{\mathrm{d}x}$ が厄介ですね．
今回は丁寧に誘導がついているので，$y^{1-n}=u$ の両辺を $x$ で微分し，$y^{-n}\dfrac{\mathrm{d}y}{\mathrm{d}x}$ の形が現れることを祈りましょう（この分野では変数変換と微分は基本セットです）．
$y^{1-n}=u$ とおいたわけですから，$u$ も $x$ の関数であることに注意して，次のように微分を行います．

```math
\begin{align}\tag{4}
\dfrac{\mathrm{d}(y^{1-n})}{\mathrm{d}x}&=\dfrac{\mathrm{d}u}{\mathrm{d}x},\\
(1-n)y^{1-n-1}\dfrac{\mathrm{d}y}{\mathrm{d}x}&=\dfrac{\mathrm{d}u}{\mathrm{d}x},\\
\therefore y^{-n}\dfrac{\mathrm{d}y}{\mathrm{d}x}&=\frac{1}{1-n}\dfrac{\mathrm{d}u}{\mathrm{d}x},\\
\end{align}
```

少々難しいですが，1行目から2行目への左辺の変形では，合成関数の微分 $\left\\{f(g(x))\right\\}^\prime = f^\prime(g(x))g^\prime(x)$ および $(x^\alpha)^\prime=\alpha x^{\alpha -1}$ を用いました．
さて，有難いことに式(4)では，求めていた $y^{-n}\dfrac{\mathrm{d}y}{\mathrm{d}x}$ の形が現れましたね．
式(4) および $y^{1-n}=u$ を式(3)に代入すると，次のようになります． 

```math
\begin{align}\tag{5}
\frac{1}{1-n}\dfrac{\mathrm{d}u}{\mathrm{d}x}+P(x)u=Q(x).
\end{align}
```

やりましたね！これは一階線形微分方程式です．わかりにくいよって方は，両辺に $1-n$ をかけてみましょう．

```math
\begin{align}\tag{6}
\dfrac{\mathrm{d}u}{\mathrm{d}x}+(1-n)P(x)u=(1-n)Q(x).
\end{align}
```

$(1-n)P(x)$ や $(1-n)Q(x)$ は $x$ の関数ですから，紛れもなく式(5)および式(6)は一般線形微分方程式です．

## 【補足】 n=0 のときと n=1 のとき

本問では $n\neq 0, 1$ としていましたが，実はどちらも一階線形微分方程式となります．

- **$n=0$ のとき**

式(1)に $n=0$ を代入すると，$y^n=y^0=1$ ですから，式(1)は次のようになります．

```math
\begin{align}\tag{7}
\dfrac{\mathrm{d}y}{\mathrm{d}x}+P(x)y=Q(x).
\end{align}
```

これはただの一階線形微分方程式です．

- **$n=1$ のとき**

式(1)に $n=1$ を代入すると，

```math
\begin{align}\tag{8}
\dfrac{\mathrm{d}y}{\mathrm{d}x}+P(x)y&=Q(x)y,\\
\therefore \dfrac{\mathrm{d}y}{\mathrm{d}x}+\left\{P(x)-Q(x)\right\}y&=0,\\
\end{align}
```

と変形できますから，これは一階線形微分方程式と扱ってもいいですし，変数分離形とも言えます．
2019年くらいの「Windowsプログラムでディレクトリ丸ごと削除」 1/4

シリーズもの一覧

1/4 https://qiita.com/macchan/items/30d81c4cb66a52fe4b0b
2/4 https://qiita.com/macchan/items/282db3e735ed0ad4bed8
3/4 https://qiita.com/macchan/items/19a06f30e8f3c553d4cb
4/4 https://qiita.com/macchan/items/9853a6d7b4e01ad4dc8d

　プログラムで「ディレクトリを丸ごと削除したい」と思って調べると、意外と面倒であるじことが判ります。Windows のAPIには RemoveDirectory が用意されていますが、「パスは空のディレクトリを指定する必要がある」と注意書きがあります。

https://learn.microsoft.com/ja-jp/windows/win32/api/fileapi/nf-fileapi-removedirectorya
https://learn.microsoft.com/ja-jp/windows/win32/api/fileapi/nf-fileapi-removedirectoryw

　多少のバリエーションがありますが、以下はファイル検索を再帰的に行い、ファイル削除を行ってからディレクトリを削除するプログラムです。

```C++:main.cpp

#include	<iostream>
#include	<Windows.h>
#include	<string.h>

BOOL	IsDir(const WIN32_FIND_DATA& rFinder);
BOOL	IsDot(const WIN32_FIND_DATA& rFinder);
BOOL	DelDir(const std::wstring& strDirName);

int wmain()
{
	setlocale(LC_ALL, "Japanese");
	BOOL bRet = DelDir(L"D:\\Work\\Dir");
	std::cout << bRet << std::endl;

	return 0;
}

BOOL	DelDir(const std::wstring& strDirName)
{
	BOOL bRet  = FALSE;
	// 検索用にワイルドカードを作る
	const std::wstring strWork = strDirName + L"\\*";

	WIN32_FIND_DATA		finder;
	HANDLE hFinder = FindFirstFile(strWork.data(), &finder);
	if (hFinder == INVALID_HANDLE_VALUE) {
		std::wcout << L"対象がみつからない " << strWork.data() << std::endl;
		return FALSE;
	}

	if (hFinder != INVALID_HANDLE_VALUE)
	{
		do {
			if (IsDir(finder) && IsDot(finder)) {
				// "." と ".." は対象外
				continue;
			}
			if (IsDir(finder)) {
				// ディレクトリならば
				// 削除するディレクトリ名を作る
				const std::wstring strNextDir = strDirName + L'\\' + finder.cFileName;
				// 再帰
				bRet = DelDir(strNextDir);
				if (!bRet) {
					return bRet;
				}
			}
			else {
				// ディレクトリでないならファイル
				// 削除するファイル名を作る
				const std::wstring strDelFile = strDirName + L'\\' + finder.cFileName;
				// ファイルを削除する
				bRet = DeleteFile(strDelFile.data());
				if (!bRet) {
					std::wcout << L"ファイルが消せない " << strDelFile.data() << std::endl;
					return bRet;
				}
			}
		} while (FindNextFile(hFinder, &finder));
		// これで該当ディレクトリ内のファイルはすべて消えたはずなので
		// 最後にディレクトリを消す
		bRet = RemoveDirectory(strDirName.data());
		if (!bRet) {
			std::wcout << L"ディレクトリが消せない " << strDirName.data() << std::endl;
			return bRet;
		}
		FindClose(hFinder);
	}
	return bRet;
}

BOOL	IsDir(const WIN32_FIND_DATA& rFinder)
{
	return (rFinder.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}

BOOL	IsDot(const WIN32_FIND_DATA& rFinder)
{
	const std::wstring strFileName = rFinder.cFileName;
	return ( (strFileName == L"." ) ||
			 (strFileName == L"..") );
}
データサイエンスのための線形代数 第28回 解の集合

:::note info
本記事は数学講座[6.3 解集合](https://www.matongxue.com/lessons/548)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# 解の集合

線形方程式$Ax=b$で全ての$x$の集合です、解がなければ空の集合$\varnothing$になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/19ec734d-3126-120a-92a6-82d8b71c1735.png)

# ２種類の線形方程式

線形方程式$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}$について考えます。

- $\boldsymbol{b}=\boldsymbol{0}$の場合、つまり$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{0}$の場合、これを**斉次方程式(せいじほうていしき)** と呼びます。
- $\boldsymbol{b}\ne\boldsymbol{0}$の場合、つまり$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{b}$の場合、これを**非斉次方程式(せいじほうていしき)** と呼びます。

# 零空間

斉次方程式$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{0}$の解の集合が$\boldsymbol{A}$のゼロ空間、$null(\boldsymbol{A})$です。

- $null(\boldsymbol{A})$が斉次方程式$\boldsymbol{A}\boldsymbol{x}=\boldsymbol{0}$の解の集合です。
- $null(\boldsymbol{A})$が必ずベクトル空間です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/96c752e0-8040-d2c0-417e-18ffd5e55859.png)

# 解の集合の構成

ベクトル空間$\boldsymbol{A}$とゼロ空間$null(\boldsymbol{A})$があります、非斉次方程式$\boldsymbol{A}\boldsymbol{x_{}}=\boldsymbol{b}$の解の集合が：
$\boldsymbol{x}=\boldsymbol{p}+null(\boldsymbol{A})$

$\boldsymbol{p}$が$\boldsymbol{A}\boldsymbol{x_{}}=\boldsymbol{b}$の一つの解です。特殊な解なので、特解も呼ばれます。

# 斉次方程式と非斉次方程式の例

- 例1
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/55773bd7-0743-8398-6472-8bcdeaa5321c.png)

- 例2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/5d856a68-ae39-1dd7-34d2-d535a2af525b.png)

- 例3
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/d0a764ce-b486-faec-8750-fec73e6e95e6.png)
rowidとは


## rowid
:::note

データベースのテーブル内の行（レコード）を一意に識別するために使用される値
:::


→データベース管理システム（DBMS）によって提供される特殊なカラム
通常はテーブル内の各行に自動的に割り当てられる

行の物理的な格納場所を示すため、データベース内で迅速に行を検索するためのキーとして使用されることがある
rowidは数値やバイナリ形式の一意の識別子で表される


[注意点]
rowid は一意性を持つものの、データベース内の行の物理的な位置に依存するため、行が物理的に移動する場合やデータベースが再構築される場合には変化する可能性がある
→rowid を永続的に参照することは避けたほうがいい
そのかわりに主キーなどの安定した一意の識別子を使用してデータを参照する
markdownの画像埋め込みをHTMLのimgタグに変換する

# はじめに

Qiitaへの投稿を含めて、markdownでドキュメントを書いているときに、埋め込んだ画像データの表示時のサイズを指定したくなることがあり、そんなときは、HTMLのimgタグに書き直す必要がある。これまでは、その度に、手動（タイピング）にて書き換えていたのだが、コマンド化して楽しようという試みである。

# HTMLのimgタグへの変換とは

Qiitaの<b>[公式ページ](https://qiita.com/Qiita/items/c686397e4a0f4f11683d#images---画像埋め込み)</b>に説明がある。

引用すると、

```markdown:画像埋め込みmarkdown
## タイトルあり
![代替テキスト](画像のURL "画像タイトル")

## タイトル無し
![代替テキスト](画像のURL)
```

上記markdownをHTMLのimgタグに書き換えると次のとおり。

```html:画像埋め込みHTML
<img alt="代替テキスト" src="画像のURL" title="タイトル">
<!--  もしくは -->
<img alt="代替テキスト" src="画像のURL">
```

ここで、画像の表示サイズを変更する場合は、以下の書式となる。

```html:画像埋め込みHTML
<img width="200" alt="代替テキスト" src="画像のURL" title="タイトル">
<!--  もしくは -->
<img style="zoom: 50%;" alt="代替テキスト" src="画像のURL" title="タイトル">
```
widthは画像の横幅をピクセル数で指定し、style:zoomは元画像からのスケール比で指定する。

:::note warn
試したところ、style:zoomはQiitaでは**機能しない**ようだ
:::


# 変換コマンド

PythonとSwiftの例を挙げておく。ただし、どちらも入力形式のチェックはしておらず、正しい書式であることを前提としている。



```python:Python3の例
input_markdown = '![代替テキスト](画像のURL "タイトル")' # markdownの画像埋め込み
output_html = '' # HTMLのimgタグ

alt, src, title = "", "", ""
af, sf, tf = False, False, False
for ch in input_markdown:
    if af and ch == ']': af = False
    if sf and ch == ')': sf = False
    if tf and ch == '"': tf = False
    
    if af: alt += ch
    if sf: src += ch
    if tf: title += ch
    
    if not af and ch == '[': af = True
    if not sf and ch == '(': sf = True
    if sf and not tf and ch == '"':
        sf, tf = False, True
        src = src[:-1].strip()

if not af and not sf and alt and src:
    title_string = '' if not title else f' title="{title}"'
    output_html = f'<img width="{300}" alt="{alt}" src="{src}"{title_string} />'
    # output_html = f'<img style="zoom: {50}%;" alt="{alt}" src="{src}{title_string}" />'
else:
    output_html = "ERROR"
```

```swift:Swiftの例
let input_markdown = "![代替テキスト](画像のURL \"タイトル\")" //markdownの画像埋め込み
let output_html: String //HTMLのimgタグ

var (alt, src, title) = ("", "", "")
var (af, sf, tf) = (false, false, false)
for ch in input_markdown {
    if af && ch == "]" { af = false }
    if sf && ch == ")" { sf = false }
    if tf && ch == "\"" { tf = false }
    
    if af { alt += String(ch) }
    if sf { src += String(ch) }
    if tf { title += String(ch) }
    
    if !af && ch == "[" { af = true }
    if !sf && ch == "(" { sf = true }
    if sf && !tf && ch == "\"" {
        (sf, tf) = (false, true)
        src = src.dropLast(1).trimmingCharacters(in: .whitespaces)
    }
}

if !af && !sf && !alt.isEmpty && !src.isEmpty {
    let title_string = title.isEmpty ? "" : " title=\"\(title)\""
    output_html = "<img width=\"\(300)\" alt=\"\(alt)\" src=\"\(src)\"\(title_string) />"
    // output_html = "<img style=\"zoom: \(50)%;\" alt=\"\(alt)\" src=\"\(src)\"\(title_string) />"
} else {
    output_html = "ERROR"
}
```


実際に**コマンド**とするには、クリップボード（ペーストボード）から＼への コピー処理を前後に付加する必要がある。


# おわりに

自分はGUI化してマウスクリック一発で変換＆結果を取得できるようにした。
ずっと前に作っておくべきだった。

**以上**