OmniAICreator/Qiita-1.07M huggingface dataset:
WindowsTerminalとWindowsTerminalPreviewを一緒に使う

~~なんでどっちもwt.exeで入るん・・・？~~
両方使いたいのでPreviewの方を`wtp`で起動出来るようにしました。

# 前提

PowerShell
winget

# インストール

WindowsTerminalのIDを調べて入れます。

    winget search Microsoft.WindowsTerminal

結果：

```
名前                     ID                                バージョン  ソース
------------------------------------------------------------------------------
Windows Terminal         Microsoft.WindowsTerminal         1.21.2701.0 winget
Windows Terminal Preview Microsoft.WindowsTerminal.Preview 1.22.2702.0 winget
```

wingetに実行ファイルの名前をリネームするオプションがあるのでそれを使って...
みたけど機能してないみたい。無効なオプションならワーニングぐらい出してくれ。

~~winget install --id Microsoft.WindowsTerminal.Preview -r wtp.exe~~


普通にIDを指定して入れます。

    winget install --id Microsoft.WindowsTerminal
    winget install --id Microsoft.WindowsTerminal.Preview

ちゃんと入ってるかの確認。

    winget show --id Microsoft.WindowsTerminal
    winget show --id Microsoft.WindowsTerminal.Preview

# Previewを別名で起動できるようにする

Previewのwt.exeの場所を調べます。

    get-command wt | format-list *

結果：

```
HelpUri            :
FileVersionInfo    : File: C:\Users\ユーザ名\AppData\Local\Microsoft\WindowsApps\wt.exe
```


Fileに表示されているパスを参考に`WindowsApps`フォルダを開いて`Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe`のフォルダの中にあるwt.exeのフルパスを取得します。
（余談だけど8wekyb3d8bbweはMSの公開元IDなので覚えておくと良いかも)

取得したパスを参考にして以下の`wtp.ps1`を作ります。
作ったスクリプトをPATHの通っている所に置きます。

```ps1
& "$env:USERPROFILE\AppData\Local\Microsoft\WindowsApps\Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe\wt.exe"
```

`wtp`と叩いて起動すれば成功です。
`wt`で通常版のWindowsTerminal、`wtp`でPreview版が起動できるようになります。
チョッパーインバーター比較型で使われているインバーターとスイッチ回路

チョッパーインバーター比較型で使われているインバーターとスイッチ回路
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/41d00e82-bb64-15a8-f03c-ccb122d899a6.png)

```
import numpy as np
import matplotlib.pyplot as plt

# 定数の設定
VDD = 3.3  # 供給電圧
time_period = 10  # 時間の全体周期
sample_interval = 0.2  # サンプルクロックの間隔を短くして周波数を上げる

# 時間の設定
time_steps = 2000  # サンプル数を増やして解像度を上げる
time = np.linspace(0, time_period, time_steps)

# Vinの定義 (0からVDDまでのランプ波形)
Vin = np.linspace(0, VDD, time_steps)

# サンプルクロックの定義
sample_clock = np.array([(i // (time_steps // (time_period / sample_interval))) % 2 for i in range(time_steps)])

# Voutの定義
Vout = np.zeros_like(Vin)
Vout[sample_clock == 1] = VDD / 2  # サンプルクロック1のとき
Vout[(sample_clock == 0) & (Vin < VDD / 2)] = VDD  # VinがVDD/2より小さいとき
Vout[(sample_clock == 0) & (Vin >= VDD / 2)] = 0  # VinがVDD/2より大きいとき

# プロット設定
fig, axs = plt.subplots(3, 1, figsize=(12, 8))

# Vinのプロット
axs[0].plot(time, Vin, color="blue", label="Vin (Ramp Wave)", linestyle="--")
axs[0].set_title("Vin (Ramp Wave)")
axs[0].set_xlabel("Time")
axs[0].set_ylabel("Voltage (V)")
axs[0].grid(True)
axs[0].legend()

# サンプルクロックのプロット
axs[1].plot(time, sample_clock * VDD / 2, color="green", label="Sample Clock", linestyle="-.")
axs[1].set_title("Sample Clock")
axs[1].set_xlabel("Time")
axs[1].set_ylabel("Voltage (V)")
axs[1].grid(True)
axs[1].legend()

# Voutのプロット
axs[2].plot(time, Vout, color="red", label="Vout")
axs[2].set_title("Vout")
axs[2].set_xlabel("Time")
axs[2].set_ylabel("Voltage (V)")
axs[2].grid(True)
axs[2].legend()

# プロットの表示
plt.tight_layout()
plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/d9b0391c-f8e5-7202-6c5e-0a82d70ad973.png)


https://www.ieice-hbkb.org/files/10/10gun_06hen_02.pdf


```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/71403232-def3-125a-7e23-e3012afb949f.png)




```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/72ed91cf-8532-c822-22d7-72d18bec3339.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3759109/db2c7814-7e2e-df55-e101-532d0d346126.png)




```

function [VX, output_bit, output_bit_inverted] = calculate_output(Vin, VDD, clock)
    % 入力: Vin (入力電圧), VDD (電源電圧), clock (クロック信号)
    % 出力: VX (計算結果), output_bit (出力ビット), output_bit_inverted (出力反転ビット)
    
    % 初期化
    VX = 0; % 出力電圧
    output_bit = 0; % 出力ビット
    output_bit_inverted = 0; % 出力反転ビット
    
    if clock == 1
        % クロックが1の場合
        output_bit = 0;
        output_bit_inverted = 0;
    else
        % クロックが0の場合、方程式に基づいてVXを計算
        % 8*(Vin - VDD/2) + 8*(Vin - VDD/2) = 8*(VDD - VX) + 8*(0 - VX)
        % 方程式を解くために変数を再配置
        left_side = 8 * (Vin - VDD / 2) + 8 * (Vin - VDD / 2);
        right_side = 8 * VDD + 8 * 0;
        VX = (right_side - left_side) / (8 + 8); % VXを求める
        
        % VXがVDD/2より大きいかどうかで出力ビットを設定
        if VX > VDD / 2
            output_bit = 0;
        else
            output_bit = 1;
        end
        
        % 出力反転ビットの設定 (数値型にキャスト)
        output_bit_inverted = double(~output_bit);
    end
end


