OmniAICreator/Qiita-1.07M huggingface dataset:
sambaでゲスト共有する

## Linux(samba)の設定
/etc/samba/smb.conf の設定

### [ global ] セクション
| 項目 | 値 |
| :--- | :--- |
| bind interfaces only | Yes |
| interfaces | 127.0.0.0/8 192.168.0.0/16 |
| server role | standalone server |
| unix password sync | Yes |
| server min protocol | SMB3 |
| map to guest | bad user |
| guest account | nobody |

- unix password sync
 SMBパスワードの更新時に、Samba が UNIX のパスワードを SMB パスワードと同期させるようになる。
- map to guest
 bad user : 存在するユーザーに対する不正なパスワードによるログイン要求は拒否する。
 指定されたユーザーが存在しなかった場合はゲストログインとして扱い、guest account で指定されたアカウントにマッピングする。
 Never : 不正なパスワードによるユーザーのログイン要求を拒否する。
 
### 共有設定
| 項目 | 値 | |
| :--- | :--- | :-- |
| [share] | 共有名 | |
| comment | コメント | |
| path | パス | |
| browseable | yes | |
| guest ok | yes | |
| public | yes | guest ok のalias |
| read only | yes / no | |
| writable | no / yes | |

### ユーザ
| ユーザ | /etc/passwd | smbpasswd |
| :---: | :---: | :---: |
| nobody | 必要 | 不要 |
| guest | 不要 | 不要 |

ゲスト接続で接続
┗ (たぶん)guestで接続、OSユーザなし。
．┗ map to guest の設定によって、sambaのゲストログインとして扱い
．┗ nobody(geust accountで設定) にマッピング

- OSユーザ「geust]を作成すると、OS認証が必要となりsambaのゲストアクセスにならなず、ID:guest/pass:****のアクセルになってしまう。

## コマンド
- smbstatus : 接続状態の表示
- smbpasswd : sambaユーザのパスワード変更。「unix password sync=sync」にすると、OSパスワードも変更。
- pdbedit : sambaユーザのコントロール。smbpasswdでは disablはできるが、削除ができない。
DockerでOracleのExpress Edition(21c) と 23c Free の初期構築→接続時にちょっとハマった小ネタ

# はじめに
そういえば、自宅にOracleってなかったなー。
昔はインストールがめんどくさかったけど、今はDockerがあるから簡単に作れるかな？
って思って、DockerでOracleを入れたけど、ちょっとハマったお話を残します。

誰かのご参考になれば幸いです。

# 前提
### Oracle Express Edition(XE) とは

https://www.oracle.com/jp/database/technologies/appdev/xe.html

すべてのユーザーにお勧めの無償Oracle Database
とのこと。


### Oracle 23c Free とは

https://blogs.oracle.com/oracle4engineer/post/ja-database-23c-free-ga

Oracle Database Freeは、Oracle Database Express Edition(XE)の後継リリース
とのこと。

# なにをやったか
## Oracle Express Edition(XE) の構築
GeminiにOracleのDocker-compose.yml が欲しいとお願いしたら、Oracle Express Edition(XE) の最新版をいただきました。（＝21c）

```yaml
version: "3.8"
services:
  oracle-xe:
    image: container-registry.oracle.com/database/express:latest
    container_name: oracle-xe
    ports:
      - "1521:1521"
      - "5500:5500"
    environment:
      - ORACLE_PWD=your_password
      - ORACLE_CHARACTERSET=AL32UTF8
      - TZ=Asia/Tokyo
    volumes:
      - oracle-xe-data:/opt/oracle/oradata

volumes:
  oracle-xe-data:
```

その後、SQL Developerで接続したく、以下で接続しました。

```
ホスト名：localhost
ポート：1521
SID：xe
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/de9e0c09-f849-446d-93fd-2fc0631140e2.png)

## Oracle Database 23c Free の構築
その後、最新のOracleは23cと知り、23cが使いたくなりました。

「Oracle Database 23c Free Docker」等で調べてか？Geminiに聞いてか、忘れましたが、こんな感じのDocker-compose.yml を作りました。
（healthcheckは後から追加したかもしれませんが、imageを freeに変えた感じです。）

```yaml
version: "3.8"
services:
  oracle-free:
    image: container-registry.oracle.com/database/free:latest
    container_name: oracle-free
    ports:
      - "1521:1521"
    environment:
      - ORACLE_PWD=your_password
      - ORACLE_CHARACTERSET=AL32UTF8
      - TZ=Asia/Tokyo
    volumes:
      - oracle-free-data:/opt/oracle/oradata
    healthcheck:
      test: ["CMD", "sqlplus", "-S", "system/your_password@localhost:1521", "SELECT 1 FROM DUAL;"]
      interval: 30s
      timeout: 10s
      retries: 5
    restart: unless-stopped

volumes:
  oracle-free-data:
```

# ハマったこと
いざ、SQL DeveloperでExpress Edtionと同じように接続しようとしましたが、つながらず・。

```
ホスト名：localhost
ポート：1521
SID：xe
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/7346472e-49f0-4680-9e47-a8eb0a81de94.png)

なぜ？っとハマりました。

# 原因
SID が XE から FREE に変わっていた。
 
ネットで調べていたら以下に辿り着き、FREE ということを知りました

https://www.oracle.com/jp/database/free/get-started/#connecting

# 対応
SID：FREE に変えて接続

```
ホスト名：localhost
ポート：1521
SID：FREE
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206526/148c8d47-623a-4641-984b-d45d2fb64e7f.png)

# 余談
その後、さらにユーザを作ろうと Pluggable Database（PDB） と Container Database（CDB）の違いにハマったことは別途書く予定になります。
『ネットワークはなぜつながるのか』学習記録：DNSについての整理

## はじめに

タイトルにもなっている「ネットワークはなぜつながるのか」を説明することができるようになるために、本書を読みました。

本記事では、その中でもデータ送信前の準備であるDNSについてピックアップし、自分なりに整理しながらまとめていきます。

## DNSサーバー

DNSサーバーとは、ドメイン名とIPアドレスの対応関係を管理するサーバーです。

Webページにアクセスする際などに、ドメイン名から対応するIPアドレスを取得するために利用されます。

## Webページ表示までの流れ

ここでは、Webページ表示するまでの流れを簡単に整理し、その中でDNSサーバーが果たす役割について見ていきます。

1. ユーザーがURLを入力する
2. ブラウザが入力されたURLからドメイン名を抽出する
    - 例：`https://example.com/page1` の場合、ドメイン名である`example.com` を抽出する
3. ブラウザがDNSサーバーに対して、ドメイン名の名前解決（IPアドレスの問い合わせ）を行う
4. DNSサーバーからIPアドレスの応答を受け取る
5. ブラウザが取得したIPアドレスを使ってWebサーバーに接続する
6. ブラウザがWebページのデータを取得し、画面に表示する

## ドメインの階層化

ドメイン名の数が膨大であるため、すべてのドメイン情報を1台のDNSサーバーに登録することは現実的ではありません。

そのため、DNSでは複数のDNSサーバーが階層構造を成し、それぞれの役割を分担しながら連携しています。

DNSは以下のような階層で構成されています：

- ルートDNSサーバー：すべてのドメイン名解決の起点となる最上位のDNSサーバー
- TLD DNSサーバー：トップレベルドメインを管理するDNSサーバー
- 権威DNSサーバー：特定のドメインに関する最終的な情報を持つDNSサーバー

## ドメイン名とIPアドレスとの対応の管理方法

DNSでは、あるドメインの情報を管理しているDNSサーバーの場所（IPアドレス）は、そのドメインの1つ上の階層にあたるDNSサーバーに登録されています。
例えば、`.com` のDNSサーバーには、`sample1.com` の情報を管理しているDNSサーバーのIPアドレスが登録されており、そこに問い合わせることで `www.sample1.com` のIPアドレスを取得できます。

登録のルールとして、以下の2点があります：

1. 1つのドメインの情報は、1つのDNSサーバーにまとめて登録する（分割は不可）
    - 例：`sample1.com` の情報（Webサーバー `www.sample1.com` やメールサーバー `mail.sample1.com` など）は、`sample1.com` のDNSサーバーにまとめて登録される
    - `www.sample1.com` だけを別のDNSサーバーに分けて登録することはできない
2. 1つのDNSサーバーには、複数のドメインを登録できる
    - 例：`.com` のDNSサーバーは `sample1.com` だけでなく、`sample2.com` など複数のドメインを管理している
    - `.jp` のDNSサーバーも同様に、`example1.jp` や `example2.jp` など複数のドメインを管理できる

```
ルートDNS
  ├── .comのDNS
  │    ├── sample1.comのDNS
  │    │    ├── www.sample1.com（Webサーバー）
  │    │    ├── mail.sample1.com（メールサーバー）
  │    │    └── sub.sample1.comのDNS
  │    │         ├── www.sub.sample1.com
  │    │         └── mail.sub.sample1.com
  │    └── sample2.comのDNS
  │         ├── www.sample2.com
  │         └── mail.sample2.com
  │
  └── .jpのDNS
       ├── example1.jpのDNS
       │    ├── www.example1.jp
       │    └── mail.example1.jp
       └── example2.jpのDNS
            ├── www.example2.jp
            └── mail.example2.jp
```

