OmniAICreator/Qiita-1.07M huggingface dataset:
wslでelixir その153

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。

# 練習問題
Livebookで、kino_bencheeを使え。

# setup


```

Mix.install([
  {:kino_benchee, "~> 0.1.0"}
])
```

# サンプルコード

```
list = Enum.to_list(1..10_000)
map_fun = fn(i) -> 
  [i, i * i] 
end

Benchee.run(%{
  "flat_map" => fn -> 
    Enum.flat_map(list, map_fun) 
  end,
  "map.flatten" => fn -> 
    list 
    |> Enum.map(map_fun) 
    |> List.flatten 
  end
})
```

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/926a2423-3ea5-cf5d-391d-44fa19b3b747.png)


以上。
【Wi-Fi ルータ】壊れたと思って買い換えたのに、実は壊れてはいませんでした

### 経緯
　Qiita の各記事の末尾に表示される「関連記事」欄は、閲覧中の記事に類似した他の有益な記事を教えてくれる便利な機能です。ところが、最近、**関連記事欄だけが表示されなくなる不具合が頻発**するようになりました。

　Qiita 運営に助けを求め、指示を受けた確認テストの結果を伝えたところ、私の**閲覧環境の不具合**の可能性が大きいとのことでした。そこで、パソコンを Wi-Fi ルータへの無線接続から、ONU への有線接続に変えてみたところ、見事に不具合が解消しました。

### 対策と結果（その１）
　そこで、約７年間使用してきた Wi-Fi ルータの寿命が尽きたと判断し、直ぐに**新型の代替品を購入**して立ち上げました。当初は快適に動作し、めでたく問題解決かと思われました。ところが、一時間ほど使用すると、電波は最強状態で出ているのに**インターネット接続が突然切断**するという事態に見舞われました。ページの表示の一部に不満があるだけだった**旧品のときよりも深刻**です。
 
　Wi-Fi ルータの電源を落としてから再起動させれば正常に戻りますが、時間が経てば同様に切断してしまいます。

### 対策と結果（その２）
　ネットの対策記事を参考に、泥沼に嵌りながら色々とやってみました。それら一つ一つについて書くと長くなるので省略しますが、どの対策も効を奏しませんでした。しかし、最後になって、今まで **「ルータモード」にしていた切替スイッチを「ブリッジモード」に切り替え**たところ、１０日間以上の継続使用でも不具合は発生しなくなりました。**問題解決**です。

### 疑問と確認
 　ここで、**古いルータでも「ブリッジモード」に切り替えていれば正常に動作していたのでは？** という疑問が湧いてきます。そこで、ブリッジモードにして確認してみたところ、１０日間以上の継続使用でも不具合は発生しません。ルータモードに戻すと、間もなく問題が再現します。なんと、**古いルータは壊れていなかった**のです。

### 種明かし

　当家の Wi-Fi 環境は下記のようになっています。
 
　**光ケーブル ～ ONU（光回線終端装置） ～ Wi-Fiルータ**

　ところが、このONU（<font Color="#aaa">PR-500KI/GE-ONU、NTT西日本からのレンタル品</font>）は光/電の信号変換だけでなく、ルータ機能も兼ね備えているようです。そのため、これに Wi-Fi ルータを「ルータモード」にして接続すると、**二重ルータ**状態になります。どうも、これが良くなかったようです。

### 反省と言い訳と教訓

　「二重ルータ」という言葉は、以前にも聞いたことはあるような・・・、あまり推奨されない状態ではあるらしいような・・・という程度の知識はあったものの、「Wi-Fi ルータは一台しか持っていないから、自分には関係ないこと」と、あまり気にも留めていませんでした。

　ONU にもルータ機能があると分かったあとでも、次のような諸情報もあり、必ず避けなければならない重大な問題であるとの認識は湧いてきませんでした。

 + ネット情報：　最近のルータは性能が向上し、二重にしても、応答が少々遅くなる程度で大きな問題はない。
 + ネット情報：　二重ルータの方がセキュリティが向上する。
 + ルータの「つなぎかたガイド」：　切替スイッチは購入時の「ルータモード」のままにして設定操作をすること。（その後、状況に応じて「ブリッジモード」に切り替えるという指示は見当たりません）
 + 現実の体験：　二重ルータ状態でも、最近になるまで異常を経験したことがない。

　教訓として・・・、いつでも効果があるとは限りませんが、**W-Fi ルータが不調になったときには、念のためモード切替スイッチを確認**してみては如何でしょう。

　なお、このスイッチは、運用中に切り替えても正常に機能できるかどうかは知りません。念のため、一旦電源を落として、切り替えた後で再投入して立ち上げました。

### その他

#### 途中から不調が現れた始めた原因

　不明ですが、想像の範囲で挙げてみれば、
+ ONU や Wi-Fi ルータのファームウェアの自動バージョンアップ？（そのような機能が備わっているのかどうかは知りませんが・・・）
+ 他の電波との干渉？　（マンション住まいなので多数の SSID が表示されますが、自 Wi-Fi 以外にはそれほど強い電波はありません。電子レンジは昔から使用しているもので、設置場所も変えていません）

#### Wi-Fi ルータの機種名

　参考までに、Wi-Fi ルータの機種名は次のとおりです。
　　旧機種：　Aterm WG1800HP2
　　新機種：　Aterm WX5400HP
現在は、旧機種を「ブリッジモード」に切り替えた状態で継続使用しており、新機種は予備機として保管待機させています。

#### プリンタの Wi-Fi 設定

　パソコン、スマホ、タブレットは複数の SSID 名を記憶しており、ルータを取り換えても自動的に動作中のルータに切り替ります。
 
 　しかし、プリンタだけは、ルータを変えるたびにパスワードを入力して再設定が必要になり、かなり面倒でした。プリンタは据え置き状態で利用する機器なので、これが普通なのでしょうね。
【Emacs】neotree-mode における quicklook を GNOME sushi と xdotool を援用して実装した

かつてこんな記事を書いたことがある。

https://qiita.com/ballforest/items/b99f3f1575adf3061363

neotree-modeにおいてquicklook機能をMacOSのQuickLook (qlmanage) をラップする形で実装したものである。

さてUbuntuユーザにも同様の機能が欲しくなる。QuickLook相当のものは GNOME sushi であり、インストールは容易である。

```bash
sudo apt install gnome-sushi
```

これでインストールされる `sushi` コマンドを使って冒頭の記事のように実装すると、プレビュー自体は起動するのだが、初回のプレビュー以降はEmacsのフレームの後ろに隠れてしまう。やはり常に前面にプレビューが出てほしい。

そこでUbuntuのコマンド `xdotool` を利用する。

```bash
sudo apt install xdotool
```

設定は下記コードによる。sushi を動かしている実体 `org.gnome.NautilusPreviewer`　を `xdotool` により探し出し、プレビューのウィンドウを前面に引っ張り出す (windowactivate) 仕組みである。

```lisp
(require 'neotree)

(defvar neotree-sushi-search-command
  "xdotool search --desktop 0 org.gnome.NautilusPreviewer windowactivate")

(defun neotree-sushi (file-path &optional arg)
  (interactive)
  (neo-global--select-mru-window nil)
  (call-process-shell-command 
   (format "sushi %s; sleep 0.1; %s"
           file-path
           neotree-sushi-search-command)
   nil 0))

(defun neotree-quick-look2 ()
  "Quick Look like NeoTree open event."
  (interactive)
  (neo-buffer--execute nil 'neotree-sushi 'neo-open-dir)
  (neo-global--select-window))

(with-eval-after-load "neotree"
  (define-key neotree-mode-map (kbd "SPC") #'neotree-quick-look2))
```

これにより、Ubuntuでも快適なプレビューが実現できる。同様のハックはdiredにも応用できるだろう。
OCI Computeインスタンスのログインユーザーを変更する

# はじめに
OCIのComputeインスタンスのデフォルトユーザーはopcですが、複数人でopcユーザーを使ってると、監査の都合上よくない場合があります。（誰が操作したかわからないので）
そこで、各自のユーザーを作成して、opcにsuするようにした際の手順です。

# ユーザーを作成し、SSHでログインできるようにする
こちらの内容を参考に各自のユーザーを作成し、SSH接続できるようにします。

https://www.ashisuto.co.jp/db_blog/article/howto-allow-ssh-connections-other-than-opc-users.html

# パスワードなしでopcにsuできるようにする
PAM認証モジュールの設定ファイル`/etc/pam.d/su`の以下の記載の下に2行追記します。

`auth            sufficient      pam_rootok.so`

```/etc/pam.d/su
・・・
auth            sufficient      pam_rootok.so

auth       [success=ignore default=1] pam_succeed_if.so user = opc #追記
auth       sufficient   pam_succeed_if.so use_uid user ingroup opc　#追記
・・・
```

opcグループに作成したユーザーを追加します。

```
$ sudo usermod -aG opc ユーザー名
```

# SSHの設定変更

`/etc/ssh/sshd_config`ファイルに`AllowUsers`の行を追加して、作成したユーザーを記載します。複数いる場合はスペースで区切ります。ついでにrootでSSH接続できないようにしておきます。

```/etc/ssh/sshd_config
PermitRootLogin no #yesをnoに変更

AllowUsers ユーザー名1 ユーザー名2 #追記
```

sshdを再起動します。

```
sudo systemctl reload sshd
sudo systemctl restart sshd
```
【PostgreSQL】メタコマンド〜\di〜

## 初めに

Qiita Engineer Festa 2024に参加中。完走目指してます。
他のメタコマンドについては以下から読んでください。

https://qiita.com/dai_chi/items/04f5339d54130f070671

## \diとは

