OmniAICreator/Qiita-1.07M huggingface dataset:
Windows10とDUALSHOCK4とのBluetooth接続がうまくいかない時の対応

:::note warn
不具合が起きた根本原因までは調査していません。
『こうやったら直った』という内容となりますので、この記事は参考情報として見て下さい。
:::

# 現象

Bluetooth接続に問題が無く1年近く使っていたWindows10とDUALSHOCK4間で発生。

DUALSHOCK4のPSボタン押して接続しても、10秒ほどですぐ切れるようになってしまいました。
何かイレギュラーなことをしたような気がしたけど、何がきっかけだったか忘れました。

下記のようにいったん『デバイスの削除』を行って、そのあとPSボタン押して接続し直しても状況変わらず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f50626d0-c82f-1f63-c1f8-df36b31a0073.png)

DUALSHOCK4とPCをUSBケーブルの有線接続した場合は問題無く使える状態。

# こうやったら直った

ポイントは…

* **デバイスマネージャーから** アンインストールを行う。
* SHAREボタンとPSマークの **2ボタン同時押しっぱなし** で改めてデバイス追加。

です。

## デバイスマネージャーからアンインストール

Windowsマーク上で右クリック ⇒ 『デバイスマネージャー』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1de392be-2f7c-9525-d076-8a72f2fb3d32.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/131056b0-6ef8-2199-5448-c7512a0c568b.png)

右クリック ⇒ 『デバイスのアンインストール』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1d79be5c-018f-48cc-2228-d3c316f0c27d.png)

## SHAREボタンとPSマークで改めて接続

DUALSHOCK4の **SHAREボタンとPSマークを同時に押しっぱなしに** 。
2～5秒ほどすると、DUALSHOCK 4のランプが ピピッ！ピピッ！ って感じの間隔で **点滅** 。

『Bluetoothまたはその他のデバイスを追加する』
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a0ee2a5c-291d-215a-9744-0e9de900190f.png)

『Bluetooth』。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/ef7b46bc-a603-fb8f-5891-16746c2a233a.png)

下記のように『Wireless Controller』が出てきたら選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/d7defe7f-be8f-a9d8-9673-bd4c5dbbf5e7.png)

接続完了すると下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9ef026bb-dfd3-44bb-5aae-100fec65ef9a.png)

これで直りました。

# 参考サイトさん

https://qiita.com/waokitsune/items/e7a4d6644f8a83d2348a

# バージョン

DUALSHOCK4 CUH-ZCT2J
Microsoft Windows [Version 10.0.19045.3693]
VisualStudioでRustを便利に相互運用する

> Visual Studio大好き(codeじゃないほう)

今回はVisualStudio(2022)でRustを快適(?)に運用する方法を共有したいと思います。

# 完成形

## ディレクトリ構造

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555292/ade3965d-31bd-91a1-7518-1e1552a178f3.png)

## 動作
プロジェクトのビルドが完了すると、Rustのコンパイルが始まり、生成結果フォルダに *(プロジェクト名).rs.dll* という名のバイナリがコピーされる。

# 長所

* ケース規則が揃う(プロジェクト直下はパスカルケース、フォルダー内はスネークケース)
* Rustとその他(今回はC#)をまとめてコンパイル結果に入れられる。

# 手順
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3555292/ade3965d-31bd-91a1-7518-1e1552a178f3.png)
### 0. Pythonの準備
インストールできてなかったらして下さい。
### 1. プロジェクトの作成
普通にプロジェクトを作る。
今回はC#(csproj)でやった。他のプロジェクトでもできると思うけど保証しない。
### 2. *Cargo.toml* の作成
公式ドキュメントに従って、好きに書いて下さい。
この時、プロジェクト名はスネークケースにしましょう。
### 3. Rustプロジェクトの準備
プロジェクトフォルダ内に *src* フォルダ、その下に *lib.rs* などを置く。
### 4. *PostBuild.py* の作成
プロジェクトフォルダー直下に *PostBuild.py* を作る。
中身はこんな感じにする。
```py
import sys
import os
import shutil
import subprocess

def snake_to_pascal(s):
    return '.'.join(word.capitalize() for word in s.split('_'))

config = sys.argv[1]
dest = sys.argv[2]

if config == "Debug":
    subprocess.run(["cargo", "build", "--lib"])
    source = os.path.join("target", "debug")
elif config == "Release":
    subprocess.run(["cargo", "build", "--lib", "--release"])
    source = os.path.join("target", "release")
else:
    raise ValueError

for file_src in os.listdir(source):
    if file_src.endswith(".dll"):
        file_dst = snake_to_pascal(os.path.splitext(file_src)[0]) + ".rs.dll"
        shutil.copy2(os.path.join(source, file_src), os.path.join(dest, file_dst))
    elif file_src.endswith(".pdb"):
        file_dst = snake_to_pascal(os.path.splitext(file_src)[0]) + ".rs.pdb"
        shutil.copy2(os.path.join(source, file_src), os.path.join(dest, file_dst))

```
### 5. プロジェクトの編集
以下の要素をProject要素直下に置く。
```xml
  <Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="py PostBuild.py $(ConfigurationName) $(TargetDir)" />
  </Target>
```
### 6. gitignore(必要であれば)
targetディレクトリを除外するため、以下の文を *.gitignore* に追加する。
```
# Cargo build target
target/
```

# おわりに

なにか改善案あればお聞かせ下さい。
rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その１８）Capabilitiesの弊害

Capabilities がデフォルトで、チェックされたままでしたが、いつの間にか外部データによって応答内容が影響されていた。