## DNSの検索プロセス

1. 最寄りのDNSサーバーへの問い合わせ
    - ユーザーがドメイン名を入力すると、まず最寄りのDNSサーバーに問い合わせが行われる
2. ルートDNSサーバーへの問い合わせ
    - 最寄りのDNSサーバーは、ルートDNSサーバーに問い合わせを行う
        - これらのルートDNSサーバーの情報は、DNSサーバーソフトをインストールした時点であらかじめ登録されている
    - ルートDNSサーバーは、TLD（例：`.com` や `.jp`）を管理するDNSサーバーのIPアドレスを返す
3. TLDのDNSサーバーへの問い合わせ
    - 最寄りのDNSサーバーは、ルートDNSサーバーから返された情報を基に、TLDのDNSサーバー（例：`.com` や `.jp`）に問い合わせを行う
    - 該当ドメインを管理している次の階層のDNSサーバー（権威DNSサーバーなど）のIPアドレスを取得する
4. 権威DNSサーバーへの問い合わせ
    - 最寄りのDNSサーバーは、TLDからの応答に基づいて、該当ドメインのDNSサーバーに順に問い合わせを行い、最終的に目的のドメイン（例：`www.sample1.com`）のIPアドレスを取得する

## 感想

- 前回の記事では、既にIPアドレスが分かっている前提で、どのようにデータが相手に届くのかを学びましたが、今回は、そのIPアドレスを「どのように取得するのか」を理解できました。
- 一冊を通して学習には時間がかかりましたが、ネットワークの全体像を把握でき、以前よりも自信を持って説明できるようになったと感じています。
ウェブ開発の技術スタック選定に Wappalyzer と ChatGPT を使う

ウェブサイトなどの開発を行う時、その技術スタック選定はとても難しい

フレームワークであれば、自分が扱いやすい言語で書けるか、サイトに必要な機能の実装ができるかが重要になるし、
バックエンドシステムであれば、フレームワークとの相性が良いか、商用利用可能か、セルフホスティングが可能かなどが重要となる

同じ種類のサービスやライブラリ、ツールなどを比較する記事もたくさんあるが、
採用基準は制作者や制作物によって変わるため、一概に人気のあるもの・使いやすいとされているものを選ぶわけにもいかない


## Wappalyzer とは

このページを読んでいる人なら使っている人も多いだろうが、
閲覧中のウェブサイトに使用されている技術を解析して表示してくれるブラウザ拡張機能である

例えば Qiita の記事作成画面だと次のような解析結果が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106753/a7c91400-b25e-4233-af7c-db5c625f01c8.png)

ここで項目をクリックするとその技術の詳細を閲覧できるのだが、そこから分野ごとに採用されている技術のランキングを閲覧することができる
例えば [Payload CMS] をクリックすると Payload CMS に関する情報が表示されるので、右上の [CMS] をクリックする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106753/b3bf4b15-2a10-4a40-846f-f0160855f645.png)

すると Wappalyzer がもつ解析情報をもとにした CMS 技術の使用率ランキングが表示される
デフォルトでは TOP10 のみ表示されているが、リスト右下からランキングの全量を確認することができる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106753/35428d84-ee7b-46ef-81a9-21621f7d7a3a.png)


## ランキング情報を ChatGPT に渡し、自分にあったものを選ぶ手伝いをしてもらう

このランキングをコピーして Excel に貼り付け、[Technology] 列をコピーする
それを ChatGPT に渡し、自分の要望や目的などを説明することで多くの人が使っている技術の中から本当に自分にあっているものを選んでいくことができる

このとき、いきなり複数の注文をするよりは少しずつ条件を絞っていくほうがよい
はじめに大枠で絞り、段々と細かい条件で絞っていくような会話をしていくと探しやすい

```
次のリストは CMS における使用率ランキングである
この中から、ヘッドレス CMS に分類されるものを抽出してほしい
なお、リストは上から順に使用率の高いものに並べられているので、以降の会話ではこの順位を保持してほしい

WordPress
Wix
Sqarespace
  :

---------------------------------------------

以下のリストから、ヘッドレスCMS（Headless CMS）に分類されるものを順位を保持した形で抜き出しました。

plaintext
17. Contentful  
24. Sanity  
33. Ghost  
34. Prismic  
39. Storyblok  
54. DatoCMS  
60. Builder.io  

---------------------------------------------

セルフホスティングが可能なものに絞ってほしい

---------------------------------------------

以下は、先ほどのヘッドレスCMSリストからセルフホスティング可能なものに絞り込んだ結果です。順位を保持しています。

plaintext
17. Contentful  
24. Sanity  
33. Ghost  
34. Prismic  
39. Storyblok  
63. Grav  
79. microCMS  

  :
```

数件まで絞り込めたら、それらを一つずつ自分で調べていくのがよいと思う

以下に絞り込み条件の例を記載しておく

- 使用できる言語
- (任意のフレームワーク) との相性がよいか
- OSS であるかどうか
- 無料で使用できるか
- 商用利用が可能か
- セルフホスティング可能か
- １年位内に更新されているか（開発・更新が終了していないか）
- API が提供されているか
- API は(RestAPI、GraphQL など任意の形式) であるか
プログラミング練習記録　2日目：GitHub アカウント作成・初期リポジトリ作成

### 1.本日の作業内容
　GitHub アカウント作成・初期リポジトリ作成

### 2.作業目的
　・GitHubのアカウントを使ってコードをクラウドに保存できるようにする
　・ローカルで作ったコードをGitHubと連携できる準備をする

### 3.前提
　・Gitがインストール済みであること
　・メールアドレスが使えること（GitHubに登録が必要）

### 4.作業手順
#### 1.GitHubアカウントを作成
- 下記URLにアクセス
　https://github.com/
- Sign upから必要な情報を入力してアカウント作成
　※無料プランで問題なし（Privateリポジトリが作成可能であるため）

#### 2.GitHub上でリポジトリを作成
- ログイン後、右上の「＋」から「New repository」を選択
- 設定項目：
  - Repository name：例）my-learning-project
  - Description：任意
  - Public/Private：どちらでもOK（Privateなら非公開）
  - Initialize this repository with：
     - README：チェックする
     - .gitignore：Node/C#　あとから追加も可能
- Create repositoryで作成完了

#### 3.GitとGitHubの連携
SSHキーを作成してGitHubと接続。
※なぜSSHキーの登録が必要なのか。
 - 毎回ログインしなくて済む
     - SSH接続なら、1度設定すればコマンド一つでpush/pullが可能
 - セキュアで安全
     - 公開鍵暗号方式で通信することで、パスワードを第三者に知られる心配が少。

↓↓設定方法
 - Git Bashで```ssh-keygen -t ed25519 -C "メールアドレス"```を実行。
     - 保存場所：そのままEnterでOK
     - 「パスフレーズ（暗証番号）」：空欄でもOK。セキュリティ的にあったほうが〇。
 - 完了後以下鍵ファイルができる。
     - 公開鍵（GitHubに登録）
     - 秘密鍵（自分のPCで使用）
 - 公開鍵をGitHubに登録
     - Git Bushで```cat ~/.ssh/id_ed25519.pub```を実装。
     - 出てきた文字列をすべてコピーして、GitHubに貼り付け。
         - GitHub登録手順：
             - 右上のアイコン→settings（設定）
             - 左メニュー→SSH and GPG keys
             - 「New SSH key」
             - タイトルをつけて貼り付け 
 - 接続確認
     - Git Bushで```ssh -T git@github.com```を実行。
     - 「Hi username! You've successfully authenticated, but GitHub does not provide shell access.」と表示されれば成功！

#### 4.ローカルからリポジトリを複製
 - Git Bushで下記を実行。
     ```
     cd ~/your-working-folder
    git clone git@github.com:あなたのユーザー名/my-learning-repo.git
    cd my-learning-repo
    ```
#### 5.ファイル追加と初回コミット
 - Git Bushで下記を実行。
    ```
    echo "# My Learning Repo" > README.md
    git add .
    git commit -m "Initial commit"
    git push
    ```

### 5.完了チェックポイント
 - GitHubアカウントが作成できた
 - GitHubに新しいリポジトリがある
 - PC上に git clone したローカルリポジトリがある
 - git push でコードをアップできた
[読書感想文]プロジェクトマネジメントの基本が全部わかる本

こんにちは。Kaneyasuです。

今回は、こちらの読書感想文を書きます。

https://amzn.asia/d/aPkkrDT

## よい点

全体的にプロジェクトマネジメントの「なぜ？」に着目していると感じました。  
契約形態の違いやタスク管理の必要性など、現代のおじさんエンジニアが自然と身につけた感覚を改めて言語化してくれています。  
ガントチャートの付け方などはOJTや実務でなんとなくやらされると思うので、そういうところではなく、もっと根本的なところを語っているのはよい構成だと思います。

途中のコラム`「仲のよさ」と「信頼関係」の違いを理解しよう`、が特によかったです。  
ここに、この本がプロジェクトマネジメントで何を重視しているかが現れていると思いました。

## 気になった点

- 索引がない  
- 実際にプロジェクトマネジメントを回す際は別の資料が必要だろう