```
spring framework。webclient。responseのhttpヘッダーにhostは含まれる？

通常、HTTPレスポンスのヘッダーにはHostヘッダーは含まれません。

Hostヘッダーは、HTTPリクエストにおいてクライアント（たとえば、ブラウザやHTTPクライアント）が送信先のサーバを特定するために使用されるものであり、リクエスト専用のヘッダーです。これはサーバに対して、どのホスト（ドメイン名とポート）に対するリクエストなのかを伝える役割を果たします。

一方、HTTPレスポンスでは、リクエストに対してサーバが応答するための情報が含まれますが、その中にHostヘッダーは通常含まれません。レスポンスには、例えばContent-TypeやSet-Cookie、Cache-Controlなどのサーバ側からクライアントへ送信される情報が含まれます。

SpringのWebClientでHTTPレスポンスを扱う場合も、同様にHostヘッダーがレスポンスに含まれることはありません。WebClientが受け取るレスポンスヘッダーには、サーバがクライアントに返す情報だけが含まれます。
HTTP 1.1のHTTPヘッダーの仕様

HTTP 1.1の仕様におけるHTTPヘッダーは、クライアントとサーバが通信する際に追加情報を付与するために使用されます。リクエストとレスポンスにはそれぞれヘッダーがあり、HTTP 1.1では特定の標準ヘッダーが定義されています。

## HTTP 1.1 ヘッダーの構造
ヘッダーは、基本的に「名前: 値」の形式で書かれ、各ヘッダーの後に改行が続きます。ヘッダーの終了を示すために、空行が必要です。

```makefile
ヘッダー名: 値
```
例えば、以下のようなリクエストヘッダーがあるとします:
```bash
GET /index.html HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9
```

この例では、クライアントがwww.example.comの/index.htmlリソースに対するリクエストを送信しています。

## HTTP 1.1 ヘッダーの種類
HTTPヘッダーは、大きく分けて以下の4つのカテゴリーに分類されます。

#### General（汎用）ヘッダー
リクエストとレスポンスの両方に使用され、メッセージ全体に適用されます。

Cache-Control: キャッシュの動作を指定
Connection: コネクションの管理（例: keep-alive、close）
Date: メッセージの送信日時
Via: プロキシやゲートウェイの情報
#### Request（リクエスト）ヘッダー
クライアントがサーバに送信する追加情報を提供します。

Host: リクエストの送信先ホスト名とポート
User-Agent: クライアントソフトウェアの情報
Accept: クライアントが受け入れるメディアタイプ
Authorization: 認証情報
Referer: リクエスト元のURL
Cookie: サーバに保存されたクライアントの状態情報
#### Response（レスポンス）ヘッダー
サーバがクライアントに対して応答する際に送信する追加情報です。

Server: サーバソフトウェアの情報
Set-Cookie: クライアントにクッキーを保存するよう指示
Location: リダイレクト先のURLを指定
WWW-Authenticate: 認証が必要であることを通知
Retry-After: クライアントに再リクエストする時間を指示（主に503エラーの場合）
#### Entity（エンティティ）ヘッダー
リクエストやレスポンスの「エンティティ・ボディ」に関する情報を提供します。エンティティとは、送信されるデータのことです。

Content-Type: メディアタイプ（例: text/html, application/json）
Content-Length: エンティティボディのサイズ
Content-Encoding: エンティティの圧縮方式
Content-Language: エンティティの言語
Content-Disposition: ファイルダウンロード用の名前や形式
## HTTP 1.1 で重要なヘッダー
#### Host
HTTP 1.1では、Hostヘッダーが必須です。これは、クライアントがどのホストに対してリクエストを送っているかをサーバに知らせます。これにより、1つのIPアドレスで複数のドメインをホスティングすることが可能になります。

例:
```makefile
Host: www.example.com
```

#### Connection
keep-aliveやcloseの値を指定して、接続を持続させるか、すぐに閉じるかを制御します。デフォルトでHTTP 1.1はコネクションを維持します。

例:
```makefile
Connection: keep-alive
```
#### Content-Type
サーバがレスポンスとして送信するデータの形式（メディアタイプ）を示します。例えば、HTMLページならtext/html、JSONデータならapplication/jsonです。

例:
```css
Content-Type: text/html; charset=UTF-8
```

#### Cache-Control
リソースがキャッシュ可能かどうか、キャッシュの有効期限などを示します。

例:
```yaml
Cache-Control: no-cache
```

#### User-Agent
クライアントがサーバに送信する自身の情報です。通常はブラウザやクライアントアプリケーションの名前とバージョンが含まれます。

例:
```css
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
```
#### Authorization
クライアントがリソースにアクセスするために使用する認証情報です。

例:
```makefile
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
```
#### まとめ
HTTP 1.1のヘッダーは、クライアントとサーバがどのようにデータをやり取りするかを制御し、各種の追加情報を提供する役割を担っています。Hostヘッダーは必須で、適切に設定されないとリクエストの処理に失敗することがあります。他にも多くのヘッダーがHTTPの機能をサポートしており、それぞれ特定の目的を持っています。
Powershellで１日前の日付文字列取得

ファイルのコピーをする際に格納フォルダに年月とかつけてほしいという依頼があり、実行日の前日の月などで作ってほしい、という依頼がありました。
コピーだけなのでBATで作ろうとしたのですが、１日前の月などを計算するのがBATでは相当大変そうだったのですが、PowerShellでは結構簡単にできました。

１日前の年
~~~
$last_yyyy_str = (Get-Date -Day 1).AddDays(-1).ToString("yyyy")
~~~
１日前の年月
~~~
$last_yyyymm_str = (Get-Date -Day 1).AddDays(-1).ToString("yyyyMM")
~~~
１日前の年月日
~~~
$last_yyyymmdd_str = (Get-Date -Day 1).AddDays(-1).ToString("yyyyMMdd")
~~~

古めのPowerShellでも動くと思います。
こちらを参考にしたと思います：
https://stackoverflow.com/questions/61189531/powershell-get-date-adddays-how-to-get-desired-format
データベースの論理削除について

## はじめに
私は、データベースの設計について取り組むことになった。そこで初めてユーザーのIDやパスワードなどさまざまなデータが保存されるデータベースには論理削除というものがあるということを知った。そこで得た知識を以下にまとめてみた。
<br>
## 論理削除(ソフトデリート)
データベースのカラムにboolean型(True or False)で定義された削除フラグというものを立て、Trueの場合、そのデータは削除されたものとみなしユーザーにはそのデータが見えないようにするというもの。
Falseに指定されているデータは見ることができる。また、ユーザー視点では削除されているように見えるが実際はデータベースには残っておりFalseに戻すことで復元も可能である。

## 用途
- ユーザーからのアカウントの復旧の依頼
- 外部に効果したくない情報があるときに利用

## まとめ
削除フラグを立てることで、データの保護を保護したりユーザーのリクエストにも答えることができる。また、対義語で***物理削除***(***ハードデリート***)というものがあり、これはデータベースから完全にデータを削除するという。これらは公開しても良いデータか否かによって使い分ける必要がある。
【Ruby】firstメソッド、lastメソッドの使い道

# はじめに
progateでRubyを勉強したのち「ゼロからわかるRuby超入門」を勉強しています。
本書ではfirstメソッドやlastメソッドについて軽く触れられていただけだったのでもう少し深堀してまとめてみたいと思い記事にしました。

環境：ruby 3.3.5

# firstメソッドとlastメソッドとは
これらを説明する前に、まずは簡単に配列(array)について説明したいと思います。
```ruby:array1.rb
alcohols = ["ウイスキー","ラム","ジン"]
puts alcohols[0]
# ウイスキー
```
配列は上記でいうと`alcohols`を指し、[]の中の1つ1つを要素といいます。
ウイスキーを出力したい場合は`alcohols[0]`のように[]の中に数字を指定します。
左から0,1,2と出力しますが最初は1ではなく0なので注意してください。

さて、ここまでで配列について説明したのでfirst・lastメソッドについてみましょう
```ruby:array2.rb
alcohols = ["ウイスキー","ラム","ジン"]
puts alcohols.first
puts alcohols.last
# ウイスキー
# ジン
```

firstは配列の最初の要素を、lastは配列の最後の要素を取得することができます。

# firstやlastはどのような場面で使用するの
用途はわかったけど、firstであれば`alcohols[0]`、lastであれば`alcohols[2]`とすれば解決では？と思います。
`alcohols[0]`のような数字の指定ではなく、これらを使うメリットを上げてみました
* 可読性が上がる
* first(n)やlast(n)で複数選択できる
* 最新の情報を追うことができる(lastのみ）

### 可読性が上がる
これはそこまで説明しなくてもいいですが、たとえば`alcohols[2]`であれば要素が3つと知らなければ`alcohols`配列の最後の要素かわかりません。
一方`alcohols.last`を使用すれば要素の数を確認しなくても最後の要素であることが瞬時にわかります

### first(n)やlast(n)で複数選択できる
first(n)やlast(n)を使うことで、配列の最初または最後から複数の要素を取得できます。
```ruby:array3.rb
drinks = ["カフェラテ", "コーヒー", "エスプレッソ", "紅茶"]

# 最初の2つの要素を取得
puts drinks.first(2)  # => ["カフェラテ", "コーヒー"]

# 最後の2つの要素を取得
puts drinks.last(2)  # => ["エスプレッソ", "紅茶"]
```


### 最新の情報を追うことができる(lastのみ）
例えば、`alcohols`配列に世界中で販売されているお酒の種類がlogとして記録されるとします(そんなシステムあったら面白い）
その際に`alcohols[2]`だと随時更新されてしまうので`alcohols.last`を使用することで最新のログを追うことができます。
ただし、これに関しては`last`だけでなく、`alcohols[-1]`でも同様に意味なので付随的な用途として覚えておいて損はないと思います。

# まとめ
本日はfirstメソッドとlastメソッドの用途について説明しました。
* 可読性が上がる
* first(n)やlast(n)で複数選択できる
* 最新の情報を追うことができる(lastのみ）
こういったメリットがありますが、`alcohols[1]`と指定して出力するのも当然便利な機能なので用途ごとに使い分ける必要があると思いました
SQLで共通の開始文字列を抽出する

## やりたいこと
このようなレコードから「東京都港区芝公園４丁目」を抽出したい。

- 東京都港区芝公園４丁目２−８ 東京タワー
- 東京都港区芝公園４丁目７−３５ 増上寺

なかなか標準で用意されているものだけでは解決できなくて、結果、集約関数を実装して解決した。

```sh
$ psql --version
psql (PostgreSQL) 14.13 (Homebrew)
```

```sql
create or replace function intersect_prefix(state text, next_value text)
returns text language plpgsql as $$
declare
  subject text;
begin
  if state is null then
    return next_value;
  else
    subject := next_value;
    loop
  	  if length(subject) is null then
        return null;
  	  end if;

  	  if starts_with(state, subject) then
        return subject;
      end if;

      subject := substring(subject, 1, length(subject) - 1);
    end loop;
  end if;
end;
$$;

create or replace aggregate intersect_prefix(text)
( sfunc = intersect_prefix,
  stype = text);
```

## 検証

```sql
SELECT
  intersect_prefix(column1)
FROM (
  VALUES ('東京都港区芝公園４丁目２−８ 東京タワー'), 
         ('東京都港区芝公園４丁目７−３５ 増上寺'));

-- 結果
'東京都港区芝公園４丁目'
```
.gitとpackage.jsonが同じディレクトリにない時のESLint+Prettier+husky+lint-staged導入


# 🧠なぜ書いたか
* 私と同じように沼る人が必ずいるから
* これ以外のやり方を知りたいから（教えてください）
* 何回もするようなことではないので忘れないように備忘録代わり

# 💻環境
* Next.js - 14.0.3
* node - 20.9.0
下記のように.gitとpackage.jsonが同じディレクトリにないリポジトリ
```
|--.git/
|--...
|--...
└──next/
    |--.../
    └──package.json
``` 
# 🔥本題
## ⓪nodeのバージョン確認　
^18.18.0、^20.9.0、または>=21.1.0ならオッケー

## ①ESLintのインストール
⏬️実行して自分の環境に合わせて質問に答えてく
```
npm init @eslint/config@latest
```
⏬️動くか確認したかったら
```
npm run lint 
```
## ②Prettierのインストール
⏬️実行すると何か言われた気がする
```
npm install --save-dev --save-exact prettier
```
⏬️空の設定ファイルと.prettierignoreファイル作成
```
node --eval "fs.writeFileSync('.prettierrc','{}\n')"
node --eval "fs.writeFileSync('.prettierignore','#Ignore artifacts:\nbuild\ncoverage\n')"
```
⏬️動くか確認したかったら
```
npx prettier . --check　//prettierを実行できてるか確認できる
npx prettier . --write  //実行できちゃう（カスタムルール決めてからにしよう）
```
## ③ESLintとPrettierの連携
⏬️eslint-config-prettierをインストール
```
npm install --save-dev eslint-config-prettier
```
⏬️eslint.config.~~ファイルに追記する
```js
import eslintConfigPrettier from "eslint-config-prettier";