[rex0220 計算式プラグインの使い方をGPTsに学習させてみる（その１7）GPTsを公開](https://qiita.com/rex0220/items/a7f6b84ad510a31fb414)の続きです。

# 概要

計算式プラグインの演算子を問合せると、計算式プラグインでは利用できない演算子が多く応答された。
他の言語の演算子を外部から勝手に取り込んで学習したんだと思われます。
安易な外部参照は、間違いのもとになります。

![2023-11-21_22h51_33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/353cbc80-6387-8ca6-d533-f7e1259c66c6.png)

# 演算子の応答
Capabilities のチェックを外すと、余計な演算子が応答されなくなった。

![2023-11-21_22h49_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/706e0699-6218-857e-c795-6ba87ea5c02a.png)
セミ・ダイナミック補正

# 地殻変動補正パラメータファイルを読み込む

[地殻変動補正パラメータファイル](https://www.gsi.go.jp/sokuchikijun/semidyna.html#file) を読み込む

```python
def load_par(filename):
    par = pd.read_csv(filename, delim_whitespace=True, skiprows=15, index_col=0)
    return par
```
※モジュールのimport は割愛

# 補正値を計算

```python
def semi_dyna_diff(par, lat, lon):
    phi_pitch = 2/3 / 8 / 2
    lamda_pitch = 1 / 8 / 2
    down  = np.floor(lat / phi_pitch  ) * phi_pitch
    up    = np.ceil( lat / phi_pitch  ) * phi_pitch
    left  = np.floor(lon / lamda_pitch) * lamda_pitch
    right = np.ceil( lon / lamda_pitch) * lamda_pitch
    
    z00 = latlon2mesh(down,  left) # 格子左下
    z01 = latlon2mesh(down, right) # 格子右下
    z10 = latlon2mesh(  up,  left) # 格子左上
    z11 = latlon2mesh(  up, right) # 格子右上
    
    p00 = par.loc[z00]
    p01 = par.loc[z01]
    p10 = par.loc[z10]
    p11 = par.loc[z11]

    t = (lat - down) / phi_pitch
    u = (lon - left) / lamda_pitch

    b00 = p00['dB(sec)'].to_numpy()
    b01 = p01['dB(sec)'].to_numpy()
    b10 = p10['dB(sec)'].to_numpy()
    b11 = p11['dB(sec)'].to_numpy()

    l00 = p00['dL(sec)'].to_numpy()
    l01 = p01['dL(sec)'].to_numpy()
    l10 = p10['dL(sec)'].to_numpy()
    l11 = p11['dL(sec)'].to_numpy()

    h00 = p00['dH(m)'].to_numpy()
    h01 = p01['dH(m)'].to_numpy()
    h10 = p10['dH(m)'].to_numpy()
    h11 = p11['dH(m)'].to_numpy()
    
    tu00 = (1 - t) * (1 - u)
    tu01 = (1 - t) * u
    tu10 = t * (1 - u)
    tu11 = t * u
    
    dB = tu00 * b00 + tu01 * b01 + tu10 * b10 + tu11 * b11
    dL = tu00 * l00 + tu01 * l01 + tu10 * l10 + tu11 * l11
    dH = tu00 * h00 + tu01 * h01 + tu10 * h10 + tu11 * h11
    
    return dB / 60 / 60, dL / 60 / 60, dH
```

# セミダイナミック補正

```python
def semi_dyna(par, lat, lon, alt=None, sokuchi=0):
    """
    sokuchi:補正方向  =0:元期→今期, =1:今期→元期
    """
    
    dB, dL, dH = semi_dyna_diff(par, lat, lon)
    if sokuchi == 1:
        # 今期→元期
        dB, dL, dH = -dB, -dL, -dH
    
    if alt is None:
        return lat + dB, lon + dL
    else:
        return lat + dB, lon + dL, alt + dH
```

とりあえず、見よう見まねで下記を計算。
いくつかサンプルでは同じになっていたけど。あってそう？

https://www.gsi.go.jp/sokuchikijun/semidyna.html
https://vldb.gsi.go.jp/sokuchi/surveycalc/semidyna/web/index.html
RemoteDevelopmentでAlpineLinuxホストに接続

# はじめに
VisualStudioCodeのRemoteDevelopment(SSH)は、ベースOSにAlpineLinuxを使用したコンテナはサポートしていますが、AlpineLinuxを使用したリモートサーバーはサポートしていません([公式ドキュメント](https://code.visualstudio.com/docs/remote/linux#_remote-host-container-wsl-linux-prerequisites))。

しかしながら、必要なパッケージと適切な設定で、AlpineLinuxサーバーでも概ね動かすことができます。

この記事では、AlpineLinuxがインストールされたサーバーに、RemoteDevelopmentでアクセスできるようになるための覚書を書いていこうと思います。

# 手順
手順は以下の3つです。
1. AlpineLinuxのインストール
1. パッケージのインストール
1. sshdサーバーの設定
### 1. AlpineLinuxのインストール
まずはリモートホストにAlpineLinuxをインストールします。インストールに関しては過去の記事をご参照ください。

https://qiita.com/elfincafe/items/0f3acd6a76b7e3cf9b19

### 2. パッケージのインストール

RemoteDevelopmentには次のパッケージが必要です。なおcurlはwgetでも構いません。
+ gcompat
+ libstdc++
+ curl または wget
+ bash
```
 # apk add gcompat libstdc++ curl bash
```

### 3. sshdサーバーの設定

/etc/ssh/sshd_config の以下の項目をyesに変更します。/etc/ssh/ssh_configという似た名前のファイルがあるので、間違えないようにしてください。
```:sshd_config
AllowTcpForwarding yes
PermitTunnel       yes
```
変更したら再起動を忘れずに。
```
 # rc-service sshd restart
```
# 接続してみる

VSCodeで接続してみると以下のようなエラーが出るかと思います。

:::note warn
The remote host may not meet VS Code Server's prerequisites for glibc and libstdc++
:::

これだけはどうしようもないので無視してください。

# 最後に
　いかがだったでしょうか。意外と簡単だと思っていただければ幸いです。AlpineLinuxはコンテナのベースOSとして一躍注目を浴びましたが、標準ライブラリにmuslを使っていてアプリケーションの動作に影響することがあったり、DebianSlimなどの軽量OSがでてきたこともあって、一時ほど話題にならなくなりました。
しかし、一時的な流行で終わらせるにはもったいないほどポテンシャルを秘めていることもまた事実です。
この記事があなたのAlpineライフの一助になることができればうれしいです。
Netezzaフルマネージド・サービス(NPSaaS)にアクセスするための資格情報確認

# 目次
1. はじめに
1. 前提
1. 手順
1. 参考資料

# 1. はじめに
NPSaaSへのアクセスに必要な資格情報はIBM Cloudの画面から確認できます。その画面遷移のコピーを本記事にメモします。


# 2. 前提
- NPSaaSインスタンスを作成済みであること。
- IBM CloudのダッシュボードからNPSaaSインスタンスにアクセスできること。


# 3. 手順
### 3.1 IBM Cloudにログイン
https://cloud.ibm.com/login
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/6b028927-ca0a-49c0-e115-3c93938e1741.png)

### 3.2 ダッシュボード左側のアイコン（リソース・リスト）をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/6aae0ffc-bbf2-a4aa-f0dd-20270e86d5c6.png)

### 3.3 リソース・リストのNetezza Performance Serverをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/d80de33e-0332-2995-982b-f5845858d626.png)

### 3.4 エンドポイントを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/3dfdc813-daf0-39af-c151-4fae7567dde7.png)

### 3.5 資格情報を作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/324c72b5-33d2-c73c-9a9c-3baa3f9403ca.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/fe9e0b94-6637-376f-a1bf-18a06ae8c1cd.png)

### 3.6 資格情報を確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/700959/1a599fd8-94b3-61e8-330e-eeb07a2d8300.png)


# 4. 参考資料
- Netezzaマニュアル：Getting started with Netezza Performance Server
https://cloud.ibm.com/docs/netezza?topic=netezza-getstarted&locale=en

- IBM Cloudカタログページ (Netezza Performance Server, NPSaaS)
https://cloud.ibm.com/nzsaas/create
【Mac/VSCODE】PHP intelephenseを使うために四苦八苦したメモ


## 概要
Mac OS 11とかの古めのMacでPHPにコード整形用にPHP intelephense （※1)を入れようとするも、
Macに入っているPHPのバージョンが古いと整形時にエラーが出てしまうため、いろいろ処理までに対応したぞというメモです。
既存のいろんな情報を寄せ集めての対応でしたが、この流れがどこかの誰かの助けになればと思い記録。

(※1 VScodeの拡張機能。割とメジャーですてき)
(※2 自分は7.3でした。)


## エラー詳細内容
すみません、忘れました。。初っ端から。。
具体的には忘れてしまいましたが、あんたのphpバージョンだと使えねーからエラーやで！
アップデートせえ！みたいなのがvs codeで出てたとおもいます。
結果、紆余曲折な旅に出ました。

## phpのバージョンが古いならアップデートしよう！
→ この辺の手順で行いました。
https://www.stub-create.com/blog/php/mamp-brew.html

が、mac osのバージョンが少し古くなってきているので落とせず。
ここもエラーは残してないので忘れた！

## ではMac自体のアップデートだ

しました。ひとまず OS13。
で、するとphpが消えました。

```
which php 
php -v
```
どちらも動作せず！

だがこれは想定の挙動。
macをアップデートするとphpが消える問題がございます。
php、homebrewで入れ直しました。

参考：
https://guntablog.com/monterey/
パスの通し方もこちらを参考にしました！

これで準備はokだと思われる！

あとは通常の設定。

## PHP intelephenseをセット
・拡張機能で　PHP intelephense　をインストール
・setting.jsonで以下を記載

```json
	"[php]": {
    	"editor.defaultFormatter": "bmewburn.vscode-intelephense-client"
  	},
```
※該当プロジェクトだけでやるなら、該当プロジェクトの.vscode下に作ってやるといいよ！

・ビルトインされているphpを無効化
以下の「解決手順」を参考に。
https://qiita.com/eighty8/items/bbee388d1e3fab46b2b9

・vscodeの左下の歯車マークをクリックし、設定から「format」と検索。
Default FormatterをPHP intelephenseにし、
Format on SaveをONに変更。
![設定-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/bdd95ab6-8423-0e8e-efe2-fa5168fc1811.png)



## 以上！
長かった。。。これでやっとphpで自動補完が走りました。
嬉しい！

## 20240501追記
また別の環境でも発生。最終的にPHP intelephenseのバージョン下げたら治った。なんじゃそりゃ！という感じである
パソコンのハードウェア情報の検索




PowerShellのwmiコマンド
    PowerShellでパソコンのメーカー、型番、シリアル番号が分かるらしい
    
    実際のコマンドは以下
    Get-WmiObject Win32_ComputerSystemProduct

    結果を見るとシリアル番号、型番、メーカー名と出てきた。



    一部だけ取り出すときは
    メーカー
    Get-WmiObject Win32_ComputerSystemProduct | select vendor

    型番
    Get-WmiObject Win32_ComputerSystemProduct | select name

    シリアル番号
    Get-WmiObject Win32_ComputerSystemProduct | select vendor




当初は、以下のwmicのコマンドを使っていた。

    メーカーは以下のコマンド
    wmic csproduct get vendor

    型番は以下のコマンド
    wmic csproduct get name

    シリアル番号は以下のコマンド
    wmic csproduct get identifyingnumber


wmicのを調べるとWindows Management Instrumentation を扱うコマンド。
しかし調べるとどうもこいつは非推奨になるようだ。

以下の公式ドキュメントを確認すると
https://learn.microsoft.com/ja-jp/windows/whats-new/deprecated-features

    WMIC ツールは、Windows 10 バージョン 21H1 
    および Windows Server の 21H1 一般提供チャネル リリースでは非推奨です。
    このツールは、Windows PowerShell for WMI に置き換えられます。
    注: この非推奨は、コマンド ライン管理ツールにのみ適用されます。 WMI 自体は影響を受けません。
    
とある
【Swift】OptionSetという複数の値をまとめて管理できるものがあるらしい

# はじめに
デフォルトで用意されているコードスニペットを見ていたら使ったことのない機能を見つけたので使ってみました。
![スクリーンショット 2023-11-21 22.35.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0ee0c7d7-186d-371e-2e98-3b46fc52f5b0.png)

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2023-11-21 at 22.34.58.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/0ea152a9-4188-f89a-d4b0-dd8d86c8fe52.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State private var sectionOptions: SectionOptions = .none
    var body: some View {
        List {
            Section {
                Text("コンテンツ")
            } header: {
                if sectionOptions.contains(.showHeader) {
                    Text("ヘッダー")
                }
            } footer: {
                if sectionOptions.contains(.showFooter) {
                    Text("フッター")
                }
            }
            
            Button {
                sectionOptions = .none
            } label: {
                Text("none")
            }
            .disabled(sectionOptions == .none)
            
            Button {
                sectionOptions = .headerOnly
            } label: {
                Text("headerOnly")
            }
            .disabled(sectionOptions == .headerOnly)
            
            Button {
                sectionOptions = .footerOnly
            } label: {
                Text("footerOnly")
            }
            .disabled(sectionOptions == .footerOnly)
            
            Button {
                sectionOptions = .headerAndFooter
            } label: {
                Text("headerAndFooter")
            }
            .disabled(sectionOptions == .headerAndFooter)
        }
    }
}

struct SectionOptions: OptionSet {
    let rawValue: Int
    
    static let showHeader = SectionOptions(rawValue: 1 << 0)
    static let showFooter = SectionOptions(rawValue: 1 << 1)
    
    static let none: Self = []
    static let headerOnly: Self = [.showHeader]
    static let footerOnly: Self = [.showFooter]
    static let headerAndFooter: Self = [.showHeader, .showFooter]
}
```

# おわり
複数の状態を1つの値で持っておけるのは便利ですね

# 公式ドキュメント
https://developer.apple.com/documentation/swift/optionset
floatプロパティについての基本解説

# floatプロパティについての基本解説

Webデザインにおいて、`float`プロパティは非常に重要な役割を果たします。このプロパティを使用することで、Webページ上の要素を柔軟に配置することが可能になります。本記事では、`float`プロパティの基本的な特徴とその使い方について初心者にも分かりやすく解説します。

## floatプロパティの特徴

### 要素の横並び

#### 横並びの実現

`float`プロパティを使用すると、要素を左や右に浮かせる（フロートさせる）ことができます。これにより、例えば複数のリストアイテムや画像が横並びに配置されます。

### 要素幅の自動調整

#### 子要素に合わせた幅の調整

`float`を適用した要素は、その子要素の幅に合わせて自動的に幅が縮小します。これにより、要素が必要以上にスペースを取ることなく、コンテンツに合わせたサイズになります。

## clearプロパティとの組み合わせ

### 横並びの回避

#### clearプロパティの活用

`float`プロパティで要素が横並びになるのを避けたい場合、`clear`プロパティを使用します。`clear`プロパティを適用すると、指定した要素は`float`された要素の横ではなく、下に配置されます。

### clearプロパティの適用方法

#### 要素への適用例

例えば、ある要素に`float: left;`を適用し、その後に来る要素に`clear: left;`を設定すると、後者の要素は横並びにならず、縦に配置されます。

## まとめ

`float`プロパティは、Webページ上で要素を横並びに配置したい場合に非常に役立ちます。しかし、その影響でページレイアウトが意図しない形になることもあります。このような状況を防ぐためには、`clear`プロパティをうまく活用することが重要です。これにより、要素の流れをコントロールし、望むレイアウトを実現することができます。初心者の方も、これらのプロパティを理解し、実際のWebページ作成に活用してみてください。
これできたら現場でめっちゃ評価される❗️開発エンジニアの質問の正しいやり方

# 概要
自分が未経験時代に現役のCTOから質問が下手すぎて、
質問するたびに注意されてました。「なんで俺だけこんな言われるんだー」って
思いながらやってましたが、ある時質問力が上達したら
あまり詰められたりしなくなり、違う環境でも「質問が上手い!」と褒められました。

質問が上手いか下手かで今後のキャリアが左右されたりするみたいです。

# この記事の対象者
- 未経験エンジニア
- 若手エンジニア


# 質問が上手いとどいういメリットがあるのか
- ```仕事ができる人と思われる```
- ```他のエンジニアの時間を奪わないので工数削減(つまり利益貢献につながり収入upにつながる)```
- ```困った時に欲しい回答が返ってくる```

### 質問が上手いと褒められた話
質問が下手な時は毎回厳しい指摘ばかりでしたが、
質問がしっかりできるようになってから開発もスムーズになりましたし、
技術面の向上にコミットできました。

コミュニケーションの問題があると技術どころの話ではなくなってしまうんですよね。

### 質問が下手すぎて困ったこと
本来5回くらいのやり取りで解決できたものが20回のやり取りが必要になってしまいます。
質問する側と受ける側が疲弊していいことなんかないです。
この時は実務ではなかったのでよかったですが、
実務だったらかなり会社に損失です。


## 開発エンジニアが時間を無駄に使うことはお金の損失
前こういうことを言われたことがあります。
僕が社内で１番技術力が高いエンジニアに質問しようとした時に、
PMの方からこのように言われました。
***「エンジニアの時間は会社のお金ってことを忘れないでね。1人優秀なエンジニアが手が止まるだけで会社が損失するって思ってね。そこを頭にれた上で質問しなよ!」***

このPMの方だけでなく他社のエンジニアの方も同じことを話してました。
***開発エンジニアって今の時代ビジネスの主人公みたいなもので、
開発エンジニアがいないと会社として成り立たないくらい貴重な人材***です。

なのでこの認識を持った上で質問すべきかなと思います。


### 「なかなか欲しい回答がもらえないなー」の原因
なかなか欲しい回答が来ない場合は質問が悪い場合もあります。
これは質問がわかるづらかったりして要点が外れた回答になってしまう場合が多いです。
質問のやり方を学ぶ必要があります。

# 実際こんな質問されたらどうですか
もし皆さんがこんな質問されたらどうですか。

```
railsでmigrationを実行したらエラーが出ました。どうすればいいですか。
```
これだとわかりづらいですよね。💦
「何がわからないのか？どういうエラーが出たのか?そもそもエラー解決する気あるのか？」
ってなりますよね。

これじゃ答える側もいちち
「どんなエラー？何して欲しいの？」みたいな会話になって余計なやり取りが増えてしまいます。
これだと ***エンジニアの時間の損失(お金の損失)*** です。

# 質問のやり方を解説
```これが1番大事です❗️。```

①***要件を伝える(結論)❗️*** ex) 質問、相談、報告、共有なのか
先ほどで言うと

「質問です。railsでmigrationを実行できず困っています。」


②***今の状況を伝える***
「〇〇ファイルで🔺🔺を実装してmigrationファイルを実行したら、以下のエラーが出てmigrationを実行できなくなってしまいました。　エラー■■」

どう言う状況かわからないと適切なアドバイスが難しいです。

③***自分が試したこと、調べたこと(自分の仮説も入れるといいです。)***
〇〇のようなエラーが出たので🔺🔺だと思ったのですが、うまくいかなかったです。
■■を調べてみたのですが、いい解決策が見つからなかったです。

- 補足　　
***仮説を立てる時はなぜその仮説を立てたのかを説明できないと何も根拠のない仮説***になってしまいます。自分の考えが浅くなってしまいます。

- 補足2
修正したなら「修正」だけでなく「〇〇を修正」など***具体的に固有名詞を使って説明***しましょう。***あと〇〇件修正など数字も使うとわかりやすい***です。

④***最後に***
〜の方向性で調べているのですが、解決できず困ってしまってます。
ご教授いただけると幸いです。



みたいな感じです。
自分の考え、状況、試したことなどがわからないとな質問に答える側も何もアドバイスできないです。








# 質問が下手な人がいる時の現場の対策
例えばSLackとかで質問する時に

```
質問箇所、困っていること、自分で調べたこと
```
これを記載しない限り質問ができないようにすればいいと思います。

後は***普段から言語化ができていないので業務日報を書くことを必須にする***
ことも大切だと思います。
その際に業務日報を書くとどんなメリットがあるのかを相手に提示すれば効果があります。

QiitaとかZennで自分の言葉で発信する習慣を少しでもつけるのも対策です。

# 自分が質問を上達させた方法

- ```スクールとかなら上で紹介したやり方を繰り返し練習する```
上記で紹介したやり方でできているかを徹底的にフィードバックをもらうのがいいです。
未経験時代に自分は毎日CTOの方からボコボコに言われてきました。😅
とにかく***練習して習慣化するのが１番***です。上のやり方ができるとエンジニア業務以外でも
「何かできそうな人」みたいに見られますし、他の仕事でも役に立ちます。

- ```ドキュメントを書く```
自分はとにかくドキュメントをひたすら書いていました。自分以外のエンジニアの方もかなり効果があったみたいです。
コツは***先生になったつもりで書くこと***、***なるべく自分の言葉でまとめること***です。

実践してみてください❗️

https://zenn.dev/norihashimo/articles/3bd51cee75cdf8
【Rails】rails db: から始まるコマンドまとめ

どうもこんにちは。

今回はRails開発で使う`rails db:`から始まるコマンドをまとめてみました。

# データベース作成

以下のコマンドでアプリケーションで使用するためのデータベースを作成します。

```
$ rails db:create
```

# データベース削除

以下のコマンドでアプリケーションで使用していたデータベースを削除します。（データやテーブル、カラムなどが全て消えます。）

```
$ rails db:drop
```

# データベースを最新にする

以下のコマンドでデータベーススキーマの状態を最新の状態にします。

```
$ rails db:migrate
```

マイグレーションファイルは以下のコマンドで生成します。

```
rails g migration AddAgeToUserModel
```

生成されるマイグレーションファイルは以下のようになります。

```ruby
class AddAgeToUserModel < ActiveRecord::Migration[6.0]
    def change
        # カラムを増やしたい時
        add_column :users, :age, :integer
        # カラムを減らしたい時
        remove_column :users, :initial, :string
    end
end
```

マイグレーションファイルの詳しい書き方は後日投稿します。

# データベースを最新の状態から巻き戻す

以下のコマンドで最新の状態のデータベーススキーマを元に戻します。

```
$ rails db:rollback
```

# データベースのマイグレーションの状態を確認する

以下のコマンドでマイグレーションの状態を確認します。

```
$ rails db:migrate:status
```

このコマンドは`db/migrate`ディレクトリ内にあるマイグレーションファイルがデータベーススキーマに反映されているかされていないかを確認できます。

`up`となっていれば反映されていて、`down`となっていれば反映されていません。

# 初期データを投入する

以下のコマンドで`db`ディレクトリ内にある`seeds.rb`の内容を反映させます。

```
$ rails db:seed
```

`seeds.rb`の内容は以下のような形です。

```ruby
User.first_or_create([
                        { id: 1, name: '山田太郎' },
                        { id: 2, name: '田中花子' }
                      ])
```

# ファイルに定義されたデータスキーマをロードする

以下のコマンドで`db`ディレクトリにある`schema.rb`の内容をデータベースに反映させます。

```
$ rails db:schema:load
```

# 現在のデータスキーマをファイルに出力する

以下のコマンドで現在のデータベースのスキーマ情報を`db`ディレクトリの`schema.rb`に反映させます。

```
$ rails db:schema:dump
```

# データベース作成+スキーマロード+初期値投入

以下のコマンドで3つの動作を一括して行えます。

```
$ rails db:setup
```

# データベース削除+再作成+スキーマロード+初期値投入

以下のコマンドで4つの動作を一括して行えます。

```
$ rails db:reset
```

# データベースが存在するしないで処理が変わる

以下のコマンドでは、データベースが存在しない場合は、`rails db:setup`と同様の動作、存在する場合には`rails db:migrate`と同様の動作がされます。

```
$ rails db:prepare
```

# データベースのスキーマバージョンを表示する

以下のコマンドを実行すると、データベースのスキーマバージョンが表示されます。

```
$ rails db:version
```

# データベースコンソールを開く

以下のコマンドを実行すると、データベースのコンソールを開きます。

```
$ rails db:console
```

# データベースの環境設定を行う

以下のコマンドを実行するとデータベースの環境設定を行います。

```
$ rails db:environment:set
```

# データベースの構造をファイルに出力する

以下のコマンドでデータベースの構造を`db/structure.sql`に出力します。

```
$ rails db:structure:dump
```

# データベースの構造をファイルからロードする

以下のコマンドで`db/structure.sql`に定義されているデータベース構造をロードする。

```
$ rails db:structure:load
```

# テスト用のフィクスチャデータをロードする

以下のコマンドでテストで使用するフィクスチャデータをロードします

```
$ rails db:fixtures:load
```

# テスト用のデータベースを開発データベースのスキーマに合わせる

以下のコマンドでテストデータベースのスキーマを開発データベースのスキーマに合わせます。

```
$ rails db:test:prepare
```

# テストデータベースにスキーマをファイルからロードする

以下のコマンドでテストデータベースのスキーマをファイルからロードします。

```
$ rails db:test:load
```

# まとめ

開発で少なくとも使用するのは、以下のコマンドかなと思います。

```
$ rails db:create
$ rails db:drop
$ rails db:migrate
$ rails db:rollback
$ rails db:migrate:status
$ rails db:seed
```

もっとデータベースのことを勉強した方が良さそうですな。。。
WSLのclip.exeの文字化け対処

気が向いから書いた
# clip.exeとは
Windowsでのコピペをしてくれるやつ
WSLでもpathが通っている。
```bash
echo "test" | clip.exe
```
みたいな感じでパイプをつないであげるとクリップボードに`test`が保存される
# 問題
`clip.exe`をパイプラインで使用すると日本語が文字化けするようになった。
ex)
```bash
echo "てすと" | clip.exe # クリップボードの中身が "縺ｦ縺吶→" となる(文字化けする)
```
# 対処法
以下のようなエイリアスを取ってあげればいい
`alias clip.exe='iconv -t sjis | clip.exe'`

エイリアスの保持のため設定を書き込む
```bash
#zshだと~/.bashrcを~/.zshrcに置き換える
echo "alias clip.exe='iconv -t sjis | clip.exe'" >> ~/.bashrc 
source ~/.bashrc 
```
これで文字化けは起こらなくなるはずです
# 参考
https://zenn.dev/kumavale/scraps/2271c61cbd19ef
AtCoder初心者 DailyTrainingメモ 2023/11/21

# ABC297-C問題
https://atcoder.jp/contests/adt_easy_20231121_1/tasks/abc297_c

![297C.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547298/a5a4d4e4-e6e0-e3cd-9905-2b4f7e85fe16.png)


**ポイント**
問題を難しく書かれているが、シンプルに "TT" を "PC" に置き換えるだけ。Pythonには、replace関数がある。

````Python:297CA.py
H,W = map(int,input().split())
L = []

# リストLに文字列を格納
for i in range(H):
    S = input()
    L.append(S)

# リストから読み込んだ文字列の中で文字列置換する
for c in L:
    print(c.replace('TT','PC')) 
````
# ABC232-B問題
https://atcoder.jp/contests/adt_easy_20231121_2/tasks/abc232_b

![232B.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547298/65871d13-3cc4-12d8-b5f9-c066a45944f1.png)

**ポイント**
・英小文字を数値に置き換えて計算する
・それぞれの数値の差をsetに格納して１意であることを判定する

````Python:232B.py
# 入力
# abc
# ijk

S = input()
T = input()

# 英小文字を数値に置き換えてリストA,Bへ格納する
A = [ord(char) - ord('a') for char in S] # A:[0, 1, 2]
B = [ord(char) - ord('a') for char in T] # B:[8, 9, 10]


# zipを使ってリストの先頭から同時に値を取り出す
# それぞれの差を求めて　A[0]-B[0]、A[1]-B[1]、A[2]-B[2]
# set で重複を削除する
C = [(X-Y) % 26 for X,Y in zip(A,B)]
ST = set(C)

# 差が１意ならYes
if len(ST) == 1:
    print("Yes")
else:
    print("No")
````
[Next.js]ユーザーの動きにまつわるものはClientで

## はじめに
Next.jsのApp Routerにおいて、Server ComponentsとClient Componentsが現れました。正確にはReactの機能ですが。そしてv14でServer Actionsが現れました。これも正確にはReactの機能ですが。これはServerなの、Clientなのなど使い分けが一見混乱するかと思います。実際に自分が使ってみてこうしたほうがわかりやすいと思い4つに分類してみました。

## GETはServer Componentsで
Server Componentsの中にClient Componentsが来ます。GETの通信処理はServer Componentsで行いましょう。すると表示も早く、またuseEffectで非同期処理や、SWRなどの非同期処理ライブラリなどを使わずasync awaitだけでGETできます。ここでGETしたものをClientに渡せば、Client側はGETに関する処理を持たなくて済むので動きだけに専念できます。
このとき、Client ComponentsはSuspenseで囲んであげましょう。

```tsx:index.tsx
import { Suspense } from "react"
import { MyClient } form "./mycomponent"
import { Loading } from "./loading" //ローディング
export default async function Index() {
    const data = await fetch("https://api.example.com")
    return (
        <Suspense fallback={Loading}>
            <MyClient data={data} />
        </Suspsense>
    )
}
```

## POSTなどの送信処理はServer Actionsで
POSTなどの送信処理はServer Actionsを通して行いましょう。ORMを使ってDBに直接POSTをしていなくても、REST APIなどでPOSTしている場合もServer Actionsを通して行うことをおすすめします。ユーザーが送るデータに関することをすべてNext.js側で責任がもてます。サーバー側のバリデーション処理だったり。
Server Actions自体はForm APIを通しているのでPOSTしかできませんが、その先にAPIを通していればPATCHやPUT、DELETEも送れると思います。
また送信するAPIのurlもユーザーからは見えなくなるため、そしてわざわざNext.js側でAPIディレクトリを作らず済むのでServer Actionsを使うことをお勧めします。

## UXにまつわる全てのことはClient Componentで
動的に表示する、画面にエラーメッセージを出す、条件によってコンポーネントの出しわけをする、ページ遷移をする等々、ユーザーの動きに関することはすべてClient Componentで処理しましょう。
そもそもuseStateなどのReact Hooksを使う場合はServer Componentsで使えません。

例えば、Server Actionsで送信に成功したさいにページ遷移するにはどうしたらいいでしょうか？Server ActionsでNextResponseを使ってredirectでページ遷移することはおすすめしません。なぜならServer Actionsは今現在はそこまで便利なAPIを提供されているわけでもなくほぼ純粋なNode.jsみたいなものなので、Server Actions自身でURLを取得したりパスを取得したりするのも複雑になります。
Client Componentsに持たせればuseRouterなどのNext.jsのライブラリを利用できるので、パスの取得やページ遷移、ページ遷移する前になんらかのClient処理などが行えます。

ここで、formはClient Componentsにおくことをお勧めします。React Hook Formなどのフォームライブラリも使えますし、フォーム送信前後の処理も書くことができます。

```tsx:form.tsx
'use client'

import { useRouter } from 'next/navigation'
import { useForm } from 'react-hook-form'
import { Action } from './action' //自作Server Action
import { useAlert } from './AlertHooks' //自作Alert

export default function Form() {
  const { trigger } = useForm()
  const { alert } = useAlert()
  const router = useRouter()
  return (
    <form
      action={async (data) => {
        //バリデーションの実行
        await trigger()
        await Action(data).then(() => {
          alert('成功しました')
          router.push('/dashboard')
        })
      }}
    >
      {/* ここにフォームの中身を書く */}
    </form>
  )
}

```

## 共通するサーバー処理はmiddlewareで
Next.jsにはmiddlewareというサーバー処理をするファイルがあります。例えば認証が必要なページでcookieがからだったらトップページにリダイレクトさせるなどの処理をするなど。ページ遷移はClientに持たせましょうといいましたが、認証処理などは逆にClient側でやるとuseEffectを駆使したり、一瞬ページが表示されてしまうなど工夫をしないとUXが悪くなるので、このようなリダイレクト処理はmiddlewareに持たせることをおすすめします。

## 終わりに
Next.jsの機能を大まかに4つにわけました。これによってApp routerの使い方に戸惑っている方も、うまく使い分けられるのではないでしょうか。
Server Components,Servr ActionsはGET POSTなどの通信処理に専念させると考えれば、Client Componentsが非常に書きやすくなると思います。
git リポジトリを clone 後に軽量化する (blobless化)

# 概要・結論

git リポジトリを clone するとき、パーシャルクローンすることで fetch してくるデータサイズを小さくすることができます。

```shell
blobless clone
% git clone --filter=blob:none git@github.com:git/git.git
```

同様に、通常の clone をしたあとからでも git repack コマンドを使うことで手元のリポジトリを blobless 化することができます。

```shell
通常の clone
% git clone git@github.com:git/git.git

手元の git リポジトリは 303MB
% du -hs git
303M	git

手元の git リポジトリを blobless 化する (git 2.43.0 以降が必要)
% cd git
% git repack -ad --filter=blob:none --filter-to=pack --no-write-bitmap-index
% git config remote.origin.promisor true
% git config remote.origin.partialclonefilter blob:none
% ls
...
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.idx
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.pack
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.rev
...
% rm pack-*.idx pack-*.pack pack-*.rev # filter で除外した pack を削除する
% cd ..

blobless 化した　git リポジトリは 169MB
% du -hs git
169M	git
```

以下、blobless 化についての解説です。

# 環境

この記事の内容は以下の環境で確認しました。

* macOS Sonoma 14.0 (Apple M1)
* git 2.43.0 (Homebrew)

# blobless クローンについて

blobless クローンはパーシャルクローンの一種です。対象リポジトリのコミットツリーをすべて取得しますが、blob は取得しないことで手元のリポジトリを小さくすることができます。

blobless クローンの詳細は以下の記事を確認してください。

https://github.blog/jp/2021-01-13-get-up-to-speed-with-partial-clone-and-shallow-clone/

# git repack

git repack コマンドは、git objects を packfile へ統合しなおすコマンドです。

https://git-scm.com/docs/git-repack

以下のコマンドにより、git リポジトリの packfile から不要な blob が除外されます。

```shell
% git repack -ad --filter=blob:none --filter-to=pack --no-write-bitmap-index
```

`--filter=blob:none` を指定すると、filter 条件を適用して packfile を生成します。

併せて `--filter-to=...` を指定すると filter 条件により除外された objects の保存先を指定できます。

> **`--filter-to=...` は git 2.43.0 から利用可能です**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/30321e79-58ab-6d4f-3c70-254e68c5a79f.png)

また、ドキュメントの指示通り `-ad` と `--no-write-bitmap-index` を付けておくとよさそうです。これらのオプションが本当に必要かどうかは不明です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/b2e4c82f-4073-4657-be9b-435bf96819a3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/e2de1543-824c-61cc-aec1-c16f807dd25b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/8a123e7b-33db-7892-f77d-cea188debe89.png)

# パーシャルクローンの設定

パーシャルクローンされたリポジトリは、未取得の objects が必要になったときにその都度 remote から objects を fetch してきます。
この動作を有効とするため、以下の設定を書き換えます。

```shell
% git config remote.origin.promisor true
% git config remote.origin.partialclonefilter blob:none
```

https://git-scm.com/docs/git-config

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17931/74f0a4fb-38d3-b73d-a49b-ce3d7286182b.png)

パーシャルクローンの動作について、詳細は以下のドキュメントを確認してください。

https://www.git-scm.com/docs/partial-clone/

# 除外された　packfile の削除

`git repack ... --filter-to=...` により packfile から除外された objects は `--filter-to=...` で指定した場所に分離して保存されているため、これを削除します。

```shell
% ls
...
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.idx
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.pack
pack-3458e8d0ab652aea3712b9be1b75603759de66a5.rev
...
% rm pack-*.idx pack-*.pack pack-*.rev
```

これで、手元のリポジトリが blobless 化されました。
chmodを使わなくなるとすぐに忘れるので備忘録

# chmodとは
UNIXおよびLinuシステムで使用されるコマンドで、**ファイルやディレクトリのアクセス権限を変更**するために使用されます。
また`chmod`は「Change mode」の略で、ファイルやディレクトリの読み取り、書き込み、実行権限を設定または変更します。

# 基本的な使用方法
```bash
    chmod [オプション] [モード] [ファイル名]
```
## モードの指定方法
モードは数値（絶対モード）または記号（記号モード）を使用して指定できます。
## 1. 数値モード

### 数値モードにおける権限設定

| 数値 | 所有者 (user) | グループ (group) | その他 (others) | 権限の組み合わせ |
|------|--------------|----------------|----------------|-----------------|
| 7    | 読み取り (r)  | 書き込み (w)    | 実行 (x)        | 全権限           |
| 6    | 読み取り (r)  | 書き込み (w)    | -              | 読み書き         |
| 5    | 読み取り (r)  | -              | 実行 (x)        | 読み取りと実行   |
| 4    | 読み取り (r)  | -              | -              | 読み取りのみ     |
| 3    | -            | 書き込み (w)    | 実行 (x)        | 書き込みと実行   |
| 2    | -            | 書き込み (w)    | -              | 書き込みのみ     |
| 1    | -            | -              | 実行 (x)        | 実行のみ         |
| 0    | -            | -              | -              | 権限なし         |

### 具体例

1. **所有者に全権限、グループとその他に読み取りと実行の権限を与える**:
   ```
   chmod 755 ファイル名
   ```
   このコマンドは、所有者に読み取り（4）、書き込み（2）、実行（1）の権限を与え（合計7）、グループとその他には読み取り（4）と実行（1）の権限を与えます（合計5）。

2. **所有者に読み取りと書き込みの権限のみを与え、グループとその他には権限を与えない**:
   ```
   chmod 600 ファイル名
   ```
   この設定では、所有者に読み取り（4）と書き込み（2）の権限を与え（合計6）、グループとその他には権限を与えません（0）。

3. **全ユーザーに読み取りの権限のみを与える**:
   ```
   chmod 444 ファイル名
   ```
   このコマンドは、所有者、グループ、その他全員に読み取り権限（4）のみを与えます。


ご指摘ありがとうございます。`chmod` コマンドの記号モードに関する詳細も追加しましょう。

### 記号モード

記号モードでは、特定のユーザーグループに対して、権限を追加、削除、または設定することができます。

| 記号 | 対象者     |
|------|------------|
| u    | 所有者 (user) |
| g    | グループ (group) |
| o    | その他 (others) |
| a    | 全員 (all)     |

| 操作 | 説明       |
|------|------------|
| +    | 権限を追加 |
| -    | 権限を削除 |
| =    | 権限を設定 |

### 記号モードの具体例

1. **所有者に実行権限を追加する**:
   ```
   chmod u+x ファイル名
   ```
   このコマンドは、所有者（u）に実行権限（x）を追加します。

2. **グループから書き込み権限を削除する**:
   ```
   chmod g-w ファイル名
   ```
   この設定では、グループ（g）から書き込み権限（w）を削除します。

3. **所有者とグループに読み取りと書き込みの権限を設定し、その他には権限を与えない**:
   ```
   chmod ug=rw,o= ファイル名
   ```
   このコマンドは、所有者（u）とグループ（g）に読み取り（r）と書き込み（w）の権限を設定し、その他（o）には権限を与えません。




# chmodの読み方
私はチェンジモードが一番しっくりきます。
- チェンジ・モード
- シー・エッチ・モード
- チモド
- チモッド
- チェモド

# 参考
https://oshiete.goo.ne.jp/qa/160457.html
firewalldを設定する（特定のネットワークからのHTTP/HTTPSのアクセスを許可する）(アドレス直接指定)

firewalld の設定について復習を兼ねて書いていきます。思いつきで書いているので順番バラバラです。内容間違ってたらすいません。
* 常に恒久的な設定として使いたいので、--permanent オプションを使います。一時的に使いたいだけなら --permanent を除去してください。
* 環境は Redhat9系です。AlmaLinux9で設定しています。
* firewalld は起動してください。 systemctl start firewalld
* selinux は切って(disable)ください。分かる人は有効に。


### 今回のパターン
* サーバのNICは ens0p3 という名前 (VirtualBoxだったので)
* このサーバではApacheサーバが動作していて、それをアクセスさせたいのでHTTPとHTTPSを通信許可したい。
* 全てのネットワークではなく 172.16.3.0/24 からのアクセスのみ許可したい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/785184/2cb4c6fd-27b1-117c-068c-ead796bce9a5.png)

### 1.ゾーンの選定
前回に引き続き externalを使用します。externalゾーンは初期では以下のような感じになっています。

基本的な動作：全てを拒否
PING応答： OK(PING応答する)
通信OKのサービス ：ssh

### 2.ゾーンから不要なサービスを削除します（前回やったのと一緒なので実行済みならやる必要なし）
* ゾーンexternalの通信OKサービスから ssh を削除する
firewall-cmd --permanent --zone=external --remove-service=ssh

### 3.通信OKなサービスとアドレスをリッチルールで許可設定する
アクセス元のIPアドレスを制限するには、「リッチルール」という方法を使う必要があります。リッチルールを使うことで単純な「許可/拒否」だけではない複雑な設定が可能です。

コマンド(1)
firewall-cmd --permanent --zone=exnternal --add-rich-rule='rule family=ipv4 source address=172.16.3.0/24 service name=http accept'
#### コマンドの意味
ゾーンexternalに対し以下のリッチルールを指定する
リッチルールの内容
* IPv4で (family=ipv4)
* アクセス元IPアドレスが 172.16.3.0/24 で (source address=172.16.3.0/24)
* HTTPサービスへのアクセス (service name=http)
* 許可 (accept)

コマンド(2)
firewall-cmd --permanent --zone=exnternal --add-rich-rule='rule family=ipv4 source address=172.16.3.0/24 service name=https accept'
#### コマンドの意味
ゾーンexternalに対し以下のリッチルールを指定する
リッチルールの内容
* IPv4で (family=ipv4)
* アクセス元IPアドレスが 172.16.3.0/24 で (source address=172.16.3.0/24)
* HTTPSサービスへのアクセス (service name=https)
* 許可 (accept)

### 3.ゾーンexternalを インターフェース enp0s3 に割り当てる(すでにやっていたら不要)
firewall-cmd --permanent --zone=external --change-interface=enp0s3

### 4. 設定を有効化する
firewall-cmd --reload

### 5. externalの設定内容を確認する
firewall-cmd --info-zone=external
```
external (avtive)
  target: default
  icmp-block-inversion: no
  interfaces: enp0s3
  sources:
  services: http https
  ports:
  protocols:
  forward: yes
  masquerade: yes
  forward-ports:
  source-ports:
  itmp-blocks
  rich rules:
        rule family="ipv4" source address=172.16.3.0/24 service name=http accept
        rule family="ipv4" source address=172.16.3.0/24 service name=https accept
```

以上で 172.16.3.0/24、172.16.4.0/24からHTTP/HTTPSサービスにアクセスができるようになると思います。
CodeWhispererのCLI補完

zshの自動補完で先月[新たな発見](https://qiita.com/itsuki3/items/8fa6c666e068bb3b1cd7)をしたばかりだが、re:Inventが近づく中、AWS CodeWhispererで似たような && オシャレな機能が追加されたので試してみた。

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/amazon-codewhisperer-command-line-preview/

## Step by Step
#### 1. まずはインストール
自分の環境はmacなので以下から。

https://desktop-release.codewhisperer.us-east-1.amazonaws.com/latest/CodeWhisperer.dmg

いつも通り、アプリケーションフォルダにコピーする。
続いて、システム設定で **「プライバシーとセキュリティ→アクセシビリティ→CodeWhisperer」** を有効化して完了。

#### 2. ターミナルを再起動
自分の場合はiTerm2。再起動しないと反映されないので注意

#### 3. 起動して試してみる

OSコマンドや各種主要ツール、およそ500ほどをカバーしているとある。試しにいくつか試してみる。

**grepコマンドの場合**
![スクリーンショット 2023-11-21 21.53.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/95b9ab46-a3d6-ee94-aedb-a5b24b671859.png)

**unameコマンドの場合**
![スクリーンショット 2023-11-21 21.55.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/5be4bfa8-1dcb-05e3-95ea-0410211ff7c5.png)

**gitコマンドの場合**
![スクリーンショット 2023-11-21 21.52.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/9652f938-9dca-0fa7-5cae-c7d8f3027385.png)

**AWS CLIの場合**
![スクリーンショット 2023-11-21 21.49.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/89f1b262-06b6-4843-621c-56cca2174d5a.png)

**dockerコマンドの場合**
![スクリーンショット 2023-11-21 21.26.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/5dbb744a-c4ed-e0f5-9009-9c0238dfd07d.png)

**kubectlにも対応（ちなみにeksctlには非対応）**
![スクリーンショット 2023-11-21 21.48.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/2863b739-4914-6408-b52a-05edad789885.png)

#### 4. 自然言語機能を試す
`cw ai`と打つことで、自然言語（英語）から生成AI経由でやりたいことの推奨を貰うことも出来る模様。

**dockerイメージを実行したい場合**
![スクリーンショット 2023-11-21 21.29.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/bd01fde6-27ea-a2d8-cff4-2cd1f9d18fd8.png)

**grepしてawkしたい場合**
![スクリーンショット 2023-11-21 21.42.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/07885d9a-7833-4dd3-81f4-bfbfed0b05e8.png)


#### 5. その他
`cw settings`とすると設定画面、`cw dashboard`とするとダッシュボードを開いてくれる。

**設定画面**
![スクリーンショット 2023-11-21 21.43.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/a9b7e974-f5b1-8446-66b2-3d27bdd2cdb5.png)

**ダッシュボード**
![スクリーンショット 2023-11-21 21.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/609876/8c1d697d-e37d-d7c7-faa1-de94870672aa.png)

## まとめ
補完系はこれ一つで大方賄えそうな。
スクリーンショットをクリップボードに保存

エビデンス取得が楽になる[プログラム](https://qiita.com/flip-flop/items/329b3155df52e4c78cd4)の検討途中にできたプログラムを紹介します。何かのお役に立てれば幸いです。

# はじめに
スクリーンショットをファイルとして保存する方法を説明したページはたくさんあったのですが、リアルタイムでスクリーンショットをクリップボードに保存する方法が見つからなかったので書いてみました。

# 完成プログラム
クリップボードの操作にwin32clipboardモジュールを使用しています。
```
#copyImageClipboard.py
from pynput import mouse
import pyautogui
from PIL import ImageGrab, Image
import win32clipboard
import io
import sys

# //////////////////////////////////////////////////
# プログラムの説明
#   ブラウザ画面の指定範囲をクリップボードにコピーする
# 引数 
#   left_up_x, left_up_y, right_down_x, right_down_y
# 実行後の画面操作方法
#   1回目のクリックでブラウザを選択
#   2回目のクリックでエビデンスの画面を選択
# //////////////////////////////////////////////////

# 実行時に引数を受け取る 
args = sys.argv
# クリック回数
num_press = 0

def main():
    with mouse.Listener(on_click=on_click) as listener:
        listener.join()
    # 引数の値を変数に設定
    _ , left_up_x, left_up_y, right_down_x, right_down_y = [*args]
    # スクリーンショット
    im = pyautogui.screenshot("screenshot.png", region=(int(left_up_x), int(left_up_y), int(right_down_x), int(right_down_y)))
    # スクリーンショットをクリップボードにコピーする
    copy_to_clipboard()
        
def copy_to_clipboard():
    # スクリーンショット画像を開く
    original_image = Image.open('screenshot.png')
    # メモリストリームにBMP形式で保存してから読み出す
    output = io.BytesIO()
    original_image.convert('RGB').save(output, 'BMP')
    data = output.getvalue()[14:]
    output.close()
    # クリップボードをクリアして、データをセットする
    win32clipboard.OpenClipboard()
    win32clipboard.EmptyClipboard()
    win32clipboard.SetClipboardData(win32clipboard.CF_DIB, data)
    win32clipboard.CloseClipboard()
   
def on_click(x, y, button, pressed):
    global num_press
    if pressed:
        # 1回目のクリックはウィンドウ選択
        if num_press == 0:
            num_press = 1
        # 2回目のクリックは表示画面を選択
        else:
            return False

if __name__ == "__main__":
    main()
```
▼ 以下の引数で実行
```
python .\copyImageClipboard.py 242 260 957 748
```
▼ 実行結果
ペイントにctrl + vで貼ってみた。
![2023-11-21 212801.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3324903/374a5e08-21bc-65eb-c7c5-1fe3ffdbee38.png)


# おわりに
[Web画面のエビデンス取得の自動化](https://qiita.com/flip-flop/items/329b3155df52e4c78cd4)の検討中にできたプログラムです。
出番のなかったプログラムですが何かのときに使えそうなので残しておきます。

# 参考リンク
* [PythonからWindowsのクリップボードに画像をコピーする](https://water2litter.net/rum/post/python_win32clipboard_set/)
* [Pythonで指定した範囲のスクリーンショットを撮る(座標値取得)](https://qiita.com/kenshin-627/items/56b4d945ac63ad8c541c)
* [このプログラムの引数で使用した座標値取得の方法](https://qiita.com/flip-flop/items/efda285db6ead5a74d81)
【Git】コミット履歴を残さずにGitHub経由でコードを共有する

## 想定ケース
Gitについて、
* 書きかけ・未完成のコードを他人へ共有したいけど、コミット履歴を汚すのはチーム的・個人的に良くないと思っている
* 別のPCへコードを移したいけど、コミット履歴を汚したくない

方向けの記事です。コミット履歴を気にしていない方には関係かな。

## 簡単に
簡単に述べると、
* （送信側が）捨てブランチに`commit`&`push`する

ことで共有ができます。GitHubなどで他人から見てもらうだけの場合は、用済みになったらブランチごと削除でいいですね。

もし、他ローカルへ移す場合はここからさらに、
* （受信側が）対象ブランチにて、未完成コードを`push`した捨てブランチを`pull`
* （受信者が）そのまま最新のコミット履歴を削除して、一個前のコミットの状態へ戻る

こうすることで、コミット履歴を汚さずに他PCでも、その時点での開発ができます。こちらの場合も用済みになった捨てブランチを受信者のローカルとリモートからブランチごと削除。

## コマンド
### 捨てブランチに`commit`&`push`

捨てブランチの名前を`temp`とします
```git
git checkout -b temp
git add *
git commit -m "temp"
git push origin temp
```

これでGitHubなどで、`temp`ブランチにアクセスするとコードが見れます。

### 対象ブランチにて、未完成コードを`push`した捨てブランチを`pull`
もし`main`ブランチで作業していたコードを共有していたとして、
```git
git checkout main
git pull origin temp
```

`main`ブランチで`temp`ブランチをpullすることによって、（コンフリクトがない限りは）mainブランチに中途半端コードを取り込めます。

### そのまま最新のコミット履歴を削除して、一個前のコミットの状態へ戻る
```git
git reset --mixed HEAD^
```

取り込んだコードを残したまま（`--mixed`）、一個前のコミット（`HEAD^`）までリセット(`reset`)するという意味ですね。これで中途半端コミットが開発中のブランチから消えます。

### 用済み捨てブランチを削除
ローカルから削除する場合は
```git
git branch -D temp
```

:::note alert
ブランチ名間違えると大変なことになるので注意してください
:::

リモートから削除する場合は
```git
git push origin -d temp
```

:::note alert
ブランチ名間違えるともっと大変なことになるので注意してください
:::

## おわりに
いいね頂けると泣きながら喜びます><
シェル芸で遊ぶROS 2

# はじめに
シェル芸とROS 2を組み合わせておもしろいことができないか挑戦してみようと思います。今回はシェル芸で`turtlesim`を動かして遊んでみます。

## シェル芸のトップページ
シェル芸の情報はこちらです。

https://b.ueda.tech/?page=01434

## ROS 2 Humbleの公式ドキュメント
ROS 2 Humbleの情報はこちらです。

https://docs.ros.org/en/humble/index.html

## 参考記事 : ROS コマンドラインツール シェル芸
ROS 1のコマンドでシェル芸を行っている方の記事があります。

https://qiita.com/yami_buta/items/2b514dc469f364be36ba

# やりたいこと
シェル芸で`turtlesim`を綺麗に動かしたいです。

# ROS 2のインストール
Tiryohさんの`ros2_setup_scripts_ubuntu`を使えばROS 2を簡単にインストールができます（ありがとうございます！）。

https://github.com/Tiryoh/ros2_setup_scripts_ubuntu

# 1. 螺旋を描く
それではさっそくシェル芸で`turtlesim`を遊んでみます。

端末1で次のコマンドを実行して、`turtlesim`ノードを起動します。

```sh
ros2 run turtlesim turtlesim_node
```

端末2で次のコマンドを実行して、螺旋を描くように亀を動かします。

```sh
awk 'BEGIN{for(i=1.0;i<10.0;i+=0.1){print i}}' | xargs -I@ ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: @, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 2.0}}"
```

実行結果は以下の画像の通りです。

![turtlesim螺旋.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/83a44d36-a7af-e4fe-e3eb-e69f0b9fd0aa.png)

綺麗なグルグルが描けました。

# 2. 複数の亀の出し方
`turtlesim`の`/spawn`サービスを`call`すれば複数の亀を出すことができます。下記のコマンドを実行すると、中央に亀が出現します。`x`と`y`が亀の位置、`theta`が亀の姿勢です。

```sh
ros2 service call /spawn turtlesim/srv/Spawn "{x: 5.5, y: 5.5, theta: 0.0}"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/28374c8e-649d-72bf-cfb9-23eb0e68c634.png)