1点目は、索引がないところです。  
個人的に読み直すとき、困ったときは索引を参照することが多いので、せっかくキーワードが広くカバーされているのにこれがないのは正直不思議です。

2点目は、この本の目指すところは全体を理解することであり、詳細な手順をカバーすることは目指していないという点です。  
なので、これはマイナスポイントではありません。

経験上、SIerであればWBS・EVMなどの詳細な手順は結構浸透しています。  
この本で全体像を学び、OJTや実務で詳細な手順を経験し、ときに書籍やIPAの試験で経験と世間のギャップを確認するのがよいかと思います。

## [まとめ] 全体的な感想

- 基本が全部わかる本というより、全体がわかる本  
- プロジェクトマネジメントの心構えを理解するのに適した本だと思う  
- この本を手元に置きつつ、個別の手法やツールについては別の資料を読むべきだろう  

プロジェクトマネジメントを理解するのに、まず手に取るべき本だと思います。

## [余談] プロジェクトマネジメントを回す際に見る別の資料

今回取り上げた書籍の中で、いろいろな設計ドキュメントの話が出てきますが、この書籍だけではピンと来ないと思います。  
個人的にドキュメントまわりは過去にこの辺を参考にしたことがあるので、実際にプロジェクトマネジメントを回す際は参考にしてはいかがでしょ

https://amzn.asia/d/jeJvdnl  

https://amzn.asia/d/7BNORpn  

同様にプロジェクトマネジメントでスケジュールを管理する際はこちらが参考になります。  
定量的にスケジュールを測ることが書かれている本で、私はこちらをずっと参考にしています。

https://amzn.asia/d/1DaAi9b
MySQLとKintoneのデータ同期をPHPで実装してみた

## はじめに

Kintone へのシステム移行を検討しているが、既存の MySQL データベースとのデータ同期に悩んでいませんか？

本記事では、PHP で開発されたオープンソースのデータ同期ツール「mysql-to-kintone-sync」を紹介します。  
このツールを使用することで、MySQL のデータを Kintone に同期し、移行期間中の並行運用をスムーズに行うことが可能になります。

## 概要

「mysql-to-kintone-sync」は、MySQL データベースと Kintone アプリ間でデータを同期するための PHP スクリプトです。  
主な機能は以下の通りです：

- MySQL からデータを取得し、Kintone に送信
- Kintone に新規レコードを作成、または既存レコードを更新（ユニークキーに基づく）
- 同期処理のログをコンソールに出力

このツールは、MySQL から Kintone への一方向の同期を行います。  
Kintone 側での変更は MySQL に反映されません。  
また、MySQL で削除されたレコードは Kintone には残ります。

## 利用シーン

このツールは、以下のようなケースでの利用を想定しています：

- 既存の PHP + MySQL アプリケーションを Kintone に段階的に移行する際のデータ同期
- MySQL の特定のテーブルを Kintone アプリとして再構築し、並行運用する場合
- Kintone へのデータ移行を自動化したい場合

特に、テーブル数が多く一括移行が難しい場合に、MySQL と Kintone のデータを同期させながら段階的に移行を進める際に有効です。

## 動作環境

- PHP 7.0 以上（PHP 8.0.30 で動作確認済み）
- MariaDB（MariaDB 10.6.21 で動作確認済み）
- Composer（依存関係の管理に使用、任意）
- MySQL データベースへのアクセス権
- API アクセス可能な Kintone アカウント

## インストールと設定

1. リポジトリをクローン：

    ```bash
    git clone https://github.com/yakiimo-bsp/mysql-to-kintone-sync.git
    ```

2. 必要に応じて Composer で依存関係をインストール：

    ```bash
    composer install
    ```

3. 設定ファイル（`.env`）を作成し、以下の情報を入力：

    ```bash
    cp .env.example .env
    ```
    
    - MySQL の接続情報（ホスト、ユーザー名、パスワード、データベース名）
    - Kintone のドメイン、API トークン、アプリ ID
    - 同期対象のテーブル名と対応する Kintone フィールド

   ```env
   # データベース接続
   MYSQL_SERVERNAME=your_mysql_server
   MYSQL_USERNAME=your_mysql_username
   MYSQL_PASSWORD=your_mysql_password
   MYSQL_DBNAME=your_database_name

   # Kintone設定
   KINTONE_DOMAIN=your_kintone_domain
   ```

## 使用方法

設定が完了したら、以下のコマンドで同期を実行します：

```bash
php mysql-to-kintone-sync.php
```

スクリプトはMySQLデータベースに接続し、`.env`ファイルで定義されたクエリに基づいてデータを取得し、Kintoneに送信します。
処理の進捗や結果はコンソールに出力されます。

## ロギング

すべての操作はコンソールにログ出力されます。エラーや成功メッセージの出力を監視してください。

## 注意点
- Kintone 側でのデータ変更は MySQL に反映されません
- MySQL で削除されたレコードは Kintone には残ります
- 大量のデータを同期する場合、Kintone API の制限に注意が必要です

## まとめ

「mysql-to-kintone-sync」は、MySQL から Kintone へのデータ移行や同期を簡単に行うことができる PHP ツールです。
段階的なシステム移行や並行運用を検討している方にとって、有用なツールとなるでしょう。

詳細な情報やソースコードは、GitHub リポジトリをご覧ください：
👉 https://github.com/yakiimo-bsp/mysql-to-kintone-sync
Googleの「ユーザーファースト」は、なぜズレているのか？

# 性能主義が生むユーザー体験の落とし穴

Googleのプロダクトは、技術的な性能や機能面において非常に優れているのは間違いないが、実際にユーザーが感じる「使いやすさ」や「快適さ」といったユーザビリティにおいては、大きな課題を抱えているように感じられる。

そもそもGoogleの思想は、「高性能なツールを提供するが、それをいかに使いこなすかはユーザー次第だ」というスタンスであり、ユーザー側に高いリテラシーや積極的な学習を求める傾向が強い。言い換えれば、ユーザーがツールに寄せていく必要があり、「真のユーザーファースト」とは乖離がある。このスタンスは、かつてMicrosoftがWindowsを展開した際の思想に近い。つまり、「コンピューターは本来使いにくいもので、ユーザーがそれに合わせるのは当然だ」という開発者ファースト的な思想である。対してAppleは、ユーザーがテクノロジーに合わせるのではなく、テクノロジーがユーザーに寄り添い、学習コストを最小化することを徹底的に追求してきた。この違いが、AppleとMicrosoftのプロダクト体験の差のみならず、Googleとの差をも生み出している。

また、市場の戦略としても、GoogleはAmazonと同じく、市場を完全に独占した上で最低限のユーザビリティ(決して使いやすくないツール)を提供する『殿様商売』的なやり方をしてきた。検索エンジンという分野ではそれが成功したが、AI市場では通用しない。AI分野は競合が非常に多く、性能だけでなくユーザー体験（UX）が極めて重要な競争ポイントになるからだ。性能が高ければ、ユーザーが勝手に使ってくれるというGoogleの従来のスタンスでは、ユーザー体験を重視するライバル企業との競争には勝てない。企業のDNAやカルチャーはすぐに変えることが難しいため、Googleが真にユーザーファーストの思想に転換するには時間がかかりそうだ。

結局、Googleが語る『ユーザーファースト』とは、ユーザー自身が能動的に性能を引き出すためのリテラシーを持つことが前提のものであり、ユーザーが求める学習コストの低い、快適な体験を指しているわけではない。この根本的な思想の差を理解しておかなければ、Googleのプロダクトを評価する際に誤解が生じるだろう。
MCreator/建造物

#前の記事:https://qiita.com/yt365/items/199eb29022348f479db0
今回はMCreatorで建造物を生成させます。
## この記事で分かること
・MCreatorで建造物を生成させる方法
## 建造物のモデル
右上の再生ボタンからマイクラを立ち上げます。
![2025-04-11_18h27_35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/29796a3c-c7df-4917-8179-f52e43d40b58.png)
シングルプレイを選びます。![2025-04-11_18h36_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/c6a17fec-f277-4600-adc2-0cd0187472e2.png)
ワールドの新規作成を押します。
ゲームモードはクリエイティブにします。
今回、難易度はピースフルにします。
![2025-04-11_18h37_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/be0fcf77-3b14-4cd5-9b89-5ca4b9909589.png)
ワールド設定を押します。
ワールドタイプはスーパーフラットをおすすめします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/a827f16a-36bb-402f-b837-caa9ae5637d9.png)
ワールドの新規作成を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/472dc473-ac00-46d3-a81d-eeaa9a426216.png)
ワールドが生成されたら建造物を作ります。
建造物ができたら、このコマンドでストラクチャーブロックを入手します。
→このコマンド：/give @s structure_block
![2025-04-11_20h35_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/431febe2-bbe6-4786-9bf7-24183b313120.png)

