OmniAICreator/Qiita-1.07M huggingface dataset:
USB のトラブルシューティングツール USB Device Tree Viewer のインストール

USB Device Tree Viewer（ユーエスビー　デバイス　ツリー　ビューワー）は、Windows に接続されている USB デバイスの情報を表示する無料のソフトウェアです。USB デバイスの故障診断を行う際に役立ちます。ここでは18歳の新入社員向けに USB Device Tree Viewer のインストール方法を紹介します。

## USB Device Tree Viewer の目的
USB Device Tree Viewer は以下のような用途で使われます。

### トラブルシューティング
USBデバイスが認識されない、接続が不安定などの問題を特定できます。

### 接続関係の確認
USB デバイスがどのハブに接続されているか、どのポートを使用しているかを確認できます。

### デバイスの識別
接続されているUSBデバイスの各種情報（製造者、製品ID、ベンダーID、リビジョン、使用中のドライバ、速度、消費電力など）を表示します。

## USB Device Tree Viewer のシステム要件
USB Device Tree Viewer は以下の環境で動作します。

- オペレーティングシステム: Windows 8, 10, 11

ここでは USB Device Tree Viewer V3.8.9 を例にして、Windows 11 へのインストール手順を説明します

## USB Device Tree Viewer のインストール手順
### ダウンロード
USB Device Tree Viewer  のダウンロードページにアクセスし、「**UsbTreeView_x64.zip**」のリンクをクリックします。