export default [
  eslintConfigPrettier,
];
```
## ④huskyとlint-stagedインストール
⏬️lint-stagedをインストール
```
npm install --save-dev husky lint-staged
```
⏬️huskyを^8でインストール（👈🏻突っ込まないで&&^9で出来る方法教えてください）
```
npm i -D husky@^8
npx husky init
```
⏬️.gitないよ〜〜〜と言われますが無視して、 package.jsonを書き換える
```json
"scripts": {
    "prepare": "husky install"
  },

// この部分をを下のように

 "scripts": {
    "prepare": "cd .. && husky install next/.husky" // next/はディレクトリ構成に合わせる
  },
```
:::note info
npm installが実行された後にprepareスクリプトが自動で走り、カレントディレクトリ(next/)から一つ上(.git/があるとこ)に移動してからhuskyのGithooksをnext/.huskyディレクトリにセットアップする
:::
⏬️てことでnpm install!!!!
```
npm i
```
⏬️作成されたnext/.husky/pre-commitファイルに記述
```
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"

npx lint-staged
```
⏬️package.jsonに追記する
```json
"lint-staged": {
    "**/*.{js,jsx,ts,tsx}": [
      "eslint --fix",
      "prettier --write"
    ]
  }
```
:::note info
ESLint のフォーマットルール（Prettier と重複する部分）を無効化し、Prettier が最終的なコード整形を担当する
:::
## ⑤動作確認
適当にコミットしてみる
できたら好みにカスタマイズ〜〜〜〜🙌🏽

# ⭐️最後に
沼ったおかげで公式ドキュメントめちゃくちゃ読めたのは良かった！！！！
* これ以外のやり方
* 最新バージョンでのやり方

誰か教えてください、今の私に色々試す気力は残ってません


# 👼🏻私を沼から救ってくれたもの
[Prettier公式doc](https://prettier.io/docs/en/install)
[ESLint公式doc](https://eslint.org/docs/latest/use/getting-started)
[eslint-config-prettier](https://github.com/prettier/eslint-config-prettier#installation)
[.git と package.json が同一ディレクトリにいないプロジェクトで husky をつかう](https://qiita.com/les-r-pan/items/c03f12bc1693983daa70)
[sendmail] メールヘッダー X-Authentication-Warning の傾向と対策

# はじめに
メールを送信していると `X-Authentication-Warning` というメールヘッダーが付いて、送信元（の更に元）のサーバーが外部に見えてしまうことがあります。
あまり気にしなくてもいいのですが、どうにも気になるので対策について調査してみました。

## 留意事項
例によって例のごとく、本件は `Sendmail` に限っての対策とします。`Postfix` 側でも同じように発生するようですが、こちらは未調査で。
大昔から変わってない機能なので、ここではバージョンを限定しません。環境によって若干の差違がある点についてはご了承ください。

また `sendmail` プロセスの再起動、ｃｆファイルの作成方法（通常ｍ４ファイルから作成する）、といった諸々の手順については明記しません。
設定ファイルについては暗黙的にｍ４ファイルを前提とします。それ以外のファイルは明示しますが、`/etc/mail/` ディレクトリ以下に配置されることを想定します。

# ２つの設定
このヘッダーが付く条件が２つあります。

- 「信頼されていない」ローカルユーザーからメール送信
- 外部サーバーからのメールの送信（付けるのはそのメールを受けるサーバー）

この問題について調べてみると、前者のケースの回答しか見当たらなくて途方に暮れます。

## 信頼されたユーザー設定
この設定はデフォルトで `root`、`daemon` あるいは `uucp` ユーザーからのメール送信を信頼する＝`X-Authentication-Warning` が付かないとなっています。
この設定に無いローカルユーザー（たとえば `www` など）からのメールを発信する場合 `X-Authentication-Warning` が付くというロジックになります。重要なので二度書きました。

対応としては以下の二つになります。

### Ct クラスの設定
追加したいユーザーを confTRUSTED_USERS[^confTRUSTED_USER] マクロでユーザー名を、空白区切りでリストアップします。

```
confTRUSTED_USERS(`www mail')
```

変更後はｍ４ファイルからｃｆファイルを作成した後、`sendmail` にｃｆファイルを読み直させる必要があります。大抵のユースケースはこれで解決します。

[^confTRUSTED_USER]: `confTRUSTED_USER` ではありません。似たような名前の設定ですが、全く別の機能です。

### Ft クラスの設定
追加したいユーザーを、一行一ユーザーでファイル[^confCT_FILE]に追加します。そのためには下記の設定が必要になります（デフォルトで機能しない）。

```
FEATURE(`use_ct_file')
```

ｍ４ファイルからｃｆファイルを作成に関しては一度だけで問題ありません。ＣＴファイルの更新自体は `sendmail` のリロードを実施する必要があります。
「信頼されたユーザー」をファイルで丁寧に管理したい向けに使用しますが、デフォルトで無効になっていますので、よほど運用上の要請が無いと使用しないと思われます。

[^confCT_FILE]: `confCT_FILE` マクロの指定によります。デフォルトは `/etc/mail/trusted-users` です。またこのファイル名を `/etc/mail/sendmail.ct` として知られている場合があります。

## 外部サーバーからのメールの送信
外部サーバー（`localhost` 等を含む）からの接続時の情報に基づき、`PrivacyOptions` 設定によるフラグ管理により `X-Authentication-Warning` ヘッダーの付与が判断されます。
具体的には `authwarnings` フラグが関係します。デフォルトで設定されていますが、ＯＳによっては更に `noexpn`、`novrfy` が付加されていることがあります。ただし後者２つのフラグは機能上は無関係です。
この設定（フラグ）が設定されている時、メール受信時（受信または転送設定によるリダイレクト等、用途に限らず）にＳＭＴＰプロトコル `HELO`/`EHLO` で主張したホスト名、接続元ＩＰアドレスおよびその逆引きした結果と合わせて、`X-Authentication-Warning` ヘッダーの付与を判断します。

対応としては以下の通りとなります。

### authwarnings フラグの削除
この設定を外せば `X-Authentication-Warning` 付与する評価自体が行われなくなります。具体的には以下のように `authwarnings` を消すように記述します。

```
define(`confPRIVACY_FLAGS', `')
```

変更後はｍ４ファイルからｃｆファイルを作成した後、`sendmail` にｃｆファイルを読み直させる必要があります。

# 参考文献
オンラインで参照できる `Sendmail` の公式ドキュメントが見当たらなくてつらい。
- [cf/README.cf](https://www.sendmail.org/~ca/email/doc8.12/cf/m4/index.html)
- [Linuxで様々なサービスを構築しよう！！！ sendmail について](https://www.bigbang.mydns.jp/sendmail-x.htm)
左Ctrlキーにできなくて右Ctrlキーにだけできること、あるんです

以下はWindows クライアントOSでの話になります。(Windows Server未確認)

# 右Ctrlキーって何のためにあんの？

誰しもがこの疑問を抱くことがあると思います。
ショートカットキーとしてCtrlを使う場合、左Ctrlキーが癖づいている方が多いのではないでしょうか？
右Ctrlキーについてインターネッツの有識者らがどう使用しているのか調べてみたのですが、別キーを割り当てるなどして右Ctrlキーのアイデンティティーを剥奪するような野蛮な行為が散見されており、右Ctrlキーの自己肯定感はもうボロボロ。

生と死は等価値なんだ、右Ctrlキーにとってはね。



# 右CtrlキーとScrLkキーの逢瀬
閑話休題
左Ctrlキーにできなくて右Ctrlキーにだけできることを発見しました！

―――――――左Ctrlキーにできなくて右Ctrlキーにだけできること、それは
　　　　　　　　　『**システムクラッシュの強制実行**』　――――――

*右Ctrlキーが秘められた力を解放し、一面を蒼に染め〈強制的にブルースクリーンを出し〉、Dumpを吐かせる！*



**やりかた**

レジストリエディタ等から
```
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\kbdhid\Parameters
```
上記レジストリキーにDWORD値[**CrashOnCtrlScroll**]を作成し、データを[1]に設定。
反映後
右Ctrlキーを押下しながらScrLkキーを2回押下するとブルースクリーンが発生します！！！
右Ctrlキーくんすごい！大活躍！



詳しくは下記サイトへ
https://learn.microsoft.com/ja-jp/windows-hardware/drivers/debugger/forcing-a-system-crash-from-the-keyboard


## あとがき
僕はこの使用方法以外まだ知らないので他にもあればコメント欄でご教示いただけると幸いです。みんなで右Ctrlキーの存在価値を高めていきましょう。
python returnの使い方がわからなかった話（自分用）

pythonの関数内で使われるreturnの意味がよくわからなかったので、自分なりにまとめてみる。

1.returnとは
-
関数の末尾に記載されている文法である。
returnすることで、関数で処理した結果を関数外へ取り出すことができる
文章では伝わりづらいが、下記のようにコードで出力して比較するとわかりやすい
```py
# 1～5の数字生成してリストに格納する関数（ returnする場合 ）

def num_list():
    numbers = [i for i in range(1,6)]
    return numbers

numbers = num_list()
print(numbers)


# 出力　⇒　[1,2,3,4,5]

#1～5の数字を生成してリストに格納する関数（ returnしない場合 ）
def num_list():
    numbers = [i for i in range(1,6)]

numbers = num_list()
print(numbers)


# 出力　⇒　None  # 何もデータがないという意味
```
2.returnのルール
-
必ず関数の一番末尾に記載すること。（return以降の処理は無視される）
```py

def num_list():
    numbers = [i for i in range(1,6)]
    print(f"before：{numbers}")
    return numbers
    print(f"after：{numbers}")  　# この行は無視される（処理されない）


numbers = num_list()


# 出力 ⇒　before：[1,2,3,4,5]
```
3.まとめ
-
関数により導き出した内容を他で使いたい場合は、とりあえずreturnしておくと良い。
なんでハンバーガーメニューの要素が下になってしまうんや！(z-indexの適用条件に気をつけろ)

休み期間に色々知識を取り戻しつつ、Next.jsとNotion連携させるのを書いてみたりしてたんですが…ページを作っていたところ、どうしてもうまく動かないことが。

## 課題

それは、**「ハンバーガーメニュー」の要素がどうしてもページの後ろにいってしまう！** 
具体的にはこれ。

![イケテナイ失敗例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/ede6a5c2-1949-47ef-7229-22dadac8e2a7.png)

目標としてはこうしたいんです。
![成功例](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443/06616a42-4595-064d-22f5-a6c30b915d6f.png)

## 原因調査

### Webページの重ね順といえばz-index
ページの重ね合わせといえばz-index。tailwindcssはz-indexの設定も簡単です。
"z-10" という感じでclass名をつければz-index:10になります。もちろんやってます。

https://tailwindcss.com/docs/z-index

### z-indexが効く条件を調べる
私もこれは効く条件があるのは知ってました。有名なのは「positionプロパティがstatic以外じゃないとだめ」とかですよね。あと親要素のz-indexを引き継いでしまうとか。

で、いろいろ調べると...どうやらこの重ね合わせ(Stacking Context)ができる条件って他にもあり。
いっぱいあるみたいなんですが、調べてたらこんなものがあり・・・

- 要素のpositionが "fixed" or "sticky"
- 要素のpositionが "absolute" or "relative" の場合はz-index:auto 以外
- 親要素が "flex" or "grid" の場合は z-index:auto 以外
- **要素にOpacityが設定され、その値が1未満の場合(透過設定あり)**
- その他ほかにも...

この4点目が盲点でした。ちょっとおしゃれかなと思ってtailwindcssで"opacity-95"なんてものを親のBox要素につけておりました…

参考：該当のhtml(2行目のところに注目。最後にopacity-95があるので、この要素ほぼ全体が適用)
```html
       <div className="pb-5">
          <div className="navbar bg-base-100 bg-white shadow shadow-2xl rounded-lg opacity-95">
            <div className="md:hidden flex-none">
              <div className="dropdown">
                <div tabIndex={0} role="button" className="btn btn-ghost btn-circle">
                  <svg
                    xmlns="http://www.w3.org/2000/svg"
                    className="h-5 w-5"
                    fill="none"
                    viewBox="0 0 24 24"
                    stroke="currentColor">
                    <path
                      strokeLinecap="round"
                      strokeLinejoin="round"
                      strokeWidth="2"
                      d="M4 6h16M4 12h16M4 18h7" />
                  </svg>
                </div>
                <ul
                  tabIndex={0}
                  className="menu menu-sm dropdown-content bg-base-100 rounded-box z-[10000] mt-3 w-52 p-2 shadow">
                  <li><a>A</a></li>
                  <li><a>B</a></li>
                  <li><a>C</a></li>
                </ul>
              </div>
            </div>
            <div className="flex-1">
              <a className="btn btn-ghost text-xl">Web Site</a>
            </div>
            <div className="flex-none invisible md:visible">
              <ul className="menu menu-horizontal px-1">
                <li><a>A</a></li>
                <li><a>B</a></li>
                <li><a>C</a></li>
              </ul>
            </div>
          </div>
        </div>
```

## まとめ
opacityを使った場合、その要素配下はz-indexは効かなくなるので注意せよ！


# 参考にさせてもらった記事
https://note.com/dev_onecareer/n/n4e9f378aa847
自分用TamperMonkey　Test１

1.これは自分用です。コード等もテスト用なので参照しないでください。
以下は、CSSでスタイリングしたボックスを画面左端に追加し、ユーザーが指定した要素の内容をそのボックス内に表示するTampermonkeyスクリプトの例です。


```
// ==UserScript==
// @name         Show Specific Element on Left Side
// @namespace    http://tampermonkey.net/
// @version      1.0
// @description  Show specific content on the left side of the screen for any site.
// @author       Your Name
// @match        *://*/*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // ユーザーがターゲットにするCSSセレクタを指定（例: 特定の要素）
    const targetSelector = 'h1'; // 任意のCSSセレクタ。たとえば、ページの<h1>タグの内容を取得します。

    // ページの読み込みを待ってから実行
    window.addEventListener('load', function() {
        // ターゲット要素を取得
        const targetElement = document.querySelector(targetSelector);
        if (!targetElement) {
            console.log('ターゲット要素が見つかりませんでした。');
            return;
        }

        // 取得した要素のテキスト内容
        const targetContent = targetElement.textContent;

        // 左端に固定表示するための要素を作成
        const displayBox = document.createElement('div');
        displayBox.style.position = 'fixed';
        displayBox.style.top = '10px';
        displayBox.style.left = '10px';
        displayBox.style.width = '300px';
        displayBox.style.padding = '10px';
        displayBox.style.backgroundColor = 'rgba(0, 0, 0, 0.8)';
        displayBox.style.color = 'white';
        displayBox.style.fontSize = '14px';
        displayBox.style.zIndex = '9999';
        displayBox.style.borderRadius = '5px';
        displayBox.style.boxShadow = '0 4px 8px rgba(0, 0, 0, 0.3)';
        displayBox.textContent = `ターゲットの内容: ${targetContent}`;

        // ボディに追加
        document.body.appendChild(displayBox);
    });
})();
```
・スクリプトの動作
ページが読み込まれると、指定されたCSSセレクタ（この場合はh1）に一致する要素を取得します。
取得した要素が存在すれば、そのテキスト内容を画面左端に固定表示するボックスに表示します。
画面左端に固定され、他のページ内容がスクロールしてもボックスは常に見える状態になります。
・使用方法
Tampermonkeyにスクリプトを追加します。
targetSelectorの値を自分が表示したい要素に変更します（例: p、.my-class、#my-idなど）。
スクリプトを保存し、どのサイトでも動作することを確認します。
【Mac】スクリプトでアプリの稼働状態を確認する方法


## 確認方法

以下のようなに記述することで指定したアプリが稼働しているか否か検証できます。

```plaintext
if application "アプリケーション名" is running
  "running"