作った建造物の近くにストラクチャーブロックをおきます。
![2025-04-11_22h45_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/0306cf8c-410e-4fcd-b888-38abdc09c480.png)
ストラクチャーブロックを右クリックします。
左下のロードボタンを押すと、ストラクチャーブロックの範囲を設定できます。
![2025-04-11_20h35_53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/ac7ee69d-2872-4a2b-b38a-cf2f2e310a11.png)
建物に合うように、範囲を設定していきます。
建物に合うように範囲を設定できたら、右下の保存ボタンを押します。![2025-04-11_20h39_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/e63cb8c2-e493-46ec-b39a-81971de423cb.png)
ワールドを保存してMCreatorに戻ります。
左のボタンのリソースを選択して、上にある、建造物を選びます。
マインクラフトから建造物をインポートを選びます。
今回作った建造物を選んでOKボタンを押します。![2025-04-11_22h52_11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/69e2dd39-1a3b-42a2-b2b6-69892e4ee4a7.png)
左のボタンのmodの要素を選んで＋ボタンから進捗を選びます。
![2025-04-11_23h07_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/b727ab51-aa6e-4d07-bf08-770cdb070463.png)
名前を入力して作成します。
進捗の名前や説明を書いたら、右上の保存ボタンを押して保存します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/29bb35c1-f03d-4c11-b9d7-b869eb6fbb26.png)
＋ボタンからプロシージャを選んで、コードを組みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/98095349-5f50-40e5-ac6b-20f363cff7fc.png)

右上の保存ボタンを押します。
右上の再生ボタンを押してマインクラフトを立ち上げます。
## 試してみる
ワールドに入れば建造物が生成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054637/d7153c9d-f3b6-4261-abde-869926d2bff4.png)
## 終わりに
今回は少しミスで生成と同時にストラクチャーブロックが一緒に生成されてしまいましたが、ストラクチャーブロックを範囲に入れなければ、ストラクチャーブロックは生成されないとおもいます。
次の記事:https://qiita.com/yt365/items/7c7d8052388fc7cf5df2
【備忘録】Windows PC 空き容量が確保できないとき

ディスククリーンアップや不要ソフトを削除しても中々Cドライブの空き容量が確保できないとき...
今回そんな事象に至ったため備忘録として書き残します。

1.復元ポイントの削除
-
・[スタート]を右クリック→[システム]をクリック[システム>バージョン情報]画面が表示
・スクロールダウンし[システムの保護]をクリック
・「システムのプロパティ」「システムの保護」タブ画面が表示される。
・「保護設定」項目の「利用できるドライブ」から[Cドライブ]を選択し[構成(O)]をクリック
・「システム保護対象 ローカルディスク(C:)」画面が表示
・「ディスク領域の使用量」項目で[削除]をクリック
・復元ポイントの削除ができる。

※削除前と削除後に復元ポイントを一覧として記録(ログの抽出)
・PowerShellで実行
.......................................................................
#USERPROFILEの確認
$env:USERPROFILE
↓結果を<ooo>へ置き換える↓

#削除前
vssadmin list shadows > "C:¥Users¥<ooo>¥Desktop¥RestorePoints_before.txt"

#削除後
vssadmin list shadows > "C:¥Users¥<ooo>¥Desktop¥RestorePoints_after.txt"
........................................................................

2.Windows Updateの隠し残骸(WinSxS)を削除
-
・C:¥Windows¥WinSxSは削除禁止ですが、「溜まった不要ファイルの整理」はできます。

・PowerShellで実行(管理者)
.........................................................................

Dism.exe /Online /Cleanup-Image /StartComponentCleanup

.........................................................................
これで古いWindows Updateの不要ファイルを削除でき、数GB空くことも。
I2C)XAIO ESP32C6とOLED SSD1306で遊ぶ((46)よろーと表示)(GROVE)



いろいろ、注意
----

- かころぐ見よ!!
- Adafruit_SSD1306をインストール
- Adafruit_GFXをインストール
- 3.2.0

結果(成功)
----

![image_original (90).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/f0e9044d-088d-4f61-9374-10a9f8b17a5d.jpeg)


プログラム
----

```c++



//ssd1306_46_XIAO_ESP32C6_1


//ヘッダーファイル
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET     -1 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(D10,D9); //C011

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

}//setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.clearDisplay();

  // テキストサイズを設定
  display.setTextSize(3);
  // テキスト色を設定
  display.setTextColor(WHITE);
  // テキストの開始位置を設定
  display.setCursor(0, 10);

  //46を設定
  int tempval = 46;

  // 1行目に46を表示
  display.println(tempval);

  // 描画バッファの内容を画面に表示
  display.display();

  delay(1000); //1秒待つ

}//loop



```
💖旧shoestring0.1.3で建ててた nodeの shoestring0.2.1でのアップグレードをするわ💖うふふっ🌸

🌺symbol-shoestring 0.2.1のインストール方法はこちらっ🌺

https://qiita.com/amenoudume/items/80cc6f081cb3119ea035

:::note info
🚨この作業をするまえにっっっ🚨
upgrade命令はねっ？命令の書き方を間違えると？
nodeが壊れちゃって復旧が大変になっちゃうの
だから？👇の方法で nodeを守っておいてねっ🌺うふふっ
:::

https://qiita.com/dusanjp/items/609608a026026009c080

　
　
　
旧shoestring 0.1.3で建てた nodeを
新shoestring 0.2.1で nodeを アップグレードする時はぁ？

shoestring 0.1.3の shoestring.iniはぁ？
新しい shoestring 0.2.1の shoestring.iniとちょっと変わるの🌺
**そのまま upgrade命令を実行するとぉ？エラーが出ちゃうわ**

# だからねっ？こうするの🌻

```
vi shoestring/shoestring.ini
```
　
**① 修正と追加**
**[network]の項目**
client = symbolplatform/symbol-server:gcc-1.0.3.8
rest = symbolplatform/symbol-rest:2.5.0
mongo = mongo:7.0.17
　
**② 追加**
**[imports]の項目**
nodekey =
　
**③ 追加**
**[node]の項目**
lightApi = false
以上の①②③を手動で変更する必要があるわ
　
　
 
こっちが修正前の shoestring0.1.3Nodeの shoestring.iniよ🌺
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246298/b4b8d5ad-9af9-42e5-bdb7-3785e92eabc6.png)
　

shoestring0.2.1用に修正した shoestring.iniよ🌺
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246298/c22b9f7a-4b88-484c-998f-b3df6f26181b.png)
　
　
　 
**💖以上の修正と追加が済んだら upgrade命令を実行よっ💖**

**mainnetの時は**
```
python3 -m shoestring upgrade --config shoestring/shoestring.ini --overrides shoestring/overrides.ini --directory $(pwd) --package mainnet
```

**testnetの時は**
```
python3 -m shoestring upgrade --config shoestring/shoestring.ini --overrides shoestring/overrides.ini --directory $(pwd) --package sai
```
　
　



# node証明書を更新するわ🌺
この記事の nodeだとぉ？コマンドで node証明書の更新をする方法はぁ？こうよ🌺

`--retain-node-key`を付けると委任者を保持するわ
```
python3 -m shoestring renew-certificates --config shoestring/shoestring.ini --ca-key-path ca.key.pem --directory $(pwd) --retain-node-key
```
　
いっしょに ca証明書も更新する時はぁ？こうね🌺
`--renew-ca`も付けるの
```
python3 -m shoestring renew-certificates --config shoestring/shoestring.ini --ca-key-path ca.key.pem --directory $(pwd) --retain-node-key --renew-ca
```
　
　
**node証明書の見かただよ🌺**

node証明書
```
openssl x509 -noout -text -in keys/cert/node.crt.pem
```
ca証明書
```
openssl x509 -noout -text -in keys/cert/ca.crt.pem
```

　
# ねっ？🌻こうよっ🌺うふふっ💕
 
 
　

:::note warn
# nodeを起動しても❓同期が進まない時
shoestring0.1.3から shoestring0.2.1にアップデートした後に❓
nodeはちゃんと動いてる様に見えていても
同期が進まない事があるみたいなの
**その時はぁ❓**
```
docker-compose down
docker compose -f docker-compose-recovery.yaml up --abort-on-container-exit
docker-compose up -d
```
👆を試してみて❗これで同期が進む事があるわ💕
**でも❓これでもだめだったら❓**
```
docker-compose down
python3 -m shoestring reset-data --config shoestring/shoestring --directory $(pwd)
docker-compose up -d
```
👆で❓blockDataをリセットして再同期してね❗

**※shoestring0.1.3から 0.2.1にアップデートした後に❓同期が進まなくなっちゃって❓再同期になっちゃった報告が数件あるの**

:::

# 🚨まだ wizardでは委任者保持の node証明書の更新はできないわ🚨

:::note alert
🚨ちゅうい🚨
shoestring 0.2.1に更新したらぁ？
コマンドでなら？委任者を保持したまま node証明書の更新が出来る様になったけどぉ？

**🚧まだ wizardでの node証明書の更新だと？委任者の保持ができないわ🚧**
:::
**でも👇の記事に wizardでやる方法があるから？これもみてね！**

https://qiita.com/TGVRock/items/15212e43da2dd349d88b#_reference-068da2b1bd3f35061bb9　

　
　
　
　
**🌺姉妹記事だよ🌺**

https://qiita.com/amenoudume/items/2d59ab4c5df2fa5d2a24
JavaScriptでオブジェクトから特定のプロパティを削除する方法

## deleteを使う

`delete`を使うと特定のプロパティを削除できます。

