OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerを使用した開発の流れ

## はじめに
開発環境のセットアップは重要ですが、それと同時に非常に面倒だと感じています。
プログラマー三大美徳の1つである「怠惰」を叶えてくれるDockerについて記事を書きたいと思います。
## Dockerを使った開発環境構築の流れ
### 要件定義
- まずどんな技術スタックを使用するかを決める
    - Next.js 
    - Rails 
    - MySQL etc

### ディレクトリの構成を決める
my_app/
    ├── backend
    ├── frontend
    ├── docker-compose.yml
    └── Dockerfile


### Dockerfileの作成
- イメージの設計図となるDockerfileを作成する

| FORM |ベースイメージを指定|
|:-:|:-:|
| WORKDIR  | 作業ディレクトリを設定  |
| COPY  | ローカルファイルをコンテナ内へコピー  |
|  RUN | コマンドの実行  |
| CMD  | コンテナ作成時に実行されるコマンドの指定  |




### docker-compose.ymlの作成
複数のコンテナをdocker-composeで管理する
起動のための設定を記述することによって、複数のDockerコンテナをひとつのコマンドで立ち上げることができる

### コンテナのビルドと起動
- イメージをビルドする
```bash
docker-compose build
```
- コンテナを起動する
```bash
docker-compose up
```

## コンテナとボリュームについて
自分はコンテナ内の作業が保存されないと聞いて、最初は「じゃあ意味ないやん」と思ったのですが、ちゃんと解決策はあります。
データや設定の永続化にはボリュームを活用することで、必要なデータを保持することができます。

## コンテナの概念
コンテナとは、アプリケーションを実行するための独立した仮想環境です。
各コンテナはアプリケーション実行に必要なパッケージやライブラリを含む
軽量であり、あくまで**実行環境**の為不要になったら削除できる。
コンテナ内の作業や設定はコンテナが削除されると失われる
コンテナは何回も壊して作り直すもの！！

## ボリュームの概念
ボリュームはコンテナ内で発生する永続的なデータを保存するための場所
ボリュームを使うことでデータが削除されず保存することができる。
例えば、MySQLコンテナ内で扱うデータベースのデータは、ボリュームに保存します
コンテナを削除して再構築しても、データベースの内容はボリュームに保持されているので、再起動後もデータは保持されます。
ローカルの変更内容がコンテナに反映される為ローカルとコンテナ間でデータを共有することも可能(ボリュームマウント)

## ボリュームとボリュームマウントの違い
- **ボリューム**
データの保存場所  
- **ボリュームマウント**
コンテナとボリュームを接続すること

## 実際にDockerを使った開発の流れ
**1. Dockerfileから作成されたファイル(frontend, backend)のコードをローカルで編集**

**2. コンテを実行し、Railsのサーバを動かす**
ローカルで編集したコードはボリュームマウントによってコンテナに反映される

**3. コンテナ内で作業**
コンテナへログイン
```bash
docker-compose exec コンテナ名 bash
```
データベースをマイグレーションしたり、必要なツールをインストールする

**4. コンテナの停止**
作業が終わったら```docker-compose down```で停止
コンテナの作業は消えるがローカルの変更は保持されたままとなる

## まとめ
Dockerは開発環境のセットアップを簡単にして、開発環境と本番環境で差異を無くし異なるユーザ間でも同じ環境を再現することができる
コンテナは軽量の一時的な実行環境であり、ボリュームを使うことでデータの永続化が可能
ローカルでコードを編集しコンテナ内で実行することで効率的に開発が進められる
【Linux】【udev】デバイスファイルが作成される仕組み

# デバイスファイル(/dev)はどうやって作成されるか？

- `udevd`が、デバイスファイルを作成する
    - デバイスファイルを管理する役割を持つデーモンプロセス

## udevdが、デバイスファイルを作成するまで

```mermaid
graph TD
    A[ユーザー] -->|1.デバイスを挿入| B[Linuxカーネル]
    B -->|"2.デバイスが追加されたことを感知し、/sysにデバイス情報を作成"| C["/sys"]
    B -->|3.デバイスが接続されたことをイベントで通知| D[udevd]
    D -->|4.デバイス情報を取得する| C["/sys"]
    D -->|5.デバイスファイルを作成| E["/dev"]
```

- デバイスの接続を感知するのは、Linuxカーネル
    - udevdにイベントを送ることで、udevdが、デバイスファイル（`/dev`）を作成する

# udevに関するコマンド・設定ファイル

### コマンド

|コマンド|詳細|
|--|--|
|udevinfo|udevが作成したデバイスファイルの情報を確認する|
|udevcontrol|デバイスの動作・停止を行う|
|udevmonitor|udevdの動作状況を確認|
|udevadm [info\|control\|monitor]|udevinfo・udevcontrol・monitorを統合したコマンド。|

### 設定ファイル

- `/etc/udev/rules.d`
    - デバイスファイル作成ルールを格納するためのディレクトリ
99.5記事目で振り返るQiita執筆の魅力と成長の複利効果

![image_converted-min.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1599258/3845dbce-815e-4d0b-831f-8d8a514fbe8a.png)

## はじめに

記事は書き始めたら、もう半分を超えたと言っていいでしょう。
というわけで、気づけばQiita執筆も**99.5記事目**を迎えました。

