OmniAICreator/Qiita-1.07M huggingface dataset:
更新しやすいサイトを作るためにチームで共有したいこと

:::note info
この記事が対象としている「サイト」とは、LPのようなキャッチーさが求められたり公開期間が限定されているページのことではなく、ある程度の定期的な更新が見込まれている静的サイトを指しています。
具体的な実装方法は割愛し理念を中心に書いたポエムです。
:::

## はじめに

**「更新しやすいサイト」** とはどんなサイトのことでしょうか？
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221915/109249e6-a43e-29bc-4f70-6b7134b54c25.png" width="200">

フロントエンドからの視点からパッと思い浮かぶのは、

 - 属人性が低い（コードが理解しやすく作業者が限定されない）
 - 作業コストが低い（作業時間が短くて済む）
 - 影響範囲が把握しやすい（意図せぬ箇所への影響がない）

といったところでしょうか？

そんな **「更新しやすいサイト」** を作るためには、 **チーム（ディレクター、デザイナー、フロントエンドエンジニア）** でどのような意識を共有すればよいのかをあらためて整理してみました。

結論をひとことでいうと
 **「CMSでないサイトでもCMSであるかのような意識を持つこと」** 
です。

以下、その理由を説明していきます。

## CMSとは？
CMSとは「Content Management System」の略で、WordPressのようなコンテンツ管理システムのことです。

クライアント自身が更新したいというニーズに応えるために導入されるケースが多いのですが、しっかりと作られたCMSではたとえWebの知識がない人でも **安全で簡単に更新作業を行うこと** ができます。

要素を消したり順番を並び替えたりなどの大幅な変更でも問題ありません。

つまりCMSに実装する意識を持って設計・デザイン・実装されたサイトは、 **安全で簡単に更新作業を行うこと** ができるということです。

## イレギュラーは最小限にする
1. この見出しだけ文字がこぼれてしまうので、ここだけフォントサイズを気持ち小さくする。
2. この画像だけ背景色に溶け込んでしまうので、ここだけ囲み線をつける。
3. 日本語と比べて英語が小さく感じるから、英語だけ大きくする。
4. このアイコンだけ隙間が空いているように感じるから、ここだけ隙間を詰める。

これらのイレギュラー対応は基本的には **「CSSによる上書き」** になります（HTMLへの独自クラスの付与や、場合によってはJavaScriptも）。
イレギュラー箇所が増えれば増えるほど **「属人性が高く」** なり、 **「作業コストが高く」** なり、**「影響範囲が把握しにくく」** なります。

これらの問題に対応するとしたら、
1. 該当の見出しの文字数の変更、または全見出しのフォントサイズの調整
2. 該当の画像の修正、または全画像へ囲み線を適用
3. フォントの種類を変更する 
4. アイコン画像を調整する 

といった感じでしょうか。

**「もしこれがCMSだったら」** と考えたら個別の対応はできないと思います。

## デザインルールを構築する
デザインは部分部分ごとの小さな視点での調整ではなく、大局・俯瞰的な **「ルール」** として構築することが肝要だと思います。

文字サイズやマージンなどのルールが定まっていれば、基本的には部分部分ごとの調整の必要はなく、局所的な崩れも発生しにくくなります。

**「もしこれがCMSだったら」** と考えたら、ルール構築の重要性がより実感できると思います。

## マークアップの視点で考える
設計やデザインは **HTMLでのマークアップ** 意識しているとベターです。

この意識がないと **レスポンシブ対応** も困難になります。

境界線は見えなくてもブロックが積まれていて、入れ子構造になっていることが意識されていれば、マージンやパディングなどは自然とルールにのっとって反映されているはずです。

最終的にはHTMLに落とし込むわけですから、設計やデザイン段階でもHTML構造の視点を持つことが望まれます。

そして設計もデザインも実装も **コンポーネント** 単位で考えることが大切です。

**「もしこれがCMSだったら」** と考えたら、コンテンツの有無や量の増減に対応できる構造の重要性がより実感できると思います。

## まとめ
「こんな考え方では『独創的』で『斬新』なサイトは作れないだろう」「実装が面倒なだけじゃないの？」「ただの怠慢」などと思われるかたもいらっしゃるかもしれません。

でもぼくはこれが長所も短所も含めた **「Webの特性」** であると思っています。

チームが一丸となってクライアントとともに満足できるようなWeb制作の理想に少しでも近づけるよう、これからもいろいろ考えていきたいと思います。
Active Directory 環境で端末をドメインに参加させたユーザーと所有者

# 概要

別記事でコンピューター オブジェクトの所有者情報を確認する手順についてまとめましたが、本記事はその続きとなります。

なおドメインに再参加させる際の対処の目的で ms-DS-CreatorSID の確認をされたいということであれば下記 Microsoft のBLOGを参照いただくほうが良いかと思います。