else
  "not running"
end if
```

**if文**: 指定したアプリケーションが実行中かどうかをチェック

**条件が真の場合**: `running` という文字列が返されます

**条件が偽の場合**: `not running` という文字列が返されます

 **end if**: `if` 文の終了

## 使用例

例えば、アプリケーション名が「Safari」の場合、コードは以下のようになります。

```plaintext
if application "Safari" is running
  "running"
else
  "not running"
end if
```

このコードを実行すると、Safariが開いている場合は「running」と表示され、開いていない場合は「not running」と表示されます。
投稿 101 CRM 2024/10/09

本日の勉強時間　4H

CRM（顧客関係管理）は顧客情報を管理するデータベースですが、それにとどまらず、顧客との「関係」まで管理して顧客満足度の向上を図るシステムです。 ERP（企業資源計画 / 統合基幹業務システム）は、基幹業務システムを統合管理するもの。
BigQueryで日付別にシャード化した空テーブルを作成する

## はじめに

BigQueryにて、指定期間内の日付別にシャード化された空テーブルをLOOP文で一度に作成するクエリを作成したので、メモ書きとして残しておくことにします。

## 背景

AWSのS3バケットにエクスポートされるCSVファイルの内容を「[Bigquery Data Transfer Service](https://cloud.google.com/bigquery/docs/dts-introduction?hl=ja)」を利用して、BigQuery内の対応する日付の空テーブルに転送していました。

なお、テーブル名は```tableName_yyyymmdd```の形となります。

その際に、事前にCSVファイルの転送先として未来の日付のBigQueryテーブル（空）を大量に作成する必要があったため、今回のクエリを作成しました。

## クエリ

以下のクエリを実行すれば、```2024/01/01-02/29```までの空テーブルを```tableName_yyyymmdd```の形で一括で作成できます。

```SQL
DECLARE date DATE DEFAULT '2024-01-01';
DECLARE yyyymmdd INT64;

LOOP
  SET yyyymmdd = CAST(FORMAT_DATE("%Y%m%d", date) as INT64);
  
  EXECUTE IMMEDIATE format("""

  CREATE TABLE projecctId.datasetName.tableName_%d
  (
    column_name_1 DATETIME
    , column_name_2 STRING
    , column_name_3 INTEGER
  )

  """, yyyymmdd);

  IF date >= '2024-02-29' THEN
    LEAVE;
  END IF;

  SET date = date + 1;

END LOOP;

```

本クエリのポイントは、以下の部分です。

不正な日付形式の文字列はINT64型への変換に失敗するため、テーブル作成のSQL文が実行されず、間接的に日付の妥当性チェックが行われます。

例えば、2024/01/32のような不正な日付のテーブルは作成されません。

```SQL
  SET yyyymmdd = CAST(FORMAT_DATE("%Y%m%d", d) as INT64);