最近は[ChatGPT](https://openai.com/)も[4.5](https://openai.com/index/introducing-gpt-4-5/)と刻んでくる時代。
私も便乗してみました（笑）。

この記事では、99.5記事目で振り返るQiita執筆の魅力について書きたいと思います。

## Qiita記事は積立投資みたいなもの

これまで**99.6記事**を書いてきましたが、正直、1記事ごとの成長は微々たるものです。
書いた瞬間は「これはいい記事だ！」と思っても、半年後に見返すと「もっとこう書けば良かったな…」と感じることもしばしば。

でも、それでいいんです。
Qiita執筆は**積立投資**のようなもの。1記事1記事は小さくても、コツコツ続けることで気づけば知識のポートフォリオが育っていきます。

### 記事は未来の自分への投資

老後問題といえば **『2000万円問題』** が話題になりますが、未来を楽しむにはお金だけでなく、**娯楽のストック**も大切です。

仮に老後の10年間で週1ペースで記事を1つずつ読み返すとしたら…
**10年 × 50週 = 500記事**くらいは必要。

つまり、今の **99.7記事では全然足りない**ということですね（笑）。
未来の自分が「当時はこんなことを考えていたのか」と笑いながら読み返せるように、もっともっと積み上げていかないといけません。

### Qiita執筆の複利効果

積立投資の魅力は **『複利の力』** ですが、Qiita執筆も同じ原理で成長していきます。

- **過去記事が次の記事につながる**  
  - 以前書いた記事をリファレンスにしたり、発展させたりできる。  
- **フォーマットの最適化**  
  - 書き慣れることで、記事の型ができ、書くスピードが上がる。  
- **作業効率の向上**  
  - コードや説明を残しておけば、次回以降の時短につながる。  
  - 浮いた時間で新しい記事を書くことができる。  

つまり、「書けば書くほど、記事を書く負担が減り、より多くの記事を書ける」という **複利の力** が働くわけです。


## **99.8記事目だから見えてきたこと**

100記事に到達する前の今、改めて気づいたことをまとめると：

1. **記事は書き始めた時点で、すでに半分完成している**  
   - 取り掛かるまでが一番大変。書き出せば意外と筆が進む。  

2. **続けることが一番の力になる**  
   - 完成度を気にしすぎるより、「習うより慣れろ」でとにかく書き続けることが大事。  

3. **過去記事は意外と役に立つ**  
   - 書いた当時は「普通の記事」でも、後から見ると「意外と使えるな」と思うことも。  

4. **Qiitaは自分の知識の資産になる**  
   - 積立投資と同じで、定期的にアウトプットすることで「書きためた記事」が**未来の財産**になる。  

5. **やっぱり、いいねやフィードバックは嬉しい！**  
   - Qiitaは技術ブログとはいえ、やっぱり**読まれている実感**があると励みになる。  
   - いいねやコメントがあると、「ああ、書いてよかったな」と思う。  

## これからも続けていくために

**99.9記事目**を書き終えて、大事にしたいのは「無理なく続けること」。  
この記事のタイトルのように、「中途半端」でもいいんです。

最後に、このような節目を迎えられたのは、定期的なイベントや特集でコミュニティを盛り上げてくれる運営の方々、  
記事を読んでくださる方々、いいねやフィードバックをくださる方々、  
そして日々執筆を続けるすべての方々のおかげです。

**『Qiitaを育て、Qiitaに育てられる』** ── そんな関係があるからこそ、10年後も20年後も、  
そして半世紀後も、このプラットフォームが変わらず楽しめる場所であると信じています。

そのためにも、アウトプットを継続し、**未来の自分のために500記事をストック**しておきたいと思います。  

というわけで、気づけば**100記事目**が完成していました。
ABC396回答メモ

# 0.はじめに
　前回茶色落ちしたものの、あと２つ上がれば緑に戻れるので
　気合を入れなおして臨んだコンテスト。
　今回はなかなか手ごたえがあり、Cでも苦戦するも
　なんとかDまで解けました。
　これは言ったかなと思いましたが、レートは+1と1足りずに
　茶色にとどまりました。
　まぁ、緑だからどうということも無いのですが、何か悔しい感じです。


# 1.A - Triple Four
　なんとなく、前回のAと似た問題。
　リストを３つ目の値から見ていき
　今見ている値が2つ前の値と同じ＆1つ前の値と同じ場合
　Ｙｅｓを出力して終了
　最後までみて終了していなければＮｏを出力して終了

　https://atcoder.jp/contests/abc396/submissions/63495376


# 2.B - Card Pile
　キューの練習のような問題。
　キューqを用意し、
　1のクエリーの時は、キューにクエリーで示された値を格納
　2のクエリーの時は、キューが空なら0を
　空でなければｑの右端を取り出して出力
　
　まぁカンタンですが、Ｂ問題でキューを使うようになるとは・・・。

　https://atcoder.jp/contests/abc396/submissions/63504130


# 3.C - Buy Balls
　意外と難しく、諦めかけた問題。
　【考え方】
　　１）黒のボール数が白以上になるという制約をなくした場合
　　　白と黒それぞれ何個ボールを取り出した場合に
　　　価値が最大になるかを求める
　　２）１）で求めた黒のボール数が、白のボール数以上なら
　　　１）で求めた価値が回答となる
　　３）１）で求めた黒のボール数が、白のボール数未満の時
　　　黒と白の数が同じになるまで、価値の減少が少なくなるように
　　　黒を減らすor白を増やすようボールを選んでいく

　【実装】
　　1.変数N、M・リストB、Wを読み込む
　　2.BとWを降順ソートする
　　3.Bからボールを取り出す場合の価値の最大を求める
　　　-1.変数BS(Bの価値の合計:初期値0)、Bi(価値がBSの時のボール数-1:初期値-1)を定義
　　　　 Bから1つも取り出さない場合の方が価値が高くなる状態を初期値とする（Bの価値がすべてマイナスの場合）
　　　-2.リストBをインデックスiで先頭から見ていく
　　　　-1.B[i]が0以上の時BSにB[i]を加算し、Biにiをセット
　　　　-2.B[i]が0未満の時ブレイク
　　4.3同様に、Wからボールを取り出す場合の価値の最大を求める
　　　変数は、WSとWi（後で考えると、Wは価値が0より大きい場合で参照すればよかったですが
　　　提出時はBと同じロジックで見ています）
　　5.BiがWiより小さい場合以下繰り返し（Bi≧Wiの時は条件を満たしているので5の処理は行わない）
　　　～黒を増やした場合の価値の減少値Bxを求める
　　　-1.BiがN-1より小さい場合、BxはB[Bi+1]*-1(黒の袋から最大の数（マイナス値）を取り出した場合に減少する価値)
　　　-2.BiがN-1と同じ場合は、黒の袋からボールは取り出せないので、BxにINF(10の18乗)をセット
　　　～白を減らした場合の価値の減少値Wxを求める
　　　-3.Wiが0以上の時、WxにW[Wi]をセット
　　　-4.Wiが0の時は白の袋からボールは取り出せないので、WxにINF(10の18乗)をセット
　　　-5.WxよりBxが大きい場合（黒のボール数を増やした方が価値の減少が少ない場合）
　　　　-1.Biに1を加算し、BSにB[Bi]を加算
　　　-6.WxがBx以上の場合（白のボール数を減らした方が価値の減少が少ない場合）
　　　　-1.WSから、W[Wi]を減算し、Wiから1減算
　　6.BS+WSを出力して終了

　https://atcoder.jp/contests/abc396/submissions/63539360


# 4.D - Minimum XOR Path
　DFS問題に単純な重さではなく、XORで色付けした問題といった感じ。
　根はCOBOL出身の古いプログラマーのため、再帰関数とか今一苦手なので
　不安に思いながら実装。
　【実装】
　　～前準備
　　1.変数N、Mを読み込む
　　2.デフォルトリスト型辞書D(キー：頂点、値：tuple（キーとつながっている頂点とその辺のラべル値）)を定義
　　3.リストR（DFS時に訪れた頂点を保持するリスト）を[0]×（N+1）で初期化
　　4.回答保持用変数ansを2の61乗で初期化
　　6.M回辺情報読み込み
　　　-1.u、v、wを読み込む
　　　-2.D[u]に(v,w)を追加
　　　-3.D[w]に(u,w)を追加
　　6.関数dfs定義（引数　x:チェック始点の頂点、y:チェック終点の頂点、w:チェック中経路のラベルXOR合計値）
　　　(後で見るとyは不要だった)
　　　-1.グローバル変数としてansとRを定義
　　　-2.xがNと同じとき
　　　　-1.ansにansとwの小さい方をセット
　　　　-2.リターン
　　　-3.以下、D[x]からxx,xwを取り出し繰り返し
　　　　-1.R[xx]が0の時（今調べている経路で通ってない時）
　　　　　-1.R[xx]に1をセット
　　　　　-2.関数dfsを引数(xx,y,w^xw)で呼び出し
　　　　　-3.R[xx]に0をセット
　　～メイン処理
　　7.R[1]に1をセット
　　8.関数dfsを引数(0,N,0)で呼び出し
　　9.ansを出力して終了

　最初、ansの初期値を10の18乗にして提出したところ2問WAとなり
　よくよく調べたら、Wの制約である2の60乗の方が大きい事に気づき
　2の61乗に変更したところACでした。
　ここさえ気づいていれば、緑行けたかも…と悔やみました。

　https://atcoder.jp/contests/abc396/submissions/63552894


以上
Macで圧縮されたファイルをWindowsで解凍したら怒られた件

# はじめに

業務中に受領した圧縮ファイルが解凍出来なかったため、備忘録も兼ねて投稿します。

圧縮ファイル作成:Mac OS
解凍作業:Windows端末

# やったこと
7-zipを使い、解凍作業実施
【結果】
無事解凍することに成功

# なぜ？Macで圧縮したファイルが解凍できなかったのか
***圧縮する際の文字コードに原因***
Macで圧縮する際、UTF-8で圧縮される。
一方、Windows標準機能を用いて解凍すると。UTF-8に対応していない。
WindowsではShift-Jisで文字コードをみなして変換してします。

そのため、Macにて圧縮したファイルをWindowsで解凍した場合、ファイル名が文字化けする原因もここにあります。

# まとめ
Macユーザより圧縮ファイルがWindwsユーザ向けに連携された場合は、
7-ZipなどUTF-8対応のソフトなどを利用するとよい。


# 参考
https://mac-windows-pc.com/mac-zip
Bootstrap入門#1導入

# 1. はじめに
この記事ではWindowsでBootstrap v5.3を使用。
udemyで学習した内容のアウトプットとなり完成品は以下。

![bs_tutorial.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481447/f13fb134-8f81-4456-a372-0260012b9f6f.gif)

# 2. 事前準備

1\. [公式サイト](https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css)からCDNリンクをコピーする。
CDN = Contents Delivery Network

2\. コピーしたリンクをindex.htmlのlinkタグの中に貼り付ける。

```index.html
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Bootstrap Practice</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"
        integrity="sha384-9ndCyUaIbzAi2FUVXJi0CjmCapSmO7SnpJef0486qhLnuZ2cdeRhO02iuK6FUUVM" crossorigin="anonymous">
</head>
```

# 3. グリッドシステムについて
まずは基本的な考え方として、Bootstrapではデバイスの画面幅を12分割し管理している。
このグリッドシステムのおかげで、画面幅が変わってもレイアウトが崩れないという仕組み。

ここではcontainerというCSSクラスで実際に挙動を確認してみる。

```index.html
    <body>
    <div class="container">
```

結果としては以下の通り。cssにメディアクエリを書かなくても画面幅に合わせてレスポンシブさせることができた。

![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481447/67490e99-a55d-43af-9ad7-ed7a3bac0c34.gif)

「チェックボックス」と「ラジオボタン」の項目に関しては、ｍd-sm-flexを使い画面幅に応じて縦並び or 横並びに切り替わるように設定。これはお手軽！

```index.html
<div class="d-sm-flex">
```

さらにbadge rounded-pillを加えて「必須」や「任意」など問い合わせフォームなんかでよく見かけるデザインを再現することができた。

![bs_tutorial_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481447/d7369342-96f5-42d6-8c60-534ba45cb50c.gif)

Bootstrapの第一印象としては用意されているパーツを使い、「それっぽいデザイン」作れてしまうということ。（今回のファイルは自分で書いたcssは一切ありません）

# 4. 反省点
「お名前」の欄に文字が入力できず調べたところ、あまりにも初歩的なミスが発覚。

・修正前
```index.html
<input type="number" class="form-control" name="myname" id="myname" placeholder="ニックネームでもOK">
```

type="number"では当然文字が入力できるはずもなく以下の通りに修正。

・修正後
```index.html
<input type="text" class="form-control" name="myname" id="myname" placeholder="ニックネームでもOK">
```

これに気が付くまでに10分ぐらい調べてしまった。こういうミスを減らせるようにコードにはしっかり目を通したい。

# 5. まとめ
cssを書かずにレイアウトを作れる点に感動。
特に驚いたのはメディアクエリを書いていないのにレスポンシブさせられること。
以前、ブレークポイントに心をへし折られかけたことがあるのでこの機能にはとにかく驚き。

ただ、細かい融通が利くのは当然cssだと思うので、すべてBootStrapではなくパーツ単位で使うのが良いかと。（ボタンだけBootstrapとか）

とはいえ、今回の学習内容は初歩の初歩なので、もっとドキュメントを読んで他のクラスも書いてみたい。Bootstrap楽しい！
JetBrains IDE、標準機能の「Presentation Assistant」で入力したショートカットキーを表示できる

JetBrains IDEを使ったプレゼンテーションやデモ、ライブコーディングの際、入力したショートカットキーを見ている人に伝えられたら便利です。

各種JetBrains IDEの2023.3以降では、入力したショートカットキーの表示を標準機能の「Presentation Assistant」で行うことができます。プラグインではなく、標準機能で可能です。

※ 本投稿のスクリーンショットは、Rider 2024.3.6のものです。

# 標準機能のPresentation Assistant

次の画像は、Presentation Assistantを有効化した設定の下、ショートカットキーを入力した時のスクリーンショットです。デモやライブコーディングの際に、何を入力したかをわかりやすく、伝えることができます。

![スクリーンショット 2025-03-09 0.10.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/e2a2c252-b0e3-49da-9d4b-f600f0340041.png)

Presentation Assistantは、メニューのView > Appearance > Presentation Assistantにチェックをつけることで有効になります。

![スクリーンショット 2025-03-09 0.36.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/86e27ba1-6b2a-43a2-b2b6-86e5f5144f58.png)

また、Settingsを開き、Appearance & BehaviorのPresentation Assistantから、挙動を調整することができます。

![スクリーンショット 2025-03-09 0.11.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/fc106caf-c2a6-4574-9dc8-68544e6dee7f.png)

* Popupのサイズ
* 表示が消えるまでの時間
* 位置
* MacとWindowsなど2つのショートカットキーを表示

などの設定ができます。

なお、表示位置は表示されたメッセージをDrag & Dropで細かく調整できます。

![スクリーンショット 2025-03-09 0.20.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/3ab57e4c-16e2-4dfd-b5c5-784b779aadff.png)


表示位置は、リアル会場でのプレゼンの場合は部屋の大きさに合わせて調整したいですし、録画する場合は字幕の位置に被らないように調整したいですし、細かく調整できるのは嬉しいですね。


# 以前は3rd partyのプラグインし、標準機能ではなかった

JetBrains IDEの2023.3より前は、入力したショートカットキーを表示する機能はJetBrains IDE標準機能にはありませんでした。そのため、JetBrains Marketplaceで第三者が作成・公開した「Presentation Assistant」というプラグインが長らく利用されてきました。

https://plugins.jetbrains.com/plugin/7345-presentation-assistant-for-2023-2

プラグイン版の「Presentation Assistant」は現在、「for 2023.​2」のような表記が追加されています。また、プラグインの説明には次のように記載されています。

> Adds an option to show name and shortcuts of any action you invoke (View | Appearance | Descriptions of Actions) in IntelliJ-based IDEs of version 2023.2 and older.
> Since version 2023.3, this functionality is provided by IntelliJ Platform, so it's available in all IntelliJ-based IDEs out of the box, see Settings | Appearance & Behavior | Presentation Assistant.

過去のJetBrains IDEの紹介ブログなどではプラグインが紹介されていますが、プラグインの説明にもあるように、2023.3以降は公式機能を使いましょう。長い間ありがとうございました。

ちなみに[JetBrains公式の動画](https://www.youtube.com/watch?v=h-HGg9b6Dqw)でも、プラグイン版の「Presentation Assistant」はおすすめされていました（すごい）。

# リンク集

* [Presentation Assistant - IntelliJ IDEA](https://www.jetbrains.com/help/idea/presentation-assistant.html)
* [Presentation Assistant - Rider](https://www.jetbrains.com/help/rider/Presentation_assistant.html)
* [Presentation Assistant - WebStorm](https://www.jetbrains.com/help/webstorm/presentation-assistant.html)
* [Presentation Assistant - PyCharm](https://www.jetbrains.com/help/pycharm/presentation-assistant.html)
pgAdmin4で実行計画の時間を色で表示する。

# 概要
実行計画の時間に色がついて、ボトルネックがわかりやすいかもしれない

# 環境
pgAdmin4 9.0

# サンプルデータ
https://neon.tech/postgresql/postgresql-getting-started/postgresql-sample-database

# サンプルクエリ（適当）
```sql
SELECT
	*
FROM
	RENTAL R
	JOIN PAYMENT P ON R.RENTAL_ID = P.RENTAL_ID
	JOIN CUSTOMER C ON R.CUSTOMER_ID = C.CUSTOMER_ID
WHERE
	R.RETURN_DATE IS NULL
```

# 手順
TimingをチェックONして、
Explain Analyzeボタンを押す.(sqlが実行される。)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25456/3999723e-bba4-43c3-a1b3-d76e16d19284.png)



`Explain`をクリックする
`Analysis`をクリックする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25456/dcc13dd7-a1cb-4590-b746-5cb51e0a80c0.png)

実行計画の時間が色で表示される。

# 設定
`Query Tool` `Explain` `Show timing?`
でデフォルトを変えられる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25456/3972df06-b959-4067-90eb-b96e664e2f27.png)

以上！
[Linux][command] ディレクトリ・ファイル管理_ディレクトリ操作_cd, mkdir, pwd

# cdコマンド
~~~terminal
$ cd [ディレクトリ名]
~~~

## 活用例 
### rootユーザの場合
- ホームディレクトリ（`/`）への移動
~~~terminal
$ cd ~

$ cd
~~~

- ホームディレクトリ配下にある「test」ディレクトリ（`/test`）に移動
~~~terminal
$ cd ~/test
~~~

- testユーザ（一般）のホームディレクトリ（`/home/test`）に移動
~~~terminal
ユーザー指定
$ cd ~test

絶対パス
$ cd ~/home/test
~~~

### testユーザ（一般）の場合
- ホームディレクトリ（`/home/test`）への移動
~~~terminal
$ cd ~

$ cd

ユーザー指定
$ cd ~test

絶対パス
$ cd ~/home/test
~~~

- ホームディレクトリ配下にある「test」ディレクトリ（`/home/test/test`）に移動
~~~terminal
$ cd ~/test
~~~

# mkdirコマンド
~~~terminal
$ mkdir [オプション] ディレクトリ名
~~~

| オプション | 由来 | 説明 |
|:--|:--|:--|
| default | make directory | - 新しいディレクトリを作成する |
| `-p` | parents | - 親ディレクトリもまとめて作成する |
|||例: `-p /home/user/project/src`<br>`/home/user/project`ディレクトリがない場合h作成する|
| `-m` | mode | - 作成するディレクトリのパーミッションを指定 |
|||例: `-m 755`|

# pwdコマンド

# Ping-t
cd
- [3077_cd, cd ~, cd ~test](https://mondai.ping-t.com/question_subjects/31/question_sessions/32244301/progressing_questions/494010604)
- [3568_cd ~test](https://mondai.ping-t.com/question_subjects/31/question_sessions/31223415/progressing_questions/478442911)

mkdir
- [3159_mkdir -m](https://mondai.ping-t.com/question_subjects/31/question_sessions/31870469/progressing_questions/488372720)
- [3632_mkdir](https://mondai.ping-t.com/question_subjects/31/question_sessions/32244301/progressing_questions/494010593)

pwd
- [3078_pwd](https://mondai.ping-t.com/question_subjects/31/question_sessions/32018863/progressing_questions/490569330)
【Power Apps】データフローを使用してテーブルにデータを追加する ～Excel追加編～

## データフローって何？？
Power Apps のデータフローとは外部からのデータを Dataverse に
手動・もしくは定期的に取り込んだり更新を行ったりすることができる機能です。

:::note warn
データフローを使用するには有償ライセンスが必要です。
詳しくは Microsoft の公式ドキュメントを参照ください。
:::

**公式：【データフローを使用するために必要なライセンス】**

https://learn.microsoft.com/ja-jp/power-query/dataflows/what-licenses-do-you-need-in-order-to-use-dataflows

### この記事で実際にやってみること
Dataverse に `社員名簿テーブル` があります。
こちらのテーブルにExcelで作成した社員名簿をデータフローを作成して追加させたいと思います。

【Dataverse内のデータ】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/22084d0b-aac5-4726-a57f-3ac14334de78.png)

【追加するExcelの社員データ】
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/a3b2d87a-f6ef-4994-9375-af836a8ab850.png)


## データフローの作成方法:shamrock:

+ Power Apps にログインして左側のメニューから `データフロー` を選択します。
+ 「+ 新しいデータフロー」を選択して、フローの名前を付けたら `作成` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/501c0691-c3be-46e5-b95d-d8ae9b2c8d38.png)

**データソースの選択** を選択します。
今回はExcelファイルを取り込むので **Excelブック** を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/c4cc3ff8-28db-43b7-81d1-019f1de39358.png)

追加したいファイルをアップロードします。
追加できたら **次へ** を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/2182d191-8bf5-4312-b9c0-897853009944.png)

取り込みを行いたいテーブルやシートを選択して **データの変換** を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/69ccf82c-d77c-4e1d-baee-63e162fec834.png)

Power Query が起動しますので、こちらでデータの変換を行っていきます。
型の変換や列のマージ、計算列の作成などを行えます。
今回は必要データは揃っていますのでこのまま **次へ** を選択します。

`時間があればデータの変換方法についての取り扱いなども行いたいと思います！`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/c57f8b46-6b34-4e7c-a7b8-979ab8ece2e9.png)

作成したテーブルの取込先を設定します。
今回は既存のテーブルを読み込むので、2つ目を選択肢宛先テーブルを選択します。

**列マッピング** 
取り込んだテーブルと取込先のテーブルのカラムについて自動でマッピングを行ってくれています。
確認して修正がなければ次は `公開設定` を行います。
今回は一度きりで良いので `手動で更新する` を選択して発行するとデータの取り込みが始まります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/032af345-d73b-4230-ba87-0f635485770c.png)