[https://www.uwe-sieber.de/usbtreeview_e.html#download](https://www.uwe-sieber.de/usbtreeview_e.html#download)

![02_officialsite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/12768863-2945-4cbc-0f8e-ceb5940bde00.png)

### ファイルの展開
ダウンロードが完了したら、ファイルを右クリックし、コンテキストメニューから「**すべて展開**」をクリックします。

![11_download.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/440b2e2a-a305-7af0-34a1-b2030746bd71.png)

### 展開先フォルダの指定
ファイルの展開先を指定します。ここでは例として **C:\ProgramFiles\UsbTreeView_x64** というフォルダに展開します。

![21_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/8d461793-9b5b-8be5-a30b-ca422711e601.png)

以上でインストール作業は終了です。

USB Device Tree Viewer を使う時は **C:\ProgramFiles\UsbTreeView_x64\UsbTreeView.exe** を実行します。

![22_install.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/eb70bc72-8eca-8927-08bc-267c3b35755b.png)
バイナリエディタ Stirling 1.31 のインストール

Stirling（スターリング） は Windows 向けの無料のバイナリエディタです。Stirling はアンドゥ機能や比較機能を持つ、高機能なバイナリエディタです。ここでは 18 歳の新入社員向けに Stirling のインストール手順を説明します。

## Stirling を使う目的
Stirling は以下のような用途で使われます。

### ファイルの解析と修正
ファイルのバイナリ表現を直接操作することで、特定のファイル形式の内部構造を調査し、必要に応じて修正できます。これは、ファイルのデータ構造が不明確である場合や特定の問題を修正するために使用されます。

### データの比較
2つのバイナリファイルを比較し、違いを特定するのに使用できます。これはプログラムのバージョン管理やセキュリティチェックに役立ちます。

### データの抽出
バイナリデータから特定の情報やリソースを抽出できます。たとえば、実行可能ファイルからアイコンやリソースを抽出することができます。

:::note warn
ソフトウェアの内部構造を解析し、動作原理を特定する行為は、リバースエンジニアリングと呼ばれます。商用ソフトウェアでは使用許諾契約書でリバースエンジニアリングを禁止していることがあります。他人のソフトウェアをリバースエンジニアリングすることは避けましょう。
:::

## Stirling のシステム要件
Stirling は以下の環境で動作します。

- オペレーティングシステム：Windows95, 98, NT4.0以降
- その他：LZH ファイルを解凍できること
- 
ここでは Stirling Version 1.31 を例にして、Windows 11 へのインストール方法を紹介します。

## Stirling のインストール手順
### ダウンロード
ベクターの Stirling の紹介ページにアクセスし、「**ダウンロードはこちら**」をクリックします。

[https://www.vector.co.jp/soft/win95/util/se079072.html](https://www.vector.co.jp/soft/win95/util/se079072.html)

![03_officialsite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/28222395-50eb-eddf-df7b-5d97605fa8f1.png)

ダウンロードページが表示されたら、「**このソフトを今すぐダウンロード**」をクリックします。

![05_officialsite.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/6a8ed7b1-1689-46b5-525b-91670068d6fe.png)

### ファイルの展開
ダウンロードが完了したら、stir131.lzh を展開します。

::: note
この記事では [7-Zip](https://qiita.com/mmake/items/e18ef5978f365b2ead3a) を使った展開方法を紹介します。7-Zip のインストールはこちらの記事をご覧ください。[「ファイル圧縮・解凍ソフト 7-Zip のインストール」](https://qiita.com/mmake/items/e18ef5978f365b2ead3a) 
:::

### 7-Zip を使った展開
ダウンロードした stir131.lzh を右クリックし、コンテキストメニューが表示されたら、7-Zip > 展開... をクリックします。

![11_lzh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/66dcc22e-a0f4-0c9d-be48-ddec7f2229f1.png)

### 展開先フォルダの指定
ファイルの展開先を指定します。ここでは例として **C:\ProgramFiles** というフォルダに展開します。

![12_lzh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/92508396-07cf-3407-4cb2-e8d9fa06b3cc.png)

以上で String のインストール作業は終了です。

Stirling を使う時は **C:\ProgramFiles\stir131\Stirling.exe** を実行します。

![21_strling.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/ea8af244-8464-bb35-40b1-ef8e1909e73e.png)
AWSの障害やメンテナンスを通知して自動で対応したい

# はじめに
この記事はDevOps on AWS大全 実践編の一部です。
DevOps on AWS大全 実践編の一覧は[こちら](https://qiita.com/tech4anyone/items/c27e74f9ae569ced259f)。

この記事ではAWSの障害やメンテナンスを通知して自動で対応するアーキテクチャを決める流れを解説しています。

具体的には以下流れで説明します。

- 解決したい課題の整理
- 今回使うAWSサービスの整理
- アーキテクチャの策定
- 策定したアーキテクチャで達成できたこと

AWSの区分でいう「Level 400 : 複数のサービス、アーキテクチャによる実装でテクノロジーがどのように機能するかを解説するレベル」の内容です。

# この記事を読んでほしい人
- DevOpsエンジニアがアーキテクチャを決めるときにどのような思考フローを踏んでいるか知りたい人
- AWSの障害やメンテナンスを通知して自動で対応するアーキテクチャを知りたい人
- AWS Certified DevOps Engineer Professionalを目指している人

# 前回までの流れ
[こちら](https://zenn.dev/tech4anyone/articles/f2aa1728b82865)の記事でAWSであらゆるものをモニタリングするアーキテクチャを策定しました。


# 解決したい課題の整理
現在、解決したいと思っている課題は以下になります。
- AWSの障害やメンテナンスが告知されたらチャットへの通知したい
- アカウント状態が健全ではなくなったら自動対応したい

ということで、これをどうやって解決するか考えていきましょう。

# 今回使うAWSサービスの整理
今回使う代表的なAWSサービスの概要とベストプラクティスは以下の通りです。

## AWS Health Dashboard
AWS Health Dashboardは、AWSのサービスのステータスやイベント情報をリアルタイムで提供するサービスです。
AWSユーザーはこのダッシュボードを通じて、サービスの健全性やパフォーマンスに関する情報を把握できます。
AWS Health Dashboardで得られる情報には、サービスの障害、予定されたメンテナンス、およびその他の健康状態に関する通知が含まれます。

なお、AWS Health DashboardにはService HistoryとYour Accountの2つの区分が存在します。

[Service History](https://health.aws.amazon.com/health/status)はすべてのリージョン、すべてのサービスのサービス状況を一覧で見ることができます。
いわゆる大規模障害の時に情報が更新されるのがService Historyです。

一方、Your Accountは以前までPersonal Health Dashboardと呼ばれていたサービスです。
今でも検索するとPersonal Health Dashboardで出てくるAWS公式ページがありますが、正式にはAWS Healthの中のDashboardに統合されています。

Your Accountは自アカウントに影響のあるアラートが表示されます。
例えばEC2インスタンスのリタイアメント通知やLambdaのランタイムサポート切れなどが通知されます。

## ベストプラクティス
以下は、このサービスを使用する際のベストプラクティスです。

| ベストプラクティス | 説明 |
| --- | --- |
| Service HistoryとYour Accountを両方確認する | Your Accountでは、AWSアカウントに影響を与えるイベントや通知だけが表示されます。一方、Service Historyでは、AWSのサービス全体の稼働状況や障害情報が表示されます。したがって、両方のダッシュボードを確認することで、AWSのサービスに関する問題をより正確に把握することができます。 |
| 通知設定を有効にする | AWS Personal Health Dashboardでは、イベントや通知が発生した場合にメールやSMSで通知を受け取ることができます。この機能を有効にすることで、問題に早期に気づき、迅速に対応することができます。通知設定は、AWSコンソールのPersonal Health DashboardのPreferencesから行うことができます。 |
| APIやRSSフィードを利用する | Your AccounとService Historyでは、それぞれPersonal Health APIとService Health APIを利用してプログラムからもアクセスできます。また、Service Historyでは、RSSフィードを購読して稼働状況や障害情報を受け取ることもできます。これらの機能を利用することで、AWS Health Dashboardの情報を自動化したり、他のシステムやツールと連携したりすることができます。 |

# アーキテクチャの策定
ここからはやりたいことを順番に考えながらアーキテクチャを策定していきます。
## AWS Health Dashboardが更新されたときに通知してほしい
1つめのやりたいことはAWS Health Dashboardが更新されたときに通知してほしい、というものです。

AWS Health DashboardはAmazon EventBridgeと連携することが可能です。
そのため、自アカウントに影響のある通知が来た際やリージョン障害が発生した際にEventBridge経由でLambdaを発火させ、チャットへ通知することができます。

ベストプラクティスは自動で通知に対する対応まで完了させることですが実プロジェクトでは報告して、対策を決定して、という場面も多くあります。
そこで、まずは通知を自動で受け取れるようにすることが大切です。

これらをまとめると以下のようなアーキテクチャになります。
![](https://storage.googleapis.com/zenn-user-upload/d04b16ef55a6-20240114.png)

## AWS Health Dashboardが更新されたときに自動対応してほしい
もう1つのやりたいことは自動での対応です。
例えばIAMのアクセスキーが流出した場合には自動でアクセスキーを削除すべきですし、EC2インスタンスのリタイアメント通知が来たら自動でメンテナンスウインドウ内の再起動を実施すべきです。

これらをまとめると以下のようなアーキテクチャになります。
![](https://storage.googleapis.com/zenn-user-upload/5e2882a2a21f-20240114.png)

# まとめ
本記事ではAWSであらゆるものをモニタリングするアーキテクチャをまとめました。

今回策定したアーキテクチャで実現できたのは以下の項目です。
- AWS Health Dashboardが更新されたときにチャットへの通知
- AWS Health Dashboardが更新されたときに自動対応


次回はセキュリティ対策を考えてみたいと思います。
Bash と Caddy サーバで ActivityPub のインスタンス(2) 他のインスタンスからの POST を取得する

## 概要

インスタンスのアクターの情報に記されている inbox へ POST される HTTP リクエストをポート（もしくは UNIX ドメインソケット）に流して、netcat で取得する。

## 実装

Caddyfile ファイルの

ホニャララ{ 〜 }

内に以下を加える。
```
ホニャララ {
（中略）
    handle_path /users/aktor/inbox {
    	reverse_proxy localhost:1682
	}
}
```
ポートを開けたくないなどの理由で UNIX ドメインソケットを使う場合は
reverse_proxy localhost:1682
を
reverse_proxy unix//tmp/sock
などに変える。

取り敢えずは
netcat -lk 1682
（UNIX ドメインソケットを使う場合は
netcat -Ulk /tmp/sock
 など）
とすれば、@aktor@ホニャララ への反応（メンションやフォローリクエスト）などをターミナルの標準出力へ流すことが出来る。
ただしこれでは HTTP ステータスコードを返せていない。Mastodon の場合、200 または 202 を返さないとおよそ 50 時間に渡って 16 回も同じリクエストを送り続ける(https://blog.noellabo.jp/entry/2020/03/07/oq3sL7PQhFMrc6Bb )ので、202 くらいを返して止めたい。しかしネットワークの状況などによってたまにリクエストのボディがないまま送られてくることもあるので、
- ボディがあったらリクエストをファイルに取り、取り敢えず 202 を返して配送を止める
- ボディが無かったら(一応ファイルには残し) 204 を返し、再配送を求める

とすることにする。
202 204 というディレクトリと、response という名前付きパイプを使うので
```bash
mkdir 202 204
mkfifo response
```
と作り
```bash:response_move.sh
#!/bin/bash

file_name=$(date "+%s")

while read -r line;
do
	trline=$(echo $line | tr -d "\r\n")
	echo "$trline"

	content_reg='Content-Length:\s(.*?)'
	[[ "$trline" =~ $content_reg ]] &&
	CONTENT_LENGTH=$(echo $trline | sed -E "s/$content_reg/\1/")

	[ -z "$trline" ] && break
done > $file_name

temp=$(head -c $CONTENT_LENGTH -)
echo $temp >> $file_name

if [ "$temp" ]; then
	printf "HTTP/1.1 202\r\n\r\n" > response
	mv $file_name ./202/$file_name
	echo "anything to 202"
else
	printf "HTTP/1.1 202\r\n\r\n" > response
	mv $file_name ./204/$file_name
	echo "anything to 204"
fi
```
このシェルスクリプトに netcat から流す。
このシェルスクリプトが何をやっているかの詳しいことはこの拙記事(https://qiita.com/tochu-cha/items/fb744ae3715c0807ecc6 )を見ていただきたい。
これを
```bash
bash while :; do cat temp | netcat -lN 1682 | bash response_move.sh ; done
```
と netcat と組み合わせて実行する。

これで Mastodon その他からの POST を 202 もしくは 204 のステータスコードを返して、 202 ディレクトリもしくは 204 ディレクトリにファイルとして残すことが出来る。

## 参考記事
[ Mastodonが配送に失敗したジョブに対処する仕組み ](https://blog.noellabo.jp/entry/2020/03/07/oq3sL7PQhFMrc6Bb)
[ netcat スクリプトで curl からのリクエストを受け取りファイルに保持してステータスコードを返す ](https://qiita.com/tochu-cha/items/fb744ae3715c0807ecc6)
JavaScriptの残余パラメータ

サイ本からのメモ。
パラメータのデフォルト値を使うことで、パラメータよりも少ない数の引数で、呼び出せる関数を記述できる。この反対を行うのが残余パラメータ。これはパラメータよりも多い数の引数で呼び出せる関数を記述できます。下記のコードは受け取った数値の中から一番大きい数を返します。

```js
function max(first = -Infinity, ...rest) {
  let maxValue = first;

  for (let n of rest) {
    if (n > maxValue) {
      maxValue = n;
    };
  };
  return maxValue
};
max(1, 10, 100, 2, 3, 1000, 4, 5, 6); // 1000
```

残余パラメータの前に3つのピリオドを記述します。残余パラメータは関数宣言のパラメータリストで最後に記述します。
残余パラメータはES6から追加されました。

#### 参考
https://www.amazon.co.jp/JavaScript-%E7%AC%AC7%E7%89%88-David-Flanagan/dp/4873119707
SwiftUIでの画面遷移問題: NavigationViewからNavigationStackへの移行

SwiftUIを使用する際に直面した、NavigationViewを用いた画面遷移の問題について共有したいと思います。この問題は、遷移前の画面でCore Dataをfetchする際に生じました。具体的には、遷移前の画面でCore Dataを取得し、遷移先の画面でそのデータを更新すると、遷移前の画面が再レンダリングされてしまいました。その結果、NavigationViewのdestinationが解除され、自動的に遷移前の画面に戻ってしまうという状況が発生しました。

この問題には、SwiftUIのNavigationStackの使用が効果的な解決策でした。最近、NavigationViewは非推奨とされ、NavigationStackが推奨されています。NavigationStackに移行したところ、上記の問題が解消されました。NavigationStackは、より直感的で使いやすいAPIを提供し、画面遷移におけるこのような問題を解決するのに役立ちます。

この記事は、同じ問題に直面している他の開発者の参考になることを願っています。SwiftUIの動作に関しては、時に直感に反することがあり、このような具体的な経験を共有することが重要だと感じています。

---
個人でアプリを開発しています。ベビーカーや車椅子利用の方に便利な、駅のエレベーター出入口を探せるアプリを開発しました。ぜひご利用ください。

https://apps.apple.com/jp/app/%E9%A7%85%E3%81%AE%E3%82%A8%E3%83%AC%E3%83%99%E3%83%BC%E3%82%BF%E3%83%BC%E3%83%9E%E3%83%83%E3%83%97/id6472233345
Blazor Serverで.NET 7から.NET 8への移行方法

# はじめに
現在、Blazor Server を使用してアプリケーションを作成しています。.NET 7のサンプルアプリから徐々に改良して作成していきました。
2023/11/14に.NET 8がリリースされました。早速、Target frameworkを「.NET 8」に変更してみると、これが動かないんですよね。
既に社内ライブラリーは、.NET 8に上げてしまったので正直焦りました。
原因を調査するには時間が足りないため、しばらくは.NET 7のまま開発を進めていました。

そして、冬季休暇になった段階で、ようやく落ち着いて調べることが出来ました。

# 変更点
.NET 8のサンプルアプリから徐々に現在のアプリケーションに近づける方法で調査していきました。

## フォルダ構成
.NET 7では、直下に`Pages`フォルダと`Shared`フォルダがありましたが、.NET 8では、直下に`Components`フォルダが追加され、配下に`Pages`フォルダと`Shared`フォルダが移動されました。

これによりネームスペースの変更が必要となります。

## _Host.cshtml から App.razor へ
`Pages`フォルダ内の`_Host.cshtml`ファイルは`App.razor`ファイルに変更になりました。
linkタグやscriptタグは、`App.razor`ファイルに記載するようになります。

他にも下記ファイルなどが変更になっています。

```html
<link rel="stylesheet" href="css/site.css" />
                                 ↓
<link rel="stylesheet" href="css/app.css" />
```

```html
<script src="_framework/blazor.server.js"></script>
                                 ↓
<script src="_framework/blazor.web.js"></script>
```

### 相対ディレクトリの指定
【2024/02/12追記】 別記事にしました。
デプロイした時に正しくレンダリングされない件がありました。

https://qiita.com/yaju/items/28c020070111b4d0ed40

## アイコンのopen-iconic削除
Blazor プロジェクト テンプレートは、アイコンの [Open Iconic](https://github.com/iconic/open-iconic) に依存しなくなったことで削除されました。

https://learn.microsoft.com/ja-jp/aspnet/core/release-notes/aspnetcore-8.0?view=aspnetcore-8.0

今回は使用していなかったので、特に影響はなかった。

## Program.cs の中身
`Program.cs`ファイルの中身も変更されています。
下記は例となります。

```cs:.NET 7のProgram.cs
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
 ⋮
app.UseAntiforgery();

app.MapRazorComponents<App>()
	.AddInteractiveServerRenderMode();
```

```cs:.NET 8のProgram.cs
builder.Services.AddRazorComponents()
	.AddInteractiveServerComponents();
 ⋮
app.UseRouting();

app.UseForwardedHeaders();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host"); 
```

## レンダーモード
.NET 7から.NET 8の変更点で一番重要でした。

サンプルアプリで、Counterの内容をHome側に追加した時に、Counterボタンをクリックしても何も動作しない。何が違うんだろうと見比べた時に「rendermode InteractiveServer」の記載がないことに気が付きました。これをHome側に追加すると、Counterボタンのクリック処理が動作しました。

```
@rendermode InteractiveServer
```

https://learn.microsoft.com/ja-jp/aspnet/core/blazor/components/render-modes?view=aspnetcore-8.0

上記サイトを読み、「アプリ全体にレンダリング モードを適用する」の記載を見つけて、`App.razor`ファイルに追加しました。

```html:App.razor
<Routes @rendermode="InteractiveServer" />
```

現在作成中のアプリケーションでは、MainLayout コンポーネント側(親子関係)にデータを反映させるのにカスケーディングを使用してパラメーターを渡す方法を採用していました。

https://qiita.com/yaju/items/dd7ec9deea615443f42a

アプリ全体にレンダリング モードを適用することで、ようやく.NET 8でも動作させることが出来ました。
一時は、「CascadingValue Value="this"」が使えないので、「AddCascadingValue メソッド」に修正しなければならないかと危惧していました。

https://zenn.dev/microsoft/articles/dotnet8-blazor-01

# 最後に
Target frameworkを「.NET 8」に変更するだけと気軽に考えていただけに、かなりキツかったです。

Blazorは発展途上のところもあるわけですが、.NET 7から.NET 8の変更が大きな転換点で、ここから先はそんな変わらないと思いたいです。
sidekiqに触れてみた

# はじめに
業務の中で非同期処理を行いたいタスクがあり、システムにsidekiqを新しく導入することで実装しました。
改めて復習も兼ねて記事を書くことにしました。

# 実装

### sidekiq用のサーバーを構築
```docker-compose.yml
sidekiq:
    uild:
      context: .
      dockerfile: Dockerfile
    volumes:
      - .:/app
    env_file:
      - .env
    ports:
      - 3000:3000
    command: bundle exec sidekiq -C config/sidekiq.yml
```

### GemFileにsidekiq追加し、bundle install実行
```ruby:GemFile
gem 'sidekiq'
```

### sidekiqの各種設定
1\. アダプターをSidekiqにする
ActiveJobをsidekiqと連携させる。
```config/application.rb
config.active_job.queue_adapter = :sidekiq
```

2\. sidekiqの設定ファイルを追加する
```config/sidekiq.yml
:queues:
  - test_job
  - default
```
キューの実行に優先順位をつけることも可能。（数字の大きい順に優先的に処理されるようになる。）
```config/sidekiq.yml
:queues:
  - ['test_job', 2]
  - ['default', 1]
```
**設定できる項目一覧**
- `max_retries` リトライ回数を指定(デフォルト25回)
  - `retry: 0` リトライしない。ジョブがデッド状態になり、sidekiqのダッシュボード画面から再試行が可能。
  - `retry: false` リトライしない。画面から再試行ができなくなる。（メール送信処理など複数回行われてはいけない処理に対して設定すると良い）
- `verbose` trueにするとより詳細なログ情報を提供される(デフォルト`false`)
- `pidfile` プロセスID（PID）を格納するファイルのパスを指定する
- `logfile` Sidekiqのログファイルを格納するパスを指定する
- `concurrency` 同時に処理されるジョブの数（1つのsidekiqプロセスで使用するスレッド数）を設定する(デフォルト25)
- `queues` sidekiqが処理を行うキュー名を指定。ここで指定されたキュー以外のジョブは処理されない。
- `timeout` ジョブのタイムアウト時間（秒）。数字で指定。

3\. sidekiqから接続するRedisのURLを設定
環境変数`REDIS_URL`は`.env`などで定義する。
```config/initializes/sidekiq.rb
Sidekiq.configure_server do |config|
	config.redis = { url: ENV["REDIS_URL"] }
end

Sidekiq.configure_client do |config|
	config.redis = { url: ENV["REDIS_URL"] }
end
```

4\. 非同期処理を行うメソッドを定義する
```app/job/sample_job.rb
class SamplemJob < ApplicationJob
  queue_as :sb_auto_exam
  sidekiq_options retry: 2, backtrace: 20

  sidekiq_retry_in do |count|
    10
  end

  def perform
    p 'test'
  end
end
```
`queue_as`　ジョブのキュー名を指定。sidekiq_optionsの方でも設定できるが、こちらで設定するケースが多い印象
`sidekiq_retry_in`　ジョブがリトライされるまでの待機時間を指定。デフォルトだと`(4 ** n(リトライ回数)) + (rand(30) * (n + 1))`

sidekiq_optionsでジョブごとに個別にsidekiqの設定ができる。
**設定できる項目一覧**
- `retry` リトライ回数を指定する
- `queue` ジョブのキュー名を指定する
- `backtrace` falseにするとエラーが発生した場合にバックトレースを保存しない。数字を指定するとバックトレースの行数を指定

4\. メソッドを実行する
```ruby.rb
# 非同期で実行する
SamplemJob.perform_later

# 同期で実行する
SamplemJob.perform_now

# 3分待ってから実行される
SamplemJob.perform_in(3.minutes)

# 2025年1月1日の午前0時0分0秒にジョブを実行する
SamplemJob.perform_at(DateTime.new(2025, 1, 1, 0, 0, 0))
```
5\. sidekiqのダッシュボードを表示するようにする
```config/routes.rb
require 'sidekiq/web'
mount Sidekiq::Web, at: "/sidekiq"
```
上記の例なら`/sidekiq`でアクセスできます。

# 補足
sidekiqで非同期でジョブを実行する場合、ジョブのキュー名(`queue_as`もしくは`sidekiq_options`で設定)とsidekiqが処理するキュー名(`config/sidekiq.yml`で設定)を同じにする必要があります。
異なっていた場合、sidekiqが処理を行わず、ジョブがどんどん貯まるだけになってしまうので要注意



# 参考
https://zenn.dev/overflow_offers/articles/20230130-how-to-use-sidekiq
https://www.cyberowl.co.jp/blog/technology/3589
https://serip39.hatenablog.com/entry/2020/12/28/235800
https://qiita.com/ryohashimoto/items/69dac29a63f682143df7
https://zenn.dev/ivry/articles/637f6f0f0c7db7
カメラに映る範囲・影になる部分を区別するシェーダー

カメラマップテクスチャを使っている場合等の映像表現で
カメラ位置から写るものと影になる部分とを分けたいことがあるので。
有償公開している[自作カメラマップアドオン](https://qiita.com/yukimituki11/items/8d709bbaf2966bf7c38c)を利用しているので　ほぼ覚え書きです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/d997fc19-ac2d-69fe-b2c6-043464ec368f.png)
カメラマップアドオンではカメラ座標でのZ値をUV出力のZに出力しています
一番左のノードグループがアドオンで自動作成したもので　別途先にレンダリングしたデプスマップをカメラマップ投影しています。
この２つの値を比較することで　デプスマップに記録された値より遠い部分
つまり　他のメッシュの影になる部分を区別することができます。シャドウマップの手法ですね

Zから分離した値に-1をかけているのは　Blenderのカメラの初期値が下向きなのでカメラ基準の座標は-なため
小さい値を減算しているのは　このままでは手間メッシュ上は同値なのでオフセットです


先に用意するデプスマップは
ビューレイヤプロパティのZのパスをオンにしてレンダリングすることで作成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/1f2416c4-4dfd-42c4-67bb-e2ab0f79a44f.png)
ノード補助のアドオン「Node Wrangler」を利用している環境なら
ビューアーのノードにのサイドバーに「Save This Image」のボタンが追加されていて　ビューアーで利用している画像を簡単に保存できます。
画像データは必ずOpenEXRで保存します。

先にも言ったように　保存したZパスの画像を　カメラマップのアドオンで投影するシェーダーを使ってノードを組むことで
影の部分を区別して別色を付けたりできます。
ubuntuPCでマイコンに書き込めない！？ってなったときの備忘録

## Arduino uno R4 minimaに書き込めない
新しくミニPCを買ったのでubuntu22.04を入れてROSとかで遊ぼうと思ってたらマイコンに書き込みできない！？ってなって困ってたのでそれの対処法をメモっときます

## 環境

* ミニPC AMD Ryzen 7 5700U、16GB DDR4 512GB M.2 NVMe SSD
* Ubuntu 22.04.3 LTS 
* vscode 1.85.1
* platformio Core 6.1.13·Home 3.4.4
* ArduinoIDE 2.2.1

## 状況
platformioを使ってArduino uno R4 minimaにLちかプログラムを書き込もうとした時ビルドは問題なかったが書き込めなかった.そこでArduinoIDEを使用するものの状況は変わらず

実際に表示されたエラー文のいちぶ↓

```bash
dfu-util: Cannot open DFU device 2341:0369 found on devnum 12 (LIBUSB_ERROR_ACCESS)
dfu-util: No DFU capable USB device available
*** [upload] Error 74
=========================================================================================== [FAILED] Took 0.52 seconds ===========================================================================================
```
## 解決
どうやらDevice Firmware Upgradモードにアクセスできないエラーが続いていますと…
実際に書き込めている別のubuntuPCと見比べてみると`etc/udev/rules.d/50-arduino-uno.rules`ってのがなかった.
そこで[これ](https://github.com/arduino/ArduinoCore-renesas/blob/main/post_install.sh)をダウンロードしてきてディレクトリを移動して

```
cd ~/Downloads
```
post_install.sh に実行権限を与えて
```
chmod +x post_install.sh
```
スクリプトを実行
```
sudo ./post_install.sh
```
udevのルールを再読み込み
```
sudo udevadm control --reload-rules
```
これで治りました

Arduino の　Back to Arduino Support　の　[Fix udev rules on Linux](https://support.arduino.cc/hc/en-us/articles/9005041052444-Fix-udev-rules-on-Linux)で対処方法が。
もっと早く見つけたかった
コミット履歴をまとめる方法

# 概要
何度もコミットしてプッシュするとリモートブランチに履歴が残ります。残す必要のあるコミットであれば問題ないですが、簡単な修正であれば1つ前のコミットにまとめた方がコードレヴューの際、レビュワーは見やすくなると考えています。また、コミットをまとめる事で、後から履歴を追う際、コミットメッセージから何をやっているか一目で分かり易くなると思います。今回は、チーム開発に於いて、便利な`git`操作を学んだのでその方法を共有します。


# 注意事項
:::note warn
- 同一のブランチで2回以上のコミットを行った場合に使用する
- `reset`を行い過ぎると、他の人の改修内容が含まれてしまうので注意が必要
- 共通で使っているブランチ(`develop`、`master`、`main`等)では、絶対に使用しない
:::

# 実施方法
- `git log`にてコミットの状況を確認する
```sh
# コマンド
git log

#　出力内容
commit **********************************a82a81 (HEAD -> feature/git_amend_test_branch, origin/feature/git_amend_test_branch)
Author: kengo-sk8 <****************@******.***>

Date:   Wed Jan 1 00:00:00 3000 +0900

    feat: 文字を追加

commit **********************************01441a
Author: kengo-sk8 <****************@******.***>
Date:   Wed Jan 1 00:00:00 3000 +0900

    feat: git amendのテストコミット1

# 以下省略

```
※　`git log`は `q` を入力する事で抜け出せる

`git hub`上で見ると下記の様になる
![コミット履歴.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/664659/5192e159-acba-29ad-0655-32c3fc63b68f.png)


- `feat: git amendのテストコミット1`のコミットに`feat: 文字を追加`のコミットをまとめたい為、下記のコマンドを使い1つ前のコミットの状態に戻す
```sh
git reset HEAD~
# ~ の後に数値を入れると2つ前、３つ前にコミットを戻せる
```

- コミットするファイルを下記のコマンド等を使用してステージングエリアに追加する
(`vscode`や`Sourcetree`等の`GUI`で`git`の操作ができるツールで行っても良い)
```sh
# 全てのファイルを追加する
git add -A

# 指定ディレクトリ配下の変更や、新規作成した全てのファイルを追加する
git add .

# 新規を対象にせずに、更新のあった全てのファイルのみを対象にする
git add -u
```


- 現在のステージングエリアの変更を含むコミットを作成する。その際、最新のコミット（HEAD）のメッセージを再利用する為、下記のコマンドを使用する
```sh
git commit -C HEAD --amend
```

- ローカルとリモートのブランチ間で差分がある為、以下のコマンドを使用を使用して、ローカルのブランチを強制的にリモートにプッシュする
```sh
git push -f origin ブランチ名
```

- git logで確認するとコミットがまとめられている
```sh
# コマンド
git log

# 出力結果
commit **********************************9574c4 (HEAD -> feature/git_amend_test_branch, origin/feature/git_amend_test_branch)
Author: kengo-sk8 <****************@******.***>
Date:   Wed Jan 1 00:00:00 3000 +0900

    feat: git amendのテストコミット1

```


# 余談
- `git`でリモートリポジトリから最新の変更を強制的に取得（`pull`）するには、以下のコマンドで行う
```shell
git fetch origin
git reset --hard origin/<branch_name>
```

# 参考資料
- [履歴の書き換え](https://www.atlassian.com/ja/git/tutorials/rewriting-history )

# まとめ
レビューワーの視点で考えると、コミットをまとめて置くことは、とても重要だと実感しました。今後は、この操作を多用して、`git`の`log`を綺麗に保てるようにしていきたいと思います。
NextcloudをDockerで構築(PostgreSQL)

## やりたいこと

docker composeでPostgreSQLを利用してNextcloudサーバーを立ち上げます。
docker composeが使える前提です。

## Nextcloudとは

> オンラインストレージの作成と使用のためのクライアント・サーバ型のソフトウェアである。機能的にはDropboxに似ているが、オフプレミスのオンラインストレージサービスは提供しない。Nextcloudはフリーかつオープンソースなので、誰でも自分のプライベートサーバにインストールして利用することができる。
[wikipedia](https://ja.wikipedia.org/wiki/Nextcloud)

## PostgreSQL

>拡張性とSQL準拠を強調するフリーでオープンソースの関係データベース管理システム（RDBMS）である。Postgresとしても知られている。
[wikipedia](https://ja.wikipedia.org/wiki/PostgreSQL)

## 手順

1. 作業用フォルダの作成
1. データを保存するディレクトリを作成
1. `docker-compose.yaml`を作成
1. `docker compose up -d`でサーバーを立ち上げる

## 前準備

作業用フォルダの作成とデータを保存するディレクトリを作成します。

:::note info
今回のdocker image は[Nextcloud manual docker image(docker hub)](https://hub.docker.com/_/nextcloud)を利用しました。今回指定していない環境変数が様々あるので、必要に応じて確認してください。
:::

```bash
mkdir nextcloud
cd nextcloud
mkdir {nextcloud_data,postgres_data}
```

`docker-compose.yaml`を以下の内容で作成します。今回はデータを永続化するために、ローカルにディレクトリを作成してマウントしています。

```yaml:nextcloud/docker-compose.yaml
version: '2'
 
services:
  postgres:
    image: postgres
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: nextcloud #postgresqlのdb名
      POSTGRES_USER: nextcloud #postgresqlのuser名
      POSTGRES_PASSWORD: P@55w0rd #postgresqlのpassword
  nextcloud:
    image: nextcloud
    environment:
      - POSTGRES_DB=nextcloud #上で設定したpostgresqlのdb名
      - POSTGRES_USER=nextcloud　#上で設定したpostgresqlのuser名
      - POSTGRES_PASSWORD=P@55w0rd #上で設定したpostgresqlのpassword
      - POSTGRES_HOST=postgres #PosetgreSQLを使う設定を行う
      - NEXTCLOUD_TRUSTED_DOMAINS=192.168.1.100 #サーバーのドメインを指定する。
    ports:
      - 8080:80
    volumes:
      - ./nextcloud_data:/var/www/html
    depends_on:
      - postgres
```

## 実行

先ほど作成した`nextcloud`ディレクトリで実行してください。

```bash:nextcloud
docker compose up -d
```

## ログの確認をしたい場合

```bash:nextcloud
docker compose logs nextcloud -f
```
## 接続

`http://192.168.1.100:8080`にアクセスすると確認できます。

![スクリーンショット 2024-01-14 1.12.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308715/c9f92814-51d0-d0da-441a-da73d186d4b2.png)

### 注意

ドメインを指定していないと、以下のようなエラーが出てくるので`NEXTCLOUD_TRUSTED_DOMAINS`環境変数を設定する必要がある。
![スクリーンショット 2024-01-13 19.42.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308715/7db04ee7-15d9-58fa-3053-2630537714a2.png)
webdriver.Chrome()のエラー

いまにゅさんの動画()
[いまにゅさんのスクレイピング講義動画](https://youtu.be/VRFfAeW30qE?si=u-zYHVgSXiPrbkNJ "【Webスクレイピング超入門")を見ながら、初めてスクレイピングをハンズオンで進めたところ、エラーが起きてしまいました。

初心者用の動画なので、他の方が躓いたときの参考になれば幸いです。



実行したのは下記コードです。
```
!pip install webdriver_manager
from selenium import webdriver
browser = webdriver.Chrome(ChromeDriverManager().install())
```

エラーコードは下記です。

```
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File c:\Users\037ta\jupyter_lab\venv\Lib\site-packages\selenium\webdriver\common\driver_finder.py:38, in DriverFinder.get_path(service, options)
     37 try:
---> 38     path = SeleniumManager().driver_location(options) if path is None else path
     39 except Exception as err:

File c:\Users\037ta\jupyter_lab\venv\Lib\site-packages\selenium\webdriver\common\selenium_manager.py:84, in SeleniumManager.driver_location(self, options)
     77 """Determines the path of the correct driver.
     78 
     79 :Args:
     80  - browser: which browser to get the driver path for.
     81 :Returns: The driver path to use
     82 """
---> 84 browser = options.capabilities["browserName"]
     86 args = [str(self.get_binary()), "--browser", browser]

AttributeError: 'str' object has no attribute 'capabilities'

During handling of the above exception, another exception occurred:

AttributeError                            Traceback (most recent call last)
Cell In[20], line 1
----> 1 browser = webdriver.Chrome(ChromeDriverManager().install())
...
---> 40     msg = f"Unable to obtain driver for {options.capabilities['browserName']} using Selenium Manager."
     41     raise NoSuchDriverException(msg) from err
     43 if path is None or not Path(path).is_file():

AttributeError: 'str' object has no attribute 'capabilities'
Output is truncated. View as a scrollable element or open in a text editor. Adjust cell output settings...
```


AttributeError: 'str' object has no attribute 'capabilities'　

この部分が、Selenium WebDriverの初期化における問題を示しているらしく、他にもOptionについてのエラーも書かれています。

下記のように、修正すると無事実行でき、ブラウザが立ち上がりました。

```
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager

options = webdriver.ChromeOptions()
# options.add_argument('--headless')  #ヘッドレスモードを使用する場合は有効にします
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')

# browser = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
browser = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=options)
```
DockerでMySQLサーバを秒で建てる

# はじめに
この記事ではDocker Desktop for Windowsを使用しています


# 1. イメージをダウンロードする
Docker Enginを起動して、ターミナルで以下のコマンドを実行します
```
docker pull mysql:8.2.0
```
（他のタグを使用したい場合は[DockerHub](https://hub.docker.com/_/mysql/tags)から探してください）


# 2. コンテナを起動する
イメージのダウンロードが終わると、Docker Desktopの`Images`タブに`mysql`というイメージが追加されています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/a8514dc5-a9b3-04eb-79df-a19710c4fbba.png)

追加されたイメージの`run`ボタン（ ▶ このマーク）をクリックして、「Optional Settings」をクリックしてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/1fd497d6-ddcb-a400-a393-841f2d1020c2.png)

各項目は以下のように入力してください
- `Container name`：任意のコンテナの名前を入力してください
- `Host port`：コンテナ側のポート番号を指定します、今回は`8080`で行きます（`0`と入力すると自動でポート番号を割り当ててくれます）
- `Environment variables`：ルートユーザのパスワードを環境変数で指定する必要があります。
    - `Variable`：`MYSQL_ROOT_PASSWORD`と入力してください
    - `Value`：任意のパスワードを入力してください

↓今回はこれでいきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/f607949a-b25d-3ad6-19bb-05eac024a62e.png)


入力が完了したら「Run」をクリックして、コンテナを起動しましょう！


# 3. MySQLが起動しているか確認
`Container`タブに移動すると先ほど作成したコンテナが確認できます
コンテナ名をクリックして中を覗いてみます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/f81b5254-1d71-60f7-73fe-bc918f78ce25.png)

`MySQL init process done. Ready for start up.`と出力されているのでうまくいっているようです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/44d6af39-d4ea-3254-6c08-d6e40dac0858.png)


ターミナルからMySQLにログインしてみましょう、以下を実行してください（mysqlコマンドない人はインストールしてね）
実行後にパスワードの入力が求められます
```
mysql -u root -h 127.0.0.1 --port=8080 -p
```
オプションの補足：
- `-u`：MySQLのユーザー名
- `-p`：パスワードの入力が求めらるようにする
- `-h` ：接続先のIPアドレスかホスト名
- `--port`：ポート番号

無事ログインできました！！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/952033/bca467ad-1062-d1bc-015e-1829c6b69175.png)

`exit`と入力すればログアウトできます。

これでいつでもMySQLが使えますね
Diffusers: 拡散モデルで画像生成

この記事では，Diffusersについて紹介します．

# 参考文献

この記事は以下の情報を参考にして執筆しました．

https://github.com/huggingface/notebooks/blob/main/diffusers/diffusers_intro.ipynb

# Diffusersとは？

Diffusersは，Hugging Faceが開発した[拡散モデル](https://arxiv.org/abs/2006.11239)のためのライブラリです．

https://github.com/huggingface/diffusers

Diffusersを使うと，拡散モデルで画像を生成することができます．

# 拡散モデルでの画像生成

拡散モデルとは，ランダムなガウスノイズを段階的に除去するように訓練された機械学習システムです．

拡散モデルの訓練では，各ステップにおいてノイズを除去する方法を予測するように訓練されます．推論では，あるステップ数の後、画像サンプルが得られます（下図参照）．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149146/ce0ff6b4-daec-396b-5648-94a8fa874f2b.png)

出典：[diffusers_intro.ipynb](https://github.com/huggingface/notebooks/blob/main/diffusers/diffusers_intro.ipynb)




# Diffusersを使った画像生成

以下のコードは，Google Colab（GPU: T4）で実行しました．

## Diffusersのインストール

```sh
!pip install diffusers==0.11.1
```

## DDPMPipeline

`DDPMPipeline`をインポートすることで，数行のコードで推論を行うことができます．

```python
from diffusers import DDPMPipeline
```

`from_pretrained()`は，コミュニティによって共有された60,000以上のモデルのリポジトリである[the Hugging Face Hub](https://huggingface.co/)からモデルとコンフィギュレーションをダウンロードすることができます．

下記のコードでは，GoogleとU.C.Berkeleyが共同で構築した`google/ddpm-celebahq-256`モデルをダウンロードしています．これは，[Denoising Diffusion Probabilistic Models (DDPM)](https://arxiv.org/abs/2006.11239) に従ったモデルで，有名人の画像のデータセットで学習されています．

```python
image_pipe = DDPMPipeline.from_pretrained("google/ddpm-celebahq-256")
image_pipe.to("cuda")
```

`DDPMPipeline`はランダムな初期ノイズサンプルを生成し，拡散処理を繰り返すことによって画像を生成します．

```python
images = image_pipe().images
```

生成された画像を表示させてみます．

```python
images[0]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149146/b274587a-ddec-0269-a60e-f1e8db5e038d.png)

# まとめ

この記事では，Diffusersについて紹介しました．
特に，Diffusersを使った拡散モデルでの画像生成についての簡単な使い方を紹介しました．
Diffusersの色々な使い方については，以下を参照してください．

https://github.com/huggingface/notebooks/tree/main/diffusers
[Python]スクレイピングして、必要な情報を加工してからcsv出力

# はじめに
ある公式リリースノートから
* 情報取得
* 抽出・加工
* 一覧形式でcsv出力
 
したかったので、Pythonで作成しました。[ETL](https://e-words.jp/w/ETL.html)のようなイメージです。
URLを載せると万が一アクセス集中した場合に迷惑がかかるので、対象は伏せます。



:::note alert
スクレイピングする際は、アクセス数に注意

私もまずは[ブラウザで閲覧してHTMLをダウンロード](https://func.jp/microsoft-edge-show-source/)してから、ローカル内で試行錯誤しています
:::



# 成果物
```python:EtlReleasenote.py
import requests
import csv
from bs4 import BeautifulSoup

# please change this setting
VERSION_LIST=["xxx","yyy","zzz"]


HEADER = ['version','Type','description']
# Webページを取得して解析する
for VERSION in VERSION_LIST:
    load_url = f"https://${URL}/xxx/{VERSION}.html"
    html = requests.get(load_url)
    soup = BeautifulSoup(html.content, "html.parser")

    with open('ReleaseNoteLists.csv', 'a', encoding='utf-8') as f:
        writer = csv.writer(f, lineterminator="\n")
        writer.writerow(HEADER)
        for elements in soup.find_all(class_="${className}"):
            for element in elements.find_all("li",recursive="False"):
                h3 = elements.find('h3')
                row = [VERSION,h3.text,element.text]
                writer.writerow(row)
```

# 解説・ポイント

### HTMLの欲しい要素のみ抽出
`find`,`find_all`を利用して、欲しいHTMLの要素を抽出している
```python
        for elements in soup.find_all(class_="${className}"):
            for element in elements.find_all("li",recursive="False"):
                h3 = elements.find('h3')
```


(漫画でスクレイピング分かりやすい)

https://codezine.jp/article/detail/12230


### 文字列中に変数を代入（`f-strings`）

`f-strings`を利用すると、以下のように変数に代入する文字列に変数を利用できる。
```python
    load_url = f"https://${URL}/xxx/{VERSION}.html"
```

https://self-development.info/%E3%80%90python%E3%80%91%E6%96%87%E5%AD%97%E5%88%97%E4%B8%AD%E3%81%AE%E5%A4%89%E6%95%B0%E3%81%AB%E5%80%A4%E3%82%92%E4%BB%A3%E5%85%A5%E3%81%99%E3%82%8B%EF%BC%88f-strings%EF%BC%89/


### csv出力
Header付csv出力は以下あたりで実装している
```python
import csv
HEADER = ['version','Type','description']
    with open('ReleaseNoteLists.csv', 'a', encoding='utf-8') as f:
        writer = csv.writer(f, lineterminator="\n")
        writer.writerow(HEADER)
                writer.writerow(row)        
```

https://tech-diary.net/python-scraping-to-csv/


### csv出力結果の空行詰める
csvの出力結果に空行が入ってしまったので、以下のように記述
```python
        writer = csv.writer(f, lineterminator="\n")
```

https://qiita.com/ikura1/items/17e6dd19f98145afc2eb

# 参考記事

2重ループうまくいかなかった時に助かりました

https://user-first.ikyu.co.jp/entry/2017/12/03/125002


# おわりに
最後まで見てくれてありがとうございます。
よかったらチャンネル登録（フォロー）と高評価（いいね:heart_decoration:）お願いします:pray:
週一で投稿目指してます。もしフォローかいいね:heart_decoration:をしてくれたら、やる気出るので、次週は投稿することを約束します。
【React】iOS Safariでリロード時に処理を実行する方法

iOS Safariで`beforeunload`を使用してもリロード時に処理を実行することはできません。
以下のように記述することでiOS Safariでリロード時に処理を実行することができます。

```react
import { useEffect } from React

export function Sample() {
  const handlePagehide = () => {
    // 画面更新時の処理
  }

  useEffect(() => {
    window.addEventListener('pagehide', handlePagehide)

    return () => {
      window.removeEventListener('pagehide', handlePagehide)
    }
  }, [handlePagehide]) 

  return (
    // ...
  )
}
```
NFTチケットの新しいプロジェクトにjoiningしませんか！

## 紹介プレゼン動画　
https://youtu.be/NRK-TDBs9aw

### 簡単な自己紹介
現在21歳です。
ドロップアウト(家出、工業高専、スケートボード)を繰り返した私が孤独になった先にはインターネットの世界でした。
この１年間エンジニアもどきとして生活していくなかでweb3に出会い自分の考えていることをまさに体現できると考え感動して泣きました。
動画を見ていただき私を受け入れてくれるのなら友達になってくれませんか、という冗談(本気）さておき一緒にデプロイのためにCrewとして活動しませんか？

https://matrix.to/#/#livesessioncrew:matrix.org
Ubuntuのファイアウォールの必要性について

Ubuntuにファイアウォールが本当に必要なのかという話について、ちょっと考えてみる。

### Ubuntuはデフォルトでファイアウォール(ufw)が無効

これは、デフォルトだとオープンしてるポートが無いからという事らしい。

### 典型的なネットワーク構成

あくまで一般的な家庭やそれに準じた構成のネットワークの場合、各機器PCやスマホはブロードバンドルータの配下にいると思う。

### ファイアウォールについて

上記のようなネットワーク構成の場合、ルータにファイアウォールがあるので基本的にインターネット側からの全ての内向き通信はブロック状態である。
外からアクセスしたければ、例えばssh用ポートを開けて、Ubuntuへポートマッピングしたりすると思う。つまり、Ubuntu側はssh用のポートを開けて、そのポートはufwファイアウォールの対象外にする必要がある。
TCPなのでufwでUDPを開ける必要はない、UDPで同じポート番号で待ち受けるソフトはいない。もしくはそれも気になるなら、ルータ側でTCPだけ開ければ良い。

そう考えると`ポート開ける=そのポートはインターネット側を含め内向きの通信を許可する`の状況であれば、　ファイアウォールは必ずしも必要ではないと思う。
仮に、Ubuntuをルータを通さず直接インターネットに接続している場合でも、結局外からアクセス可能なポートは同様。
ローカルのみsshを許可したいのであれば、ルータのポート開けをしなければ良いだけ。

ただ、色々やってるうちに色んなポート開けてしまうような可能性がある場合は、ufwをオンにした方が良いかも。
(※ 厳密には、OS側にバグがあり開いていないはずのポートに特定の通信をかけたらアクセス出来てしまうなんて脆弱性があって、ufwには脆弱性が無い場合は、ufw有効にしておいたら助かるかもしれないけど、開いていないポートは応答しないのは初歩的な話なので、可能性としてはゼロに近いと思います。)

### 結論

というわけで、`一般的なネットワーク構成で、Ubuntuインストール後に開くポートをちゃんと管理出来ているのであればufwは無効で良い`という結論にしたいと思います。
Paiza様の問題集の課題をPython3解いてみました

>***自然数 H, W, A, B が与えられます。縦に H 行、横に W 行で計 H * W 個の (A, B) という形式で文字列を出力してください。ただし、横は | (半角スペース 2 つとバーティカルライン) 区切りで、縦は = で区切って出力してください。また、縦の文字列間で = を出力する際は、その上の行と文字数がそろうように出力します。また、A と B は 9 けたになるように半角スペースを数値の前(右詰め)に埋めて出力してください。***

というpaiza様の問題集をPython3で実装しました。
実装したコードは下記です。

```Python3
values = input().split()
H = int(values[0])
W = int(values[1])
A = int(values[2])
B = int(values[3])

for i in range(H):
    for j in range(W):
        print(f"({A:>9}, {B:>9})", end="")
        if j == W - 1:
            print()
        else:
            print(end=" | ")

    if i < H - 1:
        print("=" * (22 * W + 3 * (W - 1)))
```
Apache Digest認証の認証画面が表示されない

# はじめに
Apache Digest認証を設定したところ、Apache Digest認証の認証画面が表示されない事象が起きたため、原因と対策を本記事に記載しました。

https://qiita.com/gama1234/items/bfda469f525811a3aa79

認証画面が出ない
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/768043fe-6643-4776-ffbd-524030512af1.png)

# 原因
Require all granted: このディレクティブは、全てのユーザーにアクセス権を与えるため、ダイジェスト認証の前にすべてのアクセスが許可されてしまいます。この行をコメントアウトすることでApache Digest認証の認証画面が表示されるようになりました。
```
vi /etc/httpd/conf/httpd.conf
       
    130 # Further relax access to the default document root:
    131 <Directory "/var/www/html">
    132    AuthType Digest
    133    AuthName "DigestAuth"
    134    AuthUserFile "/etc/httpd/conf/.digestpass"
    135    Require valid-user
    136     #
    137     # Possible values for the Options directive are "None", "All",
    138     # or any combination of:
    139     #   Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI MultiViews
    140     #
    141     # Note that "MultiViews" must be named *explicitly* --- "Options All"
    142     # doesn't give it to you.
    143     #
    144     # The Options directive is both complicated and important.  Please see
    145     # http://httpd.apache.org/docs/2.4/mod/core.html#options
    146     # for more information.
    147     #
    148     Options Indexes FollowSymLinks
    149
    150     #
    151     # AllowOverride controls what directives may be placed in .htaccess files.
    152     # It can be "All", "None", or any combination of the keywords:
    153     #   Options FileInfo AuthConfig Limit
    154     #
    155     AllowOverride All
    156
    157     #
    158     # Controls who can get stuff from this server.
    159     #
    160    # Require all granted ←この行の先頭にコメントアウト(#)を入れました。
    161 </Directory>
```
apacheサービスを再起動する。
```
systemctl restart httpd
```
ブラウザでhttp://apacheサーバーのIPアドレスを入力する。
認証画面が出ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2599002/8f2b970c-f01d-c3ba-3748-69dea426e525.png)
AWS Auto Scaling

## はじめに
この記事はAWS SAA試験勉強のための、AWS Auto Scalingに関する知識のまとめです。

## AWS Auto Scalingとは
AWS Auto Scalingとは複数の AWS リソースを簡単かつ安全にスケーリングして、インフラストラクチャのコストを削減しながら、アプリケーションのパフォーマンスを最適化することができるサービスです。

## AWS Auto Scalingの基本的性質
- スケーリングがうまく実行されずに24時間以上たった場合は、自動的にAuto Scaling処理が停止するようになっています。

- ELBのヘルスチェック機能では、ヘルスチェックの間隔を定義できます。他の値を変えずにこの値を小さくすると、Auto Scalingで新たに作られたインスタンスがELBに紐づくまでの時間が短くなります。

- Auto Scalingでは、トリガーとなる条件を満たしたときにインスタンスを何台増やすか(減らすか)を定義できます。

- メモリ利用率をトリガーとした設定はデフォルトでは設定できません。

- Auto Scalingグループを設定する際には起動設定または起動テンプレートを利用しますが、起動設定の利用は現在推奨されておらず、**起動テンプレート**を利用する必要があります。


:::note info
複数のAZにまたがるEC2インスタンスのAuto Scalingを実行することで、地理的に離れた冗長化を実行できます。
:::

:::note info
リバースプロキシサーバとWebサーバにAuto Scalingを追加することで、負荷の状況に応じてスケールイン/スケールアウトを自動で実行できます。
:::

Autoscalingはリソースの数を自動的に変更して、負荷の変動に対応することに焦点を当てています。一方でELBは、複数のリソースへのトラフィック分散を担当し、それによって負荷を均等に分散する役割を果たしています。

## スケジューリングに基づいたスケールアウト
負荷上昇が短期間のためスケーリングが間に合っていない時、スケーリングするべき時間帯や期間が判明している場合には、Auto Scalingにはスケジューリングに基づいたスケールアウトを設定する必要があります。

## ターゲットトラッキングポリシー
ターゲットトラッキングポリシーを使用することで、ターゲット追跡を使用してインスタンス数を比例的にスケールアウトしたり、インスタンス数を増やすことができます。

## Service Auto Scaling
Service Auto Scalingは、Amazon Web Services (AWS) の一部で、特定のAWSサービス（特にAmazon ECS、AWS App Runner、Amazon DynamoDBなど）に対して、リソースの自動スケーリングを行う機能です。この機能により、ワークロードの需要に応じてリソースを動的に増減させることができ、効率的かつコスト効果の高いリソース管理が可能になります。


## Amazon EC2 Auto Scaling と AWS Auto Scaling

複数のサービスにまたがる複数のリソースのスケーリングを管理する場合は、AWS Auto Scaling を使用します。
スケーリング対象が Amazon EC2 Auto Scaling グループのみの場合や、目的が EC2 フリートの正常性の維持のみの場合は、EC2 Auto Scaling を使用します。

![新規 テキスト ドキュメント.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/359600/53f495dd-46c2-f9f7-19f7-a84597514bad.png)

## Auto ScalingのEC2のヘルスチェック

- EC2インスタンスのハードウェアとネットワークの状態を確認します。HTTPエラーは検出できません
- EC2のヘルスチェックは強制的に有効になっています
## Aurora Auto Scaling

AuroraレプリカでAurora Auto Scalingを使用することで、リードレプリカの数を動的に調整し、急激なワークロードの増加にも対応できます。

## ターミネーションポリシー


#### NewestInstance
新しく設置されたインスタンスから削除されるポリシー設定です。


## クールダウン期間

- Auto Scalingのクールダウン期間はデフォルトで300秒で、 Auto Scaling グループが追加のインスタンスを起動または削除することが一定期間できなくなります。
Javaのインタフェースについて

## 特徴
・インスタンス化はできず、利用する場合は実現クラスを作成する。
・実現クラスを定義するときは「implements」を利用する。
・実現クラスではインタフェース内の抽象メソッドをオーバーライドして利用する。
・サブインタフェースを作成する場合は「extends」を利用する。

## 変数
暗黙的に「public static final」修飾子が付与される。
変数宣言時に初期化しておく必要がある。
```Java
interface InterfaceA {
int a = 1;
int b; // 初期化していないためコンパイルエラー
private int c = 2; //privateのためコンパイルエラー
}
```

## 抽象メソッド
・暗黙的に「public abstract」修飾子が付与される。
・実現クラスでオーバーライドする必要がある。
・実現クラスでオーバーライドする前提のため「final」修飾子は付与できない。
```Java
interface InterfaceB {
public int testA();
abstract int testB();
private int testC(); //privateのためコンパイルエラー
public static testD(); //staticのためコンパイルエラー
public final testE(); //finalのためコンパイルエラー
}
```
## 具象メソッド
・具象メソッドで付与できる修飾子は「private static」「public static」「public default」「private」である。
・Objectクラスの「toString()」「hashCode()」「equals(Object)」はdefaultメソッドとして定義できない。
・defaultメソッドは暗黙的に「public」修飾子が付与される。
```Java
interface InterfaceC {
private static int methodA(){return 1;};
public static int methodB(){return 2;};
public default int methodC(){return 3;};
private int methodD(){return 4;};
//public int methodE(){return 5;}; //publuc defaultでないためコンパイルエラー
//private default methodF(){return 6;}; //publuc defaultもしくはprivateのみでないためコンパイルエラー
}
```
Macのフォルダ内のファイル名を一括で置換する簡易GUIツールつくりました！Python

### 0.完成例!
![gamen_test1 23.14.12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/e0de2f1f-e117-bba3-8a93-a86badd1d0bf.gif)

### 1.使用するライブラリ
##### -1.pandas
```
pip install pandas
```
### 2.デスクトップなどにTrimName.py等の名前をつけて下記コードをコピペ
```py
import os
import pandas as pd
import re
import tkinter as tk
from tkinter import filedialog

# 置換を実行するフォルダのパスを指定
folder_path = "/Users/nishikawashuuhei/Desktop"  # フォルダのパスを指定してください

# ファイル名を置換する関数
def replace_filename(filename, rules):
    for before, after in rules:
        # もし置換後が空の場合、Nanを""に変換
        if pd.isna(after):
            after = ""
        filename = re.sub(before, after, filename)
    return filename

# ファイルの置換とリネームを行う関数
def process_files(df, folder_path):
    rules = df.values.tolist()

    for root, _, files in os.walk(folder_path):
        for file in files:
            old_file_path = os.path.join(root, file)
            new_filename = replace_filename(file, rules)
            new_file_path = os.path.join(root, new_filename)

            # ファイル名の変更
            os.rename(old_file_path, new_file_path)
            print(f"Renamed: {old_file_path} -> {new_file_path}")

# tkinterウィンドウの作成
root = tk.Tk()

# CSVファイルを読み込む関数
def load_csv():
    csv_file_path = filedialog.askopenfilename(filetypes=[("CSV Files", "*.csv")])
    if csv_file_path:
        df = pd.read_csv(csv_file_path)
        process_files(df, folder_path)  # フォルダパスを変数で指定

# CSVファイルを選択するボタンを表示
load_button = tk.Button(root, text="Load CSV", command=load_csv)
load_button.pack()

# tkinterメインループを実行
root.mainloop()


```

##### -1.置換を実行したいフォルダのパスを指定する
Pythonコードの8行目の`folder_path`に置換を実行したいフォルダパスを記述してください。
例：
```
folder_path = "/Users/shuhei/Desktop"
```

### 3.読み込むCSVファイルの作成
##### -1.任意の場所に「trim_01.csv」等の名前のファイルを作成し下記のように記述
```
置換前の名前,置換後の名前
.*before.*,after
```
:::note warn
【一行目】
「置換前の名前,置換後の名前」から変更しないでください。
【二行目以降】
ここに正規表現と置換後のファイル名を記載ください。
:::


### 4.ダブルクリックでPythonファイルを実行して置換完了!




### 補足:ダブルクリックでうまく起動しない時
##### -1.作ったpyファイルを右クリック>情報をみるを選択
![スクリーンショット 2024-01-13 13.05.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/b0d4eee1-5f52-fa19-e2c4-e1da07d87d99.png)

##### -2.このアプリケーションで開くに「Python Launcher.app」を選択
![スクリーンショット 2024-01-13 13.06.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/5fce94c8-1558-08f9-6611-919f2d228a19.png)

これでいけると思います。

### 補足2:Python Launcher.appの設定でターミナルが起動するように設定しないと起動しない場合があります。
##### -1.Python Launcherを起動

![gamen_test1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/331dd9d7-60e2-55f4-9778-25698f9f4e2c.gif)

##### -2.右上のタブからPython Launcher>settingを選択
![スクリーンショット 2024-01-13 23.16.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/4aa3da79-5270-b5c6-65f4-0723112f9f6a.png)

##### -3.からターミナルを起動にチェック
![スクリーンショット 2024-01-13 23.17.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/329d1339-3016-7b2a-8f23-418b53dcad02.png)

##### 補足:Python Launcher設定の日本語訳
![7efbb506-b5d7-4641-beb2-65964efe413e.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3660939/a265c135-f087-359a-c052-6c0327ef0f80.png)
競プロで使える！〜文字列から一部の文字を切り出す方法〜

# はじめに
競プロを始めて、Swiftで文字列の**先頭・途中・末尾**から文字を切り出す方法について学んだのでまとめてみました！
# 先頭から文字の切り出し

```swift
let str = "0123456789"
print(str.prefix(3))
```
出力結果
```
012
```
先頭から3文字切り出され、`012`が出力される！
### prefixとは
コレクション(配列）の先頭から指定された最大長までの部分配列を返すメソッド。

https://developer.apple.com/documentation/swift/string/prefix(_:)

今回prefixの長さは3と指定されているので、先頭から3文字が切り出される！

# 末尾から文字の切り出し

```swift
let str = "0123456789"
print(str.suffix(5))
```
出力結果
```
56789
```
末尾から５文字切り出され、`56789`が出力される！
### suffixとは
コレクション(配列）の末尾から指定された最大長までの部分配列を返すメソッド。

https://developer.apple.com/documentation/swift/string/suffix(_:)

今回suffixの長さは５と指定されているので、末尾から５文字が切り出される！

# 途中から文字の切り出し
先頭から位置を指定する方法と末尾から位置を指定する方法があります！
### 先頭から途中の位置を指定する方法
```swift
let str = "0123456789"
let index = str.index(str.startIndex, offsetBy: 2)
print(str[index]) 
```
出力結果
```
2
```
`startIndex`空でない文字列の最初の文字の位置を指すプロパティ。
offsetByは距離を指定するので、先頭から2文字右にずらしたインデックスを返す！
そのインデックスを用いて、文字列から1文字を取り出す！





### 末尾から途中の位置を指定する方法
```swift
let index = str.index(str.endIndex,offsetBy: -2)
print(str[index]) 
```
出力結果
```
8
```

`endIndex`文字列の "末尾を過ぎた "位置、つまり、有効な最後の添え字引数より 1 つ大きい位置。
`offsetBy`は距離を指定するので、末尾＋１した位置から2文字左にずらしたインデックスを返す！
そのインデックスを用いて、文字列から1文字を取り出すため、出力は8となる！




### index(_:offsetBy:)
指定されたインデックスから指定された距離のインデックスを返すメソッド。
```swift
func index(
    _ i: String.Index,
    offsetBy distance: Int
) -> String.Index
```
`i`
コレクションの有効なインデックス。

`offsetBy distance`
オフセットiまでの距離。

戻り値としては`String.Index`を返します。

https://developer.apple.com/documentation/swift/string/index(_:offsetby:)

# 注意点
今回紹介した文字列に1文字ずつアクセスする方法では、処理時間は遅くなります。
一方、配列に変換してからアクセスすることで、処理時間は短縮できます。
そのためにとても長い文字列の場合には、下記のように、配列に変換してからアクセスする方が良いと考えられます。
```swift
let str = "0123456789"
let array = Array(str)
//let array = str.map{$0}
```
以下の記事を参考にしました！
コメントで教えていただき、ありがとうございます！
### 参考文献

https://qiita.com/nak435/items/422bfdaccd7121c20467

# 参考文献

https://developer.apple.com/documentation/pencilkit/pkstrokepath/3595276-startindex/

https://developer.apple.com/documentation/swift/string/endindex

https://qiita.com/ichikawa7ss/items/42aacdea5622620775e6
Month Pickerのクリア

https://success.outsystems.com/documentation/11/developing_an_application/design_ui/patterns/using_mobile_and_reactive_patterns/interaction/month_picker/

まずはこちらの手順通りでMonth Pickerを配置してください。
その内容をベースにしてお話を進めます。

手順に従いMonth PickerのOnSelectにNew Client Actionすると、MonthPickerOnSelectedというClient Actionが作成されます。MonthpickerIdというInput Parameterもできますが、解説では触れられていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/e1f0e475-d8c5-59f0-3bb9-8bf1eb94bd2e.png)

Month Pickerで選択した後、クリックした状態で、Deleteキーや、Back Spaceキーを押すと、選択値は消えますが、これをボタンを押したら、消えるようにしたいです。

ボタンを配置して、MonthVarにNullTextIdentifier()を入れてみましたが、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/96fc5c24-8255-5933-6741-3e9c9e0a5f03.png)

ボタンを押しても、選択値が消えません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/e0e04c59-5a42-5e3b-9920-e8fedf84a2c4.png)

Screen1を右クリックし、Add Local Variable、IdVarを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/65815979-020a-2801-affd-595155153ef3.png)

MonthPickerOnSelectedのMonthpickerIdをここで、IdVarにセットします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/e366ecef-be82-a202-1d81-127fd9113042.png)

ButtonOnClickにJavaScriptを追加、IdVarを渡します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/c9bef7ef-2f00-c76a-a7f3-f218dac516fa.png)

JavaSpriptはこれです。
~~~
OutSystems.OSUI.Patterns.MonthPickerAPI.GetMonthPickerItemById($parameters.IdVar).provider.clear();
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/34279a3e-e7b3-33a2-ad40-81caec405e21.png)

これでボタンを押したら、選択値が消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254659/6b019646-eebd-439f-9f6f-53fea17d5169.png)

Month Pickerはflatpickrというのが使われているようです。

https://flatpickr.js.org/
Db2　レジストリ変数　データベース・マネージャー構成パラメーター　

## DB2 レジストリ変数設計検討箇所
### レジストリ変数変更箇所

### よく設定変更する箇所

### AIXの場合
DB2_MMAP_READ　→ OFF
DB2_MMAP_WRITE　→ OFF

https://docs.oracle.com/cd/E74890_01/books/SiebInstUNIX/SiebInstCOM_RDBMS16.html

DB2SYSTEM　
通常はホスト名


DB2_SKIPDELETED=ON
この指定により、別のトランザクションにより削除された行（インデックスのキーおよびデータで未コミットのもの）を読み取らないようにします。その結果、ロック待ちの可能性が低くなり、処理性能が向上する場合があります。
https://thinkit.co.jp/cert/tech/23/7/4.htm

当たり前の設定
DB2COMM=TCPIP

すべての表スペースに対する並列アクセス
DB2_PARALLEL_IO="*"
https://atmarkit.itmedia.co.jp/ait/articles/0409/14/news105_2.html
最適なパフォーマンスのためには、表スペースのプリフェッチ・サイズがエクステント・サイズよりも十分に大きくなるように設定してください。

HADR構成の場合
DB2_HADR_SORCVBUF
HADR用のTCPソケットの受信バッファサイズを設定する。
DB2_HADR_SOSNDBUF
デフォルト：OSのTCPソケットの送信バッファサイズ

DB2_ENABLE_AUTOCONFIG_DEFAULT
データベースの作成時に構成アドバイザーが自動的に実行されるかどうかを制御します。
NO

DB2_OPTSTATS_LOG
統計収集関連のアクティビティーをモニターおよび分析するために使用する統計イベント・ロギング・ファイルの属性を指定します
OFF

## データベース・マネージャー構成パラメーター

SYSADM_GRP 
現在のバージョンはSYSADM_GROUP？


AUTHENTICATION
defaultはSERVERだが
SERVER_ENCRYPTが望ましい

https://www.ibm.com/docs/ja/db2/11.5?topic=details-authentication-methods-servers

DIAGPATH

INSTANCE_MEMORY AUTOMATIC →　明示的な値に変更

ASLHEAPSZ 
アプリケーション・サポート層ヒープ・サイズ (4KB) (ASLHEAPSZ) = 15


以下はややこしいがこういうことみたい
コーディネーター・エージェントの最大数 (MAX_COORDAGENTS) = AUTOMATIC(200)
 クライアント接続の最大数              (MAX_CONNECTIONS) = AUTOMATIC(MAX_COORDAGENTS)