> このコマンド群において、`E`、`i`、`m`、`s`、`t`、`v`という文字はそれぞれ、外部テーブル、インデックス、マテリアライズドビュー、シーケンス、テーブル、ビューを表します。 これらの種類のオブジェクトの一覧を表示するために、これらの文字の中の任意の文字またはすべてを任意の順番で指定することができます。 例えば、`\dti`はテーブルとインデックスを列挙します。 `+`がコマンド名に付与された場合、各オブジェクトは、もしあれば永続性の状態(permanent、temporary、またはunlogged)、ディスク上の物理容量、関連する説明をつけて表示されます。 `pattern`が指定されている場合は、パターンに名称がマッチする項目のみが表示されます。 デフォルトでは、ユーザが作成したオブジェクトのみが表示されます。 システムオブジェクトを含めるためにはパターンまたは`S`修飾子を付与してください。
> 

[\diについて](https://www.postgresql.jp/docs/15/app-psql.html#:~:text=S%2B%5D%20%5B%20pattern%20%5D-,%5Cdi%5BS%2B%5D%20%5B%20pattern%20%5D,-%5Cdm%5BS%2B%5D%20%5B)

## 試してみた

まずは`\di`を使ってみる

```sql
postgres=# \di
                         リレーション一覧
 スキーマ   |      名前      |    タイプ      |   所有者    | テーブル  
----------+----------------+--------------+------------+-----------
 public   | employees_pkey | インデックス    | daichi     | employees
(1 行)
```

`+`を使って詳細も確認する

```sql
postgres=# \di+
                                               リレーション一覧
 スキーマ   |      名前      |    タイプ      |   所有者    | テーブル    | 永続性  | アクセスメソッド      | サイズ  | 説明 
----------+----------------+--------------+------------+-----------+--------+------------------+--------+------
 public   | employees_pkey | インデックス    | daichi     | employees | 永続    | btree            | 16 kB  | 
(1 行)
```

## まとめ

SQLチューニングでどんなindexがあるかを見たりするのに使ったことがあるような。
【PostgreSQL】メタコマンド〜\dn〜

## 初めに

Qiita Engineer Festa 2024に参加中。完走目指してます。
他のメタコマンドについては以下から読んでください。

https://qiita.com/dai_chi/items/04f5339d54130f070671

## \dnとは

> スキーマ（名前空間）の一覧を表示します。 `pattern`を指定すると、パターンに名前がマッチするスキーマのみが表示されます。 デフォルトではユーザが作成したオブジェクトのみが表示されます。 パターンまたは`S`修飾子を追加すると、システムオブジェクトが表示に追加されます。 コマンド名の後に`+`を付加すると、各オブジェクトに関連付けられている権限と説明が（存在すれば）表示されます。
> 

[\dnについて](https://www.postgresql.jp/docs/15/app-psql.html#:~:text=%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82-,%5Cdn%5BS%2B%5D%20%5B%20pattern%20%5D,-%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%9E%EF%BC%88%E5%90%8D%E5%89%8D%E7%A9%BA%E9%96%93)

## 試してみた

まずは`\dn`を使う

```sql
postgres=# \dn
        スキーマ一覧
  名前  |      所有者       
--------+-------------------
 public | pg_database_owner
 test   | daichi
(2 行)
```

特定のスキーマを指定

```sql
postgres=# \dn public
        スキーマ一覧
  名前  |      所有者       
--------+-------------------
 public | pg_database_owner
(1 行)
```

詳細を確認する

```sql
postgres=# \dn+
                                         スキーマ一覧
  名前  |      所有者       |              アクセス権限              |          説明          
--------+-------------------+----------------------------------------+------------------------
 public | pg_database_owner | pg_database_owner=UC/pg_database_owner+| standard public schema
        |                   | =U/pg_database_owner                   | 
 test   | daichi            |                                        | 
(2 行)
```

## まとめ

スキーマを確認することは日々の業務ではあまり使ってこなかったけど、権限を確認するのには利用できそう
【PostgreSQL】メタコマンド〜\dp〜

## 初めに

Qiita Engineer Festa 2024に参加中。完走目指してます。
他のメタコマンドについては以下から読んでください。

https://qiita.com/dai_chi/items/04f5339d54130f070671

## \dpとは

> テーブル、ビュー、シーケンスを、関連付けられているアクセス権限とともに一覧表示します。 `pattern`を指定すると、パターンに名前がマッチするテーブル、ビュー、シーケンスのみが表示されます。
> 

[\dpについて](https://www.postgresql.jp/docs/15/app-psql.html#:~:text=%E3%81%8C%E3%81%82%E3%82%8A%E3%81%BE%E3%81%99%E3%80%82-,%5Cdp%20%5B%20pattern%20%5D,-%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%80%81%E3%83%93%E3%83%A5%E3%83%BC%E3%80%81%E3%82%B7%E3%83%BC%E3%82%B1%E3%83%B3%E3%82%B9)

## 試してみた

まずは使ってみる

```sql
postgres=# \dp
                                 アクセス権限
 スキーマ   |       名前        |   タイプ    | アクセス権限    | 列の権限 | ポリシー 
----------+------------------+------------+--------------+----------+----------
 public   | employees        | テーブル    |              |          | 
 public   | employees_id_seq | シーケンス   |              |          | 
 public   | test_tbl         | テーブル    |              |          | 
(3 行)
```

パターンに一致するオブジェクトのみを表示

```sql
postgres=# \dp employees
                             アクセス権限
 スキーマ |   名前    |  タイプ  | アクセス権限 | 列の権限 | ポリシー 
----------+-----------+----------+--------------+----------+----------
 public   | employees | テーブル |              |          | 
(1 行)
```

詳細を確認する

```sql
postgres=# \dp+
                                 アクセス権限
 スキーマ |       名前       |   タイプ   | アクセス権限 | 列の権限 | ポリシー 
----------+------------------+------------+--------------+----------+----------
 public   | employees        | テーブル   |              |          | 
 public   | employees_id_seq | シーケンス |              |          | 
 public   | test_tbl         | テーブル   |              |          | 
(3 行)
```

## まとめ

検証用なのでアクセス権限を指定していないので分かりにくいが、どこにどんな権限があるのかを確認するのに使える
ディレクトリ内の全てのファイルの末尾に拡張子（.pdf）を追加するワンライナー

```zsh
find <directory_name> -type f -name '*' | xargs -I{} mv {} {}.pdf
```
## 各コマンドの意味と役割

1. ```find <directory_name> -type f -name '*'```
    
    - `find`: ファイルやディレクトリを検索するためのコマンド。
    - `<directory_name>`: 検索対象のディレクトリ名。
    - `-type f`: 通常のファイルのみを検索対象にするオプション。これにより、ディレクトリ自体は検索結果（名称変更の対象）から除外される。
    - `-name '*'`: 名前で検索するオプション。`'*'`はワイルドカードで、任意の文字列にマッチする。

    →検索したすべてのファイルを```xargs```へ標準出力する。
    
2. ```xargs -I{} mv {} {}.pdf```
    
    - `xargs`: 標準入力からデータを読み取り、それを引数として別のコマンドを実行するコマンド。
    - `-I{}`: プレースホルダーを指定するオプション。`{}`が各ファイル名に置き換えられる。

    →`{}`が、`<directory_name>`内の任意のファイル名を表す変数として使えるようになる。
    
3. `mv {} {}.pdf`

    - `mv`: ファイルを移動または名前を変更するコマンド。
    - `{}`: 変更対象のファイル名。
    - `{}.pdf`: 変更後の名前。このような簡単な書式で文字列を追加できる。
    
    →`find`コマンドで見つかった各ファイルに対して、元のファイル名に`.pdf`を追加する。

## なぜこのワンライナーを使うのか

 - finderで同じことを行おうとすると、一ファイルごとに確認が発生して面倒なため。
![2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305804/43e3a710-62d1-b672-2c05-e8dc04a175fe.gif)
【coursera勉強ノート】Practical Time Series Analysis（時系列分析）_1

コースURL
https://www.coursera.org/learn/practical-time-series-analysis/home/week/1

## 線形回帰とは
線形回帰は以下の形式でモデルを構築します：
y=β0+βx+ϵ
ここで、𝑦は目的変数、xは説明変数、𝛽0は切片、𝛽は傾き、ϵは誤差項です。

## 線形回帰モデルの適合
Rでの線形回帰モデルの適合は、lm()関数を使用します。
```R:qiita.rb
data(co2)
model <- lm(co2 ~ time(co2))
summary(model)
```

## 前提条件
回帰分析を行う際には、いくつかの前提条件があります。これらの前提条件は、回帰モデルの結果が信頼できるかどうかを判断するために重要です。
残差（residual）とは、回帰分析において観測値とモデルによって予測された値の差のことです。残差は、モデルがデータをどれだけうまく説明しているかを評価するために重要です。

* 残差の正規性:
説明: 残差（実際の値とモデルが予測した値の差）が正規分布に従うこと。
確認方法: 残差のヒストグラムやQQプロットを使用して、正規性を視覚的に確認します。

* 等分散性（ホモスケダスティシティ）:
説明: 残差の分散が説明変数の値に関係なく一定であること。
確認方法: 残差プロット（残差 vs. 予測値）を使用して、残差の分散が一定かどうかを確認します。分散が一定でない場合（ヘテロスケダスティシティ）、プロット上にパターンが現れます。

* 残差の平均がゼロ:
説明: 残差の平均がゼロであること。
確認方法: 残差の平均を計算し、ゼロに近いかどうかを確認します。通常は、回帰モデルが適切にフィットしている場合、この条件は自然に満たされます。

* 独立性:
説明: 残差が互いに独立していること。
確認方法: 残差プロット（残差 vs. 時間）を使用して、時間に関するパターンがないかを確認します。時系列データでは、ランダムなパターンがない場合、この前提が満たされていない可能性があります。

## 前提条件の確認方法
回帰モデルを作成する前にこれらの前提条件を確認するのではなく、モデルを作成した後に確認します。以下に、Rを使ってこれらの前提条件を確認する方法を示します。

1.モデルの作成
まず、データに対して線形回帰モデルを適合させます。
```R:qiita.rb
# 必要なライブラリの読み込み
# install.packages("datasets")
library(datasets)

# データのロード
data("CO2")
co2 <- CO2$conc  # 二酸化炭素濃度
time <- as.numeric(time(co2))  # 時間を数値として取得

# 線形回帰モデルの適合
model <- lm(co2 ~ time)
```

2.残差の正規性の確認
```R:qiita.rb
# 残差のヒストグラム
hist(resid(model), main = "Histogram of Residuals", xlab = "Residuals")

# QQプロット
qqnorm(resid(model), main = "QQ Plot of Residuals")
qqline(resid(model))
```

3.等分散性の確認
```R:qiita.rb
# 残差 vs. 予測値のプロット
plot(fitted(model), resid(model), main = "Residuals vs Fitted Values", xlab = "Fitted Values", ylab = "Residuals")
abline(h = 0, col = "red")
```

4.残差の独立性の確認
```R:qiita.rb
# 残差 vs. 時間のプロット
plot(time, resid(model), main = "Residuals vs Time", xlab = "Time", ylab = "Residuals")
abline(h = 0, col = "red")
```

## 前提条件が満たされない場合
前提条件が満たされていない場合、以下の対策を取ることが考えられます：

残差の正規性が満たされない場合：データの変換（例えば、対数変換）を試みる。
等分散性が満たされない場合：加重最小二乗法（WLS）や一般化線形モデル（GLM）を使用する。
独立性が満たされない場合：時系列モデル（ARIMAなど）や自己回帰項をモデルに追加する。

## まとめ
回帰分析では、まずモデルを作成し、その後に前提条件を確認します。前提条件が満たされていない場合は、データの変換やより複雑なモデルを検討する必要があります。これにより、モデルの適合度や推論結果の信頼性を向上させることができます。
Google Cloud - Professional Data Engineer 試験を振り返る

# はじめに
2024年6月29日にGoogle Cloud認定試験のProfessional Data Engineerに合格しました。私の経験を共有したいと思います。この記事が、これから試験を受ける方々の参考になれば幸いです。

# Google Cloud - Professional Data Engineer試験とは
>Google Cloud - Professional Data Engineer認定資格は、データを収集、変換、公開することで、ほかのユーザーにとってデータを有効で価値のあるものにします。ビジネス要件と規制要件を満たすために、プロダクトやサービスを評価し、選択します。Professional Data Engineerは、堅牢なデータ処理システムを作成して管理します。これには、データ処理ワークロードを設計、構築、デプロイ、モニタリング、維持、保護する能力が含まれます。

Professional Data Engineer試験では、以下に関する能力が評価されます。

- データ処理システムの設計
- データの保存
- データ ワークロードの管理と自動化
- データの取り込みと処理
- 分析用データの準備と使用

（引用: [Google Cloud - Professional Data Engineer認定資格の概要](https://cloud.google.com/certification/data-engineer)）

## 試験範囲
2024年1月30日に日本語版の試験範囲が変更になりました。

#### 削除
- 機械学習関連

#### 追加
- [Analytics Hub](https://cloud.google.com/bigquery/docs/analytics-hub-introduction?hl=ja)
- [BigQuery Omni](https://cloud.google.com/bigquery/docs/omni-introduction?hl=ja)
- [Dataplex](https://cloud.google.com/dataplex/docs/introduction?hl=ja)
- [Datastream](https://cloud.google.com/datastream/docs/overview?hl=ja)
- [Dataform](https://cloud.google.com/dataform/docs/overview?hl=ja)
- [Workflows](https://cloud.google.com/workflows/docs/overview?hl=ja)
- [BigLake](https://cloud.google.com/bigquery/docs/biglake-intro?hl=ja)

追加された箇所の公式ドキュメントを一読することをお勧めします。

# 筆者のレベル
業務でBigQueryとGCSを使用しています。使用期間は半年程度です。

# 試験準備
## 使用した教材
- **公式模擬試験:** Google Cloudの公式サイトにある模擬試験を受講しました。最初は半分も解けませんでしたが、最終的に解説まで理解している状態にしました。

https://docs.google.com/forms/d/e/1FAIpQLSd4j4bcgbYenBRFIL6Kb0cvXp13qCQ-z6JzowgDxRaPITn56g/viewform?hl=ja

- **書籍:** [Google Cloudではじめる実践データエンジニアリング入門](https://gihyo.jp/book/2021/978-4-297-11948-5)を読み、基礎的な知識を身に付けました。
- **Udemy:** UdemyのPDE用模擬試験を受講しました。

https://www.udemy.com/course/2023google-cloud-professional-data-engineer/?couponCode=KEEPLEARNING

https://www.udemy.com/course/latest-gcp-professional-data-engineer-practice-questions/?couponCode=KEEPLEARNING

## 勉強期間
- **期間:** 1か月
- **トータル勉強時間:** 40~50時間


# 試験当日
試験当日はオンラインで受験しました。

## オンライン試験の注意点

- **身分証明が必要**:
  試験開始前に身分証明書を提示する必要があります。今回はパスポートを提示したらOKでした。

- **指定されたブラウザのインストール**:
  予め指定されたブラウザをインストールする必要があります。

- **顔の登録**:
  あらかじめ自分の顔を登録しておく必要があります。

- **試験環境の整備**:
  部屋の中の本棚等は本が見えないようにする必要があります。

- **部屋の撮影**:
  4方向から部屋を映す必要があります。スマートフォンで撮影してアップロードし、その後にWEBカメラで試験官に見せるというダブルチェック体制でした。

## 試験の感想
データ分析関連のサービス名だけを覚えているだけは解けない問題も多く、しっかり理解しているかを問われた印象です。
また、新しく試験範囲に追加されたサービスも多く出題されました。


# 最後に
Professional Data Engineer試験を通して、Google Cloudのデータ分析系のサービスを体系的に理解することができました。
実務に活きる内容も多かったので（特にBigQueryの詳細部分）、日常の業務で役立つと感じています。
また、最新のデータメッシュ関連の技術や新しいデータ分析サービスについても学ぶことができ、今後も新しいサービス・技術のキャッチアップを行っていきたいと思いました。
EC2にdockerで動くアプリをデプロイする手順、コマンドまとめ

# はじめに
EC2、Linux環境にGitやdocker-composeをインストール、GitHubのアプリをクローンして動かせるようにするコマンドなどをまとめました。個人開発やハッカソン用に自分がメモしていたものをまとめましたので拙い部分もあるかと思いますが、参考になれば幸いです。
## 前提
AWS EC2でLinuxを使用
インフラは構築済み、EC2にアクセスできる状態
メモ代わりなのでコマンドなどの細かい説明は省いています。
# 手順
gitのインストール
```
sudo yum install -y git  # gitのインストール
git --version            # gitのインストール確認
```
Dockerのインストール
```
sudo yum install -y docker       # dockerのインストール
sudo systemctl start docker      # dockerの起動
sudo systemctl enable docker     # dockerの自動起動設定
sudo usermod -a -G docker $USER  # 現在のユーザーをdockerグループに追加
newgrp docker                    # 新しいシェルを開く
docker info                      # dockerの起動確認
```
Docker Composeのインストール
```
sudo mkdir -p /usr/local/lib/docker/cli-plugins
sudo curl -SL https://github.com/docker/compose/releases/download/v2.4.1/docker-compose-linux-x86_64 -o /usr/local/lib/docker/cli-plugins/docker-compose
sudo chmod +x /usr/local/lib/docker/cli-plugins/docker-compose
docker compose version   # インストールできてるか確認
```
GitHubからリポジトリをクローン
```
git clone <クローンするリポジトリURL>
```
Docker Composeを使ってアプリケーションを立ち上げる
```
cd <ディレクトリ名>     # クローンしたリポジトリのディレクトリに移動
docker compose up  # docker compose up -d でバックグラウンドで実行
```
コンテナの確認（バックグラウンド実行時）
```
docker ps
docker ps -a  # -aで停止しているコンテナも表示
```
## コンテナ、イメージ削除
コンテナ停止（バックグランドで実行しているとき使用フォアグラウンド実行時はctl+cで停止）
```
docker compose stop
```
コンテナ削除
```
docker compose down
```
特定のイメージ削除
```
docker images          # イメージの確認
docker rmi <image_id>  # イメージを削除
```
未使用のイメージを全て削除
```
docker image prune -a
```
不要なデータ（停止中のコンテナ、未使用のネットワーク、未使用のボリュームなど）を一括でクリーンアップ
```
docker system prune -a
```
## コンテナを再度立ち上げる
```
docker compose build --no-cache # キャッシュなしでビルド
docker compose up               # docker compose up -d でバックグラウンドで実行
```

公式ドキュメントはこちら

https://matsuand.github.io/docs.docker.jp.onthefly/compose/install/

## さいごに
他にも色々コマンドはあると思いますが、よく使うものをまとめました。
ECSなどを使えばDockerで動くアプリは簡単にデプロイできるのでECSも学習していこうと思います。
【Linux】シェルスクリプトにおける && と || の使い方

## 背景

他の方の技術ブログや記事を読んでいて `&&` と `||` ってコマンドラインでも使えるんだなと知りました。

## 説明

`&&` : AND制御演算子。

`command1 && command2` の場合、command1が成功したらcommand2を実行する。


`||` : OR制御演算子。
command1が異常終了した時に、それに対処する形でcommand2を実行出来る。
事後のエラー処理などを行なう時に使える。

## 実行例

### 今のファイルを用意

```sh command01.sh
echo "Test 01";
```

```sh command02.sh
echo "Test 02";
```

```sh command03.sh
echo "Test 03;
```
※command03.shはechoの `"` の閉じを敢えて消してエラーを出す狙い用

### 実行

```sh
$ sh command01.sh && sh command02.sh
Test 01
Test 02
```

```sh
$ sh command03.sh && sh command02.sh
command03.sh: line 1: unexpected EOF while looking for matching `"'
command03.sh: line 2: syntax error: unexpected end of file
```

```sh
$ sh command03.sh || sh command02.sh
command03.sh: line 1: unexpected EOF while looking for matching `"'
command03.sh: line 2: syntax error: unexpected end of file
Test 02
```

```sh
$ sh command02.sh || sh command03.sh
Test 02
```

## まとめ
上記のように、エラーが起きるcommand03.shの指定の仕方で挙動がわかりました。
なるほど〜
「Jetpack Compose の基本」のメモ#7 ~状態ホイスティング、遅延リスト~

### [8. 状態ホイスティング](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#7)
+ 状態ホイスティングとは、複数のコンポーザブル関数で更新される状態変数を、それらの関数を内包(ラップ)する（親要素）に移動させること
+ 状態変数を定義するということは、MutableStateというオブジェクトを定義すること
+ しかしby キーワードを使用することで、MutableState オブジェクトをあたかも通常の変数のように扱えるようにする
+ つまり、.valueを付けなくても値を参照できる

#### MyAppコンポーザブルでボタンを含む関数を呼び出す時のクリック動作
+ 呼び出される関数の引数にクリック時の動作を渡せるように、`onContinueClicked: () -> Unit`を定義する
+ これにより、呼び出し元からクリック動作を指定することができる
+ Unitは値を返さないことを示す型
+ `:() -> Unit`は、「`onContinueClicked`には、引数を取らず、値を返さないラムダ式」という型指定を表す
### [9. 効率の良い遅延リストを作成する](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#8)
```Kotlin
names: List<String> = List(1000) { "$it" }
↓
val names: List<String> = List(1000) { index -> index.toString() } 
```
+ {}カッコ内はは初期化処理が記述されている
+ Column
    + 画面に収まらないものも含めて、すべてのListをレンダリングする
+ LazyColumn
    + 画面に表示されているアイテムのみをレンダリングする
【ChatGPT＋Code Interpreter】『きらきら星』を作ってみた。


　どうも、カーブミラーです。

　今回は、Code Interpreterで『きらきら星』を作ってみました。Qiitaは音声ファイルを載せられないので、それぞれで作成してもらうしかありません😅

:::note info
本記事は、ChatGPT（有料版）
で行なっております。あしからず。
:::

　今日も✘いので、
　　クーラーの効いた室内で
　　　ほどほどに頑張りましょう。
***
　さて、本題です。

　昨日（2024/07/07）は
　　音が出力できるように
　　　なりました。

　ビープ音ではありますが😅

　そこで
　　今回は『きらきら星』を
　　　鳴らせてみます。

　『きらきら星』は
　　ピアノ練習曲で、
　　　初心者向けですね。

　小さな子が
　　オモチャのピアノを
　　　ポンポンと叩いて
　　　　鳴らす曲です。

　でも
　　私は音符も知らなければ
　　　楽譜もありません。
　　　　音楽の授業レベルの知識も
　　　　　ほとんど失っています😅

　そこで
　　ChatGPTさんにお尋ねして、
　　　コードを出してもらいました。

　そのやり取りをどうぞ。
　　音声ファイル生成までやります。
***
***user***
きらきら星の楽譜はわかりますか？

***ChatGPT***
はい、もちろんです。「きらきら星」の簡単な楽譜をお伝えします。

### きらきら星の楽譜

#### メロディー（Cメジャー）

```
C  C  G  G  A  A  G
F  F  E  E  D  D  C
G  G  F  F  E  E  D
G  G  F  F  E  E  D
C  C  G  G  A  A  G
F  F  E  E  D  D  C
```

#### 和音進行

```
C  C  G  G  Am Am  G
F  F  C  C  F  F  G
C  C  G  G  Am Am  G
F  F  C  C  F  F  G
C  C  G  G  Am Am  G
F  F  C  C  F  F  G
```

この楽譜は簡単なバージョンなので、ピアノや他の楽器で演奏しやすいと思います。

***user***（❶）
CodeInterpreterを使って、上記メロディーと和音進行を組み合わせて、曲を作成してください。一行ごとに区切りを入れてください。使用する楽器はサイン波を使用してギター風の音を生成してください。

***ChatGPT***
「きらきら星」のメロディーと和音進行を組み合わせた曲を作成しました。以下のリンクからダウンロードできます。

[ダウンロード: twinkle_twinkle.wav]
***
　❶の部分を説明しますね。

>CodeInterpreterを使って

　ここは
　　Code Interpreterの使用を
　　　宣言しています。

　なくてもいいのかもしれませんが、
　　確実性を求めて宣言します。

>上記メロディーと和音進行を組み合わせて、曲を作成してください。

　ここで、演奏するコード生成します。

>一行ごとに区切りを入れてください。

　ここが肝。
　　これを入れないと、
　　　音が連続してしまい、
　　　　音楽になりません。

　一拍置く、と
　　いう感じでしょうか。

>使用する楽器はサイン波を使用してギター風の音を生成してください。

　これは
　　ギターにしましたけど、
　　　実際にはビープ音のピアノです😅

　ちなみに
　　使っているライブラリを
　　　聞きました。
***
***user***
このPromptで使われるライブラリはなんですか？

***ChatGPT***
このプロンプトで使われるライブラリは以下の通りです：

1. **NumPy**: 波形データの生成と操作に使用します。
2. **SciPy**: 波形データをWaveファイルに保存するために使用します（具体的には`scipy.io.wavfile`モジュール）。

これらのライブラリは、Pythonでの科学計算や信号処理に広く使われており、音声データの生成や保存にも適しています。

### 使用するライブラリのインポート方法
以下のコードは、必要なライブラリをインポートする例です：

```python
import numpy as np
import scipy.io.wavfile as wavfile
```

このプロンプトで使用するライブラリは、NumPyとSciPyのこの2つだけです。これにより、音符の周波数を計算し、それをサイン波として合成し、最終的にWaveファイルに保存します。
***

　NumPyとSciPyの
　　ふたつでしたね。

　ほかの動画系のライブラリを
　　使っているのかと思っていました。

　みなさんの
　　作品制作の糧に
　　　なれば、幸いです。

　今回は、ここまで。
docker compose での環境変数切り替えは .env ファイルではなく environment に直接記述した方が分かりやすいんじゃ

# docker compose  の例

次のように書いておけば、何かと使いやすい気がする

- `XXX_ENV=yeah docker compose up` のようにコマンドレベルで環境変数指定が出来る
- local (ホスト端末) で 環境変数指定なしで `docker compose up` した場合の固定値も指定できる


```yml
version: '3.8'
services:
  xxx_service:
    # ...
    environment:
      # docker compose up 実行時に環境変数指定できるもの
      # ブレースの中は ${localで指定可能な環境変数名:-無指定の場合の固定値} という記法
      - 'XXX_ENV=${XXX_ENV:-foo}'
      # docker compose up 実行時に環境変数指定させていない固定値のもの
      - 'YYY_ENV=bar'
```



# 環境変数ファイルを使う例


`.env.development` のように環境変数指定用のファイルを読み込ませておいて、そのファイル自体は gitignore しておく運用を多く見かける

だがこの方法だとファイルの状態によって開発者間で環境の差異が生じたり、どこで環境変数をコントロールしているのかがわかりづらかったり、という欠点がある


```yml
version: '3.8'
services:
  xxx_service:
    # ...
    env_file:
      - .env.development
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
予定の10分前にメール通知を飛ばす機能を作ってみた！

## はじめに
社内のハッカソンで（ほぼ）初めてActionMailerとActioveJobを使ってみました。
まだ自分の中で、何の機能を誰が担うのかの整理ができていないので、復習を兼ねて記事にしてみました！

※本番環境にデプロイしていません。
## 動作環境
ruby 3.3.1、Rails 7.1.3.3
## 読んで欲しい人
ActiveJob、ActionMailerの存在は知っていて、使ってみたいと思っている人。
## 実装すること
全体のざっくりした機能の流れとしては、ユーザが予定の外出時間の登録or更新をした時に、その外出時間の10分前に確認メールを飛ばすといったものです。
もしユーザがすでに予定の外出時間を登録していて、外出時間の更新をした場合、更新前の外出時間をもとに飛ばそうとしていたメールをキャンセルし、新たにメールの通知予約を作成します。
## 実装
※ UserモデルとUserに紐づくCalendarモデルは作成済みです。
### 予定の10分前に飛ばすメールを作成
まずはメールを作成します。
※今回は準備物を確認を促す通知なので、↓のような名前で作成しました。
```
rails g mailer Essentials encourage_confirmation
```
```app/mailers/essentials_mailer.rb
class EssentialsMailer < ApplicationMailer
  default from: 'notifications@example.com'
  
  def encourage_confirmation
    @user = params[:user]
    @calendar = params[:calendar]
    mail to: @user.email, subject: '準備物を確認してください'
  end
end
```
メールのテキスト内容は省略します。
### メールを飛ばすjobを作成
先ほど作成したメールを送信する、jobを作成します。
```
rails g job send_check_essentials_mail
```
```app/jobs/send_check_essentials_mail_job.rb
class SendCheckEssentialsMailJob < ApplicationJob
  queue_as :default

  def perform(user, calendar)
    EssentialsMailer.with(user:, calendar:).encourage_confirmation.deliver_now
  end
end
```
### 外出時間の10分前にjobを実行
ユーザが登録した外出時間の10分前に通知を飛ばすので、外出時間を管理するcalendarモデルのouting_atが更新された時に、先ほど作成したjobを実行するようにします。
※ calendar.rb作成時点ではouting_atはnilです
```app/models/calendar.rb
class Calendar < ApplicationRecord
  belongs_to :user
  
  after_update do
    SendCheckEssentialsMailJob.set(wait_until: outing_at - 10.minutes).perform_later(user, self)
  end
end
```
### 更新前の外出時間をもとに飛ばそうとしていたメールの予約をキャンセルし、新たにメールの通知予約をする
ここが少し難しかったところです。
まずは、外出時間を更新した時に通知を削除できるように、calendarとjobを紐付けます。
good_jobsテーブルのactive_job_idでjobを一意に識別できるみたいなのですが、モデルが存在しません。
なので、calendarにgood_job_idカラムを挿入し、不要になったjobをcalendarに登録されたgood_job_idをもとに、生のsql文を用い削除します。
```app/models/calendar.rb
class Calendar < ApplicationRecord
  unless outing_at_before_last_save == outing_at
    if good_job_id.present?
      # jobが存在するのか確認
      sql = "select active_job_id from good_jobs where active_job_id = uuid('#{good_job_id}')"
      result = ActiveRecord::Base.connection.select_all(sql)
      # 元の通知を削除する
      if result.rows.present?
        sql = "delete from good_jobs where active_job_id = uuid('#{good_job_id}')"
        ActiveRecord::Base.connection.execute(sql)
      end
    end
    job = SendCheckEssentialsMailJob.set(wait_until: outing_at - 10.minutes).perform_later(user, self)
    # calendarのgood_job_idを新しく作成しjobのidに更新する
    update!(good_job_id: job.job_id)
  end
end
```

## 最後に
いかがだったでしょうか？
個人的に、good_jobのjobを削除する方法についての、good_jobに用意されていないことや参考になる記事が存在しなかったことが意外(探せなかっただけかも)でした。
稀なケースなんでしょうか？
それと、good_jobsテーブルがモデルであれば、calendarとhas_oneの関連付けができ、もっと実装がシンプルだったと思います。
もしテーブルをモデル化できるようであれば、シンプルな内容にして、もう一度挑戦してみたいと思います💪
ご意見、ご感想、アドバイス、どしどしお待ちしております！
X(Twitter)のDB構造を推測してみる

# はじめに

**素人**が**推測してみた**だけの内容ですが、

投稿を扱うサービスには、参考にしていただける部分があるかも。

Twitterの設計にどうこう言いたいのではなく、「変更可能な文字列IDを扱う」場合の１事例と思っていただければ。

# 検索の対象は「ツイート当時のID」

X(Twitter)には「高度な検索」という機能があります。

文言やユーザーIDなどから検索できる機能です。
通常の検索窓からも使用できます。

| [高度な検索](https://x.com/search-advanced?lang=ja) |
|:-:|
| ![スクリーンショット 2024-07-07 18.19.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457770/945cb024-9c19-4402-0f8b-d85e1c8770d2.png)  |

この機能を使用し、過去のツイートを検索してみましたが・・・

![スクリーンショット 2024-07-07 18.24.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457770/fecd079c-921b-606b-8538-f611219a56e4.png)

検索結果がありません。IDは正確です。

ふと思い当たり、昔のIDで検索すると・・・

![スクリーンショット 2024-07-07 18.24.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457770/a3817117-1e5f-3a93-fa8d-ca9af5cebe21.png)

表示されました！

「ツイート当時のIDで検索」する必要があるんですね。

なお、表示結果には「現在のID」が表示されています。

---

ここからわかるのは、以下です。

- 「ツイート」は「文字列ID」と紐づいて保存されている
- 「昔のID」と「今のID」を紐づける何かがある

```mermaid
erDiagram
    users {
        string id PK
        string user_name
    }
    posts {
        int id PK
        string user_id FK
        string body
    }
    blackbox {
        
    }
    users ||--o{ posts: ""
```
「昔のID」と「今のID」を紐づける方法の詳細はわかりませんが、
例えば、`next_id`を記録しておくのは一つかもしれません。

ただ、芋づる式にidを追う必要があり、ユーザー体験だけでなく処理効率も悪いです。

```mermaid
erDiagram
    users {
        string id PK
        string user_name
        string next_id
    }
    posts {
        int id PK
        string user_id FK
        string body
    }
    users ||--o{ posts: ""
```

# 現在のIDでも検索できる仕組み

「昔のIDを覚えてないといけない」仕組みは、ユーザー体験としてマイナスだと思います。

- 文字列IDの他に、内部的に数字IDが存在
- 文字列IDを数字IDにマッピングする

という仕組みにすると改善できそうです。

具体的には

- （擬似的に）文字列のIDを扱う
- 文字列IDのUPDATEに対応

上記の機能を持ちながら、下記の機能が追加されます。

- 現在のIDでの全履歴検索
- 古いIDでの全履歴検索


```mermaid
erDiagram
    users {
        int id PK
        string user_name
    }
    users_id_map {
        string string_user_id PK
        int user_id FK
    }
    posts {
        int id PK
        int user_id FK
        string body
    }
    users ||--o{ posts: ""
    users ||--|| users_id_map: ""
```


（テーブル名へのツッコミはご容赦を）


# おわりに

改めてにはなりますが、本記事の内容はあくまで推測です。

Twitterの設計にどうこう言いたいのではなく、「変更可能な文字列IDを扱う」場合の１事例として考察してみました。
camerax使用時に気をつけたいこと

# はじめに
以前、カメラの実装をComposeでした際に軽く詰まったところを消化していこうと思います
### 本文
https://developer.android.com/media/camera/camerax/preview?hl=ja#scale-type
上記にあるようにカメラのPreview Viewを実装するときはカメラの比率を変えることができないようになっています。
そのため、デザインに合わせた表示するには下記の２種類どちらかの対応が必要になります。
```kotlin
// Box等で無理やりカバーをしてあげる
Column(modifier = modifier) {
        Camera(
            useCase = useCase
        )
        Box(
            modifier = Modifier
                .fillMaxWidth()
                .background(Color.White)
        ) {
            Spacer(
                modifier = Modifier
                    .fillMaxWidth()
                    .aspectRatio(CoverRatio),
            )
        }
    }

// 親Viewの大きさに制約をつけてclipToBoundsではみ出さないようにする
Column(modifier = modifier.aspectRatio(4f / 3f)) {
    Camera(
        useCase = useCase
        modifier = Modifier.clipToBounds(),
    )
}
```
### 最後に
意外と触る機会が少ないのと、デザインに合わせる上で重要なことなので備忘録として残しておこうと思います
どなたかのお役に立てれば幸いです
Pytorch lightningでDeepspeedのcheckpointをロード

lighitningでdeepspeedを用いる方法は下記を参考にしてください．

https://lightning.ai/docs/pytorch/latest/advanced/model_parallel/deepspeed.html


# Deepspeedのcheckpointのロード

deepspeedのチェックポイントはディレクトリになっており， 単純に`load_from_checkpoint`ではロードできません．

なので，[`convert_zero_checkpoint_to_fp32_state_dict`](https://lightning.ai/docs/pytorch/stable/api/lightning.pytorch.utilities.deepspeed.html)関数でptファイルへと変換してからロードしましょう．

```py
from lightning.pytorch.utilities.deepspeed import convert_zero_checkpoint_to_fp32_state_dict

ckpt_dir_path = "/hoge/epochX_stepY.ckpt"
dist_path =  ckpt_dir_path + "/state_dict.pt"
convert_zero_checkpoint_to_fp32_state_dict(args.checkpoint_path, dist_path)

MyLighiningModel.load_from_checkpoint(dist_path)
```
1の補数、2の補数

## 補数とは

補数とは1と0しか使えないコンピューターが負数を表現する方法の一つです
ある自然数をn進数（n進法）で表現した時に、足し合わせるとちょうど「nのべき乗」か「nのべき乗-1」になる自然数のうち最小になるものです。

### ・基数の補数
10進数の65という数に足し合わせるとちょうど**一つ桁上りする自然数**は、足すと100になる35であり「65に対する10の補数」という。

例）
　3 の補数は 7　　　（10）
　35 の補数は 65　　（100）
　358 の補数は 642　（1000）

### ・減基数の補数
10進数の65という数に足しても**桁が増えない最大の数**は、足すと99になる34であり、（10進数における）「65に対する9の補数」という。

例）
　3 の減基数の補数は 6　　　（9）
　35 の減基数の補数は 64　　（99）
　358 の減基数の補数は 641　（999）

### ・2進数における1の補数

「足しても桁上がりしない数のうち最大の数」（減基数）は
　足した後で、0になっていた桁が全て1になるような数なのでビット反転をした数。
 
例）
　2進数4ビットの場合
　1001 の1の補数は 0110 で 1111 （10進数15）になる
 
 ### ・2進数における2の補数

 ビット反転した数に1を足し、桁上がりさせたもの。
 
 例）
　2進数4ビットの場合
　1001 の2の補数は 0111 で 0000 になる
 
 2進数4ビットであるため桁上がりした1は無視される

### ・最後に
1の補数と2の補数をつくる覚え方

 1の補数とくれば　**ビット反転**
 2の補数とくれば　**1の補数（ビット反転）に1を足す**

 >引用
 [「2の補数」「1の補数」について覚書](https://qiita.com/satellitesat/items/340de8a946ddd2bac24e)
 [IT用語辞典　e-Words](https://e-words.jp/w/%E8%A3%9C%E6%95%B0.html)
 [令和06年 イメージ＆クレバー方式でよくわかる かやのき先生の基本情報技術者教室](https://www.amazon.co.jp/%E4%BB%A4%E5%92%8C06%E5%B9%B4-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%EF%BC%86%E3%82%AF%E3%83%AC%E3%83%90%E3%83%BC%E6%96%B9%E5%BC%8F%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E3%81%8B%E3%82%84%E3%81%AE%E3%81%8D%E5%85%88%E7%94%9F%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E6%95%99%E5%AE%A4-%E6%A0%A2%E6%9C%A8-%E5%8E%9A/dp/4297138271/ref=sr_1_1?adgrpid=115303084225&dib=eyJ2IjoiMSJ9.jcRHwDtICMuPRLcD3L_sO1b96V1HJHSPSbHMlyyNX_Afyt4XJ6W3WV047qAFnS6DkrnW_YH8rFk2aAC7Xyw7wgLmqq765zKaV3rplkDqpQtnW_eDUFsAnc2ioDLyyPWFvQfOcnLbKhZBv6cWHsSD04B2rPxIn2vaKX94yBb0OXfvmJAey3LxTHTqqdQ4AjQHqQ0I0IudW4KEj2xxz4axsmFT4UKhyH5lBM0vtWwPWMM.tX9cjzt2glBvIw5yB3z--ktVYdw7U67szMq8FXv5VJk&dib_tag=se&hvadid=699009723488&hvdev=c&hvqmt=e&hvtargid=kwd-334549031671&hydadcr=26609_11804420&jp-ad-ap=0&keywords=%E6%A0%A2%E6%9C%A8%E5%85%88%E7%94%9F%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93%E6%95%99%E5%AE%A4&qid=1720402258&s=books&sr=1-1)
スクラムマスターが、ある日突然プロンプトエンジニアになった話

## はじめに
私は普段スクラムマスターを生業としていますが、最近は会社として生成AIのお仕事が多く、ある日突然プロンプトエンジニアとしてPJに参画することになりました。本記事では、突然プロンプトエンジニアリングをやることになったスクラムマスターが、**プロンプトエンジニアとしてお客様と接するなかで感じたことや学んだこと**をまとめています。

# 目次
[1.前提](#1-前提)
[2.プロンプトエンジニアとしてやっていること](#2-プロンプトエンジニアとしてやっていること)
[3.実際にお客様と接して感じたこと](#3-実際にお客様と接して感じたこと)
[4.学んだこと](#4-学んだこと)
[5.おわりに](#5-おわりに)

## 1. 前提
 - 特定のお客様及び業界を批判する意図は全くありません
     - そう感じられたとしたら、私の言語化能力の問題です
 - 具体例は多少ニュアンスを変えています
 - プロンプトとは？という点には触れていません

## 2. プロンプトエンジニアとしてやっていること
お客様が感じている業務上の課題に対し、どう生成AIを活用すれば解決に至るのかという点を、**プロンプトという側面から**ご提案させていただいています。

## 3. 実際にお客様と接して感じたこと
### 想定外の課題、ご相談が多い
 - 生成AIが得意としない領域の課題が**普通に出てくる**
     - ミスが許されないエクセルベースの業務を自動化したい
     - 高度な計算を自動化したい
     - 人の最終確認を省き、特定の業務を完全に自動化したい

### 生成AIを万能な神様だと思っている
 - 生成AIはあくまで自分の視野を広げることに利用したり、情報をサマライズするという用途で使うことが好ましいが、そこについて本質的に理解されているお客様が少ない印象
 - 生成AIでは解決しにくいこと、不得意な領域について説明すると、**「期待外れ」**　のような雰囲気になることがある
 - 生成AIでは解決できないので、業務の要所要所でAIを活用しようという提案になりがち
     - 例えばエクセルのマクロで対応するのが良い→マクロの内容を生成AIに考えてもらいましょう、のような
 - 結局人の手が必要なんだ、、とお客様が落胆されるケースが見受けられる
 
### 絶対的な解が無い
 - お客様の課題が生成AIで解決できるものなのか**我々も絶対的な解を持っているわけではない**
 - なので、プロンプトで解決できるかどうかを事前に検証するため、お客様の課題を事前に共有いただいている
 - ただ、どうしてもお客様とお話する場で、「こういうことって出来ますか？」と聞かれることがある
     - **すごくドキドキする**
 - とはいえ、こういった経験を積んでいくことで解決できる・出来ないのポイントを掴み、少しでもお客様に解決策を提案できるように精進していきたい

事前に試していたプロンプトが、実演の際に期待通りの出力をしないと泣きそうになります。

## 4. 学んだこと
### よくあるプロンプト例を紹介、実演するだけでも感心いただけることがある
 - プロンプトに「役割」を指定する、「出力形式」を指定するなど本当に基本のキといったところから
 - 重要な点やテンプレートはググればたくさん出てくるが、お客様はそこまでして生成AIを活用したいわけではないのだろうか？そもそもプロンプトがそんなに重要だと思っていないのだろうか？
     - どちらかというと後者の印象

### 課題に対する最適な解決ソリューションを考える大切さ
 - お客様の課題の多くは業務プロセスであったり、生成AI以外のソリューションで解決すべきものが多くある（生成AIの領域ではない）
 - **手段が先行してしまう**ということはありがちなので、私自身気をつけたい

### 生成AIに対する理解度が、業界によって様々である
 - 我々は職業柄、生成AIが当たり前の存在になっているが、他業界のお客様からするとまだまだよくわからないものである
     - **そもそも触れたこともない方**が普通に存在する
 - そんな方々に、生成AIの価値を届けることがIT業界に身を置く者の責務だと感じた

### 生成AIの得意領域、苦手な領域についてお客様は理解されているだろうと思い込んでいた
 - 利用してみないとイメージがつきにくいところはあるのだと痛感した
 - お客様に生成AIの本質とはなんたるやを理解をしてもらうために、どのようなコミュニケーションや手法が効果的か考えていきたい
 - 特定の課題について「生成AIでこう解決できます！」ということをご提案することができても、**『なぜこの課題はAIで解決できたのか？』**　という観点をしっかりお伝えしないと、本質的な理解になりにくい
     - 魚を与えるのではなく、魚の釣り方をしっかりお伝えしていきたい


## 5. おわりに
生成AIが世にでて以降、「プロンプトエンジニア」という職業が生まれる！という話は聞いていましたが、まさか自分がなるとは想像していませんでした。生成AIの価値を、**プロンプトという側面から**、より多くの方々へ届けていきたいと改めて思いました。
PostgreSQL index関連

すぐ忘れるので、一覧にします。

# 対象テーブルのindex確認

```
SELECT * FROM pg_indexes where tablename = '★対象テーブル名★';
```

# 対象テーブルのindex確認

https://www.postgresql.jp/document/10/html/sql-createindex.html

```
CREATE INDEX ★任意のindex名★ ON ★対象テーブル名★ (★index1カラム名★, ★index2カラム名★, ★index3カラム名★);
```

# 対象テーブルのindex削除

https://www.postgresql.jp/docs/9.4/sql-dropindex.html

```
DROP INDEX ★対象のindex名★;
```
Reactで条件検索をする時にURLへクエリパラメーターを付与したい

Reactで条件検索をする時に、GETリクエストへパラメーターを含めて送信するだけでなくURLにも付与したいということがあると思います。
本記事では、検索時にURLへクエリパラメーターを付与する簡単な実装方法を紹介します。

# 実装方針
- 最初の画面アクセス時は、URLから検索条件のクエリパラメーターを取得してGETリクエストのパラメーターに含める
- 検索時は、GETリクエストのパラメーターに条件となる値を含め、URLにクエリパラメーターを付与する

# 具体的な実装

## URLからクエリパラメーターを取得してGETリクエストにセット

最初のアクセス時に、URLから検索条件のクエリパラメーターを取得してGETリクエストに含めるための実装です。

```typescript
const searchParams = new URLSearchParams(window.location.search);
const [text, setText] = useState<string>(searchParams.get('text'))
const [categories, setCategories] = useState<string[]>(searchParams.get('categories')?.split(',') || [])

useEffect(() => {
  // TODO: URLに含まれるクエリをGETリクエストにセットして実行
}, [])
```

## 検索時にURLへパラメーターを含める

検索時に実行される関数の中で、URLにクエリパラメーターを付与できるようにします。

```typescript
const onSubmit = () => {
  const params = {}
  if (text) params['text'] = text
  if (categories) params['categories'] = categories
  
  const urlSearchParam =  new URLSearchParams(params).toString()
  navigate('/search?' + urlSearchParam)
}
```

## URLに変化があったことを検知してGETリクエストを実行

ここまででURLの切り替えはできるようになりましたが、パスは`/search`のままなので最初に実装したuseEffectは実行されません。
つまり、検索が実行されないということです。
そのため、`window.location.href`をuseEffectの第二引数に渡してクエリパラメーターが付与されたタイミングでGETリクエストを実行できるようにします。

```typescript
const searchParams = new URLSearchParams(window.location.search);
const [text, setText] = useState<string>(searchParams.get('text'))
const [categories, setCategories] = useState<string[]>(searchParams.get('categories')?.split(',') || [])

useEffect(() => {
  // TODO: URLに含まれるクエリをGETリクエストにセットして実行
}, [window.location.href])
```

# 参考

https://qiita.com/nisyuu/items/e300ccd597ac8248352f

https://qiita.com/nisyuu/items/26c5913bad0bc4d3060d
Blazor WebAssemblyをiOSで動かすときの注意点

Blazor WebAssemblyをiOSでも動かしたい時に、メモリ関連で気を付けないといけない旨が[マイクロソフトの注意書き](https://learn.microsoft.com/ja-jp/aspnet/core/blazor/host-and-deploy/webassembly?view=aspnetcore-8.0#decrease-maximum-heap-size-for-some-mobile-device-browsers)にあります。
具体的に、どこを修正したらいいのか忘れないためにメモを残します。

# プロジェクトファイル（.csproj または .vcxproj）を直接編集
１，ソリューション エクスプローラーでプロジェクトファイルを右クリック
２，「プロジェクトファイルの編集」を選択

```XML:.csproj
<Project>
  <PropertyGroup>
    <!-- 他のプロパティがあります -->
    <EmccMaximumHeapSize>268435456</EmccMaximumHeapSize> <!-- 追加 -->
  </PropertyGroup>
</Project>
```

[参考文献（笑）](https://chatgpt.com/share/4e9ca31b-b0ae-4414-be35-710848f1442b)
[AWS SUMMIT2024 セッションレポート] アプリケーション開発を加速させる AWS の生成 AI デベロッパーツール

# はじめに
受講セッションの個人的な所感と、メモです。
メモの内容は、誤字脱字などあるやもしれませんが、ご了承ください。


# 所感

Amazon Qや、wisperの存在は知っていたし、多少は使ったこともありますが、
もっぱらメインで使っているのはCopilotでして、あまりこの辺りは詳しくありませんでした。

登場当初は少し使いづらい印象で、copilotの方が使いやすかったのでそのまま採用したのですが、
率直言うと進化が凄かったです。

特にすごいと感じたのは、言語バージョンの最適化。
どこまで対応しているのか、最適化後、システムが正常に動くか、などの検証は必須ではあるものの、
かなり助かる機能ですね。

言語バージョンがアップデートされないのは、
設計・仕様にも問題はあるものの、メンテナンス上、悩みの種のひとつだと思います。
あるあるだと思います。

ここのサポートはシンプルに嬉しい。

普段のコーディングには、Copilotで十分だとは思いつつ、
AWS活用においては、やはりQの方がいいかな・・・。
悩みどころです。

# 受講メモ
## Amazon Q
Developer
- AWSに関するガイダンス
- 機能開発を加速
	- コーディング支援
- コードデバック、テスト、最適化
- アプリケーションコード変換
	- 言語のアップデートによる変換
	
- エージェント
-- システム全体の解析、実装
-- 実装指示
	
- ユニットテストの作成
- コードスキャン、脆弱性のチェック

## 言語バージョンの最適化
1000を超えるアプリの言語バージョンを、1つ10分程度、2日足らずで完了

- 技術負債の解決
- 生産性の向上
- 品質の向上

# 関連
- [AWS SUMMIT2024 参加レポート](https://qiita.com/yukiMiyoshi_fcafe/items/220bf886aa94ea552d3e)
[Python] 例外処理

## 例外処理とは

例外処理は、プログラムの実行中に予期しないエラーが発生する可能性がある場合に備えてコードを記述することです。
これにより、プログラムが突然異常終了することなく正常に実行されるようにします。


<br/>

**例外処理**の目的は次のとおりです：

- プログラムの実行中に突然のエラーによる異常動作を防ぎます。
- 発生したエラーを処理し、回復または回避することで、プログラムの正常な実行を維持します。

<br/>
Pythonでは、例えば、0で割るとZeroDivisionErrorが発生します。

```python
# 例
try:
    result = 10 / 0
except ZeroDivisionError:
    print("0で割ることはできません。")

```

上記のコードでは、0で割ろうとした際に発生する**ZeroDivisionError**を処理しています。

複数の例外を処理するために、exceptをネストして使用することもできます。

```python
# 例
try:
    some_list = [1, 2, 3]
    index = 4
    value = some_list[index]
except IndexError:
    print("インデックスが範囲外です。")
except Exception as e:
    print(f"エラー発生: {e}")

```

上記のコードでは、**IndexError**とその他すべての例外を処理する方法を示しています。
**as**を使用して例外オブジェクトを取得することもできます。

<br/>

### else

**else**節は一般的にtry-exceptブロックの後に配置され、
**例外**が発生しなかった場合に実行されます。

```python
# 例
try:
    result = 10 / 2
except ZeroDivisionError:
    print("0で割ることはできません。")
else:
    print("結果:", result)

```

上記のコードでは、0で割るエラーが発生しない場合にのみ結果を出力します。

<br/>

### finally

**finally**節は例外の発生有無に関係なく必ず実行されるブロックです。
主にリソースの後始末やクリーンアップに使用されます。


```python
# 例
try:
    f = open('somefile.txt', 'r')
    # ファイル読み込み処理を行う
finally:
    f.close()

```

上記のコードでは、ファイルを開いて読み込み操作を試み、例外の発生有無に関係なくファイルを閉じる操作を保証します。


### 追加の終わりの説明

例外処理はプログラムの安定性を高め、予測可能な動作を維持するための重要な技術です。適切な例外処理を理解し、適切な場所で活用することが推奨されます。
Rails におけるMigration対象のファイルには順番がある件

# はじめに
みなさん、こんにちは.**torihazi**です。

昨日作ったRails7 x React 18 のDocker環境の下で

現在開発を進めているのですが、

久しぶりのRailsで、はじめの始めでつまづいたので

書き記しておこうと思います

# どういうことか
例えばテーブルを4つ(A,B,C,D)作るとします。

そのためにターミナルで下記コマンドを打ち込むかと思います。

```
rails g migration createAs
rails g migration createBs
rails g migration createCs
rails g migration createDs
```
そうするとファイルがそれぞれ
```
20241111001111_create_as.rb
20241111002222_create_bs.rb
20241111003333_create_cs.rb
20241111004444_create_ds.rb
```
と作られます。

この時
- BはAのidを外部キーとしてもち
- CはAとBとDのidを外部キーとしてもつ

なんてしたときに各ファイルいじって最後に`rails db:migrate`やると思います。

が、私は失敗しました。

理由としては Cをmigrateするときにまだ未定義のDの情報を扱ったため、でした。

`rails db:migrate`するときはA、B、C、Dと進み、Cに差し掛かった所で

ターミナルから`Undefined Table`と返されました。

# 解決
CとDのmigrationファイルについている
先頭の数字を入れ替えて、再度migrateを実行しました。

そしたら無事、うまくいきました。

参考にしました！
https://qiita.com/takuo_maeda/items/17923ba3ec39cb2c5e20

# 終わりに
これって常識なんですか。

だとしたら早めにしれてよかったです。

ちなみに下記をやっていた際にぶつかりました。

https://www.techpit.jp/courses/138/curriculums/141/sections/1044/parts/4128
超初心者のためのRSpec入門ガイド

こんにちは！この記事では、RubyのテストツールRSpecの使い方を超初心者の私が説明します。一緒にステップバイステップで学んでいきましょう！

### 目次
1. RSpecって何？
2. RSpecのインストール方法
3. RSpecの基本的な使い方
4. 実際にテストを書いてみよう！
5. まとめ

# 1. RSpecって何？
RSpecは、Rubyというプログラミング言語で書いたコードが正しく動くかどうかをチェックするためのツールです。コードを書いた後に「ちゃんと動くかな？」と確かめる手助けをしてくれます。

# 2. RSpecのインストール方法
まず、RSpecを使うためにインストールします。以下のコマンドをターミナルで実行してみてください。
```
gem install rspec
```
Bundlerを使っている場合は、Gemfileに以下を追加してからbundle installを実行します。
```
group :test do
　　　　・・・
  gem 'rspec'
  ・・・
end
```
これでRSpecの準備が整いました！

# 3. RSpecの基本的な使い方
次に、プロジェクトのディレクトリで以下のコマンドを実行してRSpecを初期設定します。
```
rails generate rspec:install
```
これにより、RSpecの設定ファイルとディレクトリが作成されます。

#### 手動でcontrollersディレクトリを作成したい場合
以下のコマンドを入力
```
mkdir -p spec/controllers
```

# 4. 実際にテストを書いてみよう！
まず、簡単な計算機のクラスをテストしてみます。calculator.rbというファイルを作って、以下のコードを書いてみてください。
```
# calculator.rb
class Calculator
  def add(a, b)
    a + b
  end
end
```
次に、specディレクトリの中にcalculator_spec.rbというファイルを作成し、以下のコードを書きます。
```
# spec/calculator_spec.rb
require 'rspec'
require_relative '../calculator'

RSpec.describe Calculator do
  it 'adds two numbers' do
    calculator = Calculator.new
    result = calculator.add(2, 3)
    expect(result).to eq(5)
  end
end
```
このコードでは、Calculatorクラスのaddメソッドが2つの数を正しく足し算するかどうかをテストしています。
#### テストを実行してみよう！
ターミナルで以下のコマンドを実行して、テストを実行してみましょう。

下記のコマンドは、インストールされている全てのRSpecのバージョンから最新のものを選んでテストを実行する。
```
rspec
```
すると、テストの結果が表示されます。

# 5.まとめ
今回は、RSpecの基本的な使い方を一緒に学びました。テストを書くことで、コードのバグを見つけやすくなり、品質を保つことができます。
VSCode+PrettierでMarkdown日本語問題に対応する

Prettierは様々な言語に対応したフォーマッタであり，Markdownのフォーマットも可能です．しかし，日本語が含まれるMarkdownの場合，英数字の前後に不要な空白が挿入されてしまう問題が知られていました

この問題はPrettier v3.0.0から解決されていたようです

https://zenn.dev/kou7273/articles/9962f029ad50fc

ですが，VSCodeの拡張機能に付属するPrettierはバージョンが古く (?) この問題に対応していません

別途インストールしたPrettierを使ってフォーマットする設定が必要です

### prettierのインストール
ローカルかグローバルどちらでも良いのでインストールします．グローバルに入れる場合は適切にパッケージを管理しましょう
```bash
    # グローバルインストール
    npm install -g prettier
```

バージョン3.0.0以上がインストールされていることを確認します
```bash
    prettier -v
```

### prettierのパスを設定する
インストールしたprettierの`package.json`へのパスを取得します．通常は`/usr/local/lib/node_modules`を探せば見つかると思います
```bash
    # グローバルインストールされているパッケージを探す
    npm list -g --depth=0
```

:::note warn
prettierの実行ファイルではなくpackage.jsonへのパスです．`which prettier`で得られるパスではありません
:::

voltaなどのツールを使用している場合，別のところにあったりします．私の場合はここにありました
`/Users/user/.volta/tools/image/packages/prettier/lib/node_modules/prettier/`


### VSCodeの設定を変更する
得られたパスを`prettier.prettierPath`に指定します

```settings.json
  "prettier.resolveGlobalModules": true,
  "prettier.prettierPath": "/Users/user/.volta/tools/image/packages/prettier/lib/node_modules/prettier/",
```

`editor.formatOnSave`でMarkdownをフォーマットするように設定すれば動作確認できます

以上です
Jetpack Compose の基本のメモ#6 ~Compose の状態~

### [7. Compose の状態](https://developer.android.com/codelabs/jetpack-compose-basics?hl=ja#6)
+ レイアウトがユーザーの変更に反応する動的レイアウトを実現するために、状態を保存できるようにする
+ 状態＝反応した後か、反応する前かを示す値
+  Composeアプリは、コンポーズ可能な関数を呼び出してデータをUIに変換する
+  データが変更されると、Compose はそれらの関数を新しいデータで再実行し、更新されたUIを作成する
+  これを再コンポジションと呼ぶ
+  Composeはデータが変更されたコンポーザブルのみを再コンポジションする
+  Compose によってトラッキングされる変数を定義するためにはmutableStateOf 関数を使用する
+  State と MutableState は、なんらかの値を保持し、その値が変化するたびに UI の更新（再コンポジション）をトリガーするインターフェース

>身近なもので例えると、インターフェースはテレビのリモコンのようなものです。
テレビのリモコンには、電源ボタン、音量ボタン、チャンネルボタンなど、様々なボタンがありますよね。これらのボタンは、テレビの機能（電源のオン/オフ、音量調整、チャンネル変更など）を操作するためのものです。
>ここで、
>テレビ本体: テレビの機能そのもの
リモコン: テレビの機能を操作するための道具
ボタン: リモコンとテレビの機能を繋ぐもの
と考えることができます。

>リモコンのボタンを押すと、その情報はリモコンからテレビ本体に伝えられ、テレビ本体はそれに応じて特定の機能を実行します。このとき、リモコンはテレビ本体と私たちの間の「インターフェース」（接点）として機能していると言えます。

>State や MutableState も、これと同じように、Jetpack Compose で UI の状態を操作するための「リモコン」のような役割を果たします。State や MutableState が提供する機能（値の変更など）を使うことで、UI の状態を間接的に操作し、それに応じて UI を更新することができます。

+  コンポーザブル内の変数に `mutableStateOf` を割り当てることはできない
+  remember を使用すると、再コンポジションから保護されるため、状態はリセットされなくなる
+  rememberとmutableStateOfをセットで使用することにより、コンポーザブル内で状態変数を定義できる
useReducerの基礎を理解する【React-Hooks】

## 最初にまとめ

| hooks | 使用タイミング |
| --- | --- |
| useState | 簡単な状態管理・処理 |
| useReducer | 分岐が発生するなど、複雑な処理である・テストが必要な場合 |


## useReducerとは

- 状態を扱うためのフック（useStateと似ている）
- useReducerは宣言時に、条件分岐と処理内容を予め定義する
- 条件によって状態の更新を分岐できたり、状態の更新関数をコンポーネントの外に切り出すことができる


## 使い方

- action で受け取った値に応じて、条件分岐・処理を行い、各々の処理結果を返す

```jsx
const [state, dispatch] = useReducer((prev, action) => {条件式}, 初期値)
```

| state | 現在の状態の値 |
| --- | --- |
| dispatch | reducerを実行するための呼び出し関数（変数を宣言時、stateの更新方法をあらかじめ設定できる） |
| reducer | stateを更新するための関数(prev, action) => {条件式} の箇所 |
| action | 状態を変化させる上での条件（利用側 dispatchからオブジェクトが渡ってくる。switch文で処理の分岐を書くのが一般的） |

### 呼び出し方

```jsx
const test = () => {
  dispatch({ /*actionに渡すオブジェクト*/ });
};
```



## useStateとuseReducerの違い

### プログラムの観点から
「状態の更新の仕方を誰が担当するか」によって使い分ける

- useStateは、宣言時に初期値しか設定しないため、状態更新する側が、更新方法を定義する
- useReducerは、宣言時に更新方法を定義するため、状態更新する側は、dispatchは更新方法を指定するだけ

大規模なアプリケーション開発の現場では、
useReducerを使って、state宣言時に更新方法も定義する方が見通しの良いコードになる。


### 関数型プログラミングの観点から
- state の変更ロジックを`reducer`に切り離すことができる    
- useReducerは「純粋関数」であるため、単体テストがしやすい。
    useStateは、状況によって、不変性のある関数になりうる。


## useReducerを使って簡単なカウンターを作ってみる

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3772772/2c67e472-4ecc-664b-6818-2d9de834ee3e.gif)


```jsx
import { useReducer } from "react";

export default function App() {
  // 処理内容を定義
  const reducer = (prev: number, action: { type: string; step: number }) => {
    const { type, step } = action;
    switch (type) {
      case "countUp":
        return prev + step;

      case "countDown":
        return prev - step;
      default:
        throw new Error("不明なactionです");
    }
  };

  // useReducerの使用を宣言
  const [state, dispatch] = useReducer(reducer, 0);

  // カウントアップ関数
  const onClickReducerCountUp = () => {
    dispatch({ type: "countUp", step: 3 }); // ※オブジェクトで渡す
  };

  // カウントダウン関数
  const onClickReducerCountDown = () => {
    dispatch({ type: "countDown", step: 4 });
  };

  return (
    <div>
      <p>{state}</p>
      <button onClick={onClickReducerCountUp}>カウントアップ</button>
      <button onClick={onClickReducerCountDown}>カウントダウン</button>
    </div>
  );
}

```

`useState` を多用していましたが、
処理が増えるならば、積極的に`useReducer`を利用した方が、
コードの見通しがだいぶ変わるので、積極的に利用しようと思いました！
SSH接続を10倍速くするたった3行の設定

今回は、SSH接続を劇的に高速化する方法をご紹介します。たった3行の設定を追加するだけで、接続時間を10分の1に短縮できます。しかも、2回目以降の接続では認証も自動的に行われるので、パスワードやパスフレーズの入力も不要になります。

## 要点

`.ssh/config`ファイルの`Host *`セクションに以下の3行を追加するだけです。

```
Host *
  ControlMaster auto
  ControlPath ~/.ssh/mux-%r@%h:%p
  ControlPersist 4h
```

## 詳しい説明

### 1. ControlMaster auto

この設定で、1つのSSH接続で複数のセッションを共有できるようになります。新しくSSH接続を確立するたびに認証情報を入力し直す手間が省けて、接続がぐっと速くなります。具体的には：

- 初回の接続時のみ認証が必要
- 2回目以降は既存の接続を再利用するため、認証プロセスをスキップ
- パスワードやパスフレーズの入力が不要になり、接続がほぼ瞬時に完了

### 2. ControlPath ~/.ssh/mux-%r@%h:%p

ControlPathは、共有接続のソケットファイルの場所を指定します。`%r`はリモートのユーザー名、`%h`はホスト名、`%p`はポート番号を表します。これで、異なるホストやユーザーごとに個別の共有接続を維持できます。

### 3. ControlPersist 4h

この設定があると、最後のセッションが終了した後も、指定した時間（ここでは4時間）バックグラウンドで接続を保持し続けます。その間の再接続なら、認証も接続もほぼ一瞬で完了します。

## 効果はこんな感じ

この設定を適用すると、2回目以降の接続が驚くほど速くなります。僕の環境では、最初の接続に500ミリ秒かかっていたのが、2回目以降はたったの50ミリ秒になりました。

さらに、認証の手間も省けるので、体感的な速さはもっと向上します。パスワードやパスフレーズを入力する時間を考えると、作業効率が格段に上がります。

特に効果を実感できるのは、こんな場合です：

- よくSSH接続する人
- 同時にたくさんのSSH接続を開く人
- ネットワークが不安定な環境でSSHを使う人
- 複雑なパスワードやパスフレーズを使っている人


## ssh -O コマンド

`ssh -O`コマンドを使えば、制御接続（ControlMaster接続）を操作できます。主なオプションはこんな感じ：

- `ssh -O check <ホスト名>`: 指定したホストへの制御接続があるか確認
- `ssh -O stop <ホスト名>`: 指定したホストへの制御接続を停止
- `ssh -O exit <ホスト名>`: 指定したホストへの制御接続を終了

これらのコマンドを使えば、長時間維持されている接続を手動で管理できます。例えば、セキュリティを重視する場合は、作業終了時に`ssh -O exit`で確実に接続を閉じることができます。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（52/100）

【52日目】
トピック 6：SAPS/4HANAの需要管理（3/5）

≪問題52≫
予測MRP（pMRP）のプロセス実行に必要となるのは、以下のどのステップですか。
（２つ選択）
□シミュレーション登録
□統計データの更新
□計画結果の処理
□プロセスフロー登録

≪解答≫
■シミュレーション登録
□統計データの更新
■計画結果の処理
□プロセスフロー登録

≪解説≫
◆予測MRP（pMRP）の目的は、シンプルな資材所要量アルゴリズムを使用したシンプルな所要量計画に基づき、能力に関する潜在的な問題を早期に特定し、可能な解決策を評価することです。また、これは戦略的購買および購買業務のインプットとしても使用できます。シミュレーションを行うことで、生産計画者は、所要量計画、資源計画、生産準備段階、製造/購買の決定などに関する条件の変更に応じた意思決定に備えることができます。
◆pMRPに必要なステップは、プロセスの視点から見ると次の2つです。
1. シミュレーション登録
pMRPシミュレーション登録スケジュールアプリを使用して、シミュレーションの参照データとして考慮されるデータを定義し、シミュレーションの登録を開始します。追加のシミュレーションで同じ参照データを使用する場合、参照データに基づいてシミュレーションをコピーする必要があります。その後、シミュレートする変更を実行し、2つのシミュレーションを比較します。関連するすべての需要が指定されたバケットデータに配分され、このアプリでの定義に従ってシミュレーション計画に表示されます。
2. 計画結果の処理
pMRPシミュレーション処理アプリを使用して、複数のシミュレーションを登録し、能力または需要に対する変更のシミュレーションがKPIに与える影響を確認し、生産計画に関して十分な情報に基づく決定を行うことができます。このアプリでは、需要計画シミュレーション、能力計画シミュレーション、多段階品目シミュレーション、シミュレーション集計の機能が提供されます。
【Docker】`version` is obsoleteの解消方法

## はじめに
docker-compose.ymlを使用してビルドしようとした時に出た警告の対処方法です。

## 問題
警告内容
```sh
$ docker-compose up -d --build
WARN[0000] `version` is obsolete
```

## 解決方法
docker-compose.ymlに書いてある以下の記述を削除すれば、警告が出なくなります。
```yml
version: '3.8'
```

## 参考
https://qiita.com/ta-hiro/items/b19fcc97aac22d5c63c0