```typescript
type SampleObject = {
  key1?: number;
  key2?: number;
  key3?: number;
  key4?: number;
  key5?: number;
}

const sampleObject: SampleObject = {
  key1: 1,
  key2: undefined,
  key3: 3,
  key4: 4,
  key5: undefined,
};

delete sampleObject.key2
console.log(sampleObject);
// {"key1": 1, "key3": 3, "key4": 4, "key5": undefined} 

delete sampleObject["key3"]
console.log(sampleObject);
// {"key1": 1, "key4": 4, "key5": undefined}
```

ただし、オプショナルでないプロパティをdeleteしようとすると下記のようなエラーになります。
Property 'key3' does not exist on type 'SampleObject'. Did you mean 'key'?

## 分割代入 ＋ 残余引数を使う

プロパティの削除ではありませんが、分割代入と残余引数を使うと特定のプロパティを除いたオブジェクトを作ることができます。

```typescript
const profile = {id: 1, name: 'hoge', age: 25, height: 170, weight: 65}
const {id, ...newProfile} = profile

console.log(id) // 1
console.log(newProfile)
// { "name": "hoge", "age": 25, "height": 170, "weight": 65 } 
```

分割代入と残余引数を使うことで、newProfileにはid以外のプロパティが格納されます。
Laravel 11 + PHPでCSV処理時のempty()問題をtraitで解決する

## はじめに
CSVデータを扱うシステムの開発、特にCSVインポート機能を実装する際に、`empty()` の挙動で「えっ？」となったこと、ありませんか？  
特に `"0"`（ゼロ）が入っているとき、`empty("0")` は **true** を返してしまい、「値が入ってるのに空扱い！？」となるケースです。

Laravel 11 を使って開発中のプロジェクトで、CSVのインポート処理を実装していたところ、ある列の値が `"0"` だったのに、それが「空」として処理されてしまうという問題にぶち当たりました。そこでこの問題をtraitにまとめて再利用できるようにした方法を紹介します。

## 問題：empty("0") は true になる

```php
var_dump(empty("0")); // true になる 😱
```

CSVデータには `"0"` や `"0.0"` のような値が普通にあり得ます。  
しかし `empty()` を使って null や 空文字と一緒に判定すると、0 も「空」と判定されてしまいます。

## 目的：**null** や **""（空文字）** は「空」として判定したいけど、**"0"** は除外したい

そこで、独自の空判定関数をtraitで定義して、プロジェクト全体で使い回せるようにしました。

## traitとは

PHPのtraitは、単一継承言語であるPHPにおいて、クラス間でメソッドを再利用するための機能です。PHP公式ドキュメントによると：

> トレイトは、PHP のような単一継承言語でコードを再利用するための仕組みのひとつです。 トレイトは、単一継承の制約を減らすために作られたもので、 いくつかのメソッド群を異なるクラス階層にある独立したクラスで再利用できるようにします。
トレイトはクラスと似ていますが、トレイトは単にいくつかの機能をまとめるためだけのものです。 トレイト自身のインスタンスを作成することはできません。

つまり、継承とは異なるアプローチでコードの再利用を実現する仕組みです。継承（extends）が「is-a関係」を表現するのに対し、traitは単に機能の共有を目的としています。

## 解決策：traitで isActuallyEmpty() を作成

この問題を解決するために、CSVデータの値を厳密に判定するtraitを作成しました：

```php
namespace App\Traits;

trait StrictEmptyCheck
{
    /**
     * null または 空文字列（""） のみを "空" と判定する
     * CSVインポート時の値チェックに特に有用
     *
     * @param mixed $value
     * @return bool
     */
    public function isActuallyEmpty($value): bool
    {
        return $value === null || $value === '';
    }
}
```

これで `"0"` や `"false"`、`0`、`false` などの値は空と判定されなくなります。  
「**本当に空かどうか**」を判定するのにちょうど良い関数になります。CSVから読み込んだデータがエクセルなどで空欄だった場合は空文字として渡されるので、それをきちんと判定できます。

## 使用例

コントローラやサービスクラスで使うときは、traitを `use` するだけです。

```php
use App\Traits\StrictEmptyCheck;

class CsvImportService
{
    use StrictEmptyCheck;

    public function processRow(array $row)
    {
        if ($this->isActuallyEmpty($row['name'])) {
            // nameがnullまたは空文字のときだけ処理
        }

        // その他のロジック...
    }
}
```

## traitの活用メリット

今回の例のように、複数のクラスで使いたい機能はtraitを使うことで以下のメリットがあります：

1. **コードの再利用**: 同じ機能を複数クラスで使い回せる
2. **単一責任の原則**: 各クラスは本来の責務に集中でき、空値チェックのような共通機能は分離できる
3. **継承の複雑さ回避**: 複数継承ができないPHPで、継承関係を複雑にせず機能を追加できる
4. **メンテナンス性**: 機能の修正が一箇所で済む

## まとめ

- CSVデータ処理では、`empty()` が `"0"` を空と判定してしまう罠がある
- CSVインポート時には、null や 空文字だけを判定したいときが多く、自前で判定関数を用意するのがベスト
- traitにしておけば、複数のCSV処理クラスやその他のクラスでも再利用できて便利
react-hook-formで全てのチェックボックスのチェックする方法

Reactのライブラリreact-hook-formで複数のチェックボックスが存在する場合に全てのチェックボックスにチェックする方法です。

```React
import { useForm } from 'react-hook-form';

const Sample = () => {
  const osList = ['WindowsXP', 'WindowsVista', 'Windows7', 'Windows8', 'Windows8.1', 'Windows10', 'Windows11']

  const {
    register,
    handleSubmit,
    setValue,
    formState: { errors },
  } = useForm();

  const onSubmit = () => {
    console.log();
  };

  return (
      <form onSubmit={handleSubmit(onSubmit)}>
        {osList.map((os, index) => (
          <div key={index}>
            <input
              type="checkbox"
              value={os}
              {...register(`windows.${index}`, {})}
            />
            <label htmlFor="">{os}</label>
          </div>
        ))}
        <input type="button" value="全てにチェック" onClick={() => {
          osList.map((os, index) => {
            setValue('windows', { [index]: true})
          })
        }} />
        <input type="button" value="全てにチェックを外す" onClick={() => {
          osList.map((os, index) => {
            setValue('windows', { [index]: false})
          })
        }} />
        <input type="submit" value="送信" />
      </form>
  );
}

export default Sample;
```
UnrealEngine プロジェクトブラウザについて

## はじめに

　はじめまして、とある会社でテクニカルアーティストしてる者です。
自分は調べるのが好きでなにか残せればいいなと思って書いてます。
記念すべき第一回目はUnreal Egingeの”プロジェクト ブラウザ”です！

## プロジェクト ブラウザとは
![2025-04-10_00h17_13 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/f9361979-2aa4-4db6-816d-48f999c464c0.png)

　プロジェクト ブラウザとはUnrealEngineのアプリケーションを開いた際に開かれるウィンドウを指します。過去使用したプロジェクトや新しくプロジェクトを作成したい時に表示されます。

## プロジェクト ブラウザ上にUEプロジェクトが表示されない

　Gitからデモプロジェクトをクローンした時とかたまにプロジェクト ブラウザ上に表示されない時があります。

1. プロジェクト ブラウザの下側のブラウズ
    ![2025-04-10_00h21_009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/dc286e97-9ffb-4ace-97b0-d0f27e3b7d57.png)
    
2. 開きたいUEプロジェクトの`.uproject`を開く
    ![2025-04-10_00h51_12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/029efe6c-3134-4f29-98fd-f837af09c5a6.png)

### 「常にスタートアップ時に最新のプロジェクトをロードする」の注意点

![2025-04-10_00h17_131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/d514894c-4002-4e27-9677-b6650c4860ee.png)
 　画像下側の「常にスタートアップ時に最新のプロジェクトをロードします」のチェックボックスを入れると次Unreal Engineを開いた際、一番最後に開いたUEプロジェクトを開きます。プロジェクト ブラウザは表示されません。

　毎回同じUEプロジェクトを開く場合は問題ありませんが、いろんなUEプロジェクトを開きたい場合チェックをはずすのをおすすめします。

　一度チェックを入れてしまった場合再度プロジェクト ブラウザが表示させる方法を説明します。

1. UEプロジェクトを開く
2. ファイル>プロジェクトを選択
   ![2025-04-10_00h40_19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/9214d68e-35d7-4703-b41c-f9f34b2e5068.png)
    
3. 「常にスタートアップ時に最新のプロジェクトをロードする」のチェックを外す
    
    ![2025-04-10_00h40_18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/17279a62-ea33-49f6-ac20-23525e0d6df3.png)
　
 これでUnreal Engineを開く度、プロジェクト ブラウザが表示されます。

## ショートカットを使用してUEプロジェクトを開く

プロジェクト ブラウザを毎回開くのがめんどくさいけど、いろんなUEプロジェクトをすぐに開きたい場合便利です。

1. 開きたいUnrealProjectのフォルダをエクスプローラーで表示させる
2. `○○.uproject`を右クリック>ショートカットの作成
   
    ![2025-04-13_00h06_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/186464e4-3372-4c9a-b229-42bef206763e.png)

    
3. UEプロジェクトのショートカットが作成されました。
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4057167/63194bd6-7e62-4b92-a28e-10e5ce792745.png)


作成されたショートカットをデスクトップに置いておけばすぐにアクセス出来るようになります。