* [コンピューターアカウント再利用時のドメイン参加におけるセキュリティ強化について[KB5020276] | Microsoft Japan Windows Technology Support Blog](https://jpwinsup.github.io/blog/2023/03/23/ActiveDirectory/Authentication/KB5020276-netjoin/)

# 端末をドメインに参加させたユーザーと所有者
コンピューター オブジェクトの所有者情報を確認したいというニーズは誰が端末をドメインに参加させたかを確認したいということから発生しているのではないかと思います。
その場合には所有者情報の確認だけでは要望を満たせないです。
というのは所有者がドメインに端末を参加させたユーザーとは必ずしも一致しないからです。

確認した結果は以下です。

**パターン1**
参加させるユーザーが所属するグループ
Domain Users	〇
Administrators	×
Domain Admins	×
所有者 Domain Admins

**パターン2**
参加させるユーザーが所属するグループ
Domain Users	〇
Administrators	〇
Domain Admins	×
所有者 参加させたユーザー

**パターン3**
参加させるユーザーが所属するグループ
Domain Users	〇
Administrators	×
Domain Admins	〇
所有者 Domain Admins

**パターン4**
参加させるユーザーが所属するグループ
Domain Users	〇
Administrators	〇
Domain Admins	〇
所有者 Domain Admins

なぜこのような動作となるのかはわかりませんが、パターン2以外の場合は所有者を確認しても誰が端末をドメインに参加させたか特定をすることはできない為注意が必要です。

なおパターン1の場合は mS-DS-CreatorSID 属性に参加させたユーザーの SID が記録されるのでそちらからユーザーの特定は可能です。

詳しくは
* [MS-DS-Creator-SID 属性 - Win32 apps | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/adschema/a-ms-ds-creatorsid)
* [ユーザーがドメインに参加できる既定のワークステーション番号 - Windows Server | Microsoft Learn](https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/identity/default-workstation-numbers-join-domain)
を確認してください。

# mS-DS-CreatorSID の確認手順

mS-DS-CreatorSID の確認手順は以下です。

## GUIで確認する方法
GUI操作であれば下記になります。

1. ドメイン コントローラーにて [Active Directory ユーザーとコンピューター]を起動します。

2. [表示]をクリックし[拡張機能]にチェックを入れます。

3. 所有者を確認したいコンピュータオブジェクトのプロパティを開きます。

4. [属性エディター]タブを開きます。

5. [mS-DS-CreatorSID]の値を確認します。

## PowerShell のコマンドレットで確認する方法
mS-DS-CreatorSID 属性の情報は Windows PowerShell のコマンドレットでも取得可能です。

```
Get-ADComputer Computername -Properties ms-DS-CreatorSID | Select-Object ms-DS-CreatorSID
```

ドメインに所属する端末の mS-DS-CreatorSID 属性の情報を一括でとるなら下記です。
```
Get-ADComputer -Filter * -Properties ms-DS-CreatorSID | Select-Object Name, ms-DS-CreatorSID
```

## 補足
パターン2の場合においても所有者自体は変更が可能なため、所有者が端末をドメインに参加させたということ断言することはできないです。

またmS-DS-CreatorSID はパターン1の場合にのみしか記録されません。
なので前回の記事、並びに本記事だけでは完璧に端末をドメインに参加させたユーザーを特定することはできません。


# 関連情報
下記を参照しポリシーを構成いただければ、ドメインに端末を参加せるユーザーに制限をかけることが可能です。
* [ドメインにワークステーションを追加 | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/security/threat-protection/security-policy-settings/add-workstations-to-domain)

また今回はコンピューター オブジェクトから確認をしましたが、過去にさかのぼって確認するのでなければ監査設定を有効にしてイベント ログを確認するほうが確実かと思います。

* [Windows イベント コレクションの構成 - Microsoft Defender for Identity | Microsoft Learn](https://learn.microsoft.com/ja-jp/defender-for-identity/configure-windows-event-collection)
* [4741(S) コンピューター アカウントが作成されました。 (Windows 10) - Windows security | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/security/threat-protection/auditing/event-4741)
Active Directory 環境におけるコンピューター オブジェクトの所有者情報について

# 概要

Active Directory 環境においてコンピュータ オブジェクトの所有者を確認する必要性がありその際に確認で来た知見についてまとめます。


# 所有者情報の確認方法

所有者情報の確認方法は以下となります。

## GUIで確認する方法
GUI操作であれば下記になります。

1. ドメイン コントローラーにて [Active Directory ユーザーとコンピューター]を起動します。

2. [表示]をクリックし[拡張機能]にチェックを入れます。

3. 所有者を確認したいコンピュータオブジェクトのプロパティを開きます。

4. [セキュリティ]タブを開きます。

5. [詳細設定]をクリックします。

6. 画面上部で所有者が表示されれます。

拡張機能を表示しないと確認ができないないところがポイントになります。

## コマンド プロンプトのコマンドで確認する方法

事前準備として コンピューターの識別名(DN)を確認します。

こちらもコマンドで取得可能です。

~~~~
dsquery computer -name <computer_name> | dsget computer -dn
~~~~

ドメインに所属するコンピューターの識別名を一括でとるなら下記です。
~~~~
dsquery computer "dc=<domain_name>,dc=<com>" -o dn
~~~~

で実際に所有者の情報を確認するコマンドは下記です。

~~~
dsacls <ObjectDN> | findstr /c:"Owner:"
~~~

実行例
~~~
dsacls "CN=CL01,CN=Computers,DC=Contoso,DC=com" | findstr /c:"Owner:"
~~~

## Windows PowerShell のコマンドレットで確認する方法

事前準備としてコマンドの時同様にコンピューターの識別名(DN)を確認します。

こちらもコマンドレットで取得可能です。
~~~
Get-ADComputer -Identity Computername | Select-Object -ExpandProperty DistinguishedName
~~~

ドメインに所属するコンピューターの識別名を一括でとるなら下記です。
~~~
Get-ADComputer -Filter * -SearchBase "DC=<domain_name>,DC=<com>" -Properties DistinguishedName | Select-Object DistinguishedName
~~~

で実際に所有者の情報を確認するコマンドレットは下記です。
~~~
get-acl -Path "ad:\<ObjectDN>" | Select-Object owner
~~~

実行例
~~~
get-acl -Path "ad:\CN=CL01,CN=Computers,DC=Contoso,DC=com" | Select-Object owner
~~~

## Windows  PowerShell のスクリプトで一括で確認する方法

下記スクリプトでドメインに所属するコンピューター オブジェクトの所有者を一括で確認することが可能です。

```
$computers = Get-ADComputer -Filter *
foreach ($computer in $computers) {
  $acl = Get-Acl -Path "AD:\$($computer.DistinguishedName)"
  $owner = $acl.Owner
  Write-Output "$($computer.Name) owned by $owner"
}
```

本スクリプトでは Get-ADComputer でドメイン内の全てのコンピュータ オブジェクトの一覧を取得し、Get-Acl で所有者情報を取得して出力をしています。

# 最後に
コンピュータ オブジェクトの所有者を確認されたい場合は上記のいずれかにて確認をしていただければと思います。
でそもそもコンピューター オブジェクトの所有者を確認されたい場合に本当に確認したいのは所有者情報ではないのではなくほかの情報を確認したいというニーズから派生しているのではないかと思います。

そちらについては別途まとめたいと思います。
ノートPCの空きCD-ROMドライブベイにSSDを入れ、Linuxをインストールしてみた

　今年購入した格安中古ノートパソコン
```
Celeron 3855U 1.60GHz 2018年末製
Windows11インストール済み
```
を更にパワーアップしたい、といってもCPU乗せ換えなど私にはとてもできません。大容量SSD(500GB)、メモリー16GBにするぐらいが精一杯です。ただ、内部を見たとき気になったCD/DVD-ROM用の空きSlimline SATAコネクタ。ここに、SSDを取り付けてLinuxをインストールできないかと思い立ちました。早速、「薄型光学ドライブベイ用HDDマウンタ」なるものを購入、余っていた120GBのSSDを取り付けました。ピッタリでした。
![ドライブベイ.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/68a09645-f599-2878-041c-4e610f5a2a8c.jpeg)
もちろんCD-ROMは無いのでUSBメモリから、増設したSSDに「Manjaro Linux xfce」をインストール。さあデュアルブートできるのか、起動、緊張の一瞬？？無事にデュアルブート画面が表示されました！
![DualBoot.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/04599808-df31-eb2b-e523-e4a35c1417e2.jpeg)
　やはりwindow11からLinuxドライブは見えません。
![win2lin.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/228f03ed-d6bd-ab79-a254-c7fd874d29aa.jpeg)
でも、LinuxからはWindowsが見えます。ファイルもドラッグ＆ドロップできます。
![li2win.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/c1420818-e16d-3b1c-b329-8e4d9d0840a3.png)
　Windows上のCrystalDiskInfoでも確認してみました。
![crystal01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/31364075-5556-c068-8499-9555ae865d48.jpeg)
ちゃっかりドライブレターの無いLinuxドライブの方が優先順位が上になってました。うまくいき過ぎです。ここで一つ困ったことが。Linuxでも接続して使えるぞと喜んだのも束の間、今まで使えてたブルートゥースマウスが使えなくなってる💦。慌てて普通の無線マウスにチェンジ、これはWindows11でもManjiro Linuxでも使えます。まあこんなものでしょう、良かった。でもブルートゥースマウスどうしよう？
　今回インストールした「manjaro Linux」はローリングアップデートができるので手間いらずかなと選びました。120GB全部を使うのはもったいないと思います。いずれ、さらに別のLinuxも追加したくなるかも知れません。そのとき、GRUBってどうなるのでしょう。でも、所詮外部ドライブなのでいざとなれば外すだけですし。（windows11に影響残るかな？）
Azure Function Apps の関数を削除する方法

# やりたいこと
業務で作成した Function App にデプロイしたある関数を削除する際に、ちょっとハマってしまったので備忘録と共有も兼ねて記事にしようと思います。

# 状況
* ある Function App (Linux) に2つの関数がデプロイされていた
* そのうち1つが必要なくなったので削除したくなった
* Portal から削除しようとしたが、削除ボタンが無効化されていた
* Function App を一度停止させればいけるかと思い、やってみるも有効化されない

このあたりで、いろいろ調べてみることに。

# 原因
原因は、関数のデプロイ時に Function App Core Tools を使って Portal 以外からデプロイしていたため、Portal 上での編集が無効化されていたこと。Portal にも以下のような表示が。
```
This function has been edited through an external editor. Portal editing is disabled.
```

じゃあどうすれば？

# 解決策
Function App Core Tools でデプロイする関数 (ソースコード) から、削除したい関数を取り除く！ (削除する) 
おそらく、Function App Core Tools からデプロイする場合、変更がなくとも全部の関数を毎回デプロイするのでしょう。
そのため削除したい場合はコードごと取り除く必要があった、ということだと思います。

# ちなみに
VSCode の拡張機能から関数をデプロイした場合も同様に Portal からの編集はできないようです。確認していませんが、VSCode からの場合も同様に削除したい関数を取り除いたうえで再度デプロイすれば削除されると思います (きっと…)。


以上です。
[未達成] Kindleで買った本をまるっとブクログへ登録したいができなかった

# (追記) できました

https://qiita.com/Tomonobu3110/items/10f2f39560c8ad135312

# おこったこと

Kindleで買った本をまるっとブクログに登録したくなり、
以下のサイトを参考にJavaScriptを走らせてみましたが動作しませんでした。

https://qiita.com/taka_hira/items/8a9181c0733de2c9f8ee

# 考察

ウェブSQLはもう推奨されていないので、Kindle Cloud Readerでも使わなくなったのかな。
Cromeのデベロッパツールでみてみても、ウェブSQLが空っぽなので、たぶんそうなのだろうと。
うーむ、他の方法を考えなくては...

# ウェブSQLの様子

[ウェブSQLのテストサイト](https://haloechoes.com/websqldatabase/demo.html)
![337303457_920339262345715_4685707839102248832_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102797/8f5e6437-08c2-7cd8-e47d-2ecd8d7984bf.jpeg)

[Kindle Cloud Reader](https://read.amazon.co.jp/kindle-library)
![337521673_8913208625418839_3659836002332439181_n.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102797/b9e80dd8-b03c-f223-10fe-3c4c0c649d9f.jpeg)
y''+y'+3y=e^x「今週の微分方程式 #3」をwolframalphaとsympyでやってみたい。  

「✩基本に忠実に」しましたが、1min.– わんみん様の計算との違いがわかりませんでした。申し訳ありません。
・wolframで,
常微分方程式の分類　　二階線形常微分方程式
ODE classification　second-order linear ordinary differential equation
・sympyのplotでグラフがでます。

オリジナル

https://youtu.be/hBTvy2R2iOc

# wolframで

https://www.wolframalpha.com/input?i=y%27%27-3y%27%2B3y%3De%5Ex&lang=ja

English

https://www.wolframalpha.com/input?i=y%27%27-3y%27%2B3y%3De%5Ex


### 点検?
勉強中

# sympyで
plotでグラフがでます。

```python
from sympy import *
x = Symbol  ('x',real=True)
y = Function('y')(x)
var('C1 C2')
ans=dsolve(Eq(diff(y,x,2)-3*diff(y,x)+3*y,exp(x)))
print("#",ans)
print("#",ans.rhs)
plot (ans.rhs.subs({C1:1,C2:1})) 
# Eq(y(x), (C1*sin(sqrt(3)*x/2) + C2*cos(sqrt(3)*x/2))*exp(3*x/2) + exp(x))
# (C1*sin(sqrt(3)*x/2) + C2*cos(sqrt(3)*x/2))*exp(3*x/2) + exp(x)
```

![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/087f9bc0-d579-f531-551f-daf179ab4535.png)

# 参考

# つづく

https://qiita.com/mrrclb48z/items/84b60f287629845bf4d7
バッチファイルで複数のテキストファイルを読込ませて１つのテキストファイルに出力させるときにハマった話

#### 最初に言っておきます。本件は未解決です。ただ、経緯だけでも誰かの助けになればと思ったので記録しておきます。


環境：Windows10 Pro 1909

- やりたいこと

　あるディレクトリに入っている複数のSQLファイルを、１つのファイルにまとめたい。

　ファイルがたくさんあるので一括でやりたいのでバッチファイルで結合するようにしたかった。

バッチファイルは何度も書いたし、すぐに出来るだろうと考えていたらなかなかにハマったので記録する。



- 用意したもの

　普通のテキストエディタで作ったSQLファイル

　・createA.sql

　・createB.sql

　　・

　　・

　・FileJoin.bat

　※中身は日本語のコメントがついたCreate文



とりあえず出力を繋げちゃおうということで、ファイルの中身を標準出力に表示する「type」コマンドをファイルにリダイレクトする形で作ってみる。

```bat
# FileJoin.bat
REM ～
REM ヘッダーコメント
REM ～

REM バッチファイルのカレントディレクトリへ移動
PUSHD %~DP0
REM ●ディレクトリパラメータ指定
SET SQLDIR=%~d0%~p0
SET TABLEDIR=table
for /r %SQLDIR%%FUNCTIONDIR% %%i in (*.sql) do (
  type %%i >> make_functions.sql	//ここで~.sqlファイルに内容を追記してる
)

REM 以下略
```



- あれ、日本語が文字化けした

　なぜか日本語のコメント部分が”くぁｗせｄｒｆｔｇｙふじこｌｐ（※解読不能）”になってしまった。（アルファベットのコード部分は問題なし）



　とりあえず出来たファイルと元となったファイルを確認する。

　①Windowsのメモ帳（Notepad.exe）で開く。

　→普通。特に何もなし

　②よくあるテキストエディタで開く。（今回はsakuraを使用）

　→普通。何も…あれ？



　いくつもファイルを開いてみるとそれぞれの、文字コードが違う？？？



- ファイルの文字コードは？

　とりあえずファイル毎に文字コードを確認していくと、SJIS(ANSI)、UTF-8N、UTF-8が混在していた。

　※ここではUTF-8NとUTF-8の違い―BOM(byte order mark)については省略させてください



　調べてみるとバッチでそのまま出力するとWindows既定のSJISでファイルは出力されるようだ。

　なるほど、じゃあファイルを全部SJISにすればうまくいくんだな？



　⇒　解　決　し　て　大　勝　利



## ってちょっと待ってください！！！１



調べてると大半の記事が上記みたいな感じで終わってるんですが、今回はUTF-8Nで出力したいんです。。

（プロジェクト的にテキスト系ファイルはUTF-8Nでやらなくちゃいけなかったので。。）



なので今一度UTF-8出力にチャレンジ。

要は文字コード変えておけばいいんでしょう？コマンドで文字コードを変更すればいいとのことなので、バッチ内で「chcp 65001」を実行するように修正して再実行...どうだっ？！



- だめだった

おかしい。何故かSJISで出力されるファイル。。

もしかしてファイル全部修正しないと結局ダメなの？？？


このあたりで時間切れになって、最終的に全部手動でファイルをチョメチョメしたというオチで終わりです。
*もっとなんとかできていれば成長も出来たのに…*
SSLトンネルを繋いでLocalネットへ接続 (セキュリティ注意)

　DBの CDC関連のサービスを検討をしていると常に Local DBへのアクセスがネックになってしまい。。。
で、やむなく検証環境を期間限定で構築した際の、ちょいワル技術です。

 ＜絶対に悪用しないでくださいね＞


```
        - ssh アクセス可能
          Cloud Server
            +-----+
            |     |
 出先#A　    +-----+    Private #B
 +-----+       |        +-----+
 |     |-------+--------|     |
 +-----+                +-----+
- 外部へアクセス可能      - LocalDB 稼働                    
                       - 外部からはアクセス不能 
                       - 外部へはアクセス可能
                       - この環境はにはアクセス可能  
```
こんな状況は良くあります。
　case 1) 例えば #B が会社で、#A が自宅
　case 2) その逆で #Bが自宅で、#A が会社

　こんな時、もし自由にアクセスできるクラウドサーバがあったなら Firewall を解除することなく、またセキュリティチェックに引っかかることもなく#A から #B の DBを直接操作する方法があったりします。

　セキュリティ上は本当に良くないことなのですが、Local DB とpublic DB の CDC (Change Data Capture) などを実験するときには便利だったりします。
　方法は #A と #B の双方からクラウドサーバに ssh トンネルを確立するだけです。
　利用するクラウドサーバは、なんでもOKです

前提)
　CloudServer　Host名　　　　　= anycloud.com
　CloudServer ユーザ名　　　　　= hack
　CloudServer上の空きPort番号　= 3333
　Praive#B のDB Port番号　　　　= 3306   (mysql)
　出先#A の空きPort番号　　　　　= 9999

1) まず Private #B にアクセスできるときに以下のコマンドを実施します
  `ssh -R 3333:localhost:3306 -N hack@anycloud.com  [-i SshKeyFile]`