# 3. 複数の亀を出して動かす
それでは複数の亀を出して、いい感じに動かしてみます。

端末1で次のコマンドを実行して、`turtlesim`ノードを起動します。

```sh
ros2 run turtlesim turtlesim_node
```

端末2で次のコマンドを実行して、14匹の亀を角度をずらして出現させます。

```sh
awk 'BEGIN{for(i=0.0; i<6.28; i+=0.5){print i}}' | xargs -I@ ros2 service call /spawn turtlesim/srv/Spawn "{x: 5.5, y: 5.5, theta: @}"
```

端末3で次のコマンドを実行して、それぞれの亀が螺旋を描くように動かします。

```sh
awk 'BEGIN{for(j=1;j<=14;j++){for(i=0;i<=10;i++){print j,i}}}' | xargs -n2 bash -c 'ros2 topic pub --once /turtle$0/cmd_vel geometry_msgs/msg/Twist "{linear: {x: $1, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.0}}"'
```

実行結果は以下の画像の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/c48d549f-11c1-1520-93d8-5babd4185567.png)

あまり綺麗ではないですが、螺旋は描けました。

# 4. ジグザグに動かす
螺旋以外の動きもやってみます。

端末1で次のコマンドを実行して、`turtlesim`ノードを起動します。

```sh
ros2 run turtlesim turtlesim_node
```