```

日付の妥当性チェックがなくても、```SET date = date + 1;```の記述で不正な日付が入力されることはありません。

クエリを実行すると、指定したカラム名とデータ型で構成されたテーブルが作成されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/7d5251cb-9d70-a566-fed9-0a4429e122a0.png)

## Tips

空テーブルを作成するにあたり、AWSのS3バケットにあるCSVファイルの中身を確認してカラム数やデータ型を確認しておく必要がありました。

ただ、対象のS3バケットが他者所有で、CSVファイルの共有に手間がかかりそうだったので「Cyberduck」というツールを利用して効率化を図りました。

https://cyberduck.io/download/

Cyberduckを利用すれば、以下の手順で自由にS3バケット内の読み取りが可能になります。

1. 他者にS3バケット読み取り用のIAMユーザーを作成する（他者）
1. 1に、```AmazonS3FullAccess```のポリシーをアタッチする（他者）
1. シークレットアクセスキー、アクセスキー、バケット名を共有する（他者）
1. 3の情報を入力し、Cyberduckでコネクトする（作業者）

クライアントワークを行う方は、参考になるかもしれません。

参考：https://dev.classmethod.jp/articles/cyberduck-to-s3/

## おわりに

LOOP文を使えば、効率よく指定期間のテーブルを作成することができました。

また、後から気づいたのですが、S3バケットのCSVファイルをBigQueryテーブル化するよりも「[BigQuery Omni](https://cloud.google.com/bigquery/docs/omni-introduction?hl=ja)」を利用した方がよかったかもしれません。
【JUnit】Serviceクラス

## 1.はじめに
JUnitのテストを書いている中で、サービスクラスは何を確認しているのかwhenとverifyはどういう違いがあるのかを理解するために記事を書いていければと思います。
間違い等ございましたら、ご指摘いただけますと幸いです。

## 2.Serviceクラスの単体テスト
Serviceクラスでは何を確認すればよいのかという疑問について解消できればと思います。

Serviceクラスのテストで確認することとしては下記になるようです。

**＜メソッドの結果は正しいか＞**
サービスクラスのメソッドが正しい値を返しているかを確認します
簡単な例でいくと計算結果が正しいかどうかなど　↓
```TestService.java
@Test
void testCalculateTotal() {
    int total = service.calculateTotal(10, 20);
    assertEquals(30, total);
}
```

**＜依存するクラスとのやり取りが正しいか＞**
・サービスクラスが他のクラス（リポジトリや他のサービスクラス）に依存している場合そのクラスへの呼びだしが正しく行われているかを確認します
・Mockitoなどのモックライブラリを使って、依存クラスの動作をシミュレーションし、正しいメソッドが呼ばれているかを確認します（[Mockについての解説](https://qiita.com/yommy/items/9b16508ccf3720a453dd)）

```TestService.java
@Test
void testSaveUser() {
    User user = new User(1, "John");
    
    // リポジトリの保存メソッドが呼ばれることを確認
    service.saveUser(user);
    verify(userRepository, times(1)).save(user);
}
```
**＜エッジケースや異常系の動作＞**
・異常な入力やエッジケースに対するサービスクラスの動作を確認します
・例えば空のリストやnull値、範囲外の数値を渡したときの処理の動作が正しいかなど

```TestService.java
@Test
void testFindUserNotFound() {
    when(userRepository.findById(999)).thenReturn(Optional.empty());
    
    // 存在しないユーザーIDを渡したときの挙動
    assertThrows(UserNotFoundException.class, () -> {
        service.findUserById(999);
    });
}
```
などがあります。
その中でよく使われているwhenとverifyは何をしているのかについてのも調べていければと思います。

## 3.whenとかverifyって何？
JUnitを書いていると、whenとverifyを多く使用しているのでこれらは何をしているのかを詳しく理解できればと思います。

**when**
役割：特定のメソッドが呼ばれたときにその戻り値を定義します
```java: 例
when(userService.findById(1)).thenReturn(new User());
```
これは userService.findById(1) を呼び出したとき、モックオブジェクトが新しい User オブジェクトを返すことを指定しています。

**verify**
役割：テスト中に特定のメソッドが何回呼び出されたか、または特定の引数で呼び出されたかを検証します
```java: 例
verify(userService, times(1)).findById(1);
```
簡単にまとめると
when: モックが特定の条件に応じて返す値を設定する。
verify: モックが期待通りの方法で使用されたかを検証する。
ようです。

## 4.まとめ
まだ簡単なJUnitしか書いたことがないのですが、今自分が何をテストで確認すればよいかの基礎は理解できてよかったです。
【備忘録】SSH接続設定

## SSH接続の種類

### 公開鍵認証方式
- 公開鍵と秘密鍵のペアを使って認証を行います。
- 公開鍵は接続先サーバーに配置し、秘密鍵は接続元サーバーに保持します。
- 秘密鍵さえ安全に管理されていれば、パスワード認証よりもセキュリティが強固です。

### パスワード認証方式
- ユーザー名とパスワードを使って認証を行います。
- 事前に鍵を配置する必要がないため、設定がシンプルですが、パスワードが漏洩したり総当たり攻撃を受けるリスクがあります。

---

## 設定方法
接続元（クライアント）サーバーから接続先（サーバー）へSSH接続を設定する手順を記載します。


### 公開鍵認証

#### 1. キーペア（公開鍵と秘密鍵）の作成
作業先：接続元サーバー

```bash
ssh-keygen -t rsa -b 4096
```

- 何も入力しなければデフォルトの保存先（`~/.ssh/`）に鍵が保存されます。
- 保存時にパスフレーズ（パスワード）を設定することができます。空欄にすることでパスフレーズなしで利用することも可能です。

#### 2. 公開鍵の登録
作業先：接続先サーバー

```bash
mkdir ~/.ssh
chmod 700 ~/.ssh
echo '1で作成した公開鍵の内容（id_rsa.pub）' >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```

公開鍵を `authorized_keys` に登録することで、サーバーがこの鍵を使って認証できるようになります。

#### 3. SSH設定ファイルの確認・更新
作業先：接続先サーバー

公開鍵認証を有効にするため、SSHの設定ファイル `/etc/ssh/sshd_config` を編集します。

```bash
PubkeyAuthentication yes  # 公開鍵認証を有効化
```

#### 4.SSHサービスの再起動

```bash
sudo systemctl restart sshd
```

### パスワード認証

#### 1. SSH設定ファイルの確認・更新
作業先：接続先サーバー

パスワード認証を有効にするには、SSHの設定ファイル `/etc/ssh/sshd_config` を次のように修正します。

```bash
PasswordAuthentication yes # パスワード認証を有効化
```

#### 2.SSHサービスの再起動

```bash
sudo systemctl restart sshd
```

#### 補足: パスワード認証可能なユーザーの作成
作業先：接続先サーバー

新しいユーザーを作成し、そのユーザーにSSH接続を許可するためには、以下のコマンドを実行します。

```bash
sudo adduser 新しいユーザー名
```

これにより、新しいユーザーが作成され、SSH経由でログインできるようになります。

---

## 参考サイト  
- [https://www.value-domain.com/media/ssh/#](https://www.value-domain.com/media/ssh/#)
- [https://hnavi.co.jp/knowledge/blog/ssh/](https://hnavi.co.jp/knowledge/blog/ssh/)
- [https://www.ssh.com/academy/ssh/keygen](https://www.ssh.com/academy/ssh/keygen)
- ChatGPT

---

## 終わりに

SSH接続の設定は毎回忘れてしまいがちなので、自分用にまとめてみました。
この記事が皆さんのお役に立てれば幸いです。
SQLの基本~ SELECT編

## はじめに

前回の [ALBのアクセスログをAthenaを使って分析する
](https://qiita.com/hoyat4967/items/df43409eca85c08c92af) を実施したあとに、いざ自分でクエリを考えて実行してみようと思ったら手が動かなかったので再度基本的なところから復習します。

## 使った教材
[SQL Bolt](https://sqlbolt.com/)という教材を使用しました。
英語で若干わかりにくいですが、サクサク結果が見れるのでおすすめです。

## テーブル
使うテーブルは[SQL Bolt](https://sqlbolt.com/)で用意してくれていたのでそのまま使用します。

table:Movies
| id | title                 | director          | year | length_minutes |
|----|-----------------------|-------------------|------|----------------|
| 1  | Finding Nemo          | Andrew Stanton     | 2003 | 107            |
| 2  | Monsters, Inc.       | Pete Docter        | 2001 | 92             |
| 3  | Monsters University    | Dan Scanlon       | 2013 | 110            |
| 4  | Up                    | Pete Docter        | 2009 | 101            |
| 5  | WALL-E               | Andrew Stanton     | 2008 | 104            |
| 6  | Cars                  | John Lasseter      | 2006 | 117            |
| 7  | Toy Story            | John Lasseter      | 1995 | 81             |
| 8  | Brave                | Brenda Chapman      | 2012 | 102            |
| 9  | Toy Story 2         | John Lasseter      | 1999 | 93             |
| 10 | The Incredibles      | Brad Bird          | 2004 | 116            |
| 11 | Ratatouille          | Brad Bird          | 2007 | 115            |
| 12 | Toy Story 3         | Lee Unkrich        | 2010 | 103            |
| 13 | Cars 2              | John Lasseter      | 2011 | 120            |
| 14 | A Bug's Life        | John Lasseter      | 1998 | 95             |


## やってみた

### シンプルなSELECT

```
SELECT * FROM movies;
```
結果としてはテーブル内のデータが全て抽出されます。

お次はこちら。
```
SELECT * 
FROM Movies
WHERE Title = 'Finding Nemo';
```

タイトルがFinding Nemoの行を抽出してくれます。
`WHWRE`は、行に対してデータをフィルタリングしてくれます。


以下で、`Movies`テーブルの全てのデータを指定して、
```
SELECT * 
FROM Movies
```

以下で、`Title`が`Finding Nemo`の行を抽出します。
```
WHERE Title = 'Finding Nemo';
```

順番に一個ずつ考えると理解しやすいですね。

ちょっと変えてみます。

```
SELECT * 
FROM Movies
WHERE Title LIKE 'Toy Story%';
```

上記では以下のような結果になります。

| id | title         | director       | year | length_minutes |
|----|---------------|----------------|------|----------------|
| 7  | Toy Story     | John Lasseter  | 1995 | 81             |
| 9  | Toy Story 2  | John Lasseter  | 1999 | 93             |
| 12 | Toy Story 3  | Lee Unkrich    | 2010 | 103            |

`WHERE Title LIKE 'Toy Story%';
`の部分を変えました。
`LIKE`は特定の文字列に対してのパターンマッチングをしてくれます。
`%`はワイルドカード的な使い方です。
つまり、`Toy Story`を文字列に含んでいれば、`Toy Story`以降の文字列には何が含まれても抽出されます。
結果として2,3も抽出されました。

## おわりに
こんな初歩的なところで終わってんじゃねえという声が聞こえてきそうですが、また次回でもう少し深ぼってSQLの学習していこうと思います！
誰かの参考になれば嬉しいです。
SQLServerでファイルを取り込む

# SQLServerでファイルを取り込む
取り込みフォーマットファイル「ImportDefine.xml」を用意して、「ImportText.txt」を取り込みます。

フォーマットファイルは以下を組み合わせて作成します。
```xml
<!-- n文字を読み取る -->
<FIELD ID="1" xsi:type="CharFixed" LENGTH="n"/>
<!-- 「,」まで読み取る -->
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR=","/>
<!-- タブまで読み取る -->
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="\t"/>
<!-- 行末まで読み取る -->
<FIELD ID="1" xsi:type="CharTerm" TERMINATOR="\r\n"/>
```

# サンプル
```text:取り込みファイル：ImportText.txt
2024/10/09  22:19    1320 DESKTOP-PC\masayasu  10_xxx.txt
2024/10/09  22:19    4400 DESKTOP-PC\masayasu  11_xxx.txt
2024/10/09  22:19     440 DESKTOP-PC\masayasu  1_xxx.txt
2024/10/09  22:19    2200 DESKTOP-PC\masayasu  2_xxx.txt
2024/10/09  22:19    8800 DESKTOP-PC\masayasu  3_xxx.txt
```

```xml:フォーマットファイル：ImportDefine.xml
<?xml version="1.0"?>
<BCPFORMAT xmlns="http://schemas.microsoft.com/sqlserver/2004/bulkload/format" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <RECORD>
    <FIELD ID="1" xsi:type="CharFixed" LENGTH="17"/>
    <FIELD ID="2" xsi:type="CharFixed" LENGTH="8"/>
    <FIELD ID="3" xsi:type="CharFixed" LENGTH="1"/>
    <FIELD ID="4" xsi:type="CharFixed" LENGTH="19"/>
    <FIELD ID="5" xsi:type="CharFixed" LENGTH="2"/>
    <FIELD ID="6" xsi:type="CharTerm" TERMINATOR="\r\n"/>
  </RECORD>
  <ROW>
    <COLUMN SOURCE="1" NAME="c1" xsi:type="SQLDATETIME" />
    <COLUMN SOURCE="2" NAME="c2" xsi:type="SQLINT" />
    <COLUMN SOURCE="4" NAME="c3" xsi:type="SQLNVARCHAR" />
    <COLUMN SOURCE="6" NAME="c4" xsi:type="SQLNVARCHAR" />
  </ROW>