## あとがき

　今回はUnreal Engineのプロジェクト ブラウザについて書いてみました。プロジェクト ブラウザに表示させたいUEプロジェクトはドキュメント>UnrealProjectsフォルダ内 にいないといけないって思ってるんですけどこの解釈ってあってますかね、、、どなたかお答え頂けると嬉しいです。
　あと書いていて思ったのはスクショを撮って加工するのが思ったより大変でした。
Unrealエディタやエクスプローラーのレイアウト変えちゃってるけど直すのがめんど、、
記事やブログをたくさん書いて下さる方には日々感謝しかないです。

ではまた！

## 参考

https://qiita.com/O_Y_G/items/f66a454a2a4c56f6cc43

https://zenn.dev/daichi_gamedev/books/unreal-engine-tutorial/viewer/ready-project-broweser

https://dev.epicgames.com/documentation/ja-jp/unreal-engine/opening-an-existing-unreal-engine-project#:~:text=%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82-,%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%20%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%8B%E3%82%89%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E9%96%8B%E3%81%8F,-Unreal%20Engine%20%E3%81%AE
【Unity】stepからsmoothstepに置き換えができると思ったらできなかった

# はじめに
Shaderでstepを使用している処理で単純な0、1ではなくフェードをさせたくなり、stepならsmoothstepへの置き換えができると思い実装を行いました。

しかし、stepの第二引数とsmoothstepの第三引数を0にした場合の挙動が違っておりバグりました。
どうしてこうなったかの分析になります。

# Step
``` HLSL
step(0.0, 0.0);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/0bbb9f42-5140-40dc-811a-6db88bb71d9d.png)
全部0の場合は1.0が返ってきます。

```HLSL
step(0.0, 1.0);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/f2b90fa9-f2fe-453d-8f63-a35c9d3811ba.png)
一応第二引数が1の場合は1.0が来ます。(0.1でも0.5でも1.0が返却されます)

``` HLSL
float step(float a, float x)
{
  return x >= a;
}
```
これはstepがa以上かを判断してるためこうなります。

# Smoothstep

```HLSL
smoothstep(0.0, 0.0, 0.0);
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/8bff624d-56ef-45d9-8bb3-bfaf3bafbdac.png)
この場合は未定義となり表示されません。(多分0が返ってきます。)

```HLSL
smoothstep(0.0, 0.0, 1.0);
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608797/f4d86c5f-fef3-43f7-a41f-7e5b4624b84b.png)

一応第三引数が1の場合は1.0が来ます。(0.1でも0.5でも1.0が返却されます)

これはsmoothstepでは内部で除算をしており、0 / 0が発生し、未定義となりおそらく0が返ってくるからです。
```HLSL
float smoothstep(float a, float b, float x)
{
    float t = saturate((x - a)/(b - a));
    return t*t*(3.0 - (2.0*t));
}
```

# さいごに
stepの処理をsmoothstepに置き換える際、`step(0.0, 0.0)`は`smoothstep(0.0, 0.0, 0.0)`にできないのでifなどを使用して分岐が必要そうです
【React】FormでEnterキーが押されてSubmitされるのを防ぐ

以下のようにすればEnterでSubmitされるのを防ぐことができます。
formタグに`onKeyDown`を追加し、Enterキーが押されたらevent.preventDefault()でsubmitをキャンセルしています。


```react
import { useForm } from "react-hook-form";

const App = () => {
  const { register, handleSubmit } = useForm();
  const onSubmit = (data: any) => console.log(data);

  const handleKeyDown = (e: { key: string; preventDefault: () => void }) => {
    if (e.key === "Enter") {
      e.preventDefault();
    }
  };

  return (
    <form onSubmit={handleSubmit(onSubmit)} onKeyDown={handleKeyDown}>
      <input {...register("example")} />
      <input type="submit" />
    </form>
  );
};

export default App;
```
Arduino × AWSサーバーレスで作るIoT温度モニタリングシステム（仮）【第2回】

# 光センサーでArduinoからMacにシリアル通信！？

## はじめに