更新履歴を確認するとこのように何行作成された、何行更新された、失敗した行数などが表示されます。
今回はすべて成功しています。
ではテーブルを実際に見に行ってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/c92c0835-088a-47f1-97b5-bbe67cd73b5f.png)

Excelで作成した行が問題なく更新されていることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3719434/0ad09c1f-5471-4fb0-b18d-30a15f4f47d7.png)

## さいごに:star:
今回はデータフローの基本的な使い方について説明しました！
一行一行更新しなくても外部から大量のデータを一括で Dataverse に取り込むことができる非常に便利な仕組みです！
時間があればデータの変換やマッピングの詳細方法についても解説していきたいと思いますので、ぜひ調べて活用してみてください！
Gitでクローンが上手く出来ない（ブランチが全て取得できない）場合の対処法

# **Git クローン時に全ブランチが取得できなかった問題と解決策**

## **📝 はじめに**
Git でリモートリポジトリをクローンした際に、**すべてのブランチが取得できない** という問題に直面しました。  
本記事では、その際に試した対処方法と、最終的な解決策を紹介します。

---

## **🚨 発生した問題**
Git でプロジェクトをクローンした際、以下の問題が発生しました。

- クローンをしたが、非常に時間がかかる＋`master` しか取得できず、他のブランチが見えない！**