</BCPFORMAT>
```

```sql:実行クエリ
INSERT INTO t_file_info (ファイル名, 日付, サイズ, 所有者)
SELECT c4,c1,c2,c3
  FROM OPENROWSET
       (BULK 'D:\～\ImportText.txt',
        FORMATFILE = 'D:\～\ImportDefine.xml',
        FIRSTROW = 1
       ) AS tbl
```

https://learn.microsoft.com/ja-jp/sql/relational-databases/import-export/xml-format-files-sql-server?view=sql-server-ver16

https://learn.microsoft.com/ja-jp/sql/t-sql/functions/openrowset-transact-sql?view=sql-server-ver16
自分用まとめ ~「超訳版 貞観政要」~

## この記事について
知人におすすめしてもらった本の内容を自分用にまとめます。
読書によるインプットを増やすため、ただ読むだけではなく、自分なりにまとめることにしました。
（昔読んだ本の内容を思い出せないのが悔やまれる、、）

記念すべき1冊目は、「[超訳版 貞観政要](https://www.amazon.co.jp/dp/4863102488)」です。

## 第一印象
この本を読むにあたってまず惹かれたところは、太宗という人物の考え方。
自身を完璧なリーダーであるとは決して思わず、自分自身の弱さや脆さを自覚してリーダーという役割を担う。
部下はもちろん、農民や商人たちと対等に話をし、その意見を聞き、彼らの力を活かしながら、自らも多くを学んで常に成長していくリーダーであろうとする。

「自分で何でもできる」が完璧なリーダーなのではなく、そのチームを形成するメンバーの力を借りて強いチームを作るのがリーダーという考え方が新鮮だった。

## リーダーに必要なもの
### 自分の未熟さを知ること
- リーダーが私欲に溺れては、いい環境は生まれない
- 成功する人は常に学び続けている
- 指示に応える価値があると思ってもらえるように、自分を磨く。褒める
- 「部下に任せる」ことをしてみる。自分とやり方が違っても、そこから自分も部下も学ぶことができる
    - 仕事ができるリーダーほど「部下に任せる」ということがなかなかできない
- 人間関係の基本である仁、義、礼、智、信を意識する
    - 仁 = 常に人に対して、思いやりを持って接すること
    - 義 = 公平で正義に基づいた行動を続けること
    - 礼 = 相手を立て、謙虚でいること
    - 智 = 常によく考え、勉強を怠らないこと
    - 信 = 約束を守り、誠意を持って尽くすこと
- 「上が下に命令を出す際の原則」
    - ①誰にも分かりやすく
    - ②慎重に吟味し
    - ③内容に責任を持つこと

### 人の話を聞くこと
- 自分にとって都合の良い話はもちろん、都合の悪いことも吸い上げる
- 部下の話を聞くことで、自分を映す鏡として自分を見直すことができる
- 部下からの要望を吸い上げて、望む仕事をさせることがリーダーの役目

### 環境を整える
- 部下が発言しやすい環境をつくる
    - 意見してくれたからには、取り入れること。発言には勇気が要る
- 発言してほしい、チームをこうしていきたいといった要望は、部下に伝え続ける

### 部下を育てる視点を持つこと
- 部下はイエスマンであってはならない
    - 部下が自発的に動く環境を作るには、まずリーダーが正しく部下の声を聞かねばならない
- 部下と本音で話すこと。自分の弱みをさらけ出すくらい
- 部下へのリスペクトが基本

### 人を見る目を育てること
- 自分に意見や反論してくれる人こそ信頼できる
- 優秀な人物とは、優れた能力を持つことが全てではない


## まとめ
「マネジメントとはなにか」と迷子になっている自分にとって、ぴったりな1冊目でした。
今回まとめた各項目について、それぞれの指標のようなものを学べたように思えます。

私自身、リーダーという立場にはいないものの、似たようなポジションを与えられています。
何も思い通りに行かず困り果てていますが、自分の未熟さを再認識して一歩ずつリーダーについて理解を深めていこうと思います。
Windows 11 + WSL/Ubuntu の 定期的なメンテナンス

# 1週間に1回程度

- Windows Update
- PC Manager > 記憶域 > 詳細クリーンアップ

```zsh
sudo apt update
sudo apt upgrade
sudo apt autoremove
```

# 1ヶ月に1回程度

- Microsoft Store > ライブラリ > 更新プログラムを取得する

# 1年に1回程度

```zsh
sudo vim /etc/update-manager/release-upgrades    # 私はlts releaseにする
sudo do-release-upgrade -c
sudo do-release-upgrade -d
sudo apt full-upgrade
sudo apt autoremove
```
Junitとは？

今回はJUnit について記事にしたいと思います。

JUnitとは？
JUnitは、Javaプログラムにおける単体テスト（ユニットテスト）を行うためのフレームワークです。Javaアプリケーションのコードが正しく動作しているかを自動的にテストするために利用され、多くのJava開発者が日常的に使用しています。

なぜJUnitが重要なのか？
自動化されたテスト: JUnitを使用すると、コードを手動でテストする必要がなく、ボタン1つで大量のテストを実行できます。これにより、開発者の手間が省け、時間を大幅に短縮します。
バグの早期発見: コードを小さな部分に分割してテストできるため、バグを早期に発見し、修正がしやすくなります。
回帰テスト: アプリケーションが進化しても、既存の機能が壊れていないか確認するのに役立ちます。
品質の向上: テストを自動化することで、品質の高いソフトウェアを効率よく開発することが可能です。
JUnitの主な特徴
アノテーション: JUnitでは、テストクラスやメソッドに対して様々なアノテーションを利用できます。主なアノテーションは以下の通りです。

@Test: テストメソッドを示します。
@BeforeEach: 各テストの前に実行するメソッドを示します。
@AfterEach: 各テストの後に実行するメソッドを示します。
@BeforeAll: 全テストの前に一度だけ実行されるメソッドを示します。
@AfterAll: 全テストの後に一度だけ実行されるメソッドを示します。
アサーション: JUnitでは、期待する結果と実際の結果を比較するためにアサーション（assertion）を使います。以下はよく使われるアサーションです。

assertEquals(expected, actual): 期待する値と実際の値が等しいかを確認します。
assertTrue(condition): 条件が真であるかを確認します。
assertFalse(condition): 条件が偽であるかを確認します。
assertNull(object): オブジェクトがnullであるかを確認します。
assertNotNull(object): オブジェクトがnullでないかを確認します。
テストスイート: 複数のテストをまとめて実行するための機能です。複数のテストクラスを1つのスイートにまとめることで、効率的にテストを行えます。

簡単なJUnitテストの例
まず、簡単なJUnitのテストコードを見てみましょう。たとえば、数値の足し算を行うメソッドをテストする場合の例です。

```java
import static org.junit.jupiter.api.Assertions.*;
import org.junit.jupiter.api.Test;

public class CalculatorTest {