[前回](https://qiita.com/takataka5845/items/b7d129a738b7365cc602)は、MacからcURLでAPI Gatewayを叩き、AWS Lambda経由でDynamoDBにデータを保存できるところまでやってみました。

### 全体構成

```
Arduino → Android → AWS (API Gateway → Lambda → DynamoDB)
```

今回はその前段階として、**ArduinoとMac間のシリアル通信**にフォーカスします。  
まずは簡単な構成で、センサー値をシリアル通信で送ってみる実験です。

:::note info
この記事は「Arduino × AWSサーバーレスで作るIoT温度モニタリングシステム」シリーズの一部です。シリーズの全体リンクは記事の末尾にまとめてあります！
:::

---

## やったこと

- 光センサーを使って周囲の明るさを取得
- タクトスイッチを使ってON/OFFの切り替え制御
- スイッチONでLED点灯＋シリアル通信で値を送信
- スイッチOFFでLED消灯＋送信ストップ

---

## 実際の回路

以下のようなシンプルな構成で組んでみました👇

![回路図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/21269/a233d10c-cfbf-46c5-81a1-b388b4d14323.jpeg)

※ 上記は「光センサー」「タクトスイッチ」「LED」の役割がラベリングされた写真です

---

## Arduino側のコード（抜粋）

スイッチが押された時にLEDを点灯し、明るさの値をシリアル通信で送る処理は以下のように実装しています👇

```cpp
void loop() {
  int light = analogRead(A0);

  if (digitalRead(2) == HIGH) {
    digitalWrite(13, HIGH);
    Serial.println(light);
  } else {
    digitalWrite(13, LOW);
  }
}
```

---

## 動作の様子（動画）

スイッチを押すとLEDが点灯し、シリアルモニタにデータが流れます。  
離すとLEDが消えて、出力も止まります。

🎥 動画はこちら：
<iframe width="560" height="315" src="https://www.youtube.com/embed/iKbI_5qyHWs" frameborder="0" allowfullscreen></iframe>

👉 [YouTubeで直接見る場合はこちら](https://youtu.be/iKbI_5qyHWs)

---

## 今後の予定

この動作確認をベースに、次回は以下を進めていく予定です：

- 光センサー → 温度センサー（DHT11 or DHT22）に置き換え
- シリアル通信 → Bluetooth（HC-06）通信に変更
- Androidアプリ側でBluetoothデータ受信に対応

---

## おわりに

今回の構成はとてもシンプルですが、「ちゃんと動く」という実感が得られるとモチベが上がりますね！

次はいよいよ、センサーも通信方法も本番仕様に近づいていくので、さらに楽しくなりそうです😊

---

## シリーズ記事一覧

- 【第1回】[AWSでクラウド側の受け口を作ってみる](https://qiita.com/takataka5845/items/b7d129a738b7365cc602)
- 【第2回】[光センサーでArduinoからMacにシリアル通信](https://qiita.com/takataka5845/items/ea7999588c7c9957acd7) （このページ） 
- 【第3回】[DHT22で温湿度を取得してシリアル送信](https://qiita.com/takataka5845/items/3aff19c560c1457829a5) 
- 【第4回】[Bluetooth通信でセンサーデータをAndroidに送信](https://qiita.com/takataka5845/items/53f2d29991f7b1023949) 
- 【第5回】[自作アプリでBluetooth接続＆温湿度データ受信](https://qiita.com/takataka5845/items/dc4753bc410dd0daa0d4)
- 【第6回】[クラウド連携でDynamoDBへのPOST＆完結編](https://qiita.com/takataka5845/items/28ba83ef0087b16525b6)

> ※今後の更新もお楽しみに！
---

つづく…（[第3回へ](https://qiita.com/takataka5845/items/3aff19c560c1457829a5)）📡🌡️📲
イベントログをcsvで出力したい

# 初めに
イベントログで何かしらを調査したい時にイベントビューアーを使うけど
イベントビューアーって重いしログ提出に向かないわ...そう思ったそこの奥さん
PowerShellでcsvに出力できるんですよ。

# コマンド
ってことでコマンドはこちら
※`C:¥`直下にcsvファイルが作成されます
```powershell:アプリケーションのイベントログを出力する場合
Get-EventLog Application -After "2025/4/12 09:30" -Before "2025/4/12 12:30" | select EventID,EntryType,Message,Source,TimeWritten | Export-Csv -Encoding UTF8 -NoTypeInformation -Path C:\Application.csv
```

```powershell:システムのイベントログを出力する場合
Get-EventLog System -After "2025/4/12 09:30" -Before "2025/4/12 12:30" | select EventID,EntryType,Message,Source,TimeWritten | Export-Csv -Encoding UTF8 -NoTypeInformation -Path C:\System.csv
```

```powershell:セキュリティのイベントログを出力する場合（時間かかるかも）
Get-EventLog Security -After "2025/4/12 09:30" -Before "2025/4/12 12:30" | select EventID,EntryType,Message,Source,TimeWritten | Export-Csv -Encoding UTF8 -NoTypeInformation -Path C:\Security.csv
```

# （一応）引数の解説
一応引数とかオプションの解説
`Get-EventLog hogehoge`
* Application：ユーザーやソフトウェアが出力するログ。アプリの作り込みが雑だと、エラー発生してるのにイベントが記録されていないことがよくある
* System：Windows OSやドライバが出力するログ。割とちゃんと記録されているけれども、メーカーによってはログが雑なことがたまにある（N〇〇西とかヌ〇〇ボとか）
* Security：ログオンや監査ポリシーなどセキュリティ関連のログ。基本的にWindowsが出しているため細かさと正確性は高い。が、ログサイズが多すぎるのと、たまにすり抜けというか欲しいログが検知されていないことがある。

`-After "2025/4/12 09:30"` ⇒ 2025/4/12 09:30 より後のログを取得します
`-Before "2025/4/12 12:30"` ⇒  2025/4/12 12:30 より前のログを取得します
`select EventID,EntryType,Message,Source,TimeWritten` ⇒ イベントID、エラーレベル、ログ内容、ログのソース(何のアプリか的な)、ログ日時　を取得します
`Export-Csv` ⇒ csvに出力します
`-Encoding UTF8` ⇒ 文字コードを指定します。**csvが文字化けする場合はDefaultを指定してみてね**
`-NoTypeInformation` ⇒ csv１行目の型宣言的なものを出力しないよ宣言
`-Path C:\Security.csv` ⇒ csvファイル出力先

# 最後に
最近ようやく気付いたんですよ
なんかごちゃごちゃやるよりも、とりあえずワンライナーでデータだけ出して、
あとは使い慣れたExcelとかで加工させた方が運用がスムーズに回るってことを...
[MikanOS] error 000E: File/directory not found in workspace      の対処法       

# 環境
Intel Mac + docker

# エラー内容
```
vscode ➜ ~/edk2 (38c8be123a) $ build
Build environment: Linux-6.10.14-linuxkit-x86_64-with-glibc2.29
Build start time: 04:05:19, Apr.13 2025

WORKSPACE = /home/vscode/edk2
EDK_TOOLS_PATH = /home/vscode/edk2/BaseTools
CONF_PATH = /home/vscode/edk2/Conf
PYTHON_COMMAND = /usr/bin/python3.8

build.py...
: error 000E: File/directory not found in workspace
/MikanLoaderPkg/MikanLoaderPkg.dsc (Please give file in absolute path or relative to WORKSPACE)

Failed -
Build end time: 04:05:20, Apr.13 2025
Build total time: 00:00:00
```

# 対処法
```shell
ls -la ~/edk2/MikanLoaderPkg
cp /workspaces/mikanos-devcontainer/target.txt ~/edk2/Conf/target.txt
sed -i 's|ACTIVE_PLATFORM       = MikanLoaderPkg/MikanLoaderPkg.dsc|ACTIVE_PLATFORM       = MikanLoaderPkg/MikanLoaderPkg.dsc|' ~/edk2/Conf/target.txt
cd ~/edk2
source edksetup.sh
build
```

シンボリックが正しくMikanLoaderPkgをさしてなかった、もしくhtarget.txtがworkspaceの構造と合ってなかった。
GitLab CI/CD 変数定義と優先順位

## GitLab CI/CD 変数定義と優先順位

GitLab CI/CD における変数の優先度について整理します。複数の場所で同じ変数が定義された場合、どの変数が優先されるのかを理解しておく必要があります。

### 変数の優先順位

GitLab CI/CD における変数の優先順位は、以下の通りです。

1.  **ジョブ定義:** `.gitlab-ci.yml` ファイル内の個々のジョブで定義された変数が最も優先されます。
2.  **.gitlab-ci.yml 内のグローバル変数定義:** `.gitlab-ci.yml` ファイルのグローバルセクションで定義された変数が次に優先されます。
3.  **パイプライン実行時のWeb UI定義:** パイプライン実行時にGitLab UIで設定された変数がその次に優先されます。
4.  **プロジェクト設定:** プロジェクトの設定で定義された変数が次に優先されます。
5.  **グループレベル変数:** グループ設定で定義された変数は、プロジェクト設定よりも優先されます。
6.  **インスタンスレベル変数:** GitLabインスタンス全体で定義された変数は、最も低い優先順位となります。

### 変数の種類

GitLab CI/CD では、以下の2種類の変数を定義できます。

* **変数:** 文字列値を格納します。
* **ファイル:** ファイルの内容を格納し、ジョブ内でファイルとして利用できます。

### 定義済み変数

GitLab CI/CD には、ブランチ名やコミットSHAなど、多くの定義済み変数が用意されています。これらの変数を活用することで、パイプラインの自動化をより柔軟に行えます。

### 変数のスコープ

変数は、以下のスコープで定義できます。

* **プロジェクトレベル:** 特定のプロジェクトでのみ利用可能。
* **グループレベル:** グループ内のすべてのプロジェクトで利用可能。
* **インスタンスレベル:** GitLabインスタンス全体で利用可能。

### まとめ

GitLab CI/CD の変数定義と優先順位を理解することで、より柔軟かつ安全なパイプラインを構築できます。機密情報は保護設定とマスク設定を適切に利用し、効率的な自動化を実現しましょう。
【忘備録】Electronを利用したデスクトップアプリの作成手順

# 概要
3つの手順でデスクトップアプリの雛形が作成できたため、メモ程度に記録する。

## Node.jsのインストール
以下からインストーラをダウンロードしインストールを行う。
基本的にデフォルトの設定のまま進めていく。

https://nodejs.org/en/download

## npmを使用しテンプレートを作成
以下のコマンドを入力する。
```batch
npm create @quick-start/electron@latest
```

いくつか質問されるので、以下のように入力する。
```batch
Ok to proceed? (y) y
? Project name: » electron-app
? Select a framework: » react
? Add TypeScript? ... Yes
? Add Electron updater plugin? » No
? Enable Electron download mirror proxy? » No
```

## アプリの実行
以下のコマンドを入力し、アプリを実行する。
```batch
cd electron-app
npm install
npm run dev
```

以下のようなアプリが立ち上がる。
![electron-app.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382781/a3841c80-37f7-4003-933b-ce9cf7652485.png)
【ネットワーク】MACアドレス

# はじめに

こんにちは。アメリカに住みながら、独学でエンジニアを目指しているTairaです。
ネットワークの勉強をしていると、「MACアドレス」という言葉がよく出てきます。今回は、初心者向けにMACアドレスの基本と、IPアドレスとの違い、具体的な用途についてわかりやすく解説します。

---

## MACアドレスとは？

MACアドレス（Media Access Control Address）は、ネットワーク機器に割り当てられた**一意の識別番号**です。具体的には、PCやスマートフォン、ルーターなどに搭載されている**ネットワークインターフェースカード（NIC）**に付与されており、機器ごとに異なります。

### 特徴
- **48ビット（6バイト）**の情報で構成されている
- 通常、**16進数（例：00:1A:2B:3C:4D:5E）**で表記
- ネットワーク機器が通信相手を識別するために使う

---

## MACアドレスの用途

MACアドレスは、**同一ネットワーク内（LAN）**での通信に使われます。たとえば、Wi-Fiでスマートフォンからルーターへデータを送信する場合、スマートフォンのMACアドレスとルーターのMACアドレスが使われます。

また、スイッチやルーターなどのネットワーク機器は、MACアドレスをもとに「どのポートにどの端末がいるか」を判断して、適切な通信を行っています。

さらに、**ARP（Address Resolution Protocol）**という仕組みを使って、IPアドレスからMACアドレスを割り出して通信を行うこともあります。

---

## IPアドレスとの違い

| 項目 | MACアドレス | IPアドレス |
|------|--------------|-------------|
| 割り当て方法 | 製造時に機器ごとに設定（基本変更不可） | DHCPや手動で設定（※グローバルIPはISPによって決まる） |
| 使用範囲 | LAN（ローカルネットワーク）内 | インターネット全体 |
| 役割 | 機器そのものを識別する | 機器の“場所”を識別する |
| 表記形式 | 16進数（例：00:1A:2B:3C:4D:5E） | IPv4（例：192.168.1.10）など |

※補足：**グローバルIPアドレスは通常、インターネットプロバイダ（ISP）によって自動的に割り当てられ、個人が自由に変更することはできません**。一方、**プライベートIPアドレスはルーターの設定などで手動変更が可能**です。

---

## 通信の流れにおけるMACアドレスの役割

たとえば、自分のPCから同じLAN内のプリンターに印刷する場合：

1. IPアドレスでプリンターを指定する
2. ARPを使って、プリンターのMACアドレスを取得
3. プリンターのMACアドレスに対してデータを送信する

このように、MACアドレスは実際のデータ通信において、非常に重要な役割を果たしています。

---

## おわりに

MACアドレスは、ネットワークの中で機器を特定するための「名前札」のようなものです。IPアドレスが“住所”であるなら、MACアドレスは“名前”と言えるでしょう。

ネットワークを学ぶうえで、MACアドレスの仕組みを理解することはとても重要です。今後、ARPやスイッチの学習を進める際にもこの知識が活き
【プラクティス紹介】1分でさらっと分かる「エリアプロダクトオーナー」


![apo.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3526800/d85955cd-72a8-40ec-b4d3-f31971cfc55d.jpeg)



## プラクティス名（別名）
エリアプロダクトオーナー　（APO、POチーム）

## プラクティスの目的・狙い
* 大規模プロダクトの要求事項を複数のPOで手分けして管理する

## どんな時に使うか
* プロダクトの規模が大きすぎて一人のPOが全領域をカバーすることが難しい時

::: note info
**LeSS**: 2～8のスクラムチームで行う大規模アジャイル開発のフレームワーク
**LeSS Huge**：9チーム以上で行う大規模アジャイル開発のフレームワーク
APOというロールが登場するのはLeSS Hugeからです。8チームまではできるだけスクラムの原則通りに一人のPOが管理することが望ましいとされています。
:::

## 実施手順
1. プロダクトバックログ（PBL）に記載された要求事項（PBI）を特定の観点（例えば業務ドメインや顧客セグメントなど）で分類する（＝**要求エリア**）
1. 全体を統括するPOとは別に、要求エリア毎に管理者を任命する（＝**エリアプロダクトオーナー**）
1. APOはその要求エリアにおいて、POとして振る舞う
1. APO間で要件調整や優先順位検討が必要な場合は全体POにエスカレーションする

::: note info
**エリアプロダクトバックログ（APB）**:
PBLを要求エリア毎に切り分けたものをエリアプロダクトバックログと呼びます。概念的にはAPBはPBLから特定のエリアの情報だけを抜粋した一種のビューのようなものであり、PBL自体はあくまでも１つ、というのがLeSSの考え方です。ただし実運用上はPBLとAPBは記載粒度が異なる場合もあり、物理的に分けて管理するケースが多いと思われます。
:::

## アレンジ例
* 全体POがどこか一つのAPOを兼務する場合もある
* 8チーム以下の規模でも、専門知識が必要となる特定の領域に関してはAPOを立てる場合もある

## アンチパターン
* 全体POがAPOに任せきりで、PBL/APBの全容（全体感）を把握していない
* APO間のコミュニケーションが不十分で、各エリアで対応方針が異なる

## 参考情報
参考書籍

https://www.maruzen-publishing.co.jp/book/b10112298.html

LeSS公式WEBサイト

https://less.works/jp/less/rules

## こぼれ話（私的コメント）
スクラムガイドには「POは一人の人間であり、委員会ではない」とハッキリ書かれています。スクラムマスターやっててもPO複数名はやっぱアンチパターンだなぁ、と感じることも多いです。にもかかわらずPO委員会になってる現場って少なくないんじゃないかと。POできる人って業務側のキーマンだったりするので大抵忙しくて一人じゃ回らないんですよね。そもそも専任POじゃないケースも多いし。
APOというロール自体、POは本来一人がいいけど、プロダクト規模が大きくなると、もうしょうがないよね、という苦肉の策という印象です。POが複数名になることで、PO同士の認識合わせ/合意形成の時間も必要になってくるため、余計にPOの負荷が高まるという悪循環もあり、なかなか悩ましいです。少なくともDEVが誰に話しかければよいかは迷わないようにしておきたいところですね。


---
　[アジャイルプラクティス一覧へ戻る](https://qiita.com/kakashi_h5/items/20584998c5ca4594b9ea)
【ABC401】AtCoder Beginner Contest 401【C++】

### コンテスト名
AtCoder Beginner Contest 401

### コンテストURL
https://atcoder.jp/contests/abc401

### 開催日
2025/04/12 21:00–22:40

---

## [A: Status Code](https://atcoder.jp/contests/abc401/tasks/abc401_a)
**解法**
- 問題文通りに判定する
```cpp:ABC401A.cpp
#include <iostream>
using namespace std;

int main(){
    int s;
    cin >> s;

    if(s>=200 && s<=299){
        cout << "Success" << endl;
    }else{
        cout << "Failure" << endl;
    }

    return 0;
}
```

## [B: Unauthorized](https://atcoder.jp/contests/abc401/tasks/abc401_b)
**解法**
- ログイン状態について記録しておき、問題文通りに操作する
```cpp:ABC401B.cpp
#include <iostream>
#include <string>
using namespace std;

int main(){
    int n;
    cin >> n;

    bool flag = false;
    string s;
    int cnt = 0;
    for(int i=0; i<n; i++){
        cin >> s;
        if(s=="login"){
            flag = true;
        }else if(s=="logout"){
            flag = false;
        }else if(s=="public"){
            continue;
        }else if(s=="private"){
            if(!flag){
                cnt++;
            }
        }
    }

    cout << cnt << endl;

    return 0;
}
```

## [C: K-bonacci](https://atcoder.jp/contests/abc401/tasks/abc401_c)
**解法**
- 差分を利用する
- $K \leqq N$ のとき
    - $i < K$ のとき、 $A_i = 1$
    - $A_K = K$ 
    - $i > K$ のとき、 $A_i = A_{i-1} + A_{i-1} - A_{i-K-i}$
- $K > N$ のとき、 $A_N = 1$ であることに注意する
```cpp:ABC401C.cpp
#include <iostream>
#include <vector>
using namespace std;

long long int mod(long long int x, long long int m){
    long long int res = x % m;
  
    if(res<0){
      res += m;
    }
  
    return res;
}

int main(){
    int n, k;
    cin >> n >> k;

    if(k>n){
        cout << 1 << endl;
        return 0;
    }

    vector<long long int> A(n+1);
    for(int i=0; i<k; i++){
        A[i] = 1;
    }

    int j = 0;
    A[k] = k;
    for(int i=k+1; i<=n; i++){
        A[i] = 2 * A[i-1] - A[j];
        j++;
        A[i] = mod(A[i], 1000000000);
    }

    cout << mod(A[n], 1000000000) << endl;

    return 0;
}
```
新規ユーザーでSSH接続する手順とエラー解決

Linux上に新規ユーザーを作成し，そのユーザーで SSH 接続する設定を行った際の備忘録としてまとめます。
環境は「Ubuntu 24.04.2」です。


# SSH接続するための手順
おそらく一般にはここの手順で終わると思います

1. OS上にて新規ユーザー「new-user」を作成
1. 公開鍵ペアを作成
1. user01のホームディレクトリ `/home/new-user/.ssh/authorized_keys`に公開鍵を登録
    + `ssh-copy-id`などを使うと便利ですが，Windowsでは標準でつかえません。
    + git for windows をインストールし，Git Bashから行うことになると思います。（もちろん手動でも構いません。）
1. SSH接続ができるかを確認



# トラブルシュート
鍵ペアがそもそもあっているかどうかも確認しておきましょう。
鍵が壊れている可能性もありますが，ここでは正常な前提で進めます。

解決にはサーバー側で SSHのログを見てしまうのがてっとり早いです。以下から接続した際のログも同時に確認してみてください。
```
sudo journalctl -u ssh -e
```
または
```
sudo tail -f /var/log/auth.log
```

## `/etc/ssh/sshd_config`を確認する
現状のsshd設定がどうなっているかを確認します。

```
sudo vi /etc/ssh/sshd_config
```
以下２つの設定を確認。
```
#PubkeyAuthentication yes

# Expect .ssh/authorized_keys2 to be disregarded by default in future.
#AuthorizedKeysFile      .ssh/authorized_keys .ssh/authorized_keys2
```
デフォルト値はともに以下の通りとなっているため，上記においてわざわざコメントアウトを外す必要はありませんが，念のため明示的に設定を書いてもいいと思います。


| 項目 | デフォルト値 |
|:-:|:-:|
| `PubkeyAuthentication` | `yes` |
| `AuthorizedKeysFile`  | `.ssh/authorized_keys` |


また，以下のような制限設定がされている場合，新規ユーザーが弾かれる場合があるため，ここも設定があるかをチェックします。
```
AllowUsers existing-user01 existing-user02
```
このようなホワイトリスト・ブラックリスト設定としては以下４つがあります。上から処理される順番にしていますので，参考にしてください。
+ DenyUsers
+ AllowUsers
+ DenyGroups
+ AllowGroups


その他の変更については以下を参照してください。
>[sshd_config(5): OpenSSH SSH daemon config file - Linux man page](https://linux.die.net/man/5/sshd_config)

変更を行った場合，以下で設定を反映させます。
```
sudo systemctl restart ssh
```

## `.ssh`ディレクトリとその中のファイルのパーミッションの確認
+ `.ssh`→ 700
+ `.ssh/authorized_keys`→ 600

こちらはともに接続した際のエラーは以下のようになります。
```
$ ssh inst-dev
new-user@xxx.xxx.xxx.xxx: Permission denied (publickey).
```

エラー文でみるとわかりやすいですね。
```
Apr 13 03:43:06 inst-dev sshd[23050]: Authentication refused: bad ownership or modes for file /home/new-user/.ssh/authorized_keys
```

## ホームディレクトリのパーミッションと所有者を確認
ディレクトリが接続したいユーザーのものでないと接続できません。

```
sudo ls -al /home/new-user
```

パーミッションは`700`か，少なくとも`755`になっていることを確認します。パーミッションが緩すぎると鍵認証で蹴られることがあるそうで，私はここが`770`になっていたことで接続できなくなっていました。

エラーは上記と同様です。
```
$ ssh inst-dev
new-user@xxx.xxx.xxx.xxx: Permission denied (publickey).
```

このとき，ログは以下の通りになります。
```
Apr 13 02:55:01 inst-dev sshd[21868]: Authentication refused: bad ownership or modes for directory /home/new-user
```