OmniAICreator/Qiita-1.07M huggingface dataset:
GSAPとReactでページ遷移アニメーションを実装した話

# はじめに
reactを用いてwebページを作っていたのですが何か物足りない。
そこでアニメーションをつけてリッチに見せようと思いつきました。
# GSAPとは
要素をなめらかーに動かせるものです。
wappalyzer(サイトがどの技術を使ってるかを推定できるツール)によると「ペルソナ3リロード」や「負けヒロインが多すぎる」のWebページで採用されているらしいです。
[ペルソナ3リロード](https://p3re.jp)
[負けヒロインが多すぎる](https://makeine-anime.com)
# 基本的な使い方
```react
gsap.to(".my-element", {
  x: 100,          // x座標方向に100px移動
  duration: 1,     // アニメーションの時間を1秒に設定
  opacity: 0.5     // 不透明度を0.5に設定
});
```
toで元の位置から記述した情報に遷移してくれます。

# useGSAPとは？
useEffectと基本動作は変わりません。
GSAPを使うのに特化したuseEffectといった感じです。

# 実装の手順
- Contextの作成
- Layout.tsxで全体をラップ
- ここに要素を配置
- gsapを実装

# 実行される流れ
- ボタンを押されたらパスを指定
- isPageOutをtrueにする
- 依存関係にしてるuseGSAPが発火
- 読み込み前のアニメーションを実行
- isPageOutをfalseにする
- useNavigateでページを切り替える
- isPageInをtrueにする
- 依存関係にしてるuseGSAPが発火
- 読み込み後のアニメーションを実行
- isPageInをfalseにする

# Contextはなんでいる？
contextを使うことによって変数をpropsで渡さなくて済みます。
語弊を恐れずにいうとグローバル変数のように使うことができます。

```react
<PageContext.Provider
      value={{
        firstLoad,
        setFirstLoad,
        isPageIn,
        setIsPageIn,
        isPageOut,
        setIsPageOut,
        newPath,
        setNewPath,
      }}
    >
          {children}
 </PageContext.Provider>
```

これでchildren(小要素)に値やstateを渡すことができる。

# 値をセット
```react
const handleNext = (path: string) =>
  {
    setNewPath(path);
    setIsPageOut(true);
  };
```
パスを設置してページを離れる時のアニメーションを実行するためにisPageOutをtureにする。

# Gsapによるページ切り替え前のアニメーションとページ切り替え
これによりisPageOutを依存関係に設定してあるuseGSAPが実行される。

```react
  //ページアウトアニメーション
  useGSAP(() => {
    const tl = gsap.timeline();
    if (isPageOut) {
      tl.fromTo(
        block3Ref.current,
        { y: "100%" },
        {
          y: "0%",
          duration: 0.6,
          ease: "power2.in",
          onComplete: () => {
            setIsPageOut(false);
            navigate(newPath);//ページに飛ぶ
            setIsPageIn(true);
          },
        }
      );
      
    }
  }, [isPageOut]);
```
navigateでページ切り替える
その後isPageInをtrueにし、切り替え後のアニメーションを実行するuseGSAPが発火する。
```react

  useGSAP(() => {
    const tl = gsap.timeline();

    if (isPageIn ) {
      tl.fromTo(
        block3Ref.current,
        { y: "0%" },
        {
          y: "100%",
          duration: 0.6,
          ease: "power2.in",
          onComplete: () => {
            setIsPageIn(false);
          },
        }

    }
  }, [isPageIn]);
  ```
# 終わりに
今回自分なりに作ってみたがこれが最適解かわからないです。
他に便利なライブラリがあるのかもしれないです。
それでも今回はGSAPで作ってみたかったので作成してみました。
もし同じようなことを考えてる方がいて、参考になったら幸いです。
質問、訂正依頼お待ちしております😊
VercelPostgresの Endpoint ID is not specified エラー解決

# 状況
Vercel Postgresから、AWS AuroraにDBを移行するためにAWS DMSのソースエンドポイント（移行元）を追加しようとしたら、以下のエラーが出てしまった。
```
Test Endpoint failed.
~~省略~~
101 Message: ERROR: Endpoint ID is not specified.
Either please upgrade the postgres client library (libpq) for SNI support
or pass the endpoint ID (first part of the domain name)
as a parameter: '?options=endpoint%3D<endpoint-id>'.
See more at https://neon.tech/sni
```

# 調査
[GitHub Issue](https://github.com/vercel-community/php/issues/458)によると、VercelPostgresの`libpq`のバージョンが古く、SNIに対応していないために発生している問題らしい。（早くアップデートしてくれぃ！）

まずはエラー文の指示通り、`?options=endpoint%3D<endpoint-id>`をパラメータとして追加する。
`<endpoint-id>`は、`ab-cdef-ghikj-12345678-pooler.ap-southeast-1.postgres.vercel-storage.com`の`ab-cdef-ghikj-12345678-pooler`の部分なので、`追加の接続属性`に言われた通りの記述をしてみる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841759/f8ad33e2-ccf1-fc8d-2708-7a4eebdff771.png)
しかし、AWS DMSのエンドポイントでは、渡せるパラメータに制限があるらしく、以下のようなエラーになってしまう...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1841759/f7d34e58-aba6-6b19-163e-61eeed65c158.png)

# 解決方法
[neonの公式ドキュメント](https://neon.tech/docs/connect/connection-errors#d-specify-the-endpoint-id-in-the-password-field)に解決方法が書いてあった。
パスワードの入力フィールドに、
```
endpoint=<endpoint_id>;<password>
```
か
```
endpoint=<endpoint_id>$<password>
```
のような形式で入力すると、エンドポイントIDを特定できるようになるらしい。
AWS DMSのエンドポイント設定では、パスワードフィールドに `;` (セミコロン)を含めることはできないため、`$` で区切ってあげればOK!

# まとめ
公式ドキュメントはやはり至高！
焦ってStack Overflowばかり漁ってしまいがちなので反省...

https://github.com/vercel-community/php/issues/458

https://neon.tech/docs/connect/connection-errors#d-specify-the-endpoint-id-in-the-password-field
０除算とNullとの関係

# はじめに
これは技術的な証明をしている記事ではなく、自分なりに感じたことを書いたエッセイ的なものですので、軽い気持ちで読んでいただければ幸いです。

# 6×0=0
まずは以下を考えてみます。複雑に考えず直感で見ていきましょう。
```math
x \times y = z であれば x = z \div y が成立する
```
たとえば x = 6, y = 3 のとき、z = 18 になります。
```math
6 \times 3 = 18
```
```math
x = z \div y は、6 = 18 \div 3 で成立します
```
では、x=6, y=0のときはどうか
```math
6 \times 0 = 0 となり、zは0になります。これは特に問題ありません
```
ところが、x = z ÷ y を考えると
```math
6 = 0 \div 0
```
あれ・・・？となりますね。0 ÷ 0 は 6 になるの？ 

# ０とは？
小学生のころだったかインド文明で「０が発見された」という教科書の説明を聞いて、「どういうこと？」と感じた記憶があります。０が発見されるってどういう意味だよとツッコミ入れたくなりました。
小さいときから当たり前のように使っている０という数字、でも実はあまり分からないまま感覚的に使用しているのではないでしょうか。

# ０と無の関係
「何も無い」という意味の**無**について考えてみましょう。
「何も無い」ものをあたかも「存在する」ように考えることはできるのでしょうか？
変な言い方ですが、たとえば「空白文字」というのは、文字が無いということで「無」を表します。
古代文献では実際、無を表現するのに空白を使っていた文明もあるそうです。

ところが空白では分かりにくい。
そこで「何も無い」という概念を記号として表すのに、**０**が使われるようになったわけです。

ところが、この記号化をすることで矛盾も生じました。0が数字として使われたからです。
「0は数字だろ！」と言われそうですが、そもそも数字というのは「数えられるもの」という意味があります。
たとえば「林檎がお皿に５個あります」と言われれば
```math
🍎 \times 5 = ５個の林檎
```
ということになります。５個のリンゴがお皿に実際に存在するわけです。
ではこれが0になるとどうでしょうか？
```math
🍎 \times 0 = ０個の林檎
```
となりますね。０個と数えることもできますが、同時に「林檎は存在しない」という意味にもなります。
```math
🍎 \times 0 = 林檎は無い
```
「お皿の上の林檎を数えることはできない」ということです。

そもそも「無」というのは数えることができないものであり、「数字の0」は数えることができるものとして取り扱われているわけです。

![0とは.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/956246/cf33b504-b133-37a6-3be9-8a551679d2df.jpeg)
普段私たちが使っているのは、数字としての０であって、「無」としての０ではないんですね。０は無という概念のすべてを表しているのではなく、無という**概念の一部**を数字として表しているに過ぎないということです。

# ０が無を表すパターン
数字としての０ですが、無という使われる場合があります。それが先ほどの０除算です。
０の掛け算は数字としても無としても扱うことができます。
```math
🍎 \times 0 = 林檎は存在しない/林檎は０個 
```
それに対し、０除算は存在としての無として考えます
```math
🍎 \div 0 = 林檎は存在しない
```
やや屁理屈っぽいですが、「無」をどうやって記号化することができるか、その一つの答えが０ですが、無の概念すべてを網羅していないため限界があるということです。
実は、この「無い」ということをどのように表現するかは、現代でもプログラミングでは頻繁に出てきます。

# null
存在しないものを表す記号という、矛盾した状態を表すことが必要なわけですが、nullはまさしく無の表現の一つです。
誰もがプログラミングをしていると出会うエラーがあります。ヌルポ(NullPointerException)ですね。
初心者がつまづきやすいところです。
宣言したけどインスタンス化されていない状態とかいろいろありますが、要するに無の概念を記号化していると言えます。
0は数字としても使われていて無として使うことはできないので、代わりに発明されたのがnullなわけです。だからnullは数えることができません。
どこかで、nullは作らない方が良かったとかなんとかいう話を聞いたことがありますが、そのくらい実はややこしいものです。
他の言語では、Nothing, None, Undefinedといったものがその類と言えます。

# 静的型付け言語と動的型付け言語
C#やJavaといった静的型付け言語では、変数の型を最初から決めてコーディングをします。
それに対しJavaScriptやPythonなどは動的型付け言語と呼ばれ、実際に動作するときに、変数の型が類推されて決定されます。
実はここに無の概念というものがあります。動的ということは、最初はすべて無ということです。記号としてはそこにあるけど、実際は無いものという感じですね。
だから、UndefinedとかNoneという型が実はあてられるわけです。
もしnullや無という概念がプログラミングに導入されなかったら、動的型付け言語も誕生することはなかったかもしれません。

# 攻殻機動隊
話しは飛んで攻殻機動隊のワンシーンを紹介します。
Stand Alone Complexでのタチコマのセリフです。「神ってやつの存在も近頃は何となくわかる気がしてきたんだー。もしかしたらだけどさ、数字の0に似た概念なんじゃないかなーって、ようするに体系を体系たらしめるために要請される、意味の不在を否定するための記号なんだよ」

存在しないはずのものを存在たらしめる記号、それが０だと。それを神と比較するわけです。面白いセリフですね。
０というのはそのくらい奥深い概念ですし、単に数えられる数字ではないということです。
だから、０除算や０乗算というのは、数字として取り扱うだけではなく、存在論的に考える必要がある数式ということになります。(存在論なのか実在論や実存論なのかという議論は他所でしましょう)

# まとめ
身近な０という数字ですが、考えると数学や概念論としてだけの話ではなく、実はプログラミングにおいても似たような概念が取り入れられていることが分かりました。
nullとは何かを説明するのは、0とは何かを説明するのととても近いということになります。特にJavaはnullの取り扱いに結構苦労している印象があります。C#はそのあたりうまい具合にやっているなぁというのが個人的な感覚です。
「無」は人類が誕生して現在に至るまでいまだ未解決の概念です。
新しい無の概念を表す記号がこれからも誕生すると思います。それを楽しみに、今日もプログラミングを楽しみましょう！
区切られた文脈の特定方法とビジネス活動のモデル化 - レンタルサーバー事業を例に

この記事では、[ドメイン駆動設計をはじめよう](https://www.oreilly.co.jp/books/9784814400737/)(以下、本書)の中で語られている「区切られた文脈」（Bounded Context）について、レンタルサーバー事業を例に、特定方法とビジネス活動をモデル化する手順について考えていきます。

---

### 1. 区切られた文脈とは？

「区切られた文脈」とは、ビジネスの各領域を分割し、機能ごとに一貫した用語やルールを定義することで、システムの複雑さを管理するための設計手法です。この概念は、ビジネスの異なる領域がそれぞれ異なる要求やロジックを持つことを前提にしています。

たとえば、レンタルサーバー事業では、顧客の契約管理、サーバーの運用、料金の請求、サポートといった異なる業務領域が存在し、それぞれの領域で扱う情報やプロセスが異なります。このような状況で、一つのシステムに全てを統合すると、管理が複雑になり、変更に対する柔軟性が低下します。

本書では、こうした異なる領域を「区切られた文脈」として独立させ、各文脈ごとに専用のモデルを持たせることが推奨されています。これにより、各領域が自律的に機能し、全体の複雑さを抑えながら効率的なシステムを構築できるようになります。

---

### 2. 区切られた文脈の特定方法

本書に基づいて、区切られた文脈を特定するプロセスは以下の手順で進められます。

#### ステップ 1: ビジネス活動の洗い出し

レンタルサーバー事業におけるビジネス活動は、さまざまな領域が混在しています。契約処理やサーバーの設定、顧客対応、請求など、複数の業務が存在します。たとえば、顧客との契約はプラン選択を伴い、サーバーをどう運用するかという技術的な問題も含まれます。また、契約が更新された場合の対応や、サポートの問い合わせもビジネス活動に含まれるでしょう。

それ以外にも、請求書の発行や支払い状況の確認、顧客からの問い合わせに対する技術サポート、サーバーのメンテナンスやトラブルシューティングといった業務も存在します。こうしたビジネス活動を洗い出すことで、全体像が見えてきますが、それぞれの活動は直接的には関連しないことが多く、整理が必要です。

#### ステップ 2: 業務領域ごとの関係性を分析する

次に、各業務領域がどのように相互に関連しているかを分析します。契約管理と請求管理は密接に関係しており、契約内容に基づいて請求額が計算されます。また、サーバー運用管理は契約情報に基づいてサーバー設定を行いますが、請求管理には関与しません。

一方、サポート業務はサーバーの状態を把握し、顧客とのやり取りをサポートするために、サーバー運用管理や契約管理からの情報を必要とします。このように、各領域の依存関係を把握することで、どのようなデータのやり取りが必要かを理解し、区切られた文脈を適切に定義できます。

#### ステップ 3: 区切られた文脈の定義

本書では、各業務領域を「区切られた文脈」として明確に分離し、それぞれ独自のルールとデータモデルを持たせることが推奨されています。これにより、文脈間の依存を最小限にし、独立して運用可能なシステムを構築することができます。

- **契約管理文脈**：契約情報の管理、プランの選択や契約更新、解約の処理を行う
- **サーバー運用文脈**：サーバーの設定やメンテナンス、パフォーマンス監視を行う
- **請求管理文脈**：契約情報に基づいて料金を計算し、請求書を発行する
- **サポート文脈**：顧客からの問い合わせ対応、技術サポートを提供する

これにより、各文脈が独立して機能し、変更に強いシステムを構築することができます。

```mermaid
graph TD
    CM[契約管理]
    SO[サーバー運用]
    BM[請求管理]
    SP[サポート]

    CM -->|契約情報| SO
    CM -->|契約情報| BM
    CM -->|顧客情報| SP
    SO -->|サーバー状態| SP
    BM -->|請求情報| SP
    BM -->|支払い情報| CM
```

---

### 3. ビジネス活動のモデル化

本書では、特定された区切られた文脈を元に、具体的なビジネス活動をソフトウェアとしてモデル化する手法についても詳述されています。ここでは、エンティティ、集約、サービス、リポジトリといったDDDの基本的な概念を使って、モデル化を進めます。

#### ステップ 1: エンティティと集約の特定

各文脈内での主要なビジネスオブジェクトをエンティティとして特定します。レンタルサーバー事業では、以下のようなエンティティが考えられます。

- **顧客エンティティ**：顧客情報（名前、連絡先など）を保持
- **契約エンティティ**：顧客が契約したプランや契約期間、料金などの情報を管理
- **サーバーエンティティ**：サーバーの設定や状態を管理
- **請求エンティティ**：契約内容に基づいて生成される請求情報を管理

集約は、これらエンティティをグループ化し、一つの単位として扱います。たとえば、「契約集約」は、顧客エンティティと契約エンティティを含み、契約に関連するすべての情報を管理します。

#### ステップ 2: ビジネスロジックの定義

本書では、各集約に対して適用されるビジネスロジックの定義が重要であるとされています。たとえば、契約管理文脈では、契約が更新されるたびに通知を送るロジックや、プラン変更時にサーバー設定を即座に反映させるロジックが必要です。

- **契約更新ロジック**：契約終了の30日前に自動的に顧客に通知を送信し、更新を促します。
- **プラン変更ロジック**：顧客がプランを変更した際、即座にサーバー設定と請求金額を更新します。

#### ステップ 3: サービスとリポジトリの設計

「サービス」は、ビジネスロジックを集約内に実装する役割を果たします。たとえば、契約更新サービスでは、契約情報を操作し、必要に応じて顧客への通知やサーバー設定の更新を行います。

また、「リポジトリ」は、エンティティや集約をデータベースに保存し、必要に応じて取得するためのパターンです。これにより、データの永続化が効率的に行われ、各文脈間のデータ操作が統一されます。

---

### まとめ

この記事では、[ドメイン駆動設計をはじめよう](https://www.oreilly.co.jp/books/9784814400737/)の内容を踏まえ、レンタルサーバー事業における「区切られた文脈」の特定方法とビジネス活動のモデル化について考えました。区切られた文脈を特定し、適切に管理することで、システムの柔軟性と保守性を高めることが可能です。本書のアプローチを実際に適用することで、システム設計の強固な基盤を構築できると思います。
副作用のある関数とは

## 副作用とは？
関数やメソッドが実行された時に、外部にある状態を変更することを指す
これは、関数の出力（戻り値）以外の影響をプログラムに与えること

👇副作用のある関数
```go
type XX struct{
    Num int
}

func (x *XX) changeValue() int{
    x.Num = 1 //副作用あり
    return x.Num
}
```

👇副作用のない関数
同じ入力に対して常に同じ出力を返し、外部の状態を変更しない関数
```go
func add(a, b int) int{
    return a + b
}
```
GitHubからSHH接続でcloneしたい(Windows)

# 目的
GitHubからSSH接続でリポジトリをcloneしたい時に、以下のようなエラーが出ることがあります。
``` shell
Cloning into 'sample-app'...
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
上記エラーの解決策として、GitHubとSSH接続する際に必要な**SSHキーに生成**と**登録方法**を記録します！:pencil2:

# 手順
**①** ターミナルを開き、**以下のコマンドを実行**してSSHキーを生成します
``` shell
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
```
**②** 上記コマンド実行後、**パスフレーズ(パスワード)** の入力を求められたら、任意のフレーズを設定してください

**③ ~/.ssh** 配下に **id_rsa.pub** というファイルが生成されていることを確認してください
※このファイルの中身が、GitHubに登録する公開鍵になります

**④ GitHubのアカウント設定**から、**SSH and GPG keys** の項目を開きます

**⑤ New SSH key** ボタンをクリックします

**⑥** タイトルを入力し、キーのテキストエリアに **~/.ssh/id_rsa.pub**ファイル内の内容を **コピー＆ペースト** します

**⑦** **Add SSH key** ボタンをクリックします

手順は以上です！

# 確認
以下コマンドを実行し、Git cloneを試します
``` shell
git clone git@github.com:{GitHubのSSHコード}
```

**エラーメッセージが出ず**にクローンできれば、**SSHキーの設定**は成功です！

# まとめ
SSHキーは、ローカル環境とGitHubのようなリモートリポジトリとの間の安全な接続を確立するための鍵のようなものです。パスワードを入力する手間を省き、より安全な認証方法を提供します。

# 補足
* SSHキー生成時の、各コマンドの説明
    * **-t rsa**: RSA方式のキーを生成
    * **-b 4096**: キーの長さを4096ビットに設定
    * **-C "your_email@example.com"**: コメントとしてあなたのメールアドレスを指定（任意）
Github Copilot mdファイルのコーディング規約に基づいてレビューする

# 概要
github copilotでリポジトリ内のコーディング規約を読ませて、ソースをレビューできるか試してみました。結果はきっちりレビューしてくれました。


# 検証開発環境　
javascript 
HTML
github codespaces(ブラウザで動かす方)

# 準備
## コーディング規約
ルールは以下の通り
変数の記法はアッパーキャメル記法
配列のfor文は　for ofを使う
if文は比較したい変数は比較演算子の左側に書く

詳細の形式はgithub参照
https://github.com/RYA234/laravel9_vite_vue3/blob/master/review_test/javascritpt_rule.md


## レビュー前のファイル
適当です
```main.html
<script>
	let aCompany_printers_Number = new Array();
	aCompany_printers_Number.push(5);
	aCompany_printers_Number.push(1000);

	for (let i = 0; i < aCompany_printers_Number.length; i++) {
		if (10 < aCompany_printers_Number[i]) {
			console.log(aCompany_printers_Number[i])
		}
	}

</script>

```

# 操作方法
## ファイルをチャットに追加
ファイルを開く。エディター上で右クリックして以下操作を実行。
「Copilot」→「ファイルをチャットに追加」を選択
![{569B519F-3190-4CC5-8609-882173F63506}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/39edf0b8-6174-e84f-69f5-ba337a2374cd.png)

## チャットでメッセージを送信
以下内容を送信
「review_test/main.htmlをreview_test/javascript_rule.mdに基づいてレビューしてください。」
![{9426811C-16D1-4623-8979-0A5586F693D6}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/21a41ecf-811d-fa63-35f8-2956ab7b29b5.png)

# 結果
|項目名|結果|備考
-----|----|----
変数の記法|△|文頭のa(Array)だけが残った
for文|〇|
if文|〇|



![{89561634-954E-43A1-A765-954B6A34432B}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/c74741e7-cdb1-c9ca-c395-cf83f3eb85b6.png)

## レビュー後のファイル
ファイル名は自分で変えました。
```review_after.html
<script>
    let ACompanyPrintersNumber = [];
    ACompanyPrintersNumber.push(5);
    ACompanyPrintersNumber.push(1000);

    for (let printer of ACompanyPrintersNumber) {
        if (printer > 10) {
            console.log(printer);
        }
    }

</script>

```


# 感想
割と満足した結果ですね。実案件でも使えそうな印象を受けました。
短時間でチェック漏れを探せるところが良いと思いました。

# 参考リンク

変数の記法について
https://blog.e2info.co.jp/2015/09/24/namingrules/


配列のfor文について
https://qiita.com/redrabbit1104/items/40f3e2aa6cd4361150ee

if文について
https://qiita.com/Nossa/items/3fb1f1e4c429cacd3365

githubコミット分
https://github.com/RYA234/laravel9_vite_vue3/commit/0363936989ef91598bcbf0d2983c5818d43bb1a2
PHP技術者初級認定試験のための基礎振り返り③

# ファイル操作
**1. ファイルの読み込み**
PHPでは、fopen、fread、fgets、file_get_contentsなどの関数を使用してファイルを読み込むことができます。

file_get_contents
file_get_contents関数は、ファイル全体を文字列として取得します。
```
<?php
  $filename = 'example.txt';
  $content = file_get_contents($filename);
  echo $content;
?>
```
**2. ファイルの書き込み**
ファイルにデータを書き込むには、fopen、fwrite、file_put_contentsなどの関数を使用します。

file_put_contents
file_put_contents関数は、ファイルにデータを書き込みます。ファイルが存在しない場合は新しく作成し、既存のファイルがある場合は上書きします。
```
<?php
  $filename = 'example.txt';
  $data = "こんにちは、PHP!";
  file_put_contents($filename, $data);
?>
```
**3. ファイルの追記**
既存のファイルにデータを追加するには、fopen関数でファイルをaモード（追記モード）で開き、fwrite関数を使用します。
```
<?php
  $filename = 'example.txt';
  $data = "\n新しい行を追加します。";
  $file = fopen($filename, 'a');
  fwrite($file, $data);
  fclose($file);
?>
```
# セッションとクッキー
**1. セッション**
セッションは、ユーザーごとに一時的なデータを保存するために使用します。セッションはサーバー側に保存され、セッションIDをクライアント側にクッキーとして送信します。

セッションの開始とデータの設定
```
<?php
  session_start(); // セッションを開始
  $_SESSION['username'] = 'taro'; // セッション変数に値を設定
  echo "セッションが設定されました。";
?>
```
セッションデータの取得
```
<?php
  session_start();
  echo "こんにちは、" . $_SESSION['username'] . "さん！";
?>
```
**2. クッキー**
クッキーは、ユーザーのブラウザにデータを保存するために使用します。クッキーはクライアント側に保存され、サーバーに送信されます。

クッキーの設定
```
<?php
  setcookie('username', 'taro', time() + 3600); // クッキーを1時間後に期限切れに設定
  echo "クッキーが設定されました。";
?>
```
クッキーの取得
```
<?php
  if (isset($_COOKIE['username'])) {
      echo "こんにちは、" . $_COOKIE['username'] . "さん！";
  } else {
      echo "クッキーは設定されていません。";
  }
?>
```
# データベース接続
**1. MySQLデータベースへの接続**
PHPでは、MySQLデータベースに接続するためにmysqli拡張モジュールを使用します。

データベースへの接続
```
<?php
  $servername = "localhost";
  $username = "root";
  $password = "";
  $dbname = "test_db";

  // 接続を作成
  $conn = new mysqli($servername, $username, $password, $dbname);

  // 接続をチェック
  if ($conn->connect_error) {
      die("接続失敗: " . $conn->connect_error);
  }
  echo "接続成功";
?>
```
**2. データの挿入**
データベースにデータを挿入するには、SQLのINSERT文を使用します。
```
<?php
  $sql = "INSERT INTO users (username, email) VALUES ('taro', 'taro@example.com')";

  if ($conn->query($sql) === TRUE) {
      echo "新しいレコードが作成されました。";
  } else {
      echo "エラー: " . $sql . "<br>" . $conn->error;
  }

  $conn->close();
?>
```
**3. データの取得**
データベースからデータを取得するには、SQLのSELECT文を使用します。
```
<?php
  $sql = "SELECT id, username, email FROM users";
  $result = $conn->query($sql);

  if ($result->num_rows > 0) {
      while($row = $result->fetch_assoc()) {
          echo "id: " . $row["id"]. " - Name: " . $row["username"]. " - Email: " . $row["email"]. "<br>";
      }
  } else {
      echo "0 件の結果";
  }

  $conn->close();
?>
```
**4. データの更新**
既存のデータを更新するには、SQLのUPDATE文を使用します。
```
<?php
  $sql = "UPDATE users SET email='new_email@example.com' WHERE username='taro'";

  if ($conn->query($sql) === TRUE) {
      echo "レコードが更新されました。";
  } else {
      echo "エラー: " . $sql . "<br>" . $conn->error;
  }

  $conn->close();
?>
```
**5. データの削除**
データベースからデータを削除するには、SQLのDELETE文を使用します。
```
<?php
  $sql = "DELETE FROM users WHERE username='taro'";

  if ($conn->query($sql) === TRUE) {
      echo "レコードが削除されました。";
  } else {
      echo "エラー: " . $sql . "<br>" . $conn->error;
  }

  $conn->close();
?>
```
TypeScriptで変数名に「URL」を使うな

## 理由

importしていなくてもNode.jsのURLクラスが自動的に使用されるから。

## 何があったのか

メールでURLを送る関数を細かい関数に切り出していた。そのとき、うっかりURLを引数で渡すのを忘れていた。そうしたらグローバルなURLクラスが勝手に使われて、以下のようなメールになってしまった。

```text
下記URLをご確認ください。
class URL {
  #context = new URLContext();
  #searchParams;
  #searchParamsModified;
// 省略
```

もともとのソース抜粋は以下。

```ts
const text = `
下記URLをご確認ください。
${URL}`
```

TypeScriptだから、不足している変数はエラーが出て気づけるだろうと思っていた自分が愚かでした。グローバルに使われる変数名は気をつけたほうが良いですね。他に危険な変数名ってどういうのがあるかな……。
PHP技術者初級認定試験のための基礎振り返り②

# 文字列操作
**1. 文字列の結合**
PHPでは、文字列の結合にドット演算子（.）を使用します。
```
<?php
  $firstName = "太郎";
  $lastName = "山田";
  $fullName = $firstName . " " . $lastName;
  echo $fullName; // 出力: 太郎 山田
?>
```
**2. 文字列の長さを取得する**
strlen関数を使うと、文字列の長さを取得できます。
```
<?php
  $str = "こんにちは";
  echo strlen($str); // 出力: 15 （マルチバイト文字はバイト数でカウントされます）
?>
```
**3. 部分文字列を取得する**
substr関数を使うと、文字列の一部を抽出できます。
```
<?php
  $str = "こんにちは、世界！";
  echo substr($str, 0, 5); // 出力: こんにちは
?>
```
**4. 文字列の検索と置換**
文字列の中の特定の部分を検索したり、置換したりするためにstrposとstr_replaceを使用します。
```
<?php
  $str = "私はPHPを学んでいます。";
  $position = strpos($str, "PHP");
  echo $position; // 出力: 3

  $newStr = str_replace("PHP", "プログラミング", $str);
  echo $newStr; // 出力: 私はプログラミングを学んでいます。
?>
```
# 配列操作
**1. 配列の作成とアクセス**
配列は複数の値を一つの変数に格納するためのものです。
配列には数値キーと連想キーの2種類があります。

数値キー配列
```
<?php
  $fruits = array("リンゴ", "バナナ", "オレンジ");
  echo $fruits[1]; // 出力: バナナ
?>
```
連想配列
```
<?php
  $person = array("名前" => "太郎", "年齢" => 25, "性別" => "男性");
  echo $person["名前"]; // 出力: 太郎
?>
```
**2. 配列の操作**
PHPには、配列を操作するための多くの関数があります。

要素の追加
```
<?php
  $fruits[] = "ブドウ"; // 配列の末尾に追加
?>
```
配列の結合
```
<?php
  $arr1 = array("リンゴ", "バナナ");
  $arr2 = array("オレンジ", "ブドウ");
  $result = array_merge($arr1, $arr2);
  print_r($result); // 出力: Array ( [0] => リンゴ [1] => バナナ [2] => オレンジ [3] => ブドウ )
?>
```
3. 配列の繰り返し処理
配列の各要素を繰り返し処理するためにforeach文を使用します。
```
<?php
  $fruits = array("リンゴ", "バナナ", "オレンジ");

  foreach ($fruits as $fruit) {
      echo $fruit . "<br>";
  }
?>
```
# フォームの処理
**1. フォームデータの取得**
PHPでは、HTMLフォームから送信されたデータを$_GETまたは$_POSTスーパーグローバル変数を使って取得します。
```
<form method="post" action="process.php">
  名前: <input type="text" name="name">
  <input type="submit" value="送信">
</form>
```
// process.php
```
<?php
  $name = $_POST['name'];
  echo "こんにちは、" . htmlspecialchars($name) . "さん！";
?>
```
**2. 入力の検証**
フォームデータを処理する前に、適切な検証を行うことが重要です。
```
<?php
  if ($_SERVER["REQUEST_METHOD"] == "POST") {
      $name = trim($_POST['name']);
      if (empty($name)) {
          echo "名前を入力してください。";
      } else {
          echo "こんにちは、" . htmlspecialchars($name) . "さん！";
      }
  }
?>
```
# エラー処理
**1. 基本的なエラー処理**
PHPでは、エラーが発生した場合に表示するエラーメッセージを制御するために、try-catch構文を使用します。
```
<?php
  function divide($a, $b) {
      if ($b == 0) {
          throw new Exception("ゼロで割ることはできません。");
      }
      return $a / $b;
  }

  try {
      echo divide(10, 0);
  } catch (Exception $e) {
      echo "エラー: " . $e->getMessage();
  }
?>
```
**2. カスタムエラーハンドラ**
独自のエラーハンドラを作成して、エラー処理をカスタマイズすることができます。
```
<?php
  function customError($errno, $errstr) {
      echo "エラー: [$errno] $errstr<br>";
  }

  set_error_handler("customError");

  echo($test); // 変数が定義されていないためエラーが発生
?>
 ```
console.logで[Object]が出たとき

## 背景

```
console.log(value);
→[object Object]
```

こういうことが多々あるが、中身を見たい。

## いろんな解法

```:中身を文字列化する
console.log(JSON.stringify(value));

{"name":"hogehoge","discription":"paopao"}
```


```:console.dirでJSONの中身を確認する
console.dir(value);

{"name":"hogehoge","discription":"paopao"}
```

次のが一番かっこいいかも。

```:util.format
console.log('%o', obj);

{"name":"hogehoge","discription":"paopao"}
```

## お疲れ様でした。
わからないところ、間違っているところ、もっといい方法がある場合は、コメントでもDMでも教えてください。
PHP技術者初級認定試験のための基礎振り返り

# PHPとは何か
PHPは「Hypertext Preprocessor」の略で、動的なウェブページを生成するためのサーバーサイドスクリプト言語です。PHPはHTMLに埋め込んで使用でき、データベースと連携することで、インタラクティブなウェブアプリケーションを作成することが可能です。

# PHPの基本構文
***1. PHPタグ***
PHPコードは<?phpと?>の間に記述します。以下は基本的なPHPタグの例です。
```
<?php
  echo "Hello, World!";
?> 
```
**2. 変数とデータ型**
PHPでは、変数は$記号で始まります。変数に値を代入することで使用します。PHPの主なデータ型には以下のようなものがあります。

整数型 (integer): 整数値を扱います。
浮動小数点型 (float): 小数点を含む数値を扱います。
文字列型 (string): 文字列を扱います。
配列型 (array): 複数の値を一つの変数に格納します。
ブール型 (boolean): trueまたはfalseの値を持ちます。
例：
```
<?php
  $integer = 10;
  $float = 10.5;
  $string = "PHP入門";
  $array = array("リンゴ", "バナナ", "オレンジ");
  $boolean = true;

  echo $string;
?>
```
**3. 演算子**
PHPでは、数値や文字列の操作に使用する演算子がいくつかあります。主な演算子には以下のようなものがあります。

算術演算子: +, -, *, /, %
比較演算子: ==, !=, >, <, >=, <=
論理演算子: &&, ||, !

**4. 制御構文**
PHPでは、プログラムの流れを制御するために、条件分岐やループ構文を使用します。

if文
条件に応じてコードを実行する場合に使用します。
```
<?php
  $age = 20;

  if ($age >= 18) {
      echo "あなたは成人です。";
  } else {
      echo "あなたは未成年です。";
  }
?>
```
for文
指定回数だけコードを繰り返し実行する場合に使用します。
```
<?php
  for ($i = 0; $i < 5; $i++) {
      echo "数値: $i <br>";
  }
?>
```
while文
条件がtrueの間、コードを繰り返し実行する場合に使用します。
```
<?php
  $i = 0;

  while ($i < 5) {
      echo "数値: $i <br>";
      $i++;
  }
?>
```
関数
関数は、特定の処理をまとめて再利用可能にするためのブロックです。PHPには組み込み関数が多数用意されていますが、自分で関数を定義することもできます。
```
<?php
  function greet($name) {
      return "こんにちは、" . $name . "!";
  }

  echo greet("太郎");
?>
```
PythonでExcelファイルの指定した行や列を削除する

Excelファイルは、データ処理や分析の分野で一般的なデータ保存形式であり、Pythonでこれらのファイルを操作することで、データ科学者やアナリストに大きな柔軟性を提供します。 Pythonを使用することで、ユーザーはより快適にデータセットを管理し、その正確性とデータ分析への適合性を確保することができます。 この記事では、**Python**を使って**Excelファイルから特定の行や列を効率的に削除する方法**について説明します。

この記事で使用する方法には、[Spire.XLS for Python](https://jp.e-iceblue.com/introduce/spire-xls-for-python.html)が必要です。PyPIからインストール: `pip install Spire.XLS`。

[無料ライセンスの申請](https://www.e-iceblue.com/TemLicense.html)

## Excelの行と列を削除するために使用するクラスとメソッド：
- `Workbook` クラス: ワークブックを表します。
- `Worksheet` クラス: ワークシートを表します。
- `Worksheet.DeleteRow(rowIndex)` メソッド: 指定した行をインデックスで削除します（行インデックスは1から開始）。
- `Worksheet.DeleteColumn(columnIndex)` メソッド: 指定した列をインデックスで削除します（列インデックスは1から開始）。
- `Worksheet.DeleteRow(startRowIndex, rowCount)` メソッド: 開始行インデックスと削除する行数を指定して、複数行を一度に削除します。
- `Worksheet.DeleteColumn(startColumnIndex, columnCount)` メソッド: 開始列インデックスと削除する列数を指定して、複数列を一度に削除します。
- `Worksheet.Row[rowIndex].IsBlank` プロパティ: 指定した行が空白かどうかを判断します。
- `Worksheet.Column[columnIndex].IsBlank` プロパティ: 指定した列が空白かどうかを判断します。

## PythonでExcelファイルの指定行または指定列を削除する
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbook オブジェクトを作成
workbook = Workbook()
 
# Excel ファイルを読み込む
workbook.LoadFromFile("Example.xlsx")
 
# 最初のワークシートを取得
sheet = workbook.Worksheets[0]
 
# 5行目を削除
sheet.DeleteRow(5)
 
# 3列目を削除
sheet.DeleteColumn(3)
 
# 結果ファイルを保存
workbook.SaveToFile("Result.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

## PythonでExcelファイルの複数行または複数列を削除する
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbook オブジェクトを作成
workbook = Workbook()
 
# Excel ファイルを読み込む
workbook.LoadFromFile("Example.xlsx")
 
# 最初のワークシートを取得
sheet = workbook.Worksheets[0]
 
# 3〜7行（計5行）を削除
sheet.DeleteRow(3, 5)
 
# 4列目と5列目を削除
sheet.DeleteColumn(4, 2)
 
# 結果ファイルを保存
workbook.SaveToFile("Result.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

## PythonでExcelファイルの空白行または空白列を削除する
```python
from spire.xls import *
from spire.xls.common import *
 
# Workbook オブジェクトを作成
workbook = Workbook()
 
# Excel ファイルを読み込む
workbook.LoadFromFile("Example.xlsx")
 
# 最初のワークシートを取得
sheet = workbook.Worksheets[0]
 
# 空白行を削除
for i in range(sheet.Rows.Length - 1, -1, -1):
    if sheet.Rows[i].IsBlank:
        sheet.DeleteRow(i + 1)
 
# 空白列を削除
for j in range(sheet.Columns.Length - 1, -1, -1):
    if sheet.Columns[j].IsBlank:
        sheet.DeleteColumn(j + 1)
 
# 結果ファイルを保存
workbook.SaveToFile("Result.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

---

> これらの3つの例を通じて、我々はPythonを使用することができますExcelの単一の行や列を削除するには、複数の行や列だけでなく、さまざまなシナリオのニーズを満たすために、空白の行や列を削除します。 
また、Python用Spire.XLSはまた、生成、読み取り、編集、Excelファイルやその他の操作を変換するために完了することができます、[Spire.XLS for Pythonチュートリアル](https://www.e-iceblue.com/Tutorials/Python/Spire.XLS-for-Python/Program-Guide/Spire.XLS-for-Python-Program-Guide-Content.html)を参照してください。
自転車に乗っていたら同じ型の別の自転車を盗みかけた話　～ティンプルキーでも怖いことがある～

# 注意
割とnoteでいいだろ、という内容なのだが、Qiitaのアカウントを作る口実として今日起こったことを共有したい。

『本来の使い方じゃないだろ』というのは百も承知なので読み飛ばしてもらっても構わない。次に投稿する記事はちゃんとした技術系記事になるはずだ。たぶん多倍長演算とか円周率の算出とかそういうものになるだろう。

# 本筋
最近札幌に引っ越し、この10月から社会人になる。これを機に電動自転車を購入することにした。

Panasonicのビビ(ViVi)。コイツである。

https://cycle.panasonic.com/products/eb_shopping.html

かご付きの電動アシストなら何でもよかったのだが、電動なら信頼の置けるメーカーにしようとPanasonicにした。知人にPanasonicのオタクがいるからである。

さて、コイツは普通に使い心地が良い。それは疑いない。スタンドを停めていると前輪のハンドルがロックする仕様になっていて、駐輪場が屋内にあって狭いことが多い北海道では少し不便だが、快適に利用している。

ところが今日、コイツを使っていて事件が起きた。

# インシデント
お医者様からもらっている『睡眠・覚醒リズム表』の日常行動に、「コメダに行った」と完了形で書いてからこの自転車でお出かけをした。ホットサンドの類いが喰いたかったからである。

札幌市内の狸小路に向かい、市営の駐輪場に自転車を駐めた。手早く買い物と食事を済ませて「割と満足したな」と思って駐輪場に戻り、自分の自転車を探した。

まだ購入してから日が経っていないので、目印になるようなものもつけておらず少し迷ったが、二分ほどで見つけた。自分のものと同じ、黒いビビである。

鍵を入れてひねる。普通に開く。この時点では自分の自転車だと思っているのだから特に気にせず駐輪場を出た。

が、「ヨシ帰るか」と自転車にまたがったところで違和感に気づく。

- いつも常にギアを三速に入れっぱなしにしているのに一速になっている
- サドルがいつもより高い
- 警告鈴の位置が微妙に違う

しかし、バッテリー残量は同じ70％。それにそもそも鍵が開いているのである。最初は自分がメシを喰っているちょっとの間パクられていたのかと思った。

だが、だんだん違和感に怖くなって自転車から降りると、ほぼ新品のはずなのにほんの少し錆がついていることに気づいた。こうなるともう居ても立ってもいられず、駐輪場の前に一旦その自転車を駐めて鍵を掛け(鍵はちゃんとかかった)、中に私だけ入って駐めたような記憶のある場所をもう一回探す。

# 全く同じ型のビビがもう一台あった
どう見てもほぼ新品でバッテリー残量70％の同じビビがもう一台あったのだ。

(まさかな……)と思って手に持った鍵をさして回す。

開いた。そして締まった。

慌てて外に駐めた赤の他人のビビの下へ戻り、もう一度鍵を回す。難なく開いた。

自分が一瞬自転車泥棒になりかけていたことに気がついて、背筋が寒くなった。

# 事後処理
「これ警察か駐輪場の管理者に言うべきか？」と悩んだのだが、ともかく一旦ちゃんと自分のものであることを確認してから帰宅した。

幸い防犯登録番号の確認が取れたので、自分のものである証明は帰宅後にできた。

そして、「同じ型の自転車であれば同じ鍵で開いてしまう」なんてガバ仕様がホントにあるのか？と調べてみた。

# 自転車の鍵が同一であることはあるのか
結論から言うと、かなりよくあるようだ。
一番信頼の置けそうな事例を参考に貼っておく。

https://bbs.bengo4.com/questions/454646/

ここまでだと「調べてみました！いかがでしたか？」状態なので、もう少し深く考えてみる。

# 同一のティンプルキーが存在する
私の購入したビビは単純なティンプルキータイプなのだが、構造がかなり簡素で大・中・小のくぼみが7カ所に配置されている。リバーシブルな鍵なので裏面も同じプリントだ。

となると存在しうる鍵のパターンは単純に計算して3^7通り、つまり2187通り。結構少ない。実際は全部小とか全部大のような複製しやすすぎる鍵は作っていないだろうが、街中の駐輪場は大体数百台の自転車が駐まっているのだから鍵の構造を共通にしている自転車が二つ出現することも大いにあり得る。

今回は自転車の型や色まで同じという偶然が重なったが、量産されている人気の自転車で同じような事象に遭遇する例は充分ある。

ティンプルキーが本来防犯性が高いとされるのは、くぼみを打つ配置が非常に多岐にわたるからだ。家用の鍵などであれば同じくぼみでも配置がほんの少しずれるだけで開かない、という風に偽造しにくい鍵になるわけだ。

ただ、どうも今回の自転車の鍵は場所が7カ所で固定されている(ようにみえる)。ぶっちゃけ2188本鍵を作ればあっさり突破できるので、ティンプルキーの強みが全くない鍵のようだ。

家と自転車では防犯価値も量産性も違うから構造が簡素化されているのかもしれないが、自分の手元にあるティンプルキーがちゃんと防犯性の高いティンプルキーであるか、一度真面目に観察する必要がありそうだ。

# おまけ

![IMG_7114.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3890732/efa59c06-24af-d118-97b2-4768061065b0.jpeg)
コメダ珈琲の月見バーガーである。おいしかった。
【Jest】テスト作成の過程で感じた難しさ

# はじめに
Jestを使ったテスト作成は、最初はとっつきにくいものだと思います。テストって一体何？何をすればテストになるの？そんな疑問を抱く方も多いのではないでしょうか。今回は、Jestを使ったテスト作成で私が苦労した点についてく解説していきます。

# テストってそもそも何？
テストとは、プログラムが意図通りに動作しているかを確認する作業です。例えば、計算機アプリなら、足し算や引き算が正しく実行されているか、入力された値が適切に処理されているかを確認します。

# テストが必要な理由
テストを行うことで、以下のメリットが得られます。
+ ***バグの早期発見***
開発の早い段階でバグを発見できるため、修正コストを削減できます。

+ ***コードの品質向上***
テストに合格するためには、コードの品質を高める必要があり、その結果、全体の品質が向上します。

# Jestでテストを書くのはなぜ難しいと感じたのか？
私がJestでテストを書く際に苦労した点は、以下の3つです。
+ ***テストが抽象的でイメージしにくい***
テストは目に見えない作業であるため、何をやっているのかが把握しづらく、モチベーションが下がることがありました。

+ ***フロントエンド開発とのギャップ***
画面に表示される要素を作るフロントエンド開発に比べ、テストは裏側のロジックを検証するため、面白みに欠けると感じていました。

+ ***毎日やっても理解が進まない***
テストは一度理解すれば簡単ですが、最初の壁が高く、毎日続けてもなかなか理解が進まないという焦りがありました。

例えば、次のコードは、タイトルが表示されているかを確認する簡単なテストです。初めの頃は、これがどうしてタイトルの存在を確認するテストになるのか、理解できませんでした。
```javascript
describe("App", () => {
  test("タイトルがあること", async () => {
    render(<App />);
    await waitFor(() => {
      screen.getByTestId("table");
    });
    const title = screen.getByTestId("title");

    expect(title).toBeInTheDocument();
  });
});
```

# Jestを学ぶ上で役立ったこと
Jestを学ぶ上で最も役立ったのは、公式ドキュメントを徹底的に読み込むことでした。Jestの機能や書き方、さまざまなケースでの活用方法が詳細に記載されており、疑問点が生じた際もすぐに解決できました。

また、とにかく多くのテストを書いてみることも非常に有効でした。テストを書くことで自然とその書き方に慣れ、次第に「テストの書き方自体はそこまで多くない」と感じるようになりました。数をこなすことで、テストを書くことへの抵抗感が減り、徐々にテスト作成が日常の一部となりました。

特に、例題を見ながら実際にコードを書いてみることで、より深く理解できました。


# 終わりに
Jestを使ったテスト作成は、最初は難しく感じるかもしれませんが、継続して学習すれば必ず習得できます。テストを書くことは単なる作業ではなく、コードの品質を向上させるための重要なステップです。

私自身、Jestについて2〜3週間学習しましたが、最後まで諦めずに取り組んで本当に良かったと思っています。最初は理解に苦しむこともありましたが、続けることで徐々にコツを掴み、今ではテストを書くことに少し自信がつきました。

私にもできたので、皆さんも必ずできると思います。最初は難しく感じるかもしれませんが、少しずつ慣れていけば、テスト作成が楽しくなってくるはずです。この記事を参考に、ぜひJestを使ったテスト作成に挑戦してみてください。
yukicoder No.2621 Fee Schedule 解説

[問題文](https://yukicoder.me/problems/no/2621)

# 解説
答えは $\min(A\times C,B)$ となる。
このような数を求めるときは min関数を用いるとよい。
```C++
min(a,b)
```
このように書けば、 $a$ と $b$ のうち小さいほうを返してくれる。

# 解答例
```C++
#include <bits/stdc++.h>
using namespace std;

int main() {
  int a,b,c;cin>>a>>b>>c;
  cout<<min(a*c,b)<<endl;
}
```
yukicoder No.2607 Add One Digit 解説

[問題文](https://yukicoder.me/problems/no/2607)

# 解説
setを使った方針で進めていく。
$N$ を文字列にして入力しておいて、毎回insertする（stringのinsert関数についてはここでは説明しない）。
setでこれまでの操作でできた文字列をinsertしていけば、答えはsetのsizeとなる。
$N$ の桁数を $K$ としたとき、stringのinsertがボトルネックとなり $O(K^2)$ で求まる。
なお、実装時には先頭が0であるような文字列を候補に入れないことに注意。

# 解答例
```C++
#include <bits/stdc++.h>
using namespace std;

int main(){
  string n;cin>>n;
  set<string> ans;
  for(int i=0;i<=n.size();i++)
    for(int j=(i==0);j<10;j++){
      string s=n;
      s.insert(s.begin()+i,j+'0');
      ans.insert(s);
    }
  cout<<ans.size()<<endl;
}
```
AWS Transfer Family SFTPで使用される暗号化アルゴリズムと決定プロセス

# 確認したい内容
Transfer FamilyでSFTP通信をする際、使用される暗号化アルゴリズムとその決定プロセス

# 構成
![sftp01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/645debe2-cbfc-a0ff-73de-5ce69ac26716.png)

* SFTPサーバを作成する。
* SFTPサーバは内部接続とするため、VPCエンドポイントが作成される。
* SFTPサーバ内にマネージドユーザとしてsftp_userを作成する。
* sftp_userにロジカルディレクトを使用してS3のフォルダを割り当てる。
* EC2サーバ内でSSHのキーペア(keyとkey.pub)を作成する。
* sftp_userに公開鍵(key.pub)を登録する。

EC2から`sftp -v -i key sftp_user@xxxx.vpce.amazonaws.com`コマンドを実行しTransfer Family経由でS3に接続する。

# SFTP通信の流れ
最初にSFTP通信の流れを確認します。（SSH情報のバージョン交換等一部の処理を割愛して記載しています。）

![sftp003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/e9dd9b74-2d33-8c45-7995-1072a3289342.png)

②③④でクライアント側、サーバ側で利用可能な暗号化アルゴリズムを比較しクライアント側の優先順位によって利用する暗号化アルゴリズムを決定します。暗号スイート（SshCiphers）、鍵交換アルゴリズム（SshKexs）、メッセージ認証コード（SshMacs）の3つを決定します。鍵交換アルゴリズムは緑色の箇所、暗号スイートとメッセージ認証コードは赤色の箇所で使用されます。


# Tranifer Familyサーバ側の設定
サーバのセキュリティポリシーの設定で使用する暗号化アルゴリズムを制限することが可能です。

https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/security-policies.html

TransferSecurityPolicy-2024-01のSshCiphersの箇所を抜粋、暗号化スイートでは下記5つが使用可能です。

```
{
    "SecurityPolicy": {
        "Fips": false,
        "SecurityPolicyName": "TransferSecurityPolicy-2024-01",
        "SshCiphers": [
            "aes128-gcm@openssh.com",
            "aes256-gcm@openssh.com",
            "aes128-ctr",
            "aes256-ctr",
            "aes192-ctr"
        ],
```

# クライアント側の設定

Amazon Linux 2023の例です。Ciphersの箇所を抜粋、見やすいように改行していますが実際のファイルは改行はありません。最初に書いてあるものほど優先度が高いです。

```shell
# cat /etc/crypto-policies/back-ends/openssh.config
Ciphers
aes256-gcm@openssh.com,
chacha20-poly1305@openssh.com,
aes256-ctr,
aes128-gcm@openssh.com,aes128-ctr
```

# アルゴリズム決定のプロセス

`sftp -v`でデバックした際の情報の一部抜粋です。
クライアント側とサーバ側で共通する暗号化スイートの内、クライアント側で優先度が高い`aes256-gcm@openssh.com`が選択されていることが分かりました。

```shell
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: rsa-sha2-512
debug1: kex: server->client cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none
debug1: kex: client->server cipher: aes256-gcm@openssh.com MAC: <implicit> compression: none
debug1: kex: curve25519-sha256 need=32 dh_need=32
debug1: kex: curve25519-sha256 need=32 dh_need=32
debug1: expecting SSH2_MSG_KEX_ECDH_REPLY
debug1: SSH2_MSG_KEX_ECDH_REPLY received
```

# 確認方法
SFTPサーバの接続情報はCloudWatchログに記録されます。下記のログから使用している暗号アルゴリズムの確認が可能です。

```
{
    "role": "●●●",
    "activity-type": "CONNECTED",
    "macs": "<implicit>,<implicit>",
    "ciphers": "aes256-gcm@openssh.com,aes256-gcm@openssh.com",
    "client": "●●●",
    "source-ip": "●●●",
    "resource-arn": "●●●",
    "home-dir": "LOGICAL",
    "user": "●●●",
    "kex": "curve25519-sha256",
    "session-id": "●●●"
}
```
【Google Cloud】社内セキュリティでRDPが禁止されている場合のGCEへの接続方法

# はじめに
Google Cloud上にWindowsサーバを構築し、リモートデスクトップを試みた際、社内のFWでブロックされ接続に失敗する事象が発生しました。FWの穴あけには時間を要するため、他の手段を考えなければいけません。

あなたならどのような方法で対処しますか？


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665293/6eb352a4-df0f-41f2-396f-ddfe2a18540e.png)


# SSHポートフォワーディングの利用
対応方法としてSSHポートフォワーディングの利用が考えられます。

SSHポートフォワーディングとは、SSHによる安全なトンネルを通じて、指定したポートを利用しトラフィックを転送する技術です。

ローカルポートフォワーディング、リモートポートフォワーディング、ダイナミックポートフォワーディングの3種の接続方式が存在しますが、今回はローカルポートフォワーディングを利用します。これは接続元であるローカル端末の指定ポートから、SSH接続先の指定ポートに通信を転送する手法です。

構成イメージとして、ローカル端末と接続ターゲットのWindows Server間に新たにサーバを追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665293/36efb12f-0c97-82de-4f1a-f0a033052ae8.png)

本構成に関する前提条件は以下の通りです。
- 社内FWでSSH(TCP22)が禁止されていない
- サーバA-B間に疎通性があり、サーバAからサーバBに対するRDP(TCP3389)が許可されている
- サーバAにてSSH接続用の公開鍵と秘密鍵が作成されており、秘密鍵がローカル端末側に保存されている

# 設定方法
まずローカル端末からPowerShellを開きサーバAにSSH接続し、RDP用ポートをフォワードします。これにより、サーバA経由でサーバBにRDP接続が可能になります。

~~~ bash
ssh -L 13389:<サーバBの内部IPアドレス>:3389 -i <ローカル端末内の秘密鍵の保存パス> <ユーザ名>@<サーバAの外部IPアドレス> 
~~~
- `-L` オプションでローカル端末のポート`13389`を、踏み台を経由して接続先のポート`3389`に転送します
※ローカル端末用のポート`13389`は、ユーザーポート(1024～49151)の中で未割当のものであれば変更可能です
- `-i`オプションで秘密鍵のファイルを指定します

次にローカル端末からリモートデスクトップを開き、`localhost:13389`と入力し接続します。RDPの接続に必要なユーザ名／パスワードは以下の方法をもとに設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3665293/ebe36086-d269-8f97-af57-a94a2c39f003.png)


これで接続できるはずです。

# 終わりに
いかがだったでしょうか。セキュリティポリシーが原因で本来意図していた通信が阻まれるケースは多々あります。今回の構成案をもとに解消のお役に立ていただければ嬉しいです。

# 参考
https://tech-lab.sios.jp/archives/37377

https://dev.classmethod.jp/articles/rdp-via-bastion-server/

https://zenn.dev/apo_zenn/articles/188e2c16be902e

https://qiita.com/gc_garden/items/76208ee60e934c1aa439
yukicoder No.2599 Summer Project 解説

[問題文](https://yukicoder.me/problems/no/2599)

# 解説
$S,T$ の文字列によって場合分けするという方法で解ける。
```C++
//初見で解いたときのコード抜粋
#include <bits/stdc++.h>
using namespace std;

int main(){
  string s,t;cin>>s>>t;
  if(s=="watermelon"&&t=="beachball")cout<<"shrinebell\n";
  else if(t=="watermelon"&&s=="beachball")cout<<"shrinebell\n";
  else if(s=="watermelon"&&t=="shrinebell")cout<<"beachball\n";
  else if(t=="watermelon"&&s=="shrinebell")cout<<"beachball\n";
  else cout<<"watermelon\n";
}
```
これで終わりです。
しかし、場合によってはいっぱい場合分けを書くのが面倒という人がいると思う（実際いると思ってる）。
この場合、 **辞書順で $S>T$ となれば、$S$ と $T$ をswapしてしまう**というすれば場合分けを $3$ つに減らすことができる。これなら、実装が少し楽になるのではないだろうか。

# C++での解答例
```C++
#include <bits/stdc++.h>
using namespace std;

int main(){
  string s,t;cin>>s>>t;
  if(s>t)swap(s,t);
  if(s=="beachball"&&t=="watermelon")cout<<"shrinebell\n";
  else if(s=="shrinebell"&&t=="watermelon")cout<<"beachball\n";
  else cout<<"watermelon\n";
}
```
【Android】Firebaseメール認証でメールリンクが開けない

Firebase 認証で Android アプリに **メールリンク認証** 機能を導入したのですが
メールに送られた認証リンクをクリックすると
**「Invalid Dynamic Link - Blocked」** というエラーがブラウザ上で表示され
アプリが起動しませんでした。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/385759/af1276e5-6c84-75c3-d861-d481caa2573d.png">


エラーにはドメインをホワイトリストに登録してくださいとのメッセージだったので
[メールリンクの設定](https://qiita.com/jozuko_dev/items/bf343ba3f2b37a0184be#firebaseauth%E3%81%AE%E3%83%A1%E3%83%BC%E3%83%AB%E3%83%AA%E3%83%B3%E3%82%AF%E3%82%92%E6%9C%89%E5%8A%B9%E5%8C%96%E3%81%97%E3%81%BE%E3%81%99)や[ホワイトリストの登録](https://qiita.com/jozuko_dev/items/bf343ba3f2b37a0184be#authentication%E3%81%ABwhitelist%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%99)などは完了済みで
マニフェストで[intent-filter](https://qiita.com/askldfghj/items/f7f2a93da657c0614b5c)設定も正確にやったつもりでした。

https://qiita.com/jozuko_dev/items/bf343ba3f2b37a0184be#authentication%E3%81%ABwhitelist%E3%83%89%E3%83%A1%E3%82%A4%E3%83%B3%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%97%E3%81%BE%E3%81%99

### 解決策
結果的に、`intent-filter` に次の一文を追加して、リンクの自動検証を有効にする事で解決いたしました。

```xml
<intent-filter android:autoVerify="true">
```
https://stackoverflow.com/questions/73687138/firebase-dynamic-link-not-working-with-android-12
RDS for PostgreSQLへのOrafceの導入方法

## はじめに
RDS for PostgreSQLでOrafceを使えるようにするには公式の記事の方法だけではできなかったので私なりの導入手順を載せようと思います。

[**AWS公式の記事**](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Appendix.PostgreSQL.CommonDBATasks.Extensions.html)

## 原因
Orafceを導入した際に作成されるOracleスキーマにsearch_pathがsetされていなかった。

## 手順1
まず、上記のAWS公式の記事を参考に以下の手順を行ってください。
* Orafce拡張機能オン
* Oracleスキーマの所有者へrds_superuserロールを付与

ロールが付与できたか確認するには以下のコマンドを実行してください。
```言語:権限確認
コード
```SELECT roleid::regrole, member::regrole					
					
db-> FROM pg_auth_members					
					
db-> WHERE member = 'Orafce_user'::regrole					
					
db-> AND roleid = 'rds_superuser'::regrole;					
					
roleid | member					
					
---------------+-------------					
					
rds_superuser | orafce_user					
					
(1 行)
```
## 手順２
ここからは公式の記事には載っていなかった内容です。
まずは現在の環境変数を確認します。
```
db=> SHOW search_path;		
   search_path		
-----------------		
 "$user", public		
(1 行)		
```
RDSではデフォルトで環境変数がpublicになっているようです。
また、$userがありますが、これはログインしたユーザーと同じ名前のスキーマをまずは検索するように設定されたものです。

ここにOracleスキーマを加えたいのです。
以下の様にセットしていきます。
```
db=> set search_path to "$user", oracle;					
SET					
db=> SHOW search_path;					
            search_path					
-----------------------------------					
 "$user", oracle					
(1 行)
```
これで環境変数にOracleスキーマのパスを設定できました。

## 稼働確認
稼働確認にはDUALテーブルが使えることを確認できればいいので、以下の様にクエリを打ってください。
```
db=> SELECT * FROM dual;
 dummy
-------
 X
(1 行)
```
実行結果がこのようになれば成功です。
OrafceはOracleのシステムテーブルDUALを模倣して提供されたものらしく、Oracleではよく使われる仮想テーブルなので上記の方法でDUALテーブルを使えることが確認できれば、無事Orafceの導入が完了ということになります。

また念には念を、、、
以下の様にoracle特有のデータ型を持ったテーブルが作成できるか試してみます。
```
db=> CREATE TABLE emp(emp_id NUMERIC, first_name VARCHAR2(30), last_name NVARCHAR2(30), birth_date DATE);												
CREATE TABLE												
												
db=> \d emp												
(省略）
------------+-----------------+---------------------------+-------------------+------------------------------												
 emp_id     | numeric         |                           |                   |												
 first_name | varchar2(30)    |                           |                   |												
 last_name  | nvarchar2(30)   |                           |                   |												
 birth_date | date            |                           |                   |				
 ```
 結果がこのように、Postgresqlがサポートされていないデータ型を持ったテーブル作成できていたらorafceが使えているという事になります！
[Git] fatal: repository 'https://github.com/xx/' not foundの対処法

# まえがき（という名のわたくしごと）
はじめてQiitaとMarkDownを使ってみました。なのでエンジニアの方たちからすると凄く汚い記事になっていると思います。が、自分の成長のためにも忘備録がてら書いてみようと思います。
マサカリや指摘コメントしてくれるとすごくうれしいです。

# 詳細
該当コマンド↴
```
git push origin master
```
エラー↴
```
remote: Repository not found.
fatal: repository 'https://github.com/名前/リポジトリ/' not found
```

# 解決方法
ChatGPTに聞いてみると 
- エラーが発生する理由は適切なアクセス権を持っていないから
- エラーを抑えるにはトークンを取得してURLにセットすればよい
らしい
### 手順

**アクセストークンの作成方法**


1. [**GitHub**](https://github.com/)にログインする。
2. 画面右上の自分のアイコンをクリックし、**Settings** を選択する。
3. 左側のメニューで **Developer settings** を選択し、その中の **Personal access tokens** → **Tokens (classic)** をクリックする。
4. 右上の**Generate new token** → **Generate new token (classic)** をクリックする。
4. repo スコープを選択する。
5. **Generate token** をクリック
6. トークンをコピーして保存する。（後で再表示できないためテキストファイル等にまとめておくと安心）

:::note warn
トークンは二度と表示できません。(多分)
:::

:::note alert
5の**Expiration**はトークンの有効期限です。有効期限を過ぎたら使えなくなります。
:::


**GitBash**で以下コマンドを実行します。

```
git remote set-url origin https://なまえ:とーくん@github.com/リポジトリ所有者/リポジトリ名.git
```
**なまえ**にはユーザー名が、**とーくん**には先ほどのトークンが、**リポジトリ所有者**にはリポジトリ所有者のユーザー名が入ります。
例：　ユーザー名=hoge_tarou; トークン=ghp_abcdefg;　リポジトリ所有者のユーザー名=fuga_joshi;

```
git remote set-url origin https://hoge_tarou:ghp_abcdefg@github.com/fuga_joshi/リポジトリ名.git
```

あとはgit push origin master等のお好きなコマンドを打てばおkです
GitHubからデスクトップ通知を受け取る方法(2選)


### はじめに

私はこれまでGitHubからの通知をメールとGitHub Mobileで受け取り、携帯のプッシュ通知で毎回気づいていました。しかしこれでは、携帯を見るまでプッシュ通知に気づくことができません。

私が実現したいのは、**デクトップでリアルタイムに通知を受け取ること**でした。

方法について先に知りたい方は、[こちら](#導入したこと)

### 検討したこと

#### Slack連携

https://zenn.dev/easy_easy/articles/298c9728e01819db9f50

こちらの記事に詳しく書かれています。
これはチームで管理する通知としては最適化されていますが、個人向きではありません。

#### Chrome拡張機能

https://qiita.com/hisw/items/fc271b3186aacfad0820

こちらの記事で紹介されていました。
とても良いプロダクトだと感じたのですが、個人開発なためメンテナンスに不安がありました。

### 導入したこと

#### 1. Gitify

https://www.gitify.io/

OAuth経由で設定するとOrganisationによってはそれが許可されていない場合があるので、Private Access Token (PAT) を使って設定するとよいです。

#### 2. mailアプリのデスクトップ通知

https://support.google.com/a/users/answer/9308767?hl=ja#:~:text=Gmail%20%E3%82%92%E9%96%8B%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82&text=%5B%E3%81%99%E3%81%B9%E3%81%A6%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E8%A1%A8%E7%A4%BA,%E4%BF%9D%E5%AD%98%5D%20%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

メールには通知が送られるので、送信内容をデスクトップ通知に表示すれば実現できます。
私はGmailで受けとているので、上記を参考に設定しました。
また、ラベル付けをしてフォルダ管理すると他のメールと混合しないのでおすすめです。

### さいごに

Gitifyとメールのデスクトップ通知のどちらかを設定することで満たしたいことを実現できました🙌
GitHubの通知に困っている方はぜひ試してみてください。
RubyMineで複数のプロジェクトを接続した後、不要になったプロジェクトの接続を解除したいけど、うまくいかない。

# RubyMineでプロジェクトの接続を解除する方法

## 問題
RubyMineで複数のプロジェクトを接続した後、不要になったプロジェクトの接続を解除したいけど、うまくいかない。


## 解決法

1. RubyMineを開く
2. 画面左側の「プロジェクト」ビュー（ファイルツリーが表示されている部分）を確認
3. 接続を解除したいプロジェクトを右クリック
4. 表示されたメニューから「プロジェクトビューから除去」を選択

これだけで簡単にプロジェクトの接続が解除できます。

注意点：この操作はプロジェクトをRubyMineから切り離すだけで、実際のファイルは削除されません。ファイルシステム上にはそのまま残っているので、必要になったら再度開くことができます。

## 補足

プロジェクトを接続すると、同じウィンドウ内で複数のプロジェクトを切り替えて操作できるので非常に便利です。特に関連するプロジェクトを同時に扱う際に重宝します。

ただ、プロジェクトが増えすぎると管理が煩雑になることもあるので、適度に整理するのがおすすめです。今回紹介した方法を使えば、すぐに整理整頓できますよ。

## 参考

この解決方法は、JetBrainsの公式コミュニティフォーラムの投稿を参考にしています。
詳細は[こちら](https://intellij-support.jetbrains.com/hc/en-us/community/posts/360010593499-opposite-of-attach-project)をご覧ください。
macOS Sequoia（セコイア）にアップデートしたらGitが動かなくなった件


macOS Sequoia（セコイア）にアップデートしたらGitが動かなくなった

...こんなタイトルで毎回macOSのアップデートごとに書いてる気がします。

> ![](https://i.gyazo.com/3b93f985a2d0365bc175ad48d6d3ad34.png)

```
git
You have not agreed to the Xcode and Apple SDKs license. You must agree to the license below in order to use Xcode.
```

> ![](https://i.gyazo.com/f105caad98afc6e3d301d8341922e1c9.png)


ということでXcode開いてライセンス許諾してねって感じです。

Xcodeを開いてみると確かに許諾が

> ![](https://i.gyazo.com/57f57867b76d7fddeba7946e26a2acf9.png)

`Agree`を押して進めてOK。

無事にGitが使えるようになりました。
3D プリント材料に関するポピュラーサイエンス: 素材の「ファッションショー」

新しい 3D プリンターを入手し、自分のスキルを披露する準備ができたとき、次の疑問が生じます。それを印刷するにはどのような素材を使用する必要がありますか?ファッション デザイナーが生地を選択するのと同じように、適切な 3D プリント素材を選択することが重要です。それぞれの素材には独自の「個性」があり、硬いもの、柔らかいもの、未来のテクノロジーのようにクールなものもあります。ということで、今日はその印刷物の「ファッションショー」を見ていきましょう！

1. PLA: 環境に優しく、さわやかです
PLA (ポリ乳酸) は、3D プリンティングの世界に新たな要素を加えたもので、コーンスターチまたはサトウキビ抽出物から作られた環境に優しい素材です。 PLA は無毒で無臭であるだけでなく、エッジの反りの問題もほとんどなく、印刷時に非常に優しい素材です。あなたが初心者であれば、PLA は間違いなくあなたの親友です。印刷物の表面は滑らかで、色は多彩で、圧力をかけなくても劣化するため、非常に環境に優しい素材です。

PLA の唯一の欠点は?熱にさらされると変形するため、PLA でコーヒー カップを印刷し、そこに熱いコーヒーを注ぐことは考えないでください。そうしないと、カップが小さなプラスチックの湖になってしまう可能性があります。

2. ABS: 強いタフガイ
次は ABS (アクリロニトリル ブタジエン スチレン) です。これはタフなやつです。 ABSはPLAに比べて耐熱性や強度が非常に高いため、玩具部品やカーモデルなどの機能部品の製造に適しています。

ただし、ABSは少し気まぐれです。印刷時に刺激臭が発生し、反りやすくなります。密閉チャンバーを備えたプリンターをお持ちでない場合、ABS プリントは少し「不安定」になる可能性があります。したがって、ABS を使用する前に排気換気の準備をすることが最善です。

3. PETG: アイアンマンと新人の組み合わせ
PLA の親しみやすさと ABS の強度を組み合わせた材料が必要な場合、PETG は夢の「スーパーヒーロー」です。強度が高いだけでなく、耐薬品性や柔軟性にも優れています。 PETGは印刷が比較的容易で、ABSのように反りにくく、臭いも発生しません。

PETG はアイアンマンのように振る舞い、外側がタフであるだけでなく、内側も非常に強力です。ボトル、食品容器、電子製品のケースのいずれを製造する場合でも、この製品は役に立ちます。欠点がほとんどなく、オールラウンダーです。

4. TPU: 柔らかくてかわいい弾力のあるエルフ
最もかわいいプリント素材といえば、TPU (熱可塑性ポリウレタン) でしょう。このエルフは弾力性、柔らかさ、耐摩耗性が特徴で、印刷物はゴムのように曲げたり伸ばしたりすることができます。携帯電話のケースや靴底、おもちゃなどの伸縮性が必要なものの印刷に使用できます。

ただし、TPU は印刷時に少し「遅い」場合があります。柔らかさが強いため、印刷時に速度をコントロールしないと、プリントヘッドに絡みついたり、結び目が発生したりする可能性があります。しかし、一度印刷してみると、わぁ、本当にかわいくて実用的だということがわかるでしょう。

5. ナイロン: 実用主義者の選択
ナイロン素材は、3D プリント業界のもう 1 つの「ハードコア プレーヤー」であり、非常に強く、耐久性があり、高温や衝撃に強く、一部の機械部品やギアなどのプリントに適しています。ナイロン素材からプリントされたオブジェクトは非常に高い強度と耐久性を備えており、実用主義者の間で人気があります。

ただし、ナイロンは吸湿性が高いため、使用前に乾燥していることを確認する必要があります。そうしないと、印刷プロセス中に気泡が発生し、最終的な印刷効果に影響します。

3D プリント マテリアルの世界は豊かでカラフルで、それぞれのマテリアルには独自の特徴と目的があります。環境に優しい新鮮な PLA から、丈夫な ABS、万能 PETG、弾性 TPU、丈夫なナイロンまで、どの素材を選択するかは、必要な印刷効果の種類によって異なります。だから、もうためらわないで、3D プリンターを手に取り、この素材の「ファッション ショー」を始めましょう!

https://www.revopoint3d.jp/
RPCエンドポイントを利用してウォレットを実装してみる　＃４ウォレットの存在チェック

# テーマ設定
RPCエンドポイントを利用してあるウォレットアドレスが実際に存在しているかチェックする。

# 前提環境
+ Node.js がインストールされている。
+ Web3.js ライブラリがインストールされている。

+ RPCエンドポイントを取得（無料）
https://cabinet-node.com/ja/docs/user-guide/create-access-token

### web3のインストール
```bash
npm install web3
```

# 実装
以下の内容でcheck_wallet_existence.jsファイルを作成してください。
 ```js
const { Web3 } = require('web3');

// RPCエンドポイントを設定
const web3 = new Web3('https://gateway-api.cabinet-node.com/{access_token}');

// ウォレットアドレスを設定
const walletAddress = 'YOUR_WALLET_ADDRESS';

// ウォレットアドレスの存在を残高チェックで確認
async function checkWalletExistence(address) {
    try {
        const balance = await web3.eth.getBalance(address);
        return balance !== null; // 残高が取得できれば存在している
    } catch (error) {
        console.error('Error fetching balance:', error);
        return false;
    }
}

async function main() {
    const exists = await checkWalletExistence(walletAddress);
    if (exists) {
        console.log('The wallet address exists.');
    } else {
        console.log('The wallet address does not exist.');
    }
}

main();

 ```

 # 実行
 
  ```
node check_wallet_existence.js
  ```

### 結果の例

```
The wallet address exists.
```
Github Actionでpushすると画面が真っ白に...

## 初めに
今回Reactを用いてプロジェクトを作成しています。
今までも何回かReactプロジェクトをGithub Actionでデプロイしてきました。
ですが今回のエラーによる、画面真っ白現象は初めてだったので共有します。

## 問題点
Github Actionsでデプロイした時に画面が真っ白になりました。
まず初めに確認したことは、Github secretにsupabase URLが渡っていること。
ですがこれは問題なさそうでした。

原因はApp.tsxに書かれている以下の部分です。
```react
function App() {
  console.log('App component rendered');
  return (
    <>
      <Routes>
        <Route path="/home" element={<Home />} />
        <Route path="/register" element={<Register />} />
        <Route path="/cards">
          <Route index element={<Cards />}/>
          <Route path=":userId" element={<Users />} />
        </Route>
      </Routes>
    </>
  )
}
```

## 解決策
今回の原因はルートのパス`"/"`が記述されていないことでした。
firebase ホスティングで最初に表示するページは`"/"`のページです。
その記述がなかったため、表示するページがなく画面が真っ白になりました。

修正したコードは以下の通りです。
```react
function App() {
  console.log('App component rendered');
  return (
    <>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/register" element={<Register />} />
        <Route path="/cards">
          <Route index element={<Cards />}/>
          <Route path=":userId" element={<Users />} />
        </Route>
      </Routes>
    </>
  )
}
```

## まとめ
Routerについて復習しながらの記述していたため、全く気づいていませんでした。
画面真っ白になる原因としては、APIkコードがGithub secretに登録されていないことが多いです。
ですが今回はあまり見たことのない凡ミスであったため、逆になかなか気づかないエラーでした。