    @Test
    public void testAddition() {
        Calculator calculator = new Calculator();
        int result = calculator.add(2, 3);
        assertEquals(5, result);  // 期待する結果と実際の結果が同じかを確認
    }
}
```

このコードでは、Calculatorというクラスのaddメソッドが正しく動作しているかをテストしています。assertEquals(5, result)によって、2と3を足した結果が5であるかを確認しています。

JUnitを使用する際のポイント
テスト駆動開発 (TDD): JUnitを使うと、TDD（Test-Driven Development）が効果的に行えます。TDDでは、最初にテストを書き、その後にコードを書いてテストが成功するように開発を進めます。

カバレッジの確認: JUnitのテストだけでなく、テストがコード全体をどれだけカバーしているか（カバレッジ）も確認することが重要です。これにより、テストが十分かどうかを判断できます。

継続的インテグレーション (CI): JUnitはJenkinsやGitHub ActionsなどのCIツールと連携して、コードの変更があるたびに自動でテストを実行するように設定することができます。

今回はJUnit について記事にしてみました。
python 関数の基礎（自分用）

pythonを学ぶ上で、避けては通れない関数について学ぶ。

1.基本編（再利用可能な関数）
-
関数の構造は次のようになっており、<strong>def 関数名（引数）:</strong>と表される。
関数として定義しておくと、後からいつでも再利用が可能となるため、同じような処理が続く場合などは関数にすることを検討すること。
関数内に関数を書くことも可能であり、global変数やlocal変数という概念も出てくるが、それについては後ほどまとめることにする。
```
# "Hello World"と出力する関数（引数なし）

def hello():
    print("Hello World")

say_hello = hello()
# 出力 ⇒ Hello World


# 引数の計算結果を出力する関数（引数あり）

def add_calc(a,b):
    c = a + b
    print(c)
    return c

result = add_calc(1,1)


# 出力 ⇒　2
```

2.lambda（無名関数）
-
計算の途中で１回だけ使いたいなど再利用をしない場合については無名関数を用いることで、コードが１行になりシンプルな記述にすることができる。
lambda関数を単体で使うよりは、map、fitter、sortedといった文法と組み合わせて使うことが一般的である。
```
# filter関数とlambda関数（無名関数）の組み合わせ

def list_append():
    num_list = [i for i in range(1, 6)]
    return num_list

numbers = list_append()
odd_numbers = list(filter(lambda x: x % 2 != 0, numbers))
print(odd_numbers)


# 出力　⇒　[1,3,5]
```
3.まとめ
-
1.まとまった処理は関数化しておくことで、可読性、保守性の向上につながる。
（いわゆるコンポーネント化という概念）
2.lambda は def による関数の定義を一行にまとめることができる
3.基本的には他の関数・メソッドなどと組み合わせて用いる
4.def の代わりにそのまま使うことは推奨されていない
デジタルフィルタ



---

# 【Z変換の基本公式】ディジタル信号処理における基本シーケンスのZ変換まとめ

ディジタル信号処理（DSP）では、Z変換が重要な役割を果たします。本記事では、よく使われる基本シーケンスのZ変換と、その導出に関連する数式を紹介します。

## 基本シーケンスのZ変換一覧

以下は、ディジタル信号の基本シーケンスとそのZ変換です。ここで、シーケンスは一般的に \( n \) として表され、Z変換の結果は \( z \) の関数として示されます。

1. **インパルス関数：**
   \[
   \delta[n] \leftrightarrow 1
   \]
   インパルス関数は、Z変換すると常に1になります。

2. **遅延インパルス関数：**
   \[
   \delta[n - q] \leftrightarrow \frac{1}{z^q}, \quad q = 1, 2, \ldots
   \]
   \( \delta[n - q] \) は \( q \) サンプル遅延したインパルスであり、そのZ変換は \( z \) の負の冪で表されます。

3. **単位ステップ関数：**
   \[
   u[n] \leftrightarrow \frac{z}{z - 1}
   \]
   単位ステップ関数 \( u[n] \) のZ変換は、特性方程式 \( \frac{z}{z-1} \) で表されます。

4. **単位ステップ関数の和：**
   \[
   u[n] + u[n - q] \leftrightarrow \frac{z^q - 1}{z^{q - 1}(z - 1)}, \quad q = 1, 2, \ldots
   \]
   2つの単位ステップ関数の和のZ変換は、少し複雑な形になります。

5. **指数重み付き単位ステップ関数：**
   \[
   a^n u[n] \leftrightarrow \frac{z}{z - a}, \quad a \text{ は実数または複素数}
   \]
   係数 \( a \) で重み付けされた指数関数シーケンスのZ変換です。

6. ** \( n \) 倍の単位ステップ関数：**
   \[
   n u[n] \leftrightarrow \frac{z^2}{(z - 1)^2}
   \]
   時間領域での係数 \( n \) をかけると、Z変換は2次の分数形になります。

7. ** \( n + 1 \) 倍の単位ステップ関数：**
   \[
   (n + 1) u[n] \leftrightarrow \frac{z}{(z - 1)^2}
   \]
   こちらも \( n \) 倍の場合と似た形になりますが、分子と分母の次数が異なります。

8. **コサイン変調シーケンス：**
   \[
   (\cos \Omega n) u[n] \leftrightarrow \frac{z^2 - (\cos \Omega) z}{z^2 - (2 \cos \Omega) z + 1}
   \]
   コサイン変調されたシーケンスのZ変換です。

9. **サイン変調シーケンス：**
   \[
   (\sin \Omega n) u[n] \leftrightarrow \frac{z^2 - (\sin \Omega) z}{z^2 - (2 \cos \Omega) z + 1}
   \]
   サイン変調されたシーケンスのZ変換です。

10. **指数重み付きコサインシーケンス：**
    \[
    a^n (\cos \Omega n) u[n] \leftrightarrow \frac{z^2 - (a \cos \Omega) z}{z^2 - (2 a \cos \Omega) z + a^2}
    \]
    係数 \( a \) で重み付けされたコサインシーケンスのZ変換。

11. **指数重み付きサインシーケンス：**
    \[
    a^n (\sin \Omega n) u[n] \leftrightarrow \frac{(a \sin \Omega) z}{z^2 - (2 a \cos \Omega) z + a^2}
    \]
    同様に、指数重み付きサインシーケンスのZ変換です。

## 基本シーケンスのシステム応答例

### 1. 1次システムのZ変換特性
以下は、システムの出力 \( Y(z) \) を入力 \( X(z) \) およびシステム関数 \( H(z) \) で表した例です。

- システムの応答:
  \[
  Y(z) = H(z) \cdot X(z), \quad H(z) = \frac{bz}{z + a}
  \]

### 2. システムのフィードバック特性


  システム関数 \( H(z) \) は以下のように求まります。
  \[
  H(z) = \frac{1 - a}{1 - az^{-1}}
  \]

### 3. 平均化フィルタの特性
平均化フィルタのシステム関数は次のように表されます。

- 平均化フィルタのシステム関数:
  \[
  H(z) = \frac{1}{M+1} \sum_{m=0}^{M} z^{-m}
  \]

### 4. システムの遅延特性
1サンプルの遅延特性は次のように示されます。

- 遅延特性:
  \[
  H(z) = 1 - z^{-1}
  \]

### 5. 共振器の条件
システムがレゾネータになる条件は以下の不等式で表されます。

- 共振器の条件:
  \[
  a_1^2 + 4a_2 < 0
  \]

システム関数 \( H(z) \) は次のように定義されます。
\[
H(z) = \frac{1 - a_1z^{-1} - a_2}{1 - a_1z^{-1} - a_2z^{-2}}
\]

## おわりに
本記事では、基本的なディジタルシーケンスのZ変換といくつかのシステム応答の例を紹介しました。Z変換の公式をしっかりと理解することで、ディジタル信号処理におけるシステム解析やフィルタ設計が容易になります。


http://www.ic.is.tohoku.ac.jp/~swk/lecture/yaruodsp/dfbasic.html


https://haratta-tech-lab.com/getting-started-iir-filter/

https://bluefish.orz.hm/sdoc/fftw_digifil.html#%E7%A7%BB%E5%8B%95%E5%B9%B3%E5%9D%87%E3%83%95%E3%82%A3%E3%83%AB%E3%82%BF%E3%81%AE%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0
Ansible　基礎

# 最初に

Ansibleを業務で使用することになりました。
そのため勉強したことをまとめています。

# Ansibleとは

IaC(Infrastructure as code)でOSSの自動構成管理ツールの一種

## Ansibleの利点

・エージェントレス
⇒管理対象のサーバ等にエージェントのインストールが不要
　SSHで接続することが出来れば管理が可能なため自動化するさいのハードルが低い

・冪等性(べきとうせい）の担保
⇒冪等性とは何度繰り返し行っても常に同じ結果になること。
　Ansibleは上記を保証する設計になっており、例としてNginxをインストールしようとするさい既にインストールされていなければインストールしインストールされていたら処理をスキップしてくれる。

 ・インフラ構成を定義するPlaybookはYMAL形式で記載
 ⇒YMALというもので書かれており読みやすく、低い学習コストで文法を取得しやすい

 ・多種多様な環境に対応
 ⇒Linuxサーバのほか、Cisco/Winodws等も管理することが可能
 　環境の違いを意識せず統一された方法でインフラに対する変更作業等の自動化が可能

  ## Ansible動作要件

  ・Pythonが導入された環境で動作する。

  ・動作するホストをコントロールノード
  　自動化対象をターゲットノードと呼ぶ

   ・ターゲットモジュールにはPythonがインストールされている必要がある。

   ## Ansibleのコンポーネント

   Ansibleには下記４つのコンポーネントがある。
   ☆：Ansible利用時にユーザが作成しなければいけない対象

   ・プレイブック（Playbook）☆

   ・インベントリ（Inventory）☆

   ・モジュール（Module）

   ・プラグイン（Pligin）


## 最後に

次はプレイブックとインベントリについて勉強しまとめたい
Redmineによるメール連携機能をGmailで実現する

# 背景

Microsoftのoutlook.comのメールを使って、以下の機能を持つRedmineとメールを連携させたシステムを作っていました。

- メールが届くと、メール内容を元に自動でRedmineにチケット登録する
- 期限数日前に、Redmineからリマインドメールを送る
- チケットが発行されたりチケットの状態が変わると、関係者にメール通知する

2024年9月16日に[Outlookのセキュリティが強化されました。](https://news.mynavi.jp/techplus/article/20240613-2964652/)このシステムはoutlook.comのベーシック認証(IDとパスワードによる認証)を使っていたため、メール連携機能が使えなくなってしまいました。
Outlookでは難しそうだったので、Gmailで同様のメール連携機能が使えるようにしました。


# Redmineのメール連携機能

RedmineではSMTP・IMAPを使ってメールサービスと連携することができます。[^1][^2]

2024年9月16日以降、Outlookでは、ベーシック認証ではSMTP・IMAP認証ができなくなったので、他の方法を探す必要があります。
そこで、GmailでSMTP・IMAP認証を通すことにします。


# Gmailで認証を通す方法

GmailもOutlook同様、現時点(2024年10月)では、標準ではベーシック認証でSMTP・IMAP認証を通すことができません。
その代わり、[アプリパスワードを発行する](https://support.google.com/mail/answer/185833?hl=ja)と、GoogleのIDとアプリパスワードでSMTP・IMAP認証を通すことができるようになります。
アプリパスワードを発行するには、2段階認証が必須となります。


# Redmineの設定方法

私が使っている[sameersbn/redmine](https://github.com/sameersbn/docker-redmine)の場合は`docker-compose.yml`を以下のように記載します。

```yaml
    environment:
      ...
      - SMTP_ENABLED=true
      - SMTP_METHOD=smtp
      - SMTP_DOMAIN=www.gmail.com
      - SMTP_HOST=smtp.gmail.com
      - SMTP_PORT=587
      - SMTP_USER=メールアドレス
      - SMTP_PASS=アプリパスワード
      - SMTP_STARTTLS=true
      - SMTP_AUTHENTICATION=:login
      - IMAP_ENABLED=true
      - IMAP_HOST=imap.gmail.com
      - IMAP_PORT=993
      - IMAP_USER=メールアドレス
      - IMAP_PASS=アプリパスワード
      - IMAP_SSL=true