2) 出先にて以下のコマンド実施します
  `ssh -L 9999:u-software.tk:3333 -N hack@anycloud.com`

3) 例えばDB がMySQL なら、#A から以下のコマンドでアクセスできてしまいます
  `mysql -h 127.0.0.1 -P 9999 -u {DB-User} -p [DatabaseName]`

`#A---Cloud` と `Cloud---#B` の二つのsshトンネルを構築して、 Cloud側の終端ポートを同じにすることで二つのトンネルが繋がってしまうことを利用しています。
     
とても便利な方法ではあるのですが、トンネル２本が繋がると完全なセキュリティホールなので、利用には細心にも細心の注意を払ってご利用ください。
【React】「型Promiseを割り当てることはできません」を解決したい

# はじめに
リファクタリングで非同期処理をコンポーネント化しようとしたところ、型エラーに詰まってしまったので簡単にまとめてみます。

# やりたいこと
①axiosでエンドポイントにアクセスして値を取得する処理を非同期で実行したい
②取得した値をセッターに渡して状態を更新したい
③①と②を1つのコンポーネントにしたい

# 方法
useEffectでaxiosを実行することで型エラーを解決できました。
エラーの原因としては、axiosの処理で値を取得する前に画面のレンダリングが走ってしまうことでした。この状態だとセッターに渡す値の型がPromise型となるため、型エラーになってしまっていました。
useEffectを使うと非同期処理が完了するまで待機してくれるため、値の取得が終わってからセッターに値を渡すことができます。これによってセッターが受け取る値の型がPromise型でなくなりました。

# 該当コード(解決前)
```tsx
略
// useGetData内でaxiosを実行している
export const useGetData = async (data_id: string | undefined) => {
  const [data, setData] = useState<Data>()
  await axios.get(`${apiURL}/data/${data_id}`).then(function (res: AxiosResponse<Search>) {
    setData(res.data.data);
  });
  return data
}
```

# 該当コード(解決後)
```tsx
略
// useEffect内でaxiosを実行している
export const useGetData = (data_id: string | undefined) => {
  const [data, setData] = useState<Data>()
  useEffect(() => {
    if (data_id === undefined) { return }
    const getData = async () => {
      await axios.get(`${apiURL}/data/${data_id}`).then(function (res: AxiosResponse<Search>) {
        setData(res.data.data);
      });
    }
    getData();
  }, [])
  return { data }
}
```