---

## **🔍 試した対処方法**
この問題を解決するために、以下の2つの方法を試しました。

---

### **① バッファサイズの拡張（自分のケースでは効果なし）**
```bash
git config --global http.maxRequestBuffer 1073741824
```

#### **📌 解説**
- `git clone` は **HTTP 経由** でリポジトリを取得するため、`http.postBuffer` のサイズが影響する  
- **この設定を大きくすることで、clone の速度向上やエラー (`RPC failed`) の回避が期待できる**
- **100MB → 1GB に増やすことで改善することが多い**

#### **❌ 結果**
今回のケースでは、クローンが遅かった原因は **fetch 設定にあったため、この方法では解決しなかった**。

---

### **② `git config --list` で設定をチェックし、fetch 設定を修正（解決！）**
```bash
git config --add remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin
```

#### **📌 解説**
- 通常、`git clone` すると、`fetch` のデフォルト設定は **`main`（または `master`）ブランチのみを取得** するようになっていることがある
- 設定を確認するには以下を実行
  ```bash
  git config --get remote.origin.fetch
  ```
  **デフォルトの出力（main ブランチのみ取得する場合）**
  ```
  +refs/heads/main:refs/remotes/origin/main
  ```
  → **この場合、`main` しかフェッチしない設定になっている！**
  
- これを **`+refs/heads/*:refs/remotes/origin/*`** に変更することで、**すべてのブランチをフェッチ可能に！** 🎉

#### **✅ 結果**
```bash
git fetch origin
git checkout develop  # 例: develop ブランチを使いたい場合
```
すべてのリモートブランチが取得できるようになり、問題が解決しました！

---

## **🎯 まとめ**
| No | 方法 | 結果 |
|----|--------------------------|----------------|
| ①  | `http.maxRequestBuffer` を増やす | ❌ 効果なし |
| ②  | `remote.origin.fetch` を修正 | ✅ **解決！** |

### **✨ 結論**
Git の `fetch` 設定がデフォルトで `main` のみになっている場合があるため、  
`+refs/heads/*:refs/remotes/origin/*` に変更することで **すべてのブランチを取得できるようになる！**
Cloudflare pages+Next.jsの環境でServerActionsを実行すると405が返ってくる件について

# はじめに
今回、[新サービス](https://brainlink.site)を開発するにあたりLPのコストをできるだけ抑えようと思った結果、以下のスタックで開発することにした。

**Next.js**
フロントエンドの実装
**Supabase**
WaitinglistのDBやストレージ
**v0**
LPのUIデザイン
**Cloudflare pages**
本番/ステージング環境

このスタックを用いて開発した結果費用は**¥0**となりコスト削減は達成できたが、問題が発生した。


# ServerActionsが動かねぇ!!!
### 問題
本来であれば

```mermaid
flowchart LR

フォーム --> ServerActions --> Supabase
```
の順にデータ処理を行いSupabaseにデータを格納したかったのだが、
ServerActionsを叩いたときに`405 method not allowed`が返された。

### 考察
どうもNext.js v13の時は問題ないようなのだが、v14以降でServerActionsが動かなくなってるらしい。
ましてや今回はv15のAppRouterを使っているので諦めようとした。

### 解決策
**ServerActionsではなくAPIRoutesを使う**


つまり、ServerActionsだと静的ページにPOSTを送るためなんらかの制限がかかっているが、APIRoutesは普通に処理ができるらしいので今回は
```mermaid
flowchart LR
フォーム --> APIRoutes --> Supabase
```
の流れで処理を行った。


# 結果
最高の環境でいいLPができました(**¥0で**)
作ったLPはコチラ↓

https://brainlink.site
DavinciResolve無償版　スクリプト実行時にResolveオブジェクトがNoneを返してくるとき

プログラム初心者なので不備不足があったら申し訳ございません。
使用バージョン：
DavinciResolve19
Python3.12 
## 結論
- そもそも内部スクリプトやコンソール実行時は、Resolveオブジェクトを取得する必要はない
  - つまり`resolve = GetResolve()`や`resolve = dvr_script.scriptapp("Resolve")`を書かなくていい
  - いきなり`fusion = resolve.Fusion()`と記述してもFusionオブジェクトが取得できる
  - あえて記述したいなら`resolve = app.GetResolve()`が使える

## 問題
- DavinciResolve無償版でスクリプトを動かそうとしたが、最初のResolveオブジェクトの取得がうまくいかなかった。
  - 中身が`None`のResolveオブジェクトが返ってきてしまう。
そのため、たとえば下のコードでは`fusion = resolve.Fusion()`が通らない。

```python:公式ドキュメントのサンプルコード
import DaVinciResolveScript as dvr_script
resolve = dvr_script.scriptapp("Resolve")
fusion = resolve.Fusion()
projectManager = resolve.GetProjectManager()
projectManager.CreateProject("Hello World")
```


- 有償版（DavinciResolveStudio）では、環境設定から外部スクリプトの使用許可を「ローカル」以上にすることで解決できるようだが、無料版にその設定項目はない。
## 解決
- 内部スクリプトやコンソールから実行する場合は、最初からResolveオブジェクトが使える状態で置いてあるようなので、そのまま呼び出して使用することができる。改めて取得する必要はない。
  - 以下のようにResolveオブジェクト取得の行を無効化すれば問題なく実行できるはず。

```python:公式ドキュメントのサンプルコード：Resolveオブジェクト取得の行を無効化
import DaVinciResolveScript as dvr_script
#resolve = dvr_script.scriptapp("Resolve")
fusion = resolve.Fusion()
projectManager = resolve.GetProjectManager()
projectManager.CreateProject("Hello World")
```
- もしResolveオブジェクト取得の行を記載する必要がある場合は、代替として`app.GetResolve()`が使える。
```python:公式ドキュメントのサンプルコード：Resolveオブジェクト取得の行を代替
import DaVinciResolveScript as dvr_script
resolve = app.GetResolve()
fusion = resolve.Fusion()
projectManager = resolve.GetProjectManager()
projectManager.CreateProject("Hello World")
```

---
取り急ぎ以上です。
LibreChatでAzure AI Foundryでデプロイしたモデルを使う

Azure AI Foundryでデプロイしたモデルを、LibreChatで使う方法です。
（プレビュー機能を使いますので、実環境には向かないと思います）

## 環境

- LibreChat v0.7.7

## Azure AI Foundryでモデルデプロイ

以下のような感じでデプロイさせました。
別プロジェクトでAOAIも表示されていますが、ここでは使用しません。
（ちなみに、AAIFでデプロイしたAOAIモデルもここで紹介する方法で使用可能です）

![スクリーンショット 2025-03-09 115747.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4030765/3f5c90a0-c1a9-4b93-8980-f9b7f3fc3200.png)


## 設定してみる

以下例では、Phiをcustom endpointとして追加しています。

~~~librechat.yaml
endpoints:
  custom:
    - name: "Microsoft"
      baseURL: "${AZUREAIFOUNDRY_URL}"
      apiKey: "${AZUREAIFOUNDRY_KEY}"
      models:
        default: [
          # 以下にAAIFでデプロイしたモデルを入力する
          # 複数入力も可
          "Phi-4-mini-instruct",
          "Phi-4",
          "Phi-4-multimodal-instruct"
          ]
        fetch: false
      serverless: true
      titleConvo: true
      titleModel: "Phi-4-mini-instruct" 
      modelDisplayLabel: "Phi"
      headers:
        # ヘッダつけておかないと、エラーになります
        api-key: "${AZUREAIFOUNDRY_KEY}"
        Content-Type: "application/json"
~~~

.envに以下追加します。

~~~.env
AZUREAIFOUNDRY_URL=(Azure AIモデル推論エンドポイント)
AZUREAIFOUNDRY_KEY=(APIキー)
~~~

![スクリーンショット 2025-03-09 114558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4030765/148e5b3d-6bf0-4a4d-a24f-996aa6230d98.png)

できました。

![スクリーンショット 2025-03-09 135309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4030765/2c116641-a9b8-4149-bcb3-edb444d4ede3.png)

きちんと応答してくれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4030765/d7456953-e36f-4b65-8e09-4186d270380a.png)