```

他の方法[^1][^2]でも同様に設定できると思います。
[^1]: https://redmine.jp/guide/Email_Configuration/
[^2]: https://www.redmine.org/projects/redmine/wiki/RedmineReceivingEmails
Googleのソフトウェアエンジニアリング（リームリーダー入門編）

## 背景
エンジニアとして広い視野を持つために、エンジニアリング論全体が記載されている本を読みたくなった。
本記事は意識したい言葉の抜粋のみのため、詳しい中身は本でご確認ください。

## 目的
ソフトウェア開発の正しい姿とは？リーダーとは？ぼんやりでもイメージを持つこと

## 本文
> バナナを育てているのにりんごを数える罠に落ちてはならない。

IC（個人作業者）の時はりんごを育てて数えるが、マネージャー側は育てる側に回るため、「1日の終わりに今日は全くやらなかったな」という感覚になりやすい。ただし、それは正常なこと。

> 何よりも管理しようという衝動に抵抗せよ

新人のマネージャーが一番強く感じる衝動が管理しようという気持ち。相手を大人として扱い、やる方法はチームに任せ、何をやり遂げられたかを気にしよう。


> 自分自身が貫ける、とチームメンバーに感じさせよう

リスクを避けすぎず、失敗しても問題ないことをチームに感じさせよう。完遂できることがわかりきっている取り組みより、失敗するほど難しいことを実施し早く失敗してそこから学ぼう。


> 会社を歯車の連鎖として見よ

上が1回転すると、下は2、3回転する。そうして上に行くほど多くの歯車を回す。

> どんな時も平静を保つ能力を真に会得せよ

自分の印象を伝え、平静を保つことが、より多くの者を率いる上で重要になってくる。

> チームがうまくやっている時はチームにそれを知らせる

モチベーションを維持する上で重要

> 元に戻すのが簡単なものに「イエス」と言うのは容易い

技術的な決定も非技術的な決定も思ったより元に戻せる物事は多い。

> 人は植物のようなもので動機づけや方向づけが必要な人もいる

何が必要かはチームメンバーによって違う。
動機づけも方向づけも必要としないのに行おうとすれば単に迷惑。

> 決定とは、トレードオフ群の継続的なバランス調整と反復である。

トレードオフを特定して調整してく反復していく作業が必要になるかもしれない。
完全な解放を探し求める罠に陥いることを避けよう。

## 学び
今回、プログラマーのヘルプとして入ることで、どこまで自分が検討して、どこまで彼に実施してもらうのか難しいところだった。ついついバナナを育てそうになるが、方向を決定してあとは任せる、くらいの方がちょうど良いのだろう。
ただ、正しい方向を決定する能力は、意識して磨いていきたい。
楽観的UI更新について

# 楽観的UIとは？
楽観的UIとは、ユーザーの操作が完了する前に、その結果を即座に画面に反映させる技術です。通常、データがサーバーと同期されるまでの待ち時間を短縮し、ユーザー体験を向上させることが目的です。操作後にすぐフィードバックを得られるため、特にレスポンスの遅いAPIや不安定なネットワーク下でも快適なユーザー体験を提供できます。

**Reactで楽観的UIを実装する際、以下の流れで進めます。**
- ローカル状態を即座に更新
- APIリクエストを送信
- レスポンスに基づき最終的な状態を確定

では、具体的にどのように楽観的UIを実装するのか、シンプルな例で見ていきましょう。

## 例：タスク管理アプリにおける楽観的UI
### 前提
サーバーからタスクを取得し、追加・更新・削除を行うシンプルなタスク管理アプリを例にします。

#### 1. タスクの追加機能
まず、タスクを追加するUIを考えます。通常のタスク追加処理では、サーバーにリクエストを送信し、そのレスポンスを待って画面を更新しますが、楽観的UIではそのリクエストの前に画面を更新します。

``` tsx
import { useState } from 'react';
import { supabase } from './supabaseClient';
import { Task } from './types';

type Task = {
  id: number;
  title: string;
  status: 'pending' | 'complete';
};

function TaskList() {
  const [tasks, setTasks] = useState<Task[]>([]);

  const addTask = async (title: string) => {
    // 1. 楽観的にローカル状態を更新
    const newTask: Task = { id: Date.now(), title, status: 'pending' };
    setTasks([...tasks, newTask]);

    try {
      // 2. サーバーにデータを送信
      const { data, error } = await supabase.from('tasks').insert([{ title }]);
      if (error) throw error;

      // 3. サーバーからのレスポンスに基づいて状態を更新
      setTasks((prevTasks) =>
        prevTasks.map((task) =>
          task.id === newTask.id ? { ...task, id: data[0].id, status: 'complete' } : task
        )
      );
    } catch (error) {
      setTasks((prevTasks) => prevTasks.filter((task) => task.id !== newTask.id));
      console.error('Error adding task:', error);
    }
  };

  return (
    <div>
      <h1>Task List</h1>
      <button onClick={() => addTask('New Task')}>Add Task</button>
      <ul>
        {tasks.map((task) => (
          <li key={task.id}>{task.title} ({task.status})</li>
        ))}
      </ul>
    </div>
  );
}

export default TaskList;
```
##### 実装のポイント
**楽観的な状態更新**
APIリクエストを行う前に、ローカル状態に新しいタスクを即座に追加します。この段階では、サーバーのレスポンスを待たず、あくまで「楽観的」にUIを更新します。

**APIリクエストの処理**
Supabaseを使ってサーバーに新しいタスクを送信します。サーバーからのレスポンスが返ってきた際に、タスクIDやステータスを更新して、最終的なデータをローカル状態に反映させます。

**エラーハンドリング**
万が一サーバー側でエラーが発生した場合、ローカルで追加したタスクを削除して、楽観的な更新を取り消します。これにより、ユーザーに不正なデータが表示され続けることを防ぎます。

#### 2. 削除機能
同様に、タスクを削除する際にも楽観的UIを適用できます。
``` tsx
const deleteTask = async (taskId: number) => {
  // 1. ローカル状態から即座にタスクを削除
  const previousTasks = tasks;
  setTasks(tasks.filter((task) => task.id !== taskId));

  try {
    // 2. サーバーに削除リクエストを送信
    const { error } = await supabase.from('tasks').delete().eq('id', taskId);
    if (error) throw error;
  } catch (error) {
    // エラーハンドリング（削除失敗時は元の状態に戻す）
    setTasks(previousTasks);
    console.error('Error deleting task:', error);
  }
};

```
## 楽観的UIのメリット
レスポンス速度の向上: APIリクエストの処理時間を待たずに、即座にUIが更新されるため、ユーザーの操作感が向上します。
ユーザーエクスペリエンスの向上: サーバーとの通信遅延を感じさせないスムーズな体験を提供できます。
## 楽観的UIのデメリット
サーバーとの不整合の可能性: サーバーとの通信が失敗した場合、表示されている内容が実際のデータと一致しなくなる可能性があります。このため、エラーハンドリングやロールバック処理が重要です。

# まとめ
Reactで楽観的UIを実装することで、ユーザー体験を大幅に向上させることができます。特に、APIのレスポンスが遅い場合や、リアルタイム性が求められるアプリケーションでは有効です。

# 最後に
他にも色々な記事を書いているので、よければ読んでいってください！

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11