# おわりに
型エラーと仲良くなりたいです。
y'-y/x=1+cos(y/x)「今週の微分方程式 #2」をwolframalphaとsympyでやってみたい。 

申し訳ありません。1min.– わんみん様の計算との違いがわかりませんでした。
・wolframで勾配場?(Slope field)がでます。
・sympyのplotでグラフがでます。

オリジナル

https://youtu.be/vJzWLNtF5f8

# wolframで

https://www.wolframalpha.com/input?i=y%27-y%2Fx%3D1%2Bcos%28y%2Fx%29&lang=ja

English

https://www.wolframalpha.com/input?i=y%27-y%2Fx%3D1%2Bcos%28y%2Fx%29

### 点検?
勉強中

# sympyで
plotでグラフがでます。

```python
from sympy import *
x = Symbol  ('x',real=True)
y = Function('y')(x)
var('C1')
ans=dsolve(Eq(diff(y,x)-y/x,1+cos(y/x)))
print("#",ans)
print("#",ans.rhs)
plot (ans.rhs.subs({C1:1})) 
# Eq(y(x), -2*x*atan(C1 - log(x)))
# -2*x*atan(C1 - log(x))
```
plotは、縦横比が異なります。

![0png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/7c9adccf-d88e-af2d-acbf-3a164cdf7658.png)


# 参考

# つづく

https://qiita.com/mrrclb48z/items/64c2c8b13853b0decdda
ECRにdocker pushしたときにでたEOF

個人的エラーメモ
```
38ff5230ceaa: Retrying in 1 second
2b1e4f4b009b: Retrying in 1 second
110a9d65d7bc: Retrying in 1 second
048467aadd06: Retrying in 1 second
ee3b24cddab4: Retrying in 1 second
67e6d63121e8: Retrying in 5 seconds
0dcf489b944a: Retrying in 5 seconds
ac504d030134: Retrying in 5 seconds
52ebb9a789db: Retrying in 5 seconds
86d774dafc20: Waiting
da68f13652fc: Waiting
cf2e8433dbf2: Waiting
EOF
```

ECRのリポジトリ名とdockerのイメージ名が違ったので同じにしたら直りました
二重数と自動微分

# 本記事について