## 最後に

デプロイ管理画面で、「エンドポイントの取得」から設定することもできますが、これだとモデル毎にエージェントを選択することになるので、あまりキレイではありません。
AAIFはAAIFでまとめなければいけないということもなく、modelsの内容を変えるだけで会社ごとにカテゴライズできます。

この記事が何かのお役に立てれば幸いです。
クラス？何それ？？関数で良くね？？？(Python)

# 初めに
初学者が作った備忘録程度のものです。

# 簡単な例
太郎君の3教科の点数の平均を出せる関数とクラスを作ってみる
まずは関数から
```python
taro_japanese = 60
taro_math = 30
taro_english = 90

#関数で平均を求める
def average(japanese, math, english):
    return ((japanese + math + english) / 3)

taro_average = average(taro_japanese, taro_math, taro_english)

print(taro_average)
```
```:実行結果
60.0
```

次にクラス
```python
#クラスで平均を求める
class TestScore :
    def __init__(self, name, japanese, math, english):
        self.name = name
        self.japanese = japanese
        self.math = math
        self.english = english
            
    def average(self):
        return ((self.japanese + self.math + self.english) / 3)

taro = TestScore('Taro', taro_japanese, taro_math, taro_english)

print(taro.average())
```
```:実行結果
60.0

```
いや関数でええやん。
なんか長くなってるし、そもそもクラス内で関数宣言してるしメリットなくね？

そこで次だ。
平均だけでなく分散も知りたくなった。
関数、クラス両方のやり方で分散を求めてみよう。

```python
# 関数で分散を求める
def variance(japanese, math, english):
     ave = average(japanese, math, english)
     var = ((japanese - ave)**2 + (math - ave)**2 + (english - ave)**2) / 3
     return var

print(variance(taro_japanese, taro_math, taro_english))
# 600.0

# クラスで分散を求める
def variance(self):
     ave = self.average()
     var = ((self.japanese - ave)**2 + (self.math - ave)**2 + (self.english - ave)**2) / 3
     return var

#test_scoreクラスにvarianceメソッドを追加
TestScore.variance = variance

print(taro.variance())
# 600.0
```
クラスの作成がない分長さは同じくらいになっただろうか。
ここで注目してほしいのは関数の場合は変数を渡す必要があるのに対して、
クラスの場合は変数を渡す必要がなくなっているという点だ。

今回は変数が3個だから恩恵はそこまで感じられないが、これが仮に100個ぐらいあったらどうだろうか？
明確に見やすいコードになるし、処理も速くなる。

また、これに加えて標準偏差も求めたい、偏差値も求めたい、さらに別に...
としたい処理が増えていき、関数もその分増えていったらどうだろうか？
さらに、全く別の処理も途中でしたくなり、別の処理に使う関数が途中に混ざっていたらどうだろうか？
コードを書いた自分自身は分かるかもしれないが、他の人が見たら何がしたいか分からなくなる。
その分、クラスはそのクラスで使えるメソッドを見れば何がしたいか一瞬で分かる。
また、今回で言えば「name」のように必要なデータもまとめることができる。

# 結論
1. 複数の処理が必要な時、関数はその都度変数を渡す必要があるが、クラスは一回変数を渡すだけで済む(処理が早い)
2. クラスは、必要なデータや処理を一まとめにすることができて分かりやすい
3. 処理が少ない場合は関数で十分
LeetCode 6. Zigzag Conversion の回答

## 初めに
今回もLeetCodeを解いていこうかと思います。
問題文は以下

```
The string "PAYPALISHIRING" is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
A P L S I I G
Y   I   R
And then read line by line: "PAHNAPLSIIGYIR"

Write the code that will take a string and make this conversion given a number of rows:

string convert(string s, int numRows);
 

Example 1:

Input: s = "PAYPALISHIRING", numRows = 3
Output: "PAHNAPLSIIGYIR"
Example 2:

Input: s = "PAYPALISHIRING", numRows = 4
Output: "PINALSIGYAHRPI"
Explanation:
P     I    N
A   L S  I G
Y A   H R
P     I
Example 3:

Input: s = "A", numRows = 1
Output: "A"
 

Constraints:

1 <= s.length <= 1000
s consists of English letters (lower-case and upper-case), ',' and '.'.
1 <= numRows <= 1000
```

## 回答
私の回答は以下

```python
class Solution:
    def convert(self, s: str, numRows: int) -> str:
        final_value = ""
        final_dict = {}
        if numRows >1 :
            result = [s[i:i+numRows-1] for i in range(0, len(s), numRows-1)]
        else:
            return s
        for i, ss in enumerate(result):
            even_key = 1
            odds_key = numRows
            if i % 2 == 0:
                for s in ss:
                    if even_key in final_dict:
                        final_dict[even_key] += s  # すでにある値の後ろに追加
                    else:
                        final_dict[even_key] = s
                    even_key += 1
            else:
                for s in ss:
                    if odds_key in final_dict:
                        final_dict[odds_key] += s  # すでにある値の後ろに追加
                    else:
                        final_dict[odds_key] = s
                    odds_key -= 1

        for i, s in final_dict.items():
            final_value += s

        return final_value 

```

nowRowsの個数に合わせて文字列を分割して、その中でdictに保存する方法を偶数個目のグループと奇数個目のグループで分けてみることで対応しました。
中々難しかった。。あとコード長い笑

## 最後に
もっといい方法あれば教えていただきたいです。
日本語プログラミング言語Mindの小技 「等価」

# はじめに
日本語プログラミング言語Mindの小技「等価」について説明したいと思います。

# 対象読者
日本語プログラミング言語Mindのユーザー、または日本語プログラミング言語に興味のある方

# この小技に関連するMind言語マニュアル

この小技に関連するMind言語マニュアルの記述はありません。または発見できませんでした。つまり裏技？

失礼しました。Mind8プログラミングマニュアルに記載がありました。
２ プログラム表記の基本
└等価定義

>ある単語に別の名前を付ける機能である。
>
>構文＝
>＜新名称＞は ＜旧名称＞と 等価。

本機能（本記事）は、下記のバージョンに対応しています。Mind８のLinux版も対応していると思いますが、本記事では特に検証を行っておりません。

# 対応バージョン
■Mind７　■Mind８　■Mind９
■Windows版　□Linux版

# 小技の解説
「等価」はMindの定義済単語を別名に置き換える機能です。サンプルを使って
説明します。

# Mindプログラムソース

```mind:touka.src
文字列コンソール出力して改行は　　一行表示と　　等価。

メインは　　
「小技の等価とは単語名を変えること」を　一行表示
「小技の等価とは単語名を変えること」を　文字列コンソール出力して改行。

```

# コンパイル結果
ではコンパイルしてみます。下位ライブラリはfileを指定します。

## Mind９
下図はMind９βです。
```cmd:
C:\developments\vscode\mind9>mind touka file   

日本語プログラミング言語 Ｍｉｎｄ Version 8.11 for Windows
          Copyright(C) 1985 Scripts Lab. Inc.
コンパイル中 .. 終了
Coping.. C:\mind9-beta\mind9-beta\bin\mindex.exe --> touka.exe
```
## Mind8
```cmd:
C:\developments\vscode\mind9>mind touka file

日本語プログラミング言語 Ｍｉｎｄ Version 8.07 for Windows
          Copyright(C) 1985 Scripts Lab. Inc.
コンパイル中 .. 終了
Coping.. c:\pmind\bin\mindex.exe --> touka.exe
```
## Mind7
```cmd:
C:\developments\vscode\mind9>mind touka file
日本語プログラミング言語 Ｍｉｎｄ Version 7.5 for Windows
          Copyright(C) 1985-2004 Scripts Lab. Inc.
          Single user license.  Serial No:XXXXXXX
コンパイル中 - 終了
Coping.. C:\mind7\bin\mindexec.exe -> touka.exe
```
# 実行結果
つづいて実行してみます。Mind９βの結果です。記述は割愛していますがMind7/8も同じです。

```cmd:
C:\developments\vscode\mind9>touka
小技の等価とは単語名を変えること
小技の等価とは単語名を変えること
```

# 参考情報
この小技を使った記述例の記事です。

https://qiita.com/mylifewithviolin/items/3288336a9c346a429fee

https://qiita.com/mylifewithviolin/items/903a0a7c8aeea6ec3148

# おわりに
いかがでしたでしょうか？なにかの参考になれば幸いです。2025年は日本語プログラミング言語Mind生誕４０周年です。

## 本記事シリーズのご紹介
本記事シリーズ「日本語プログラミング言語Mindの小技」は日本語プログラミング言語Mind生誕４０周年プロジェクトの一環です。興味を持たれた方は[日本語プログラミング言語Mind公式サイト](https://www.scripts-lab.co.jp/mind8download/download.html)にアクセスして、Mindコンパイラをダウンロードできますよ。[Mindプログラミングマニュアル（基本文法）](https://www.scripts-lab.co.jp/mind/ver8/doc/index.html)ページから気になるお題の構文を選んで、この記事のようにサンプル実装実行してQiitaにアウトプットしてみましょう！筆者はMind7/8/9βで検証しておりますが、もちろんMind8だけでもじゅうぶんです。またお題が既存記事とかぶるのはまったく問題ありません。同じお題でみなさまの多様斬新なサンプルをお待ちしております:grinning:
CTF初挑戦

CTFに初挑戦した際の記録になります。
同じ境遇の方の参考や私の備忘として投稿します。

まず私がチャレンジしたものは常設のCTFであるksnctfです。
URL：https://ksnctf.sweetduet.info/

そこで、以下のEasy Cipherという問題に取り組んでみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4031278/cff46ea8-04b9-422a-874d-4e8954b2ff19.png)