端末2で次のコマンドを実行して、14匹の亀を角度をずらして出現させます。

```sh
awk 'BEGIN{for(i=0.0; i<6.28; i+=0.5){print i}}' | xargs -I@ ros2 service call /spawn turtlesim/srv/Spawn "{x: 5.5, y: 5.5, theta: @}"
```

端末3で次のコマンドを実行して、亀をジグザグに動かします。

```sh
awk 'BEGIN{for(j=1;j<=14;j++){for(i=0;i<20;i++){if(i%2==0){print j,0.0,1.0}else{print j,0.0,-1.0}print j,1.0,0.0}}}' | xargs -n3 bash -c 'ros2 topic pub --once /turtle$0/cmd_vel geometry_msgs/msg/Twist "{linear: {x: $1, y: $2, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 0.0}}"'
```

実行結果は以下の画像の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031721/7912a12a-5481-c8e6-f912-a6ab883d0a0a.png)

またしてもあまり綺麗ではありませんが、ジグザグを描くことができました。

# おわりに
シェル芸でROS 2の`turtlesim`を遊びました。もっと綺麗な模様を描きたかったのですが、意外と難しいようです。またいつか挑戦したいですね。

# 参考記事
xargsで引数を二つ以上取る方法はこちらの記事を参考にさせていただきました。