- 本記事は二重数と自動微分の関係性と応用について ざっくりとした理解をまとめます.
- 応用先に逆伝播を用いないで神経回路学習機を学習させる枠組みなどがあります.
    - [Baydin, Atılım Güneş, et al. "Gradients without Backpropagation." arXiv preprint arXiv:2202.08587 (2022).](https://arxiv.org/abs/2202.08587)

- また, wikipedia の内容を参照します 
    - [dual number](https://en.wikipedia.org/wiki/Dual_number) アクセス日 2023/03/23
    - [Automatic differentiation](https://en.wikipedia.org/wiki/Automatic_differentiation#Automatic_differentiation_using_dual_numbers) アクセス日 2023/03/23

# 二重数について

- 二乗して$0$になるような 抽象代数 と呼ばれる分野で登場する値: $$\epsilon^2=0,\epsilon\neq 0.$$

- こちらの$\epsilon$は 実数$\mathbb{R}$上の多項式環$\mathbb{R}[X]$の、不定元$X$の二乗$X^2$によって生成される主イデアル $\langle X^2 \rangle$による剰余環 $$\mathbb{R}[X]/\langle X^2 \rangle$$によって定義される.

- 行列を用いて $a,b\in\mathbb{R}$に対して$a+\epsilon b$は以下のように表せる.

```math
\begin{pmatrix}
a & b \\
0 & a \\
\end{pmatrix}

```

# 実解析関数と二重数

実解析関数 $f:\mathbb{R}^d\rightarrow \mathbb{R}$に対してテーラー展開を考えると,$x,y\in\mathbb{R^d}$に対して次が成立する:

$$
f(x+\epsilon y)=f(x)+\epsilon y^{\rm T}\left.\frac{\partial f(t)}{\partial t}\right|_{t=y}
$$

- ここで,右辺は微分があり複雑であるが左辺は, 三角関数や対数関数, 指数関数や 積・商などの公式を導くことができるため 右辺を直接計算することなく これを計算することができる.
    - 公式: [Automatic differentiation (wiki)](https://en.wikipedia.org/wiki/Automatic_differentiation#Automatic_differentiation_using_dual_numbers) アクセス日 2023/03/23

- これと同様の数学背景を用いて、Googleが提供する機械学習ライブラリの JAXにおけるヤコビ行列とベクトルの積の計算においても実装されている.
    - [JVPs in math (JAXの公式document)](https://jax.readthedocs.io/en/latest/notebooks/autodiff_cookbook.html#jvps-in-math) アクセス日 2024/10/19
    - https://github.com/jax-ml/jax/discussions/10157#discussioncomment-2513008 アクセス日 2024/10/19

# 応用先

上記より 関数  $f$ が どれだけ深い神経回路学習機であって,どれだけ複雑であっても,解析関数である限り,二重数を用いることで伝幡のみで微分の情報を抽出することが可能であることがわかった.

しかし, 微分情報を直接取り出せないため 神経回路学習機の学習アルゴリズムに直接用いることができないことに注意する.

ただし, 論文(1)では $v$を平均$\mathbf{0}$分散$I$に従う確率変数とすると 

```math
\left(v^{\rm T}\left.\frac{\partial f(t)}{\partial t}\right|_{t=w} \right)v \in\mathbb{R^d}
```

は

```math
\left.\frac{\partial f(t)}{\partial t}\right|_{t=w}
```
の不偏推定量であることを導き, 独立同分布に従うように$v$を発生させることで,その有用性を確かめた.

- (1)[Baydin, Atılım Güneş, et al. "Gradients without Backpropagation." arXiv preprint arXiv:2202.08587 (2022).](https://arxiv.org/abs/2202.08587)


# あとがき

- 数学的に細かいことは追っていませんが, 二重数という不思議な値には 実用的な応用先があるとわかりました.
GitHubにコミットする際のsummaryやdescriptionの書き方

## 概要
### summary
一言で説明すると、何を変更したかを簡潔にまとめたもの。例えば、「Fix a bug」、「Add a new feature」など。

### description
変更の詳細な説明。 変更の目的や背景、変更内容の詳細、影響範囲などを記述する。また、レビュワーに対して、特にチェックしてもらいたい箇所や注意点なども明記すると良い。

特に、複数のコミットを一度にまとめる場合は、各コミットの変更点を簡潔にまとめたsummaryと、それらを総合した全体の説明を含むdescriptionを用意することが重要。これにより、後からプロジェクトを参加する人や、プロジェクトの変更履歴を確認する人が、変更内容を把握しやすくなる。

## summaryの例
* Fix a bug that caused the application to crash when uploading large files
* Add a new feature to allow users to sort their tasks by priority
* Update the design of the login page to improve usability
* Refactor the code for better performance and maintainability
* Improve error handling for better user experience

## descriptionの例
* Fix a bug that caused the application to crash when uploading large files:
  * The previous implementation of the file upload functionality did not handle large files properly, leading to a crash when trying to upload files larger than a certain size. This has been fixed by optimizing the file upload process and adding proper error handling.
* Add a new feature to allow users to sort their tasks by priority:
  * Users can now sort their tasks by priority, which makes it easier to focus on the most important tasks. The sorting functionality can be accessed via a new dropdown menu in the task list.
* Update the design of the login page to improve usability:
  * The login page has been updated to have a more modern and user-friendly design. The new design includes clearer labels and buttons, as well as a simplified layout.
* Refactor the code for better performance and maintainability:
  * The code has been refactored to improve performance and maintainability. This includes removing duplicate code, optimizing database queries, and improving code readability.
 
* Improve error handling for better user experience:
  * Error handling has been improved throughout the application to provide a better user experience. This includes adding more descriptive error messages and handling errors more gracefully.
ESP32のWi-Fi接続でAPとWiFiServer同時に使用する。

AVRを使ったマイコンボードをスマホまたはタブレットで操作する。
自分用の備忘録として記しています。また初めての記事なので書き方不備等がありかもしれませんm(_ _)m

# 開発環境
1.ESP32の開発環境 Arduino IDE
2.スマホアプリの開発環境 MIT App Inventor
3.マイコンアプリの開発環境 MPLAB X IDE 5.50　(ATMega2560を使用)

# 条件の検討
条件１：BruetoothはAndroid-OSがバージョンアップした場合等でその権限等が変わる可能性があるのでWi-Fi接続する。
条件２：Wi-Fiルーターを使用せず、端末と直接つなぎたい。
条件３：接続先のマイコンは ATmega2560を使用しており、UARTでESP32と有線接続する。

# 解決手段
解決方法：以下を参考に、ESP32をアクセスポイントとし、且つWi-Fiサーバーと立ち上げることにした。
参考にしたWebサイト：https://a-tomi.hatenablog.com/entry/2020/09/27/212032

# 問題点
AP接続の場合、端末がWi-Fi専用でない場合は機内モードにしなければならない。
端末アプリをMIT App Inventorで作成しているため、アプリのデバッグ中 ESP32のAPと接続するとアプリ更新等ができなくなる。

# 解決策
前問題を解決するため、条件コンパイルすることにした。
デバッグ時は `#define AP_Mode` をコメントアウトすることで対応することにした。
下の行のIPアドレスは、デバッグモードの時に割り振られたIPアドレスを設定しておくと
アプリケーション側のURLを書き換えなくて済む
`const IPAddress ip(192, 168, 1, 206);   // *** set any addr ***`

```diff_c
// このサンプルプログラムは、同じWiFik接続下にあるESP32ボードとPC或いはモバイル端末の間で
// モバイル端末からESP32ボードの IP アドレスにアクセスすることで、ブラウザから操作できるもの
#include <WiFi.h>

// デバッグ時はAP_Modeをコメントアウトする
// #define AP_Mode

#ifdef AP_Mode
const IPAddress ip(192, 168, 1, 206);   // *** set any addr ***
const IPAddress subnet(255, 255, 255, 0); 
const char ssid[]  = "HOGEHOGE-00X";   // *** set any ssid ***
const char pass[] = "hoge00xpw";  // *** set any pw   ***
#else
const char* ssid     = "aterm-######";
const char* password = "############";
#endif

// Set web server port number to 80
WiFiServer server(80);

// Variable to store the HTTP request
String header;

// Auxiliar variables to store the current output state
String output26State = "off";
String output27State = "off";

// Assign output variables to GPIO pins
const int output26 = 26;
const int output27 = 27;

// Current time
unsigned long currentTime = millis();
// Previous time
unsigned long previousTime = 0; 
// Define timeout time in milliseconds (example: 2000ms = 2s)
const long timeoutTime = 2000;

int inByte = 0;
char buffer[15];


void setup() {
  Serial.begin(115200);     // デバッグ用シリアルモニタ
  Serial1.begin(9600,SERIAL_8N1 , 16 , 17 );    // 制御基板との通信条件
  // Initialize the output variables as outputs
  pinMode(output26, OUTPUT);
  pinMode(output27, OUTPUT);
  // Set outputs to LOW
  digitalWrite(output26, LOW);    // テスト用 LowでLED点灯
  digitalWrite(output27, LOW);

#ifdef AP_Mode
  WiFi.softAP(ssid, pass);
  delay(100);
  WiFi.softAPConfig(ip, ip, subnet);
  IPAddress myIP = WiFi.softAPIP();
  server.begin();
  Serial.print("SSID= ");
  Serial.println(ssid);
  Serial.print("Fixed IP addr= ");
  Serial.println(myIP);
  Serial.println("Server starting!");
#else
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  server.begin();
#endif
}
```
今回は setup()関数のみとしました。

# 応用範囲等
仕事では機械等のコントロールパネルとしてスマホ、タブレットが活用できる。
遊びでは、ロボット等のコントローラーとしてスマホ、タブレットによる操作が可能になる。
色々遊べそうです＾＾
Next.jsでの外部APIを使用する際の注意点

Reactは、現在Webアプリケーション開発において最も人気のあるフレームワークの1つです。Reactを使うことで、簡単かつ効率的にWebアプリケーションを構築することができます。Reactを学ぶことで、Webアプリケーション開発のスキルを向上させ、より多くの仕事の機会を得ることができます。

しかし、Reactを使用して外部APIを呼び出す場合、いくつかの重要な注意点があります。これらの注意点を知っておくことは、Reactアプリケーションの開発において不可欠です。以下に、React及びNext.jsでの外部APIを使用する際の注意点をいくつか紹介します。

## CORSポリシー
最初に考慮しなければならないのは、CORSポリシーです。CORSポリシーは、異なるドメインからのリクエストを制限する仕組みであり、多くの場合、外部APIからのデータを取得する際に問題を引き起こします。この問題を解決するためには、外部APIサーバーでCORSを有効にする必要があります。

```const express = require('express');
const app = express();

app.use((req, res, next) => {
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
  next();
});

app.listen(3000);
```


## データの型と形式
外部APIからのデータを取得する場合、データの型と形式にも注意が必要です。外部APIがJSON形式でデータを提供する場合、ReactアプリケーションでJSON.parse()を使用して、データをパースすることができます。また、外部APIがXML形式でデータを提供する場合、ReactアプリケーションでXML解析ライブラリを使用する必要があります。


```
import React, { useState, useEffect } from 'react';

function App() {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch('https://example.com/data')
      .then(response => response.json())
      .then(data => setData(data));
  }, []);

  return (
    <div>
      {data.map(item => (
        <p key={item.id}>{item.title}</p>
      ))}
    </div>
  );
}

export default App;
```

## エラー処理

外部APIを使用する場合、APIがダウンしている場合や、応答が遅い場合など、さまざまなエラーが発生する可能性があります。Reactアプリケーションでは、これらのエラーに対処する必要があります。エラー処理のためには、Reactアプリケーションでエラー処理のためのライブラリを使用することができます。
CloudflareとGmailでmisskeyのメールサーバーを設定

# やること
Cloudflare Email Routingを使って自分で立てたMisskeyインスタンスにメールサーバーを設定．

# 必要なもの

- 独自ドメイン
    - Cloudflareにドメインを登録しておく
- Gmailで使用するアカウントの二段階認証の有効か

# 手順
## メールの設定
こちらを参考に，独自ドメインでメールを送受信できるようにする．
https://qiita.com/rokuosan/items/e3415ea30ad5e48d3b0f
※アプリパスワードについて
現在(2023/3/23)，設定画面はGoogleアカウントのセキュリティタブ内で，Googleにログインする方法>二段階認証プロセスの一番下にあります．

## misskeyに登録
1. misskey用に新しくアプリパスワードを作成する．
2. misskey コントロールパネル内のメールサーバーの設定で
    - メールアドレス：使用する独自ドメインのメールアドレス
    - SMTPサーバーの設定：Gmailにメールアドレスを追加した際と同様．ただし，パスワードは1で生成したものを使う
 
配信テストをして，うまく受信できたら完了
y'+y/x=(x+1)x^2y「今週の微分方程式 #1」をwolframalphaとsympyでやってみたい。 


1min.– わんみん様の計算との違いがわかりませんでした。申し訳ありません。
・wolframで勾配場?(Slope field)がでます。
・sympyでplotでエラーがでます。

オリジナル

https://youtu.be/65R1JBvNW_8

# wolframで

https://www.wolframalpha.com/input?i=y%27%2By%2Fx%3D%28x%2B1%29x2y&lang=ja

English

https://www.wolframalpha.com/input?i=y%27%2By%2Fx%3D%28x%2B1%29x2y

### 点検?
勉強中

# sympyで
plotでエラーがでます。

```python
from sympy import *
x = Symbol  ('x',real=True)
y = Function('y')(x)
var('C1')
ans=dsolve(Eq(diff(y,x)+y,(x+1)*x**2*y))
print("#",ans)
print("#",ans.rhs)
#plot (ans.rhs.subs({C1:1})) 
# Eq(y(x), C1*exp(x*(x**3/4 + x**2/3 - 1)))
# C1*exp(x*(x**3/4 + x**2/3 - 1))
```

# 参考


# つづく

https://qiita.com/mrrclb48z/items/771058bfbe462c264d36
HTMLから特定の値を返す

```array.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>jQuery Example</title>
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
</head>
<body>
  <select id="dropdown"></select>
  <button id="button">送信</button>
  <p id="result"></p>

  <script src="script.js"></script>
</body>
</html>
```

```array.js
$(document).ready(function() {
  const data = {
    "key1": "value1",
    "key2": "value2",
    "key3": "value3"
  };

  // Populate dropdown with the keys from the associative array
  for (const key in data) {
    $('#dropdown').append(`<option value="${key}">${key}</option>`);
  }

  // On button click, show the value corresponding to the selected key
  $('#button').click(function() {
    const selectedKey = $('#dropdown').val();
    const selectedValue = data[selectedKey];
    $('#result').text(`選択された値: ${selectedValue}`);
  });
});

```
jotai-trpc開発秘話（インフォメティス株式会社では採用しなかったけども）

## はじめに

インフォメティス株式会社でのアプリ開発では[Jotai](https://jotai.org)を採用しています。

https://qiita.com/daishi/items/a701d4f3ab1e2757da82

また、TypeScriptも積極的に使い、end-to-endでの型安全を目指しています。

Jotaiの利用範囲を広げていく中で、APIも検討視野に入りました。その際、tRPCを活用する案が出てきました。

そこで、、、。

## jotai-trpcの開発

[jotai-trpc](https://github.com/jotaijs/jotai-trpc) というライブラリを開発しました。初期のバージョンはほんの30行ほどの簡単なラッパーライブラリでした。atomWithQueryだけを実装したもので、tRPCのVanilla Clientを呼び出すだけでしたが、ちゃんと使えるものになりました。

その後、atomWithMutationなど追加機能も実装し、tRPCのVanilla Clientを全て対応しました。

[tRPC Vanilla Client](https://trpc.io/docs/client/setup)

ところで、jotai-trpcの開発途中に、tRPCの作者からもうすぐv10が出るよと聞かされました。公開予定のv10のAPIを調べてみると、とても大きな変更があることを知りました。短くない道のりでしたが、tRPCのコミッターとも相談しながら、v10対応のjotai-trpcが完成しました。

採用する準備は整ったのですが、、、。

## tRPCは採用せず

結果として、tRPCおよびjotai-trpcは、インフォメティス株式会社でのアプリ開発では採用しませんでした。いくつかの理由があるのですが、ポイントをまとめるとおよそ次のようになります。

- v9からv10からの変更が大きく、近い将来、仮にv11が登場した時の変更の大きさが予想できなかった
- とあるプロジェクトではApollo Clientおよびgraphql-codegenを使用しており、すでにend-to-endの型安全が実現できていた
- とあるプロジェクトではバックエンドとフロントエンドのリポジトリが分断していて、tRPCによる型の共通化がやりにくかった

将来的には分かりませんが、現状の構成では採用するメリットが薄かったことになります。

## おわりに

とは言え、場合によってはtRPC採用のメリットはあるとは思っています。特に、GraphQLがオーバースペックなケースで、型安全だけを実現したい場合はtRPCのマッチ率は高いでしょう。

現状、jotai-trpcの完成度はそれほど低くないと思います（依然として簡単なラッパーであるため）が、利用実績もそれほどなさそうです。理由の一つとして推測しているのが、tRPCを使いたいユーザの多くが、react-queryやNext.jsを採用しているからだと思います。それらとjotai-trpcを組み合わせることは不可能ではないにしてもあまり自明ではありません。joti-trpc自体に興味を持ってくださる方はいるようなので、今後の発展に期待します。

---

最後に、インフォメティス株式会社の採用情報は[こちら](https://www.informetis.com/recruit/)にありますので、ご興味をお持ちになられた方は是非ご覧ください。
備忘録Uipath1

※個人的備忘録です。情報の欠落や相違がある可能性があります。
Uipathでスクリーンショットの動作が安定しない場合

1.ウィンドウサイズが小さいため、画面の下部が見えていない可能性があります。
　この場合、ウィンドウサイズを大きくするか、スクリーンショットを複数に分ける必要があります。

2.ウィンドウがスクロール可能な場合、スクロールしていないため画面の下部が見えていない可能性があります。
　この場合、スクロールアクティビティを使用して画面をスクロールし、必要な部分を表示する必要があります。

3.スクリーンショットのアクティビティが正しく構成されていない可能性があります。
　この場合、スクリーンショットアクティビティのプロパティを確認して、正しい範囲を指定していることを確認してください。

4.ページの読み込みが完了していない
SpringBoot3.0 RedisHttpSession を利用している場合のセッションID変更時のエラーハンドリング

springboot でセッション管理に redis を利用している場合、セッションIDが変わった際にセッションが切れるまでの間エラーになり続ける事象が発生することがある。

springboot2.7 時点では[こちら](https://sadique.io/blog/2016/11/02/handling-deserialization-errors-in-spring-redis-sessions/)を参考にして以下のように対応していた。

```java
@Configuration
public class SessionConfig extends RedisHttpSessionConfiguration {
  @Autowired
  RedisTemplate<Object, Object> redisTemplate;

  @Bean
  @Override
  public <S extends ExpiringSession> SessionRepositoryFilter<? extends ExpiringSession> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
    return super.springSessionRepositoryFilter(new SafeDeserializationRepository<>(sessionRepository, redisTemplate));
  }
}

public class SafeDeserializationRepository<S extends ExpiringSession> implements SessionRepository<S> {
　～略～
  @Override
  public S getSession(String id) {
    try {
      return delegate.getSession(id);
    } catch(SerializationException e) {
      // セッション ID が変わってデシリアライズエラーになった場合はその ID を削除
      logger.info("Deleting non-deserializable session with key {}", id);
      redisTemplate.delete(BOUNDED_HASH_KEY_PREFIX + id);
      return null;
    }
  }

  @Override
  public void delete(String id) {
    delegate.delete(id);
  }
}
```

しかし springboot3.0 に上げると RedisHttpSessionConfiguration が SpringHttpSessionConfiguration を継承しなくなったので上記コードはビルドエラーとなる。

# 対応内容

1. 直接 SpringHttpSessionConfiguration を継承する
2. `@EnableRedisHttpSession` アノテーションを付与する
3. プロパティで `spring.main.allow-bean-definition-overriding = true` を設定する。

```java
@Configuration
@EnableRedisHttpSession // 1.
public class SessionConfig extends SpringHttpSessionConfiguration { // 2.
    @Autowired
    private RedisTemplate<Object, Object> redisTemplate;
 
    @Bean
    @Override
    public <S extends Session> SessionRepositoryFilter<? extends Session> springSessionRepositoryFilter(SessionRepository<S> sessionRepository) {
        return super.springSessionRepositoryFilter(new SafeDeserializationRepository<>(sessionRepository, redisTemplate));
    }
}
```

```yml:application.yml
spring:
  main:
    allow-bean-definition-overriding: true # 3.
```
【HTML＋JS】コードを書くのがめんどくさいのでAIにやってもらった


巷で流行っているAIChatBotの一種、ChatGPT。
様々な使い方をされている中、プログラム・スクリプトを提案してもらえるという話を小耳に挟んだので、筆者も使ってみることにしました。
※執筆当時のバージョン3を使用しています。

ChatGPTの登録方法・使用方法については割愛させていただきます。

# 要件を伝える
まずは画像の通り、要件を伝えました。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/c388c545-f29d-e6f0-0c7d-881fdfa3d171.png)
**「ゴリラ」ボタンを押すと、テキストエリアに🦍が出る。連打するといっぱい出る。**
という内容です。AIが相手なので少し細かく記載しました。

# 返答を確認する
こちらがChatGPTからの返答です。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/b7b6588f-902d-aafe-848c-032fea75bfda.png)
シンプルに完成度の高いコードを書いてくれました。
`addGorilla`や`gorillaTextarea`など良い感じの変数・関数名も設定されています。
コードの説明もされているので、後から自分が手を加えるときも楽そうです。

# 動かしてみる
これを実際に動かしてみると……。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2149621/db097bbd-773c-eea8-afa7-9053f50e843e.gif)
**ゴリラが増える！！！！**

要件に忠実に沿っていて、実際の動作も問題ないですね。

ただ、要件を伝えたとき
「ボタンの **下部** のテキストエリアに～」と書いていたのですが、
改行がされておらず、テキストエリアがボタンの右に位置してしまっています。
理想通りのものが提案されなかった場合、こういった箇所は手作業で修正を加える必要がありますね。

# AI利用のメリット・デメリット
色々あるかと思いますが、筆者が使用する範囲で思いつくのはこれでしょうか。

#### メリット
- 指示した要件でのコードを提案してもらえる
- 変数名や関数名のみ提案してもらうこともできる
- コードの最適化など、ぐちゃぐちゃなコードの整形もできる
- やりたいことが言語化さえできれば、手を動かす工数を大幅に減らせる

#### デメリット
- 100％の正確性はないので、自分が理解できないレベルのコードを生成されても修正できない
→人に聞くという手段もありですが、とある質問サイトではAI生成されたコードに関する質問が制限されているケースもあるようです。
参考：https://www.itmedia.co.jp/news/articles/2212/06/news069.html

- 質問が学習されている可能性があり、セキュリティの面で懸念がある
→使用を禁止している会社も多く、仕事で使用する場合は先方の意向に注意したいです。
参考：https://www.businessinsider.jp/post-265674

# AIと和解せよ
あまりアンテナを張っていない筆者でも、AIの分野の成長のめざましさには目を見張るものがあります。
賛も否も意見がたくさんありますが、筆者個人としては程よい距離感で新しい技術に触れて、楽しみつつプログラミング学習のサポートとして利用できたらと思っています。
vagrant almalinux/9 に supermarket.io のpostgresql v13+ をインストールしようとするとエラーが発生する

supermarket.io の postgresql レシピを使って vagrant の almalinux/9 にpostgresql13とかインストールしたいのだけど、どうやら postgresql の最近のバージョンでインストール時に ` dnf -qy module disable  'postgresql'` を実行してオリジナルのパッケージを参照しないようにしているらしく、このコマンドを実行しようとしてエラーになる

(なぜ package 'postgresql' とかしないのかというと pg_hba.conf の編集やらデフォルトユーザーの追加やらチマチマとやりたくないから)

なので `berks update` とかした後で postgresql レシピの一部を書き換える

Berksfile

```ruby
source "https://supermarket.chef.io"

cookbook 'postgresql', '~>  11.2.3', :supermarket
```

自分のpostgresql 用のレシピ

```ruby
#
# Cookbook:: pgsql
# Recipe:: default
#
# Copyright:: 2022, The Authors, All Rights Reserved.

postgresql_client_install 'My PostgreSQL Client install' do
    version '14'
    action :install
end

postgresql_server_install 'My PostgreSQL Server install' do
    version '14'
    initdb_locale 'ja_JP.UTF-8'
    initdb_encoding 'UTF8'
    action [:install, :create]
end

postgresql_server_conf 'PostgreSQL Config' do
    additional_config({
        :listen_addresses => '*'
    }) 
    notifies :restart, 'service[postgresql]'
end
postgresql_access 'postgresql access' do
    access_type       'host'
    access_db         'all'
    access_user       'all'
    access_addr       '192.168.56.0/24'
    access_method     'password'
    notifies :restart, 'service[postgresql]'
end
postgresql_access 'postgresql local access' do
    access_type       'host'
    access_db         'all'
    access_user       'all'
    access_addr       '127.0.0.1/32'
    access_method     'password'
    notifies :restart, 'service[postgresql]'
end

postgresql_database 'postgresql database' do
    database          'testdb'
    encoding          'UTF8'
    template          'template0'
    locale            'ja_JP.UTF-8'
end
postgresql_database 'wellness database' do
    database          'wellness'
    encoding          'UTF8'
    template          'template0'
    locale            'ja_JP.UTF-8'
end
postgresql_database 'wellness_personal database' do
    database          'wellness_personal'
    encoding          'UTF8'
    template          'template0'
    locale            'ja_JP.UTF-8'
end

postgresql_user 'postgresql user' do
    create_user       'testuser'
    password          'password'
end
postgresql_user 'wellness user' do
    create_user       'wellness'
    password          'password'
end
postgresql_user 'craft user' do
    create_user       'craft'
    password          'craft1234!'
end

service 'postgresql' do
    service_name 'postgresql-14'
    supports restart: true, status: true, reload: true, enable: true
    action [:enable, :reload]
end

```

修正  chef-repo\cookbooks\postgresql\resources\repository.rb

```
    # 21行目付近のブロックを削除/コメントアウト
    ## dnf_module 'postgresql' do
    ##   action :disable
    ##   only_if { node['platform_version'].to_i >= 8 && platform_family?('rhel', 'fedora') }
    ## end
```
TerraformでAWSのCloudWatchまわりをデプロイする

Terraformシリーズ第７弾は**CloudWatch**（以下CW）です:alarm_clock:

※過去のTerraform記事はこちら
第１弾：[TerraformでAWSリソースをデプロイしてみる](https://qiita.com/hiyanger/items/ca337f70ad4801072850)
第２弾：[TerraformでAWS環境をデプロイする前に認識しておくべきこと](https://qiita.com/hiyanger/items/9efdc570e6cfed5aab13)
第３弾：[TerraformでAWSのIAMまわりをデプロイする](https://qiita.com/hiyanger/items/8f925e21166461a5ddb1)
第４弾：[TerraformでAWSのネットワークまわりをデプロイする](https://qiita.com/hiyanger/items/cabb1697c29d2ba93b5a)
第５弾：[TerraformでAWSのEC2まわりをデプロイする](https://qiita.com/hiyanger/items/cabb1697c29d2ba93b5a)
第６弾：[TerraformでAWSのS3をデプロイする](https://qiita.com/hiyanger/items/e68b07f8d88123ddcea3)

### Event Rule
ここではセキュリティグループのモニタを例とします。イベントパターン自体はjson記述で外出しです。通知先はちょっと特殊ですが、別アカウントのイベントバスとしています。
```terraform
resource "aws_cloudwatch_event_rule" "SecurityGroupMonitor" {
        name = "SecurityGroupMonitor"
        description = "Monitoring Security Group Configurataion"
        is_enabled = false
        event_pattern = file("folder/SecurityGroupMonitor.json") 
}

resource "aws_cloudwatch_event_target" "SecurityGroupMonitor" {
  rule     = aws_cloudwatch_event_rule.SecurityGroupMonitor.name
  arn      = "arn:aws:events:ap-northeast-1:XXXXXXXXXXX:event-bus/default"
  role_arn = aws_iam_role.対象ロール名.arn
}
```

### Metric Filter
ロググループから指定の文字列をフィルタリングします。以下では**Error**という文字列でひっかけています。**metric_transformation**で次に記載する**Metric Alarm**と連携させています。
```terraform
resource "aws_cloudwatch_log_metric_filter" "Error" {
  name           = "Error"
  pattern        = "Error"
  log_group_name = "ロググループ名"

  metric_transformation {
    name      = "メトリクス名"
    namespace = "LogMetrics" #名前空間
    value     = "1" #メトリクス値
  }
}
```

### Metric Alarm
メトリクスフィルタで拾った情報を通知させます。コードだとわかりにくいので、コンソールと照らし合わせながらみるとわかりやすいです。
```terraform
resource "aws_cloudwatch_metric_alarm" "Error" {
  alarm_name                = "アラーム名"
  comparison_operator       = "GreaterThanOrEqualToThreshold" #アラーム条件
  evaluation_periods        = "1" #アラームを実行するデータポイント
  metric_name               = "メトリクス名"
  namespace                 = "LogMetrics" #名前空間
  period                    = "60" #期間（秒）
  statistic                 = "Sum" #統計方法
  threshold                 = "0" #アラーム条件のしきい値
  alarm_actions             = ["arn:通知先"]
  actions_enabled           = "false"
}
```
※こちらの記事が参考になります
https://qiita.com/hengineer/items/382c4f45b83cedfaea85

プロジェクトによっては大量のフィルタを作ったりするので、そういった場合はスピードの観点で強い恩恵をうけることができますね。またアクションをそれぞれ**false**にしているのは、まだ運用に入らないという前提で**false**にしています。あとから手動で切り替えられるので適宜設定してください。
備忘録 forwardRefとIconButtonPropsの関係性

# はじめに
MUIのIconButtonPropsをtypeとして、かつforwardRefを用いた際に以下のエラーメッセージがコンソール上に表示された。
```
Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?
```
# エラーメッセージが表示された時のコード
```TypeScript
import type { IconButtonProps } from "@mui/material";
import { IconButton } from "@mui/material";
import { memo } from "react";

export const GoogleIconButton = memo<IconButtonProps>(({ children, ...props }) => {
    return <IconButton {...props}>{children}</IconButton>;
});
```
# やりたいこと
前項のコードにおけるエラーメッセージを解消する。
# やったこと
色々と調べると『ref属性にuseRefの変数をpropsとして渡そうとする』と最初に記載したエラーメッセージが表示される様子。
（参考サイト:https://devsakaso.com/react-forwardref/）

https://devsakaso.com/react-forwardref/

確かに、前々項のコードは汎用コンポーネントで、使用していた一部の親コンポーネントにref属性を扱っているものがあった。
そのため、親コンポーネントから子コンポーネント（関数コンポーネント）のref属性を使用できるようにするため、以下のコードのように`forwardRef`を使用した。
（参考サイト:https://nishinatoshiharu.com/overview-react-ref/）

https://nishinatoshiharu.com/overview-react-ref/

```TypeScript
import type { IconButtonProps } from "@mui/material";
import { IconButton } from "@mui/material";
import { forwardRef, memo } from "react";

export const GoogleIconButton = memo(forwardRef<IconButtonProps>(({ children, ...props }) => {
    return <IconButton {...props}>{children}</IconButton>;
}));
```
すると、以下の別のエラーメッセージが表示された。
```
Component is not optimized. Please add a shouldComponentUpdate method.
```
これは簡単に言うと『コンポーネント中でpropsの各プロパティを使おうとするとESLintによってエラー扱いになる』ということだそう。
なので定義を分割してコードを再構築した。
（参考サイト:https://qiita.com/ckbys/items/7a7904a95289b7160c93）

https://qiita.com/ckbys/items/7a7904a95289b7160c93

```TypeScript
import type { IconButtonProps } from "@mui/material";
import { IconButton } from "@mui/material";
import { forwardRef, memo } from "react";

const GoogleIconButtonDefinition = forwardRef<IconButtonProps>(({ children, ...props }) => {
    return <IconButton {...props}>{children}</IconButton>;
});

export const GoogleIconButton = memo(GoogleIconButtonDefinition);
```
ここでまた別のエラーメッセージが表示された。
```
プロパティ 'children' は型 '{}' に存在しません。
```
`forwardRef<IconButtonProps>`という形だと認識されないようだったので、原因など色々調べた結果、次項のコードに落ち着いた。
（参考サイト:https://zenn.dev/doke/articles/880f03c35576b5）

https://zenn.dev/doke/articles/880f03c35576b5

# 回避策（コード内容）
```TypeScript
import type { IconButtonProps } from "@mui/material";
import { IconButton } from "@mui/material";
import { forwardRef, memo } from "react";

const GoogleIconButtonDefinition = forwardRef(({ children, ref, ...props }: IconButtonProps) => {
    return (
        <IconButton ref={ref} {...props}>
            {children}
        </IconButton>
    );
});

export const GoogleIconButton = memo(GoogleIconButtonDefinition);
```
これで最初のエラーメッセージは解消された。
Seeed XIAO RP2040をPlatformIO IDEで使う際の設定メモ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/11bfb1b1-89b1-b222-59e3-865528725643.png)



＜事前準備＞
・Windows用Gitをインストール
　こちらを参考にさせていただきました。
　https://sukkiri.jp/technologies/devtools/git/git_win.html

＜Platformsインストール時のロングファイルパスエラー解消のため＞
・windowsの長いパスを有効にする
　https://itojisan.xyz/trouble/20895/#4_Win32
・gitのlong pathを有効化
　https://myscreate.com/filename-too-long/

＜PIO設定＞
　1.PIO Home　⇒　Platforms　⇒　Advanced Installation　をクリック。
　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/dc0ef829-52ce-904d-6f79-dd276bd78ab5.png)

　2.「 https://github.com/maxgerhardt/platform-raspberrypi.git 」 を入力しinstallをクリック。
　しばらく待つ。（15分くらい掛かりました）
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611426/48a672ba-3c77-267f-05a2-e1661eaa7922.png)


以上で無事使用できるようになりました。
Vueをdockerコンテナで開発

# Vueをdockerコンテナで動かしたい
ほぼ個人的なメモです
## 環境
M1 macOS:12.5
```Dockerfile:Dockerfile
FROM node:18-slim

WORKDIR /home/node
USER node
```
## 問題
つまづいた所。
・Vueのサーバーはインストール時のOSの環境依存性がある
・コンテナからローカルマシンに対して応答が返らない
　（「ページが動作していません」と表示される。ポートフォワーディングそのものがおかしければ、アクセスが拒否されるはずだが...）

## 流れ
Vueは初めて触ったので、私は初見時普通にローカルで`$ npm install`しました...
![スクリーンショット 2023-03-21 16.39.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3112825/36df4139-9309-8699-e975-b093efe66aae.png)
すると上記のエラーが発生。ただ難しいことは書いていなくて、`another platform`の記述を見てなるほどとすぐに気づきました。
ローカルでインストールしたからmacOSの依存性があるのにdockerコンテナのLinuxOS下で動かそうとしてるからエラーになると...
`$ docker-compose exec [サービス名] /bin/bash`
でコンテナに入り
```terminal:コンテナ内
$ npm install
```
を実行。これで問題なく動作するはずです。

### 応答が返らない問題
https://choice-site.com/2021/06/24/docker%E3%81%ABvite%E3%82%92%E5%85%A5%E3%82%8C%E3%81%A6vue%E3%81%A7%E9%96%8B%E7%99%BA%E3%81%97%E3%82%88%E3%81%86%E3%81%A8%E3%81%97%E3%81%9F%E3%81%A8%E3%81%8Dlocalhost%E3%81%AB%E7%B9%8B%E3%81%8C/
こちらの記事と全く同じ現象が発生。
Vueのインストール方法はいろいろあるっぽいですが、私は
`$ npm init vue@latest`
でインストール。
この際のvite.configの設定だとネットワークの設定がダメなようで、
コンテナ内ではサーバーが起動していますが、ローカルのマシンまで応答が返らず
「ページが動作していません」となります。かなりこれに時間を使った...

```diff_javascript:vite.config.js
export default defineConfig({
    plugins: [vue()],
+    server: {
+        host: true
+    }
})
```
この記述を増やすだけでやっと繋がります。

### 備考
https://qiita.com/subun33/items/b051f5697482203aa31d
調べてる途中で見つけた記事ではyarnでインストールされていて、試してみると特に処理をすることなく動作。
コンテナを利用する場合はnpmでのインストールは注意が必要。
type guard function: Element implicitly has an ‘any’ type

~~~types.ts
export type Hoge =
  | {
      a: number;
    }
  | {
      b: number;
    };
~~~
この型からts-auto-guardを使ってtype guard functionを生成すると
~~~types.guard.ts
export function isHoge(obj: unknown): obj is Hoge {
    const typedObj = obj as Hoge
    return (
        ((typedObj !== null &&
            typeof typedObj === "object" ||
            typeof typedObj === "function") &&
            typeof typedObj["a"] === "number" ||
            (typedObj !== null &&
                typeof typedObj === "object" ||
                typeof typedObj === "function") &&
            typeof typedObj["b"] === "number")
    )
}
~~~
~~~.ts
typedObj["a"]
~~~
ここで
`TS7053: Element implicitly has an 'any' type because expression of type '"a"' can't be used to index type 'Hoge'.   Property 'a' does not exist on type 'Hoge'.`
が出てしまう。（`typedObj["b"]` も同様）

次の様にするとエラーが消える
~~~types.ts
export type Hoge =
  | {
      a: number;
      b: never;
    }
  | {
      a: never;
      b: number;
    };
~~~
~~~types.guard.ts
export function isHoge(obj: unknown): obj is Hoge {
    const typedObj = obj as Hoge
    return (
        ((typedObj !== null &&
            typeof typedObj === "object" ||
            typeof typedObj === "function") &&
            typeof typedObj["a"] === "number" ||
            (typedObj !== null &&
                typeof typedObj === "object" ||
                typeof typedObj === "function") &&
            typeof typedObj["b"] === "number")
    )
}
~~~
ページレイアウトを設計する

div要素にstyleを記述して配置する方法では、HTMLページのレイアウトが思い通りにならなかった。

だから、chatGPTに聞きながら、HTMLページを作成することにした。

私「htmlページの画面レイアウトが、思い通りできなくて困っている。簡単にできるレイアウトの手法を教えて。」

chatGPT「・・・、CSSのFlexboxとGrid Layoutがあります。・・・」

Grip Layoutを採用することにした。

## chatGPTに二回問いかけて、提示してくれたプログラムを１行だけ自分で書き直して使った。
指示１「bodyは、画面いっぱいの大きさにする。Grid Layoutでヘッダー、コンテンツエリア、フッターがある。各幅は画面いっぱいにする。位置は順序通りにする。」

指示２「body要素を2x2のグリッドに分割して」

htmlファイル
```html
<div class="grid-container">
  <div class="grid-item header">Header</div>
  <div class="grid-item sidebar">Sidebar</div>
  <div class="grid-item content">Content Area</div>
  <div class="grid-item footer">Footer</div>
</div>
```
cssファイル
```css
.grid-container {
  display: grid;
  /*grid-template-columns: 1fr 1fr; chatGPTは均等に分けたので、左を200pxに固定に修正する*/
  grid-template-columns: 200px auto;　/*手修正*/
  grid-template-rows: auto 1fr;
  height: 100vh;
}

.grid-item {
  padding: 20px;
  box-sizing: border-box;
}

.header {
  background-color: #ccc;
  grid-column: 1 / span 2;
}

.sidebar {
  background-color: #eee;
  grid-row: 2 / span 1;
}

.content {
  background-color: #fff;
  grid-row: 2 / span 1;
  grid-column: 2 / span 1;
}

.footer {
  background-color: #ccc;
  grid-column: 1 / span 2;
}
```
webに表示してみると
![スクリーンショット 2023-03-23 14.41.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3268288/16a6e2a9-658a-a6e3-27d6-148f9948aa18.png)

## 注意書き
何度も指示の仕方を試行錯誤してうまくいった場合を書いた。
gridの最終的な行列分割を指定すると上手くいく。