暗号に関する問題ですが、最初は読み方も分からないし、どこからどこまでが問題文かも理解できていませんでしたｗ

ChatGPT先生のお力も借りながら以下のとおり整理できました。


### 1. 問題の概要
このCTF問題は **ROT13 (Caesar Cipherの一種)** に関するもので、
**ROT13** はアルファベットを13文字ずらす単純な暗号方式です。

---

### 2. EBG KVVV の意味  
「EBG」は「ROT」を13文字ずらした結果です。  
「KVVV」も同様に13文字戻してみます。

```
EBG → ROT
KVVV → XIII
```

つまり、「EBG KVVV」は **「ROT XIII」** を意味しています。  
ROT13のルールに従って暗号化または復号することを示唆しています。

---

### 3. 暗号文を復号する  
次に、この文章全体をROT13で復号します。

```
EBG KVVV vf n fvzcyr yrggre fhofgvghgvba pvcure gung ercynprf n yrggre jvgu gur yrggre KVVV yrggref nsgre vg va gur nycunorg.
```

ROT13を適用すると…

```
ROT XIII is a simple letter substitution cipher that replaces a letter with the letter XIII letters after it in the alphabet.
```

→ **「ROT13は、アルファベット内で文字を13文字後ろに置き換える単純な置換暗号である。」** という意味になります。

---

### 4. 「SYNTFjmtkOWFNZdjkkNH」の解読  
最後の部分「Synt vf SYNTFjmtkOWFNZdjkkNH.」もROT13で復号すると…

```
Flag is FLAGSwzgxBJSMQWqxXXU.
```

つまり、**フラグは「FLAGSwzgxBJSMQWqxXXU」** となります。

---

### まとめ

初めてのCTF問題でしたが、かなり入門向けということもあり、全くの知識０でも調べながら解くことができました。

この問題のポイントは **ROT13を使って文章を復号する** ことでした。  
手順としては：
1. 「EBG KVVV」が「ROT XIII」を意味することを理解する。
2. 文章全体をROT13で復号する。
3. フラグ部分もROT13で復号し、答えを得る。
Salesfore Apexから外部システムのOAuthトークンを取得する

## はじめに
Apexから外部システムのOAuthトークンを取得する処理を実装しました。
（指定ログインを用いたコールアウトで、トークン取得は成功しても、認証ではじかれるケースがあったため）
認可方式は、Client Credentialsを想定しています。

## Apexの実装
```Apex
String END_POINT_AUTH = '外部システムの認証用エンドポイント';
String CLIENT_ID = '外部システムのclientId';
String CLIENT_SECRET = '外部システムのclientSecret';

HttpRequest req = new HttpRequest();
// リクエストヘッダ
req.setEndpoint(END_POINT_AUTH);
req.setMethod('POST');
String authString = CLIENT_ID + ':' + CLIENT_SECRET; 
String base64EncodedAuth = 
EncodingUtil.base64Encode(Blob.valueOf(authString));
req.setHeader('Authorization', 'Basic ' + base64EncodedAuth);

// リクエストボディ
String body = 'grant_type=client_credentials';
req.setBody(body);

Http http = new Http();
HttpResponse res = http.send(req);

// レスポンスボディをJSONとして解析
Map<String, Object> responseBody = (Map<String, Object>) JSON.deserializeUntyped(
  res.getBody()
);

// アクセストークンを取得
String accessToken = (String) responseBody.get('access_token');

```

## 補足
レスポンスボディの解釈は外部システムのレスポンスボディに合わせて変更する必要があります。
コールアウトするときには、リモートサイトの設定に外部システムのURLを設定しておく必要があります

## 参考文献 
この記事は以下の情報を参考にして執筆しました。