https://qiita.com/knknkn1162/items/806604341508d32b160e
レンダリングとは何ですか?

レンダリングは、フレーミングで最もよく使用される用語の 1 つです。レンダリングまたはレンダリングは、製品を作成する最終段階を実行できるツールです。 では、レンダリングとは何でしょうか? そしてそれをレンダリングするように設定するにはどうすればよいでしょうか? この記事ではWebTech360で調べてみましょう。
レンダリング (Rendering) は、アプリケーション プログラムによって 1 つまたは複数のモデルから 2 次元または 3 次元の画像を作成し、3D 画像、漫画のキャラクター、または特定の映画のシーンを作成するプロセスです。
https://ja.webtech360.com/detail/%E3%83%AC%E3%83%B3%E3%82%BF%E3%82%99%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%99%E3%81%A8%E3%81%AF%E4%BD%95%E3%81%A6%E3%82%99%E3%81%99%E3%81%8B-88890582.html
[OCI] Database with PostgreSQLをつくってみる

## OCID atabase with PostgreSQL
とうとうリリースされたOracle Cloud の PostgreSQLサービス。
さっそく作ってみます。


https://www.oracle.com/jp/cloud/postgresql/

## どんなサービス？
最初は、AWSのRDS for PostgreSQL かと思っていたのですが、作ってみるとそれは間違い。
どちらかというとAuroraのようなサービスでした。
リードレプリカの作成も簡単！
価格やストレージ性能などを比較するときもAuroraと比較したほうがよさそうです。

それでは作ってみましょう。



## OCI PostgreSQL Databaseの作成
メニューから「PostgreSQL」のデータベースを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/bc2cead2-b24f-edb3-d802-2a895e652a28.png)

PostgreSQLデータベースを作成するにあたって、前提条件が表示されるため
必要に応じてOCI環境の設定を行います。
以下が必要です。ユーザ、グループ、ポリシーについて管理権限があれば問題ありません。
・「プライベートサブネット作成」
・「ユーザ、グループ作成」
・「ポリシー付与」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/d0d535d8-f0a0-c990-3a84-393b9a044cb2.png)

「新規データベースの作成」を選択して進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/15266fd9-4ce8-d1eb-8b8b-14717620cd99.png)

PostgreSQLのバージョンを選択します。
2023年11月時点でバージョン16までリリースされていますが、14しか選べないようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/833fc91d-15e6-c665-5324-3cd3d96111d3.png)

クラスタのノード数になります。2以上にすると参照用ノードが追加されます。
ディスクIOは 300K IOPS固定のようです。
300K IOPSというと、Block Volumesの場合、Ultra high performance に VPU 120と同等のため
かなり高スペックのディスクが割り当てられるようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/aff18eba-e229-fc1a-d213-92f1eeb81fe0.png)

CPUを選択します。最低は2でした。
シェイプは VM.Standard.E4.Flex しか選択できません。AMDです。
メモリはOCPU数によって自動的に変わります。1OCPU 16Gです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/333fe689-2fc0-b8dc-8e91-847839f68e21.png)