[OAuth Grant Types 概要](https://qiita.com/KWS_0901/items/bb2c1dae9dcb66a3c6f3)

[HTTP のクラス](https://developer.salesforce.com/docs/atlas.ja-jp.252.0.apexcode.meta/apexcode/apex_classes_restful_http.htm)

[サーバー間インテグレーション用の OAuth 2.0 クライアントログイン情報フロー](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_client_credentials_flow.htm&type=5)

[リモートサイトの設定の追加](https://developer.salesforce.com/docs/atlas.ja-jp.252.0.apexcode.meta/apexcode/apex_callouts_remote_site_settings.htm)
ハッカソンでインフラを担当してみました

※当記事は[Zenn](https://zenn.dev/mo_ri_regen/articles/hackathon2025winter)で作成した記事をQiitaにも書いています

## はじめに

[RareTECH](https://raretech.site/) という IT スクールでおこなわれたハッカソンに参加しました。
このスクールのハッカソンでは入門コース、基礎コース、実践コースの 3 つにわかれるのですが、
わたしは基礎コースのインフラを担当しました。
今回でハッカソンの参加自体は 2 回目なのですが、インフラを担当しようと思った経緯は前回のハッカソンでインフラ関係は担当者に任せきりで
理解ができていなかったので自分で実際に触って理解したいと思ったからです。

基礎コースのハッカソンでは Django を使って Web3 層構造でおこなうこと、マルチ AZ 構成で EC2 を作成することなど使用技術が限定された状態で開発します。

## 使用技術

- HTML,CSS
- Django
- MySQL
- AWS
- Docker
- nginx

わたしは Docker で開発環境の構築と AWS を作成しました。

## 構成図

AWS 自体は座学で知識がある程度で実務経験はほぼなしという状態でしたが、すぐデプロイができること、作業の消し忘れがないことを考慮して CDK を使ってデプロイしようとしました。
エンドユーザは Route53 でドメインを取得し名前解決をしたらインターネットゲートウェイ →ALB を経由して EC2 のサーバにアクセスします。RDS はコスト面を考慮して 1 つだけ設置しました。インフラ担当者は Session Manager を使って EC2 にアクセスしデプロイ作業をします。

![構成図](https://storage.googleapis.com/zenn-user-upload/d37d8888b0d4-20250306.jpg)

## スケジュール

全体のスケジュールは 2025 年 1 月 4 日から始まり 2025 年 3 月 1 日に最終発表の約 2 ヶ月程度ありました。
1 週目〜2 週目：作りたいアプリの相談、要件定義(構成図の作成)
3 週目以降は担当ごとに開発開始でした。

## 体験した感想

結局、**デプロイ作業ができません**でした。
CDK を使ってデプロイ作業をおこなったときに自分では予期しないところでセキュリティグループが生成されたせいで、インターネットに接続できないエラーを解決するのに時間がかかってしまいました。
基礎を疎かにして構築するとうまくいかないことを痛感しました。
お金がかかることを意識しすぎて先延ばしにしてしまったところもあったので、要件どおりの AWS 構築をする前に AWS の公式などから似たような構成図のものでハンズオンをするなどして理解を深めてから作業をすればよかったかなと思いました。

## 資料

- スライド

https://speakerdeck.com/morleyjp/raretechhatukason2025dong-nozhen-ctimu

- GitHub

https://github.com/Hackathon2025winter-teamC/RareTicle
複数の入力フォームにdata-testidを付与して要素を取得する方法

## 記事を書こうと考えた背景について
入力フォームに入力ができるかをテストする際に、
findByLabelTextを要素の取得を行うときに使用していました。
findByLabelTextだとラベル名が今後変ってしまう可能性があるため、data-testidの方が良いといただいたので、変更しようと思いました。
しかし、複数のフォームでそれぞれにdata-testidを付与して要素を特定するにはどのようにしたらよいのかを迷ってしまったのでまとめておこうと考えました。

# 元のコード
画面側
```App.jsx
<InputForm
        name="content"
        value={inputs.content}
        onChange={handleInputChange}
        label="学習内容"
        id="learnContent"
      />
      <InputForm
        name="time"
        value={inputs.time}
        onChange={handleInputChange}
        label="学習時間"
        id="learnTime"
        suffix="時間"
        pattern="^[0-9]*$"
      />

```
コンポーネント側
```InputForm.jsx
export const InputForm = (props) =>{
    const {name,value, onChange, label,id,suffix,pattern}=props;
    return(
        <>
        <label htmlFor={id}>{label}</label>
        <input id={id} name={name} value={value} onChange={onChange} pattern={pattern} />
        <span>{suffix}</span>
        </>
    );
};

```
テストコード
```componenteSample.spec.jsx
 describe("フォームに入力ができること", () => {
    test("学習内容が入力できる",
      async () => {
            const learnRecordForm = await screen.findByLabelText("学習内容");
            fireEvent.change(learnRecordForm, {target: { value: "test" }});
            expect(learnRecordForm).toHaveValue("test");
      }
    );
  });

  describe("フォームに入力ができること", () => {
    test("学習時間が入力できる",
      async () => {
            const learnTimeRecordForm = await screen.findByLabelText("学習時間");
            fireEvent.change(learnTimeRecordForm, {target: { value: 12 }});
            //入力した値を数値に変換して入力値と等しいかを比較する。
            expect(Number(learnTimeRecordForm.value)).toBe(12);
      }
    );
  });
```
# 行ったこと
* 入力フォーム（画面側の表示をしているファイル）でプロパティとしてidを使用し、コンポーネント側にpropsとしてidを渡します。
コンポーネント側でpropsを受け取り、受け取ったidをdata-testidを使用して、どちらの入力フォームであるかを特定できるように定義しました。

* findByLabelTextではなく、findByTestIdで要素の取得をするように変更しました。
## 修正したコード

画面側
特に変更していないので元のコードと同じです。

コンポーネント側
```InputForm.jsx
export const InputForm = (props) =>{
    const {name,value, onChange, label,id,suffix,pattern}=props;
    return(
        <>
        <label htmlFor={id}>{label}</label>
        <input id={id} name={name} value={value} onChange={onChange} pattern={pattern} data-testid={id} />
        <span>{suffix}</span>
        </>
    );
};

```
テストコード
```componenteSample.spec.jsx
describe("フォームに入力ができること", () => {
    test("学習内容が入力できる",
      async () => {
            const learnRecordForm = await screen.findByTestId("learnContent");
            fireEvent.change(learnRecordForm, {target: { value: "test" }});
            expect(learnRecordForm).toHaveValue("test");
            screen.debug(learnRecordForm);
      }
    );
  });
  describe("フォームに入力ができること", () => {
    test("学習時間が入力できる",
      async () => {
            const learnTimeRecordForm = await screen.findByTestId("learnTime");
            fireEvent.change(learnTimeRecordForm, {target: { value: 12 }});
            //入力した値を数値に変換して入力値と等しいかを比較する。
            expect(Number(learnTimeRecordForm.value)).toBe(12);
            screen.debug(learnTimeRecordForm);
      }
    );
  });
```
Pythonのrequestsでセッションを利用する

# Pythonのrequestsでセッションを利用する

Webスクレイピングでセッションを保持する場合は、requests.Session() を利用するのが簡単です。

**手順）**

1. requests.Session() でセッションを保持する
2. get()、post()で操作を行う

**ポイント）**

- withを利用することでセッションのクローズ忘れを防止できる

**サンプル）**

単純にセッションを利用してページの情報を取得したサンプルです

```python:requests_test.py
import requests

def main():
    # セッションを利用する
    with requests.Session() as sec:

        # URLからページ情報を取得する
        url = r'https://pystyle.info/apps/scraping/'
        res = sec.get(url)

        # 失敗の場合は例外を発生する
        if not res.ok:
            raise f"ページの取得に失敗しました。status: {res.status_code}, reason: {res.reason}"
        else:
            print(res.status_code) # ステータスコード
            print(res.text) # 本文

if __name__ == '__main__':
    main()
```
Android StudioをWaylandでネイティブに実行する

# Android Studioについて
Android向けアプリ開発のためのIDEです。IntelliJ IDEAというIDEがベースになっています。

# 今回使用したバージョン
android-studio 2024.3.1.13

# シェル変数でWaylandでネイティブに実行する
Wayland上で実行するとき、そのままだと、XWayland上で実行されます。特に拡大倍率が整数倍でないときには、文字がにじんで、非常に読みにくくなります。
Waylandでネイティブに実行するには、次のようにオプションを追加して起動します。

```
$ android-studio -Dawt.toolkit.name=WLToolkit
```
文字がにじまず、読みやすくなりました。

# Hyprlandで実行する場合の注意
NvidiaのGPUを使用している場合、`cursor.no_hardware_cursors`がデフォルトのままだと、マウスが表示されなくなります。ハードウェアカーソルは無効にしておきましょう。

# 参考

https://blog.jetbrains.com/platform/2024/07/wayland-support-preview-in-2024-2/

https://www.reddit.com/r/archlinux/comments/117sk8u/invisible_cursor_issues_hyprland_nvidia/
【ChatGPT】人の言っていることに確証はあるのかをチェックするPromptです。


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

　今回は、【ChatGPT】人の言っていることに確証はあるのかをチェックするPromptです。

:::note info
本記事は、ChatGPT（Plus版）
で行なっております。
画像はありません。あしからず。
:::
　ChatGPT等の動作状況を知らせる
　　OpenAIのステータスページ。
　　　[OpenAIステータス](https://status.openai.com/)
***
　こちらも載せますね。
　　[ChatGPTが使えない？ログインできない・反応しない原因やエラー時の対処法を解説](https://aismiley.co.jp/ai_news/chatgpt-error-resolution-explanation/)
***
　まずは、ニュースです。

　フィクションに
　　特化したAI「Muse」が
　　　発表されました。

　文学を愛し、
　　物語の執筆だけに
　　　専念したAIモデルだとか。

　[木内翔大さんポスト](https://x.com/shota7180/status/1898493478184910927?t=LkDM58SLfmRArLIJlYk6KA&s=19)

　アクセスしてみましたが、
　　パソコンでの操作に
　　　特化しているらしく、
　　　　“解像度が低い”って
　　　　　メッセージをもらいました😅

　それでも
　　ログイン画面には
　　　説明書きがありましたので
　　　　読んでみました。

　　ほほすべての言語に
　　　対応している、とか。

　　なぜか、単独で
　　　“ChatGPT”と三度も出てきます。

　　よくある質問には、
　　　複数のモデルから
　　　　トレーニングした、と
　　　　　書かれています。

　どうなのかは
　　みなさんにお任せしますね。
***
　では、【本題】です。

　今回は、
　　人の言っていることに
　　　確証はあるのかを
　　　　チェックするPromptです。

　先日、
　　性格判断のような記事があり、
　　　ChatGPTにチェックして
　　　　もらいました。

　記事の内容には触れませんが、
　　“そんなわけあるかい！”と
　　　言いたくなる内容でした。
　　　　それでチェックして
　　　　　みたわけです。

　記事には、なんの確証も
　　書かれていなかったのもあって、
　　　信じられなかったのです。

　まぁ、チェックの結果、
　　その記事の背景には
　　　確かに統計が取られて
　　　　あったようです。
***
　それはともかく、
　　なんでも鵜呑みにせず、
　　　調べてみるのが、最善です。

　しかし、
　　内容によっては、
　　　途方もない量を相手にして
　　　　調べねばなりません。

　その点、
　　ChatGPTなどがあるので
　　　そうした調査も
　　　　やりやすくなりました。

　さて、
　　こちらが、そのPromptです。
　　　＊＊＊に検証したい内容を
　　　　コピペして、送信してください｡
```Text:有効性を検証するPrompt
下記の有効性を検証して。

（＊＊＊）
```

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

　今回は、ここまで。
Javaの三層構造について

# はじめに
* 備忘録として残しておこうかと
* 業務でJavaを使用することを想定し、慣れるためにTODOアプリを開発してみました

# 三層構造（Layered Architecture）
1. **コントローラー層（Controller Layer）**  
   - 各操作をルーティングしてレスポンスを返す
   - クライアントからのリクエストを受け取り、適切な処理を `Service` に委譲  
   - 必要に応じてリクエスト/レスポンスの変換を行う  
   - 最終的なレスポンスを返す

2. **サービス層（Service Layer）**
   - データの作成、削除、更新、読み取りといったクエリに相当するロジックを担当（今回はJPAというAPIを使用）  
   - ビジネスロジックを担当し、データの作成・更新・削除・取得を管理  
   - JPA を利用して `Repository` にアクセスし、データを操作  
   - トランザクション管理を行うことも多い

3. **モデル層（Model Layer）**  
   - データの構造を定義する（エンティティ、DTO、VO などを含む）  
   - JPA の `@Entity` を用いてデータベースのテーブルと対応するクラスを定義  
   - ビジネスルールを持たせることもある 

## コントロール層が持つ機能
* サービス層で作成したロジックを呼び出す
* 例えばTODOアプリで入力したタスクを呼び出すルーティング
```java
@GetMapping("/read")
public ResponseEntity<List<Todo>> readTodos() {
    List<Todo> todos = todoService.getAllTodos();
    return ResponseEntity.ok(todos);
}
```

* サービス層の`todoService`に関するクラスからリスト構造の`getAllTodos`メソッドを呼び出す

# サービス層が持つ機能
* JPAのAPIを呼び出す
* 実際のデータ処理を担当する

# モデル層が持つ機能
```java
package com.example.todo_backend.model;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "todos")
@Getter
@Setter
public class Todo {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    private String title;
    private boolean completed;
}
```
* データ構造を定義する
* アノテーションでメタ情報を付与させる
    * 例えば、`＠Id`の場合では、主キーを指定
* privateをつける意図として、外部から直接アクセスできないようにするため
    * カプセル化するため
        * 内部処理へ依存させることでエラーを特定しやすく

# 工夫点や学んだこと

## リスト構造について
* なんとなく使用していたが、調べてみるとリスト構造というのは柔軟性のあるデータ構造であることがわかった
    * `ArrayList` は **サイズを動的に変更できる**（TS の `Array<T>` と異なる)
    * `LinkedList` のような異なる実装もあるみたいでとても奥深い...
* TSをメインに開発していた人間からは想像できないような構造で驚いた

## ゲッターセッターを使用
* Nullや空文字を防ぐバリデーションの役割がある
* 直接アクセスでなく、ゲッターセッターを通してなのでカプセル化を守れる

## アノテーションすげえ...
* @とつけるだけで色々な情報を付与できるのはとても便利
* @EntityでDBと紐づけできたり、@Idで主キーを設定できたりととても便利

# さいごに
* 今回のTODOアプリ開発を通じて、SpringBootの基本的なアーキテクチャやJPAを使ったデータ操作について学ぶことができた。今後は以下の点を改善・発展させたい

- **バリデーションの強化**  
  - セッターを使ったチェックに加えて、`@Valid` を使ったバリデーションを導入したい。
- **フロントエンドとの連携を強化**  
  - CORS の設定を環境ごとに変えられるようにして、本番環境でも適用できる形にする。
  - JWTを使った認証機能
      - その際は、DB設計を見直さねば

* この備忘録を通じて、自分の学びを整理することができました。引き続き開発しながら学ぶようなスタイルでWeb開発の知見を深めたいな～と思います！
v6プラス環境下でIPv4/IPv6デュアルスタックを実現する方法

# はじめに
筆者は、So-netのv6プラス環境下で、自宅サーバーを構築しているのですが、まだまだIPv4接続の需要は高く、IPv6接続一本に絞るというわけにはいかないのが現状です。
ということで、Arch LinuxサーバーにPPPoEパススルーを使って、v6プラス環境下でもIPv4/IPv6デュアルスタックを使えるようにしたときのメモを残しておきます。

# PPPパッケージのインストール
プロバイダとの間にPPPoEセッションを張るために、PPPを使用します。
```shell-session:shell
$ sudo pacman -S ppp
```

# 接続設定ファイルの編集
## 接続設定
まず、接続設定を行います。
/etc/ppp/peers/dsl-providerを編集します。

```shell:/etc/ppp/peers/dsl-provider
# PPPoE Plugin
plugin pppoe.so

# Network Interface
eth0

# Login Name
name "LOGIN NAME"

# Settings
usepeerdns
persist
defaultroute
replacedefaultroute
hide-password
noauth
noproxyarp
```
ここでは、外部とのネットワークインターフェースはeth0であることを想定しています。異なる場合は、適宜読み替えてください。*LOGIN NAME*には、プロバイダから付与されている接続ユーザーのログイン名を書き込んでください。

## シークレットファイル
つぎに、シークレットファイルを編集します。
/etttc/ppp/chap-secretsにログイン名とパスワードを書き込みます。
```shell:/etc/ppp/chap-secrets
"LOGIN NAME" * "PASSWORD"
```
*LOGIN NAME*と*PASSWORD*はそれぞれプロバイダから付与されている接続ユーザーのログイン名とそのパスワードを書き込んでください。

## 設定ファイルの有効化
先に編集したdsl-providerファイルを有効化します。
```shell-session:shell
$ sudo ln -s /etc/ppp/peers/dsl-provider /etc/ppp/peers/provider
```

# 接続と切断
## 接続
PPPoE接続を確立するには、以下のコマンドを使います。
```shell-session:shell
$ sudo pon
```
接続できているかどうかの確認をします。
```shell-session:shell
$ ip a
```
これでppp0が表示されていればOKです。

## 切断
PPPoE接続を切断するには、以下のコマンドを使います。
```shell-session:shell
$ sudo poff provider
```

## ppp0をデフォルトルートに追加
PPPoE接続で張ったppp0をデフォルトルートに追加します。
```shell-session:shell
$ sudo ip route add default dev ppp0
```

# 起動時に自動接続
起動時に自動的にPPPoE接続を確立するようにします。
まず、/etc/modules-load.d/ppp_generic.conf
というファイルを作成し、そこに以下の内容を書き込みます。
```shell-session:/etc/modules-load.d/ppp_generic.conf
ppp_generic
```
つぎに、ppp@providerサービスを有効化します。
```shell-session:shell
$ sudo systemctl enable ppp@provider.service
```
これで、起動時に自動的にPPPoE接続が確立され、IPv4での通信が可能になります。

# まとめ
今回は、v6プラスでPPPoEを使ってIPv4/IPv6デュアルスタックを実現する方法を紹介しました。ただし、この方法はプロバイダがPPPoE接続を許可していることが前提となります。
PPPoE接続が許可されていない場合には、どうしたらよいのかは分かりません。もし良い案がありましたら、コメント頂けると幸いです。
それでは、よいLinuxサーバーライフを。
SaaSってなに！？

# SaaSってよく見るよね
エンジニアに転職してはや2年が経過しようとしています。
保険営業という全く別の業界から転職してきた私はいまだに困惑していることがあります。

**「この業界ってアルファベットだけの略称が多くないか！？」**

特によく見かけるのが今回触れたい"SaaS"

毎回聞くたびに調べてはなんとなく「へーそんな感じね🤔」で終わらせていましたが、今日を持ってそんな無駄な時間とはおさらばしたい！

ということで、今回は備忘録も兼ねてSaaSについてまとめていきます。
（生成AIさんの力を存分に借りつつ…）

# そもそも何の略？
SaaSとは「Software as a Service」の略。直訳で「サービスとしてのソフトウェア」
インターネット経由でソフトウェアを利用できるクラウドサービスの一形態です。

# 特徴
**即時利用可能**
ソフトウェアをインストールする必要がなく、クラウドにアクセスすることで契約後すぐに利用可能

**運用負担軽減**
物理サーバーを置いて自身で管理が不要で、更新やメンテナンスは提供者側が実施

**コスト削減**
初期投資が少なく、月額料金などで利用可能

**複数人での利用**
同時アクセスやデータ共有が容易

# 代表例
**グループウェア**
企業内での情報共有や業務効率化を目的としたツール。
例: Google Workspace、Microsoft 365、サイボウズ Office

**コミュニケーションツール**
チーム間の連絡やプロジェクト管理に特化したツール。
例: Slack、Chatwork、LINE WORKS

**ストレージサービス**
オンライン上でデータを保存・共有するサービス。
例: Google Drive、Dropbox

**会計・経理ソフト**
経理業務を効率化するためのサービス。
例: 弥生会計オンライン、Money Forward クラウド、freee

**SNS**
個人や企業が情報発信・交流を行うプラットフォーム。
例: Facebook、Twitter、Instagram

# 他のモデルとの違い
ここまで読んでくださった方。言いたいことはわかります。
見たことあるのはSaaSだけではないですよね？他にも似たようなのがありますよね？

詳細までは触れませんが、他のクラウドサービスモデルとの違いはこんな感じ。
|モデル|概要|例|
|:-:|:-:|:-:|
|SaaS|完成されたソフトウェア提供|Salesforce, Dropbox|
|PaaS|アプリ開発用プラットフォーム提供|Google App Engine|
|IaaS|サーバーやネットワークなどインフラ提供|AWS, Microsoft Azure|

※IaaS: Infrastructure as a Serviceの略
※PaaS: Platform as a Serviceの略

意外と身近なところで関わっていたんですね☝️

# 参考
http://cloud-ace.jp/column/detail297/

https://digital-shift.jp/flash_news/s_210518_4

https://cloud-ace.jp/column/detail01/
# Pythonの `load_dotenv()` とは？

# Pythonの `load_dotenv()` とは？

`load_dotenv()` は、Python の `dotenv` ライブラリに含まれる関数で、環境変数を `.env` ファイルから読み込むために使います。

---

## 🔹 `load_dotenv()` の基本

まずは `dotenv` ライブラリをインストールしましょう。

```sh
pip install python-dotenv
```

次に、Pythonスクリプトで `load_dotenv()` を使って `.env` ファイルを読み込みます。

```python
from dotenv import load_dotenv
import os

# .env ファイルを読み込む
load_dotenv()

# 環境変数を取得
api_key = os.getenv("API_KEY")
print(api_key)
```

これで、`.env` に書いた環境変数が Python で使えるようになります！

---

## 🔹 `.env` ファイルの例

`.env` ファイルは、プロジェクトのルートディレクトリに配置し、環境変数を定義します。

```env
API_KEY=your_api_key_here
DATABASE_URL=postgres://user:password@localhost:5432/mydatabase
```

`.env` 内の変数は `os.getenv("変数名")` を使って取得できます。

---

## 🔹 `load_dotenv()` のメリット

### ✅ 1. 環境変数を簡単に管理
`.env` に書いた情報を `os.environ` に読み込むことで、環境ごとに設定を切り替えやすくなります。

### ✅ 2. セキュリティの向上
APIキーやデータベースURLなどの機密情報をソースコードに直接書かなくて済むので、安全性がアップ！

### ✅ 3. Docker やクラウド環境でも便利
ローカルと本番環境で異なる設定を簡単に切り替えられます。

---

## 🔹 `load_dotenv()` のオプション

### 🔸 `.env` ファイルのパスを指定

デフォルトではカレントディレクトリの `.env` を読み込みますが、別のパスを指定することも可能です。

```python
load_dotenv(dotenv_path="/path/to/.env")
```

### 🔸 既存の環境変数を上書き

デフォルトでは、既に環境変数に設定されている値は `.env` の値で上書きされませんが、`override=True` を指定すると上書きできます。

```python
load_dotenv(override=True)
```

---

## 🔹 まとめ

| 項目 | 説明 |
|------|------|
| **関数** | `load_dotenv()` |
| **目的** | `.env` から環境変数を読み込む |
| **メリット** | セキュリティ向上・環境管理が簡単 |
| **オプション** | `dotenv_path` でファイル指定、`override` で上書き |

環境変数を安全に管理するために、`load_dotenv()` を活用しましょう！