ネットワークを選びます。プライベートサブネットが必須です。
パブリックサブネットを指定すると次の画面でエラーになります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/614dd220-12f0-c94e-50f6-5c8641fc4679.png)

管理者DBユーザのIDとパスワードを指定します。
「Input Password」を選択するとパスワード入力できるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/27b3ffda-1ddc-1356-8492-ad46a0b367cf.png)

バックアップポリシーを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/9e20ba99-5048-8f6d-938d-41fc6fe2ecb6.png)

5-10分程度で作成されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/328a1943-53af-e200-c48d-8cd3de09bdd9.png)

作成されたデータベースをみると接続先のIPアドレスが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/f2d41316-535a-bd85-9cb6-082b87ec9008.png)

構成のリンクからPostgreSQLのパラメータが表示できました。
「構成」というパラメータのセットを作成して、パラメータを指定するようです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/9948fe39-c351-9477-5fda-b99787e413d8.png)

## PostgreSQLへの接続確認
ComputeでWindowsサーバを作成し、postgresql標準の psql ツールで接続、SQL実行を試しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2551183/48dbc7df-c697-bae5-e75f-9ba2f6abfe07.png)
StepFunctions Map実行時の権限設定について

# はじめに

StepFunctionsのMapフローを使って、csvやS3オブジェクトを並列でいてレートすることができます。その際のStepFunctionsの権限設定がやや独特に感じたのでメモしておきます。

# 結論

Mapフローを使う場合は、ステートマシンのロールに`states:StartExecution`の権限を付ける必要がある。

# 経緯

まず、下記のようなステートマシンを用意します。
S3バケット内にあるcsvファイルをMapでイテレートします。

今回はcsvに対する処理は関係ないので、Mapの中身はPassとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/a8428cb7-c58c-af96-afec-288dac30a961.png)

CSVの中身は↓を用意しました。
```
id,name
1,Alice
2,Bob
3,Charlie
4,David
5,Eva
6,Fiona
7,George
8,Hannah
9,Ian
10,Julia
```
csvファイルをS3から取得するための権限が必要なので、ステートマシンへのロールには`AmazonS3FullAccess`を付与しました。FullAccessである必要は別にないですが、検証なのでね。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/4f348206-a96e-d7d9-6367-b9186131d9f7.png)


直感的にはこれで処理はうまくいきそうです。



しかしステートマシンを実際に実行すると処理は失敗してしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/932cf08e-58da-15c1-3ec0-3da0742aaf33.png)


原因のメッセージを見ると下記が表示されていました。(アカウントIDは変更してあります。)

```
Error contacting AWS Service. | Message from Service: User: arn:aws:sts::0123456789012:assumed-role/StepFunctions-MyStateMachine-role-bcb29a25/mgCIjMOxLHclkIkSWmwZkPCBaQSEOcvn is not authorized to perform: states:StartExecution on resource: arn:aws:states:ap-northeast-1:0123456789012:stateMachine:MyStateMachine-i2lr7s9t4 because no identity-based policy allows the states:StartExecution action (Service: Sfn, Status Code: 400, Request ID: f5158edf-c257-4e60-8196-f162b95f4959)
```

`is not authorized to perform: states:StartExecution on resource` とあるのを見るに、`states:StartExecution` の権限が足りていないようです。

インラインポリシーで権限を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/cb8812b5-1fee-9d46-dd50-4355295e5697.png)

再度実行すると、今度は処理に成功しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/8e29df86-180a-684d-91c0-59e09acd326a.png)


このように、Mapフローを使う場合は、ステートマシンのロールに`states:StartExecution`の権限を付けないと、権限不足で処理に失敗してしまうようです。
ステートマシンにStepFunctionsの実行権限をつけるのはあまり直感的ではないので注意したいですね。