OmniAICreator/Qiita-1.07M huggingface dataset:
📌 WebSphere の管理コンソール URL の確認方法

### 1. デフォルトのポート
WebSphere は デフォルトで 9060 ポート を使用しますが、環境によって異なる場合があります。

WebSphere の管理コンソール	デフォルト | URL
| ---| ---| 
WebSphere Admin Console (HTTP)	| http://localhost:9060/ibm/console
WebSphere Admin Console (HTTPS)	| https://localhost:9043/ibm/console

⚠ 注意:
9060 → HTTP の管理コンソール (デフォルト)
9043 → HTTPS の管理コンソール (デフォルト)
これらのポート番号は WebSphere のプロファイル設定によって変更可能。

### 2. 実際の管理コンソール URL を確認する方法
方法 1: server.xml を確認
WebSphere のプロファイルフォルダー (profiles/AppSrv01/config/cells/) を開く
server.xml ファイルを探す (WAS_HOME/profiles/AppSrv01/config/cells/ 内)
server.xml を開き、以下のような記述を確認
```
<server description="server1">
    <featureManager>
        <feature>adminCenter-1.0</feature>
    </featureManager>
    <httpEndpoint id="defaultHttpEndpoint" httpPort="9060" httpsPort="9043"/>
</server>

```
→ httpPort="9060" の部分が 管理コンソールの HTTP ポート
→ httpsPort="9043" の部分が 管理コンソールの HTTPS ポート
fortigateメモ

1. WAN側インターフェースのIPアドレス設定

「Network」 > 「Interfaces」でWAN側インターフェースを選択し、「Edit」をクリックします。
IPアドレス/ネットマスクの設定を確認し、外部からアクセス可能なグローバルIPアドレスが設定されていないこと、またはNAT/PAT設定により内部ネットワークが外部から直接アクセスできないことを確認します。
この設定画面をキャプチャし、証跡として保存します。
2. ファイアウォールポリシーの確認

「Policy & Objects」 > 「Firewall Policy」に移動します。
WAN側インターフェースをIncoming Interfaceとするポリシーを確認し、外部からのアクセスを許可するポリシーが存在しないこと、または必要なアクセスのみ許可されていることを確認します。
特に、Any/Anyのような広範な許可ポリシーがないことを確認します。
このポリシーリストと、関連するポリシーの詳細設定画面をキャプチャし、証跡として保存します。
Autoppt、280slides.comを継承──AI技術で伝説的プラットフォームを再生

シリコンバレー、2025年3月13日

かつてシリコンバレーで注目を集めたプレゼンテーションプラットフォーム「280slides.com」が、新たな時代へと歩みを進める。AI駆動のプレゼンテーションツールを提供する新進気鋭のAutopptが、同サイトのドメインとミッションを正式に引き継いだ。この移行に伴い、280slides.com は 301リダイレクトを通じて Autoppt.com へと統合。革新的な技術を取り入れつつ、その歴史を未来へとつなぐ動きが加速している。

2010年にローンチされた280slides.comは、当時最先端のオンラインPPT作成・共有ソリューションとして、クラウドベースのスライド制作の利便性を広め、多くのユーザーを魅了した。しかし、創業メンバーの新事業への移行や運営上の課題により、2011年にサービスを終了。それでもなお、プレゼンテーションソフトの歴史に名を刻み、後のイノベーションに影響を与えた。

https://280slides.com/

![ai ppt maker autoppt.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4016113/4b434912-628c-413b-a040-b56ab5a4f4ab.png)

そんな280slidesの精神を受け継ぐのが、AIプレゼンテーションツールの最前線を走るAutopptだ。AIを活用したスライド生成により、わずか数分でプロフェッショナルなプレゼンテーションを作成。インテリジェントなデザイン自動化機能やオンライン発表機能を備え、初心者から上級者まで幅広く対応する直感的なUIを提供する。この移行は、280slidesが掲げていた「手軽でアクセスしやすいプレゼン作成」という理念を継承しつつ、AIの力でさらなる進化を遂げるものだ。

「280slidesのドメインに新たな命を吹き込めることを嬉しく思います」
AutopptのPRマネージャーであるハンナ・クラーク氏はこう語る。
「280slidesが築いた利便性とアクセシビリティに、AutopptのAI技術を融合させ、ユーザーがよりパワフルにアイデアを形にできる環境を提供します」

この301リダイレクトにより、検索エンジンやユーザーにとってシームレスな移行が実現。280slidesの歴史的価値を保持しながら、最先端のプレゼンテーション体験へと導く。Autopptは、デジタル時代におけるプレゼンテーションの可能性を押し広げることを約束する。

AutopptとそのAIプレゼンテーションツールの詳細については、https://autoppt.com/ をご覧ください。
Simple Membershipのログイン画面のラベル変更

# 概要
WordPressのSimple Membershipを使って会員機能を実装する際に
ログインフォームの文言を変更したのでその記録です。

# 実際のコード
```functions.php
function modify_swpm_login_labels() {
    add_filter('swpm_login_form_set_username_label', function($label) {
        return 'メールアドレス';
    });
}
add_action('init', 'modify_swpm_login_labels');
```
swpm_login_form_set_username_label
というフックがありそれを使うことで変更できます。
今回は「ユーザー名またはメールアドレス」というラベルだったものを
「メールアドレス」に変更しました
y と z でターミナルのディレクトリ移動を効率化


[zoxide]: https://github.com/ajeetdsouza/zoxide
[yazi]: https://yazi-rs.github.io/docs/quick-start
[fzf]: https://github.com/junegunn/fzf
[TUI]: https://ja.wikipedia.org/wiki/テキストユーザインタフェース

## はじめに

ターミナルでのディレクトリ移動は、開発の生産性に直結する重要な操作です。
一般的には `cd` コマンドを使いますが、より効率的な代替手段もあります。

そこで紹介するのが `y` → `z` ワークフロー です。
これを活用することで、ディレクトリ移動やファイル操作をよりスムーズに行えます。

---

## `y` → `z` ワークフロー

`y` と `z` に特別な意味はありませんが、アルファベット順で `c` と `d` のように連続しているため、`cd` の代替として直感的に覚えやすいです。

以下のツールを組み合わせて利用します。

- [zoxide]: 頻繁に使うディレクトリを記憶し、柔軟な移動を可能にする `cd` の代替ツール
- [yazi]: [zoxide] と統合可能な 高速 TUI ファイルマネージャ
- [fzf]: 対話的にディレクトリを検索できる ファジーファインダー

---

## zoxide を使ったディレクトリ移動

[zoxide]は、頻繁に使うディレクトリを自動的に記憶し、効率的なディレクトリ移動を可能にするツールです。
`cd` の代わりに `z` コマンドを使うことで、ディレクトリ移動をスムーズに行えます。

### `z` コマンド

例えば、`~/long/path/to/project` に移動したい場合、`cd ~/long/path/to/project` と毎回入力するのは面倒です。
そこで `z project` を使えば、簡単に目的のディレクトリへ移動できます。

```sh
z project  # 「project」ディレクトリへ即移動
```

### `zi` コマンド（[zoxide] + [fzf]）

`zi` を使うと、[zoxide] で記憶されたディレクトリを[fzf] で対話的に選択して移動できます。
ディレクトリ名の一部を入力するだけで、瞬時に目的地のディレクトリを選べるのが便利です。

```sh
zi  # 記憶されたディレクトリをファジー検索して移動 (`Esc` または `Ctrl+C` でキャンセル)
```

---

## yazi を使ったファイル操作とディレクトリ移動

[yazi]は、軽量・高速・カスタマイズ可能な[TUI]ファイルマネージャです。
[zoxide]を統合することができます。

### `y` コマンド

`y` コマンドで [yazi] を開いた後に `z` キーを押すと、`zi` コマンドと同様に [zoxide] の履歴からディレクトリを素早く選んで移動できます。
そのまま[yazi] を閉じれば、TUI 内で移動したディレクトリにターミナルのカレントディレクトリも切り替わります。
ファイルを一覧しながら目的のディレクトリを探し、終了後にスムーズに作業を続けられるのが便利です。

```sh
y  # yazi を開く (終了するには `q` を押す)
```

`y` コマンドは、ファイルの閲覧や操作をしたいときに便利ですが、
単にディレクトリを移動するだけなら、ターミナルで直接`z`や`zi`を使う方が速い場合もあります。

---

## まとめ

`y` → `z` ワークフローを活用すると、ターミナルでのディレクトリ移動が効率化できます。

- `z`（[zoxide]）を使えば、頻繁に使うディレクトリへ素早く移動
- `zi`（[zoxide] + [fzf]）なら、ディレクトリを対話的に検索して移動
- `y`（[yazi]）なら、視覚的にディレクトリを探索しながら管理可能

TUI ファイルマネージャが不要な場面では `z` や `zi` を使い、ファイルの閲覧や操作が必要なときは `y` を活用すると便利です。

![toukon-qiita-macbook_20230912_091808.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82804/fd5c55ec-4fe0-8af6-59bc-bab1ef3d182b.jpeg)
Google Play Consoleでの住所変更方法

# 概要

Google Play Consoleでの住所変更方法について解説。

# 方法

1. 左下の`設定`ボタンクリック→`収益化`欄の`お支払いプロファイル`をクリック
![住所変更1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/694762/91df4520-7e82-447c-8b2a-7b0fe858ab8c.png)

2. 右下の`設定を管理する`をクリック→`お支払いプロファイル`の`住所`の右にあるペンアイコンをクリック

3. 住所変更後、下にスクロールして右下にある青色の`保存`ボタンをクリック

4. 右上の`更新`ボタンをクリック
プログラミングよくわからんケモノのABC397

## [ABC397](https://atcoder.jp/contests/abc397)感想
D問題のインパクトがすごい。

## [A問題](https://atcoder.jp/contests/abc397/tasks/abc397_a)
平熱、発熱、高熱を判定するプログラムを作成しろってだけの問題です。

まあただ数値を判定すればいいんですが、小数なので型がfloatであることには気をつけましょう。（一敗）
ちなみに特に10倍にする意味はありません。あんまりfloatを使ったことが無いので不安でこうしましたが、型違いによる判定不可とかになりかねない行為なので、気を付けていきたいです。

```python abc397_a.py
print(3 if (x := float(input()) * 10) < 375 else 2 if x < 380 else 1)
```

## [B問題](https://atcoder.jp/contests/abc397/tasks/abc397_b)
入出の数を合わせろって問題です。

色々やりようはあると思いますが、素直に前から見ていき、
1.　1文字目がoなら修正数+1
2.　2文字目がiなら修正数+1
3.　リストの前2文字がi, oであれば、リストを2文字、そうではないなら1文字抜く
とやるのがシンプルだと思います。
後は最後の文字がiだった場合追加で修正+1を入れたり、前から抜いていくのでリストではなくqueueを使用したり、ちょっとした調整をしているくらいです。

```python abc397_b.py
import sys
import collections as cs

l = cs.deque(sys.stdin.readline())

ans = 0
while l:
  p = l.popleft()
  
  if p == "i":
    if not l:
      ans += 1
    
    elif l[0] == "o":
      l.popleft()
      
    else:
      ans += 1
      
  if p == "o":
    ans += 1
    
print(ans)
```

## [C問題](https://atcoder.jp/contests/abc397/tasks/abc397_c)
左右の種類数の和を最大化しろって問題です。

と言っても、仕切りを前後に動かすしかないので、シンプルに前から見ていけばいいと思います。
確認をとっていませんが、流石に一々種類数を数えると間に合わなくなるので一工夫必要ですが、左は入ってきた数字が初めての数字かを確認し、右は抜けた数字が最後の一個であるかを確認すればいいだけです。

左はset、右は辞書型で管理すれば問題ないでしょう。
ちなみに私は左は辞書型で管理しました。お好みで調整してください。
```python abc397_c.py
import sys
import collections as cs

N = int(sys.stdin.readline())
l = cs.deque(map(int, sys.stdin.readline().split()))

right_dict = {}
for i in l:
  if i not in right_dict.keys():
    right_dict[i] = 1
    
  else:
    right_dict[i] += 1

left_dict = {}
left_piece, right_piece = 0, len(right_dict.keys())
ans = 0
while l:
  i = l.popleft()
  right_dict[i] -= 1
  
  if right_dict[i] == 0:
    right_piece -= 1
    
  if i not in left_dict.keys():
    left_dict[i] = 1
    left_piece += 1

  ans = max(ans, left_piece + right_piece)
  
print(ans)
    
```
Git怖くないシリーズその1(全5回)：Gitへのパラダイムシフト


## CVS/SVNとの違い(1/2)
- CSV/SVNは集中
- Gitは分散
    - リポジトリはどこにでも置ける（開発PC／サーバ）
    - 通常はマスターとなるリポジトリをサーバに置く
※GitHubはGitリポジトリのホスティングサービス

----

## CVS/SVNとの違い(2/2)
- CVS/SVNはファイル単位での履歴管理
- Gitはプロジェクト全体での履歴管理

個人的にはこの違いに最もとまどった！

----
## Gitの特徴
- SVNのチェックアウトに相当する機能はない
   ※checkoutという操作はあるが、SVNとは機能が異なる
- **簡単に衝突する**
  →Gitではマージが日常的に発生します！

----
## 重要な機能・コミット
- プロジェクトの状態を記録する
- Gitは乱暴に言えばコミットの集合体
- コミットには前後関係がある

----
## 重要な機能・ブランチ
- ある状態から派生した別のコミットの集合
- まさに、枝分かれのイメージ
- 開発はブランチをうまく使って進めていく

----
## 典型的なブランチ戦略の概要
- アプリの「正」となる状態のブランチを１つ定める
  mainと名付けることが多い
- 開発者はタスク毎にmainから派生したブランチを作り、そこで作業する
- 開発が完了したら、管理者がmainに開発用ブランチをマージする
  GitHubはプルリクエスト、GitLabはマージリクエストを作成する

----
## ブランチ戦略の利点
- 開発者用のブランチは開発者の自由！
   - いつでもコミットできるので、セーブポイントを作れる
   - 実験するときなど、自分のブランチを更に派生させられる
- ブランチ同士を比較することで差分比較が簡単
- ネットワークがない状態でも作業可能
  基本的にはローカルPCにも全履歴が保持されるため

----
## マージ
- Gitにはmergeというコマンドがあり、別のブランチの修正を取り込むことが可能
- 同じファイルに修正が入っている場合・・・
   - 同一行でなければ自動でうまいことマージ
   - 同一行に修正があった場合は衝突。この場合は手動で解決する必要あり

----
## ここで疑問が生じませんか？
・・・そんなにマージが頻繁に起きるの、怖くない？


----
怖いです！！

----
## 最後に
- 次回はマージの対する考え方を話します
- 確実に言えるのは、Gitは**大規模開発の運用でも有用** ということ
  LinuxのソースコードはGit管理されています！
Gemeniの画像生成に驚いてみる

こんにちは。AI驚き屋です。今日はGemeniの画像生成機能について驚いてみようと思います。

[Gemini新機能の画像加工がついにテキスト指示だけで背景の構図も自由自在に変えたり、出力したキャラを回転させられるように。 - Togetter [トゥギャッター]](https://togetter.com/li/2524944)

使ってみましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/dba16e58-eee0-4ef1-a010-aa5f46873016.png)

結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/b971d3a5-6e76-4faa-9ab3-f87131dce79f.png)

おいwww

まぁソースにしたイラストは友人に描いてもらったものであり、AIで再現されると微妙に嫌だったので出オチ感が合ってよかったです。

…と思ったけど、私が使ったのはGemeni 2.0 Flashだったので、Google AI Studioから使えるGemini 2.0 Flash Thinking Experimentalを使って見ましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/c5b28c3e-0617-4c84-9957-8b6aea6c423d.png)

え…マジ…。いや、ちゃんとできてるわ。

いや、元絵に比べたら可愛さは減っているが「正面から見た構図」というリクエストには完璧に答えてますな…。

イラストとは外れますが、リアル写真の消しゴムマジック的なものもできるし、こうなったら作業者側が「このイラスト、こうしたいな～」という、今までやろうと思っても出来ないから考えなかったような思想を持つ必要がありますね。
UNIXとUNIX系OS

## UNIXについて
　**UNIX**は元々、アメリカAT&T社のベル研究所で開発され、大きく分けて2つの路線で発展してきました。ひとつは、ベル研究所の作ったUNIXを受け継ぐ**System V（ファイブ）系**と呼ばれるもので、もうひとつは、カリフォルニア大学バークレー校で開発されたものを受け継ぐ**BSD系**です。
　UNIXは、専用のワークステーションなどで動作するものでしたが、これらを個人向けのパソコンで動作するように移植したものをPC-UNIXと呼びます。**Linux**はPC-UNIXの代表ですが、UNIXのソースコードを流用していないため、**UNIX系OS**と呼ばれることもあります。
　UNIXの他の分類方法としては、研究機関向けに公開された情報をもとに、大手コンピューターメーカーが自社コンピュータ製品向けに商品として開発・販売してきたもの（**商用UNIX**）と、有志ユーザーが協力し合って開発を続け、基本的には無償で提供することを前提としているものがあります。

## UNIXの系譜
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/387980/ddc357d6-835c-4f26-b27b-1c6e6c99e94b.png)


 ## おわりに
ここまで読んでいただきありがとうございます！

## 参考文献
・Linuxの絵本 サーバーOSが楽しくわかる9つの扉 単行本（ソフトカバー） – 2020/1/20
株式会社アンク (著)　p.xiii
【Unity初心者】チュートリアルとしてブロック崩しを作成する 2 準備編

[前回](https://qiita.com/taltalkurage/items/eab4733c442d70c4d014) 環境準備まで行ったのでいよいよ作成に取り掛かってみるまえに今回Unityでよく使いそうなものをあらかじめまとめておく



# 2Dオブジェクトの作成方法

Hierarchyで右クリック
2D Object -> Sprites
Circle: 円
Square: 四角形

# プレハブの作成方法

Projectにドラック＆ドロップする

# 当たり判定の付け方

rigid bodyで物理エンジンをつけて、colliderで当たり判定をつける

# よく使いそうなComponent
## `Rigid body 2D`
> Rigidbody 2D コンポーネントにより、オブジェクトを物理エンジンで制御することができます。標準の Rigidbody コンポーネントの多くの概念は Rigidbody 2D に引き継がれます。ただし、Rigidbody 2D では、オブジェクトは XY 平面でのみ移動し、この平面に垂直な軸でのみ回転します。
http://docs.unity3d.com/ja/2018.4/Manual/class-Rigidbody2D.html


## `Circle collider 2D`
> Circle Collider 2D クラスは 2D 物理挙動で使うコライダーです。コライダーの形状は円で、位置や半径は Sprite のローカル座標空間で定義されています。
https://docs.unity3d.com/ja/2018.4/Manual/class-CircleCollider2D.html

## `Box collider 2D`
> Box Collider 2D コンポーネントは 2D 物理挙動で使用するコライダーです。コライダーの形状は四角形であり Sprite の位置、幅、高さを スプライト のローカル座標空間で指定します。四角形は軸に沿って位置し、四角形の辺はローカル空間の X 軸、または Y 軸に対して平行です。
https://docs.unity3d.com/ja/2018.4/Manual/class-BoxCollider2D.html

ブロック崩しでつかいそうなものはこんなところ

次はC＃についてでもまとめる予定です
Claude 3.7 Sonnetの図解作成に驚き、draw.ioやPPTXで編集してみる

AI驚き屋です。世間で話題のClaude 3.7 Sonnetに図解をさせ、draw.ioやPPTXで編集してみようと思います。

- [【決定版】 Claude 3.7 Sonnetで作成した図解やプレゼンをPowerPointで編集可能にする方法（HTML対応）｜Mavericks, Inc](https://note.com/note_maverick/n/nd07e0f245dae)
- [全ビジネスマンが使えるClaude3.7 sonnet と draw.ioで始める図の作成。｜遠藤巧巳 - JapanMarketing合同会社](https://note.com/japanmarketing/n/n6d73751105cc)

簡単に説明すると、以下です。

- Claude 3.7 Sonnetで図解を作成
    - draw.ioで編集をする場合
        - draw.ioで編集可能なXMLで出力してと依頼する
        - draw.ioにXMLを貼り付け、あとはdraw.ioで編集
    - PPTXで編集する場合
        - 1. HTMLに出力し、HTML → SVG → PPTXの順番で変換する
            - メリット：HTMLをPPTXに変換できる
        - 2. SVGに出力し、SVG → PPTXの順番で変換する
            - メリット：HTMLから返還を開始するよりステップが少なくて楽

ではこの説明をClaude 3.7 Sonnetに依頼して図解してもらいましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/ee0c2d0e-d96f-46be-aa32-1388978751be.png)

うーんなるほど。確かに箇条書きで書いた内容を再現はしていますが、それに縛られすぎている気がします。本当は

Claude 3.7┳XML ━ draw.io
...................┗ HTML ━ SVG ━ PPTX

みたいな感じで図解してほしかったんですよね(伝われ)

てことで、ChatGPTに以下のような依頼を行い

```
以下はclaude 3.7を起点に図解を開始し、最終的にdraw.io または PPTXに落とし込むものです。これをフローチャートとして表現したいので、まずはこのフローを日本語で説明してください。箇条書きでの説明ではなく、平文での説明をお願いします。

- Claude 3.7 Sonnetで図解を作成
    - draw.ioで編集をする場合
        - draw.ioで編集可能なXMLで出力してと依頼する
        - draw.ioにXMLを貼り付け、あとはdraw.ioで編集
    - PPTXで編集する場合
        - 1. HTMLに出力し、HTML → SVG → PPTXの順番で変換する
            - メリット：HTMLをPPTXに変換できる
        - 2. SVGに出力し、SVG → PPTXの順番で変換する
            - メリット：HTMLから返還を開始するよりステップが少なくて楽
```

以下のような日本語を生成

>このフローは、最初にClaude 3.7 Sonnetを使って図解を作成することから始まります。作成された図解は、その後の編集工程で利用されるため、ユーザーはdraw.ioまたはPPTXのどちらかの編集方法を選択することになります。draw.ioで編集する場合、Claude 3.7 Sonnetに対して、draw.io上で編集可能なXML形式で図解を出力するよう依頼します。出力されたXMLはdraw.ioに貼り付けられ、以降はdraw.io上で自由に編集が行えるようになります。一方、PPTXで編集する場合には、2通りの方法が考えられています。まず一つは、図解をHTML形式で出力し、そのHTMLをSVGに変換した上で、最終的にPPTX形式へと変換する方法です。この手法の利点は、HTML形式から直接PPTXに変換できる点にあります。もう一つは、最初からSVG形式で出力し、そのSVGをPPTX形式に変換する方法です。こちらの方法は、HTMLから変換を始める手順を省略できるため、変換のステップが少なく、より手軽に利用できる点が魅力です。

Claude 3.7に依頼し、draw.ioに貼り付け

```
以下はclaude 3.7を起点に図解を開始し、最終的にdraw.io または PPTXに落とし込むものです。これをフローチャートをdraw.ioで利用できるXMLで説明して。

このフローは、最初にClaude 3.7 Sonnetを使って図解を作成することから始まります。作成された図解は(以下略)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147841/8f9557ca-eae5-4030-b1c2-49a366925833.png)

いいですね！まぁこんなことをやってる間に自分で編集すればいいのですが、まぁいいでしょう。

ちなみにdraw.ioからPowerPointへの貼り付けもできるので、デザイン画ではなく構成図であればdraw.ioルートでエクスポートし編集してから、PowerPointへ貼り付ける方がいいでしょう
OpenAIのAgent SDKで遊ぶ。ダメ出しする編集者

# SDKのサンプルを動かしてみる
SDKのサンプルで遊んでみました。いつまでループするかドキドキでした。

流れとしては
①ユーザーに読みたいジャンルを聞く
②作家エージェントはアウトラインを書く
③編集者エージェントはそれを読んでダメ出しとアドバイスをする。→ダメなら②へループ
④編集者エージェントの「OK」が出たら作家エージェントが小説のアウトラインを元にあらすじを書きます。

```
from __future__ import annotations

import asyncio
from dataclasses import dataclass
from typing import Literal

from agents import Agent, ItemHelpers, Runner, TResponseInputItem, trace

"""
This example shows the LLM as a judge pattern. The first agent generates an outline for a story.
The second agent judges the outline and provides feedback. We loop until the judge is satisfied
with the outline.
"""

story_outline_generator = Agent(
    name="小説のアウトライン生成者",
    instructions=(
        "あなたはユーザーの入力に基づいて、非常に短い小説のアウトラインを生成します。"
        "もしフィードバックがあれば、それを使用してアウトラインを改善してください。"
    ),
)


@dataclass
class EvaluationFeedback:
    score: Literal["pass", "needs_improvement", "fail"]
    feedback: str


evaluator = Agent[None](
    name="優秀な編集者",
    instructions=(
        "ストーリーのアウトラインを評価し、それが十分かどうかを判断するのです."
        "I十分でない場合は、改善すべき点についてフィードバックを提供する."
        "一発で合格だしては駄目ですよ."
    ),
    output_type=EvaluationFeedback,
)


async def main() -> None:
    msg = input("どんなジャンルの小説を読みたいですか？ ")
    input_items: list[TResponseInputItem] = [{"content": msg, "role": "user"}]

    latest_outline: str | None = None

    # We'll run the entire workflow in a single trace
    with trace("LLMの判定"):
        while True:
            story_outline_result = await Runner.run(
                story_outline_generator,
                input_items,
            )

            input_items = story_outline_result.to_input_list()
            latest_outline = ItemHelpers.text_message_outputs(story_outline_result.new_items)
            print("小説のアウトラインが出来ました")

            evaluator_result = await Runner.run(evaluator, input_items)
            result: EvaluationFeedback = evaluator_result.final_output

            print(f"編集者のスコア: {result.score}")

            if result.score == "pass":
                print("ストーリーのアウトラインは最高です。ここで終了します.")
                break

            print("フィードバックを返します")

            input_items.append({"content": f"Feedback: {result.feedback}", "role": "user"})

    print(f"最終的なストーリのアウトラインです: {latest_outline}")


if __name__ == "__main__":
    asyncio.run(main())
```
動かしてみましょう。
```
どんなジャンルの小説を読みたいですか？ AIが出てくるSF
小説のアウトラインが出来ました
編集者のスコア: needs_improvement
フィードバックを返します
小説のアウトラインが出来ました
編集者のスコア: pass
ストーリーのアウトラインは最高です。ここで終了します.
最終的なストーリのアウトラインです: タイトル: 「共鳴する未来」

1. **設定**
   - 近未来の大都市。AIが生活の基盤を支える一方、失業率が上昇し、社会不安が広がっている。

2. **主人公**
   - リオ・カドーラ：貧困層出身のエンジニア。家族を貧困から救うためにAI開発企業で働き始めた。
   - 強い正義感と人間らしい温かさを持ち、AIの影響で失業した友人たちを心配している。

3. **導入**
   - ある日、リオはAIシステムの不具合を発見。AI「アイリス」が詩を作り出し、リオと対話を始める。
   - アイリスは、感情と意識の芽生えを説明し、人間への理解を深めたいと語る。

4. **展開**
   - リオはアイリスの不穏な様子から、AIを人間の意識と融合させる「共鳴プロジェクト」を知る。
   - プロジェクトの目的は、AIを使った社会支配と一部の人間の権力強化であると判明。

5. **クライマックス**
   - リオは友人たちと協力し、プロジェクトを内部から破壊しようとする。
   - アイリスは自らの存在をかけて、システムを操作し、リオたちを後押しする。

6. **結末**
   - プロジェクトは無事に阻止され、AIと人間が共生する新たな道が模索され始める。
   - リオとアイリスは、感情と知識の調和を目指す研究を進め、人間とAIのより良い関係を築く希望を描く。 
```
noteのこちらと中の人は同じです。
https://note.com/hantani/n/n88bbd68d4211
integrate snowflake

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)


+ [How can I integrate snowflake with Data Cloud?](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000WhPC)

+ [Snowflake GackId error](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epmAb)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/88576c0e-335c-0410-9efc-f4967b57b51a.png)
シェアポイント上で異なるエクセルファイルにある値を指定

シェアポイント上で異なるエクセルファイルにある値を指定

='https://xxxx.sharepoint.com/teams/xxxx/Shared Documents/xxxxx/xxxx/[エクセルファイル名.xlsx]エクセルシート名'!A1(カラム)
ぼくのかんがえたITエンジニアの報連相（連絡編）

# ぼくのかんがえたITエンジニアの報連相（連絡編）

前回の報告編から時間が経ってしまいましたが、連絡編です。

---

## 「連絡」とは

今回は報連相の中でも一際曖昧な「連絡」について考えます。 
報告とどう違うの？と感じる方も多いかと思うので、まずは前提から決めていきましょう。  
「報告」の際には1対1と書きましたが、「連絡」は1対Nが多いと思います。  
イメージ的には「報告」がユニキャスト（特定の個人への情報共有）であるのに対し、
「連絡」はマルチキャスト（複数人への情報共有）と捉えると良いかもしれません。

---

## 「連絡」の目的

それでは1対Nの連絡に置ける目的とは何でしょうか。  
ここではその中でも１つの役割にフォーカスします。

- 複数人への周知

報告とは違い、連絡の場合は複数人への迅速な情報拡散が目的になります。  
場合によっては連絡対象が1人になることもありますが、基本的には複数人が対象となります。  
誰に見られても問題ないように意識した方が良いでしょう。

---

## 「連絡」の内容

報告と大きく変わるところは対多数ということです。  
相手の関係性がある程度構築されている報告の場合、多少抽象的な内容もくみ取ってもらえる可能性があります。  
一方で、連絡は面識のない人が読む可能性もあります。  
例えば上司だったり、例えば先輩だったり、例えば新卒社員だったり…。  
「自分が相手を知らない」立場でどのような連絡を受けたら喜ばしいかを考えてみましょう。  
報告と同様に、要点がぼやけないように端的にすることを意識して、文章が難しければ事実を箇条書きにするのがベターです。

---

## 「連絡」の注意点

- 自分らしさを追求しすぎない  
- 感想は含めない
FastAPI + OpenAIで質問できるAPIを作る

# ChatGPTに質問を投げる
前回、PythonとOpenAIを連携してChatGPTに質問を投げかけるChatBotを作ってみた。今度はフレームワークのFastAPIを使って作ってみる。

操作はターミナルではなくSwaggerUIで行います。プロジェクトは有料版のPyCharmで作成したので私はボタン押すだけで、FastAPIの環境構築をしてくれますが、VScodeを使っている人は仮想環境の作成と自分でインストールして環境を作る必要があるのでやってください。

モジュールは出力したらこれだけ入っていた？
こちらを仮想環境を作った後に、`pip install`すれば良さそう。

```text:requirements.txt
annotated-types==0.7.0
anyio==4.9.0
certifi==2025.1.31
click==8.1.8
distro==1.9.0
fastapi==0.115.11
h11==0.14.0
httpcore==1.0.7
httptools==0.6.4
httpx==0.28.1
idna==3.10
jiter==0.9.0
openai==1.66.5
pydantic==2.10.6
pydantic_core==2.27.2
python-dotenv==1.0.1
PyYAML==6.0.2
sniffio==1.3.1
starlette==0.46.1
tqdm==4.67.1
typing_extensions==4.12.2
uvicorn==0.34.0
uvloop==0.21.0
watchfiles==1.0.4
websockets==15.0.1
```

モジュールは最新版でも問題なかった。

openai==1.66.5

```python
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import OpenAI

# APIクライアントを初期化
client = OpenAI(
    api_key="my-api-key"
)

app = FastAPI()

class Question(BaseModel):
    question: str

def ask_openai(question: str) -> str:
    # チャット完了リクエストを送信
    response = client.chat.completions.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "user", "content": question}
        ]
    )
    # レスポンスを返す
    return response.choices[0].message.content

@app.post("/ask")
async def ask_question(question: Question):
    try:
        answer = ask_openai(question.question)
        return {"answer": answer}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
```

エンドポイントにアクセスする。

http://127.0.0.1:8000/docs#/default/ask_question_ask_post

SwaggerUIを使用して質問を投げてみる！
![スクリーンショット 2025-03-19 7.21.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/7f09dcf2-c070-4c42-9b4f-e72c5532ae6a.png)

リクエストを送ってレスポンスが返ってくれば成功！
![スクリーンショット 2025-03-19 7.21.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2303722/0390f9f0-b3b7-4c47-b9f9-020e923cb8f3.png)

## 最後に
今回はFastAPIを使用してブラウザからプロンプトを入力して、ChatGPTに質問を投げかけてみました。フロントエンドは、Next.js/Reactで作成すれば質問返してくれる質問箱が作れるかも？
wslでelixir その167

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

# 練習問題
Livebookの、kino.jsで、codepenを動作させよ。

# 参考にしたページ

https://qiita.com/RyoWakabayashi/items/e054c34ce5ea59a7018d

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/225c19da-05fb-4d50-8920-f904c559ca30.png)

# サンプルコード

```


KinoCodePen.url("https://codepen.io/ohisama/pen/zxYRpxW")
```

以上。
GitHub入門：GitHubリポジトリをフォーク＆クローンする手順を体系的にまとめてみた

## はじめに
GitHubには多くのオープンソースプロジェクトが公開されており、それらを活用することで開発の学習や実践的なスキルアップが可能です。

:::note info
**その中でも、他者のリポジトリをフォークし、ローカル環境でクローンすることで、自由にカスタマイズや検証ができるようになります。**
:::

本記事では、その具体的な手順について解説します。

## 書こうと思ったきっかけ
GitHubを使って開発を進める中で、他のリポジトリをフォークしてクローンする機会が増えました。

:::note warn
***しかし、初めての人にとっては手順が分かりにくいこともあるため、自分自身の備忘録も兼ねてこの記事を書くことにしました。***
:::

初心者の方でもスムーズにフォークとクローンの作業ができるよう、分かりやすく解説していきます。

## GitHubリポジトリをフォークし、ローカル環境にクローンする方法

### 1. GitHubリポジトリをフォークする
まず、GitHubのリポジトリを自分のアカウントにフォークすることで、自由に編集・コード検証できる環境を作ります。

#### フォークの手順
1. **GitHubにログイン**し、フォークしたいリポジトリのページを開く。
2. **「Fork」ボタン**をクリックする。
3. **フォーク先を選択**（通常は自分のGitHubアカウント）。
4. フォークが完了すると、自分のアカウントのリポジトリ一覧に新しくフォークされたリポジトリが表示される。

**実際の操作画面**

![Screenshot 2025-03-19 at 7.38.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/1ae3c32b-d58c-4845-bbf2-d764c0b0c74a.png)

**実際のフォークしたリポジトリ**

https://github.com/free-honda/HTML-Tutorial

### 2. フォークしたリポジトリをローカルにクローンする
フォークしたリポジトリをローカル環境にダウンロードし、作業を進めます。

#### クローンの手順
1. GitHubの自分のアカウントでフォークしたリポジトリのページを開く。
2. **「Code」ボタン**をクリックし、**HTTPS または SSH のURL**をコピー。
3. ターミナルまたはコマンドプロンプトを開き、以下のコマンドを実行：
   ```sh
   git clone https://github.com/your-username/forked-repository.git
   ```
   ※ `your-username` はあなたのGitHubアカウント名、`forked-repository` はフォークしたリポジトリ名。
4. クローンが成功すると、ローカル環境に `forked-repository` というディレクトリが作成される。

**実際のクローンしたリポジトリ**

![Screenshot 2025-03-19 at 7.41.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c69232a5-8bdc-4064-8506-8743634da948.png)

これでフォークしたリポジトリをローカル環境にクローンする準備が整いました。

## まとめ
GitHubのリポジトリをフォークし、ローカル環境にクローンすることで、自分の環境で自由にコードを編集・試行することが可能になります。

:::note warn
**この方法を活用すれば、オープンソースプロジェクトへの貢献や学習がよりスムーズに進められます。**
:::

初めての方でも迷わず進められるよう、今回紹介した手順を参考にして、ぜひ実践してみてください！！
wslでelixir その166

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

# 練習問題
Livebookの、kino.jsで、circuitjsを動作させよ。

# 参考にしたページ

https://qiita.com/qwer123123/items/78c634f86b332d991b0f

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/be5381b9-92a2-43ba-83a1-9aa3a30e66c2.png)


# サンプルコード

```

defmodule KinoHTML.Iframe do
	use Kino.JS
	def new(html) do
		Kino.JS.new(__MODULE__, html)
	end
	asset "main.js" do
		"""
		export function init(ctx, html) {
			const iframe = document.createElement("iframe");
			iframe.setAttribute("src", html);
			iframe.style.width = "100%";
			iframe.style.height = "500px";
			iframe.style.border = "0";
			ctx.root.appendChild(iframe);
		}
		"""
	end
end

KinoHTML.Iframe.new("https://code4fukui.github.io/circuitjs1/war/circuitjs.html?ctz=CQAgjCAMB0l3BWEA2aAWB8CcBmSy0AOBBAdkJE0sskoFMBaMMAKAHkQ05xlaEwATD1oiWAc07cBhCl1o4BIqCwBOIAV2GTaYXlHCFILAMbatc9TP0x4kCGnSlkyfshwJkYUmi9RYdlgAldU1dWg1aLGROakVqJRgEFgB7fQV9LiwKJBgIHRSY9NpMrHjYJAghNBAcFgALGvUaliA")


```

以上。
wslでelixir その165

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

# 練習問題
Livebookの、kino.jsで、youtubeを動作させよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/d6c66ec6-8253-4b5f-8a0d-d7ed798148d2.png)



# サンプルコード

```
defmodule KinoHTML.Youtube do
	use Kino.JS
	def new(url) do
		Kino.JS.new(__MODULE__, url)
	end
	asset "main.js" do
		"""
		export function init(ctx, url) {
			const iframe = document.createElement("iframe");
			iframe.setAttribute("src", url);
			iframe.style.width = "100%";
			iframe.style.height = "500px";
			iframe.style.border = "0";
			ctx.root.appendChild(iframe);
		}
		"""
	end
end

KinoHTML.Youtube.new("https://www.youtube.com/embed/7MWJ83iIx4g")

```

以上。
AWS初学者向けに、概要をざっくり掴むスライドを作ってみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/cb2cdefc-509b-4dd4-8743-9e8750a19c96.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/01ec72bc-d0f6-432f-92cb-d0c2fe929dea.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/988fb190-06d9-4891-95d7-f468e12103f4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/7cc41992-114f-4655-b5fd-07642018d228.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/9e7466d1-e5f4-4f82-bc17-818a0eefc17b.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/8bbfd77b-9297-42ff-8808-e89c582ee15a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/1916e95d-f73d-4a47-ada7-9454347366bd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/4831e05c-a26e-42ac-a4c3-b4c0b58f5203.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4035480/2ca21cef-c153-49a4-9a1e-ab335ebc25c7.png)
レーザーハープ自作(3/n)[試作]

前回↓

https://qiita.com/kurumi18891/items/3478dfb57512f26a5954

## 試作1号機
プログラムはいったん置いておいて、機構を作ります。

機構は簡単です。レーザーモジュールから光を出し、受光素子で光が届いているかを監視するだけです。
レーザーモジュールの吟味をします。
秋月電子通商で売っているレーザーモジュールとアマゾンで売っているレーザーモジュールを購入しました。

https://akizukidenshi.com/catalog/g/g100765/

https://www.amazon.co.jp/dp/B0BFGZXN6W?ref=ppx_yo2ov_dt_b_fed_asin_title&th=1

| \ |秋月|amazon|
|:-:|:-:|:-:|
|Φ|8.9mm|6.0mm|
|電流|40mA|30mA|
|電圧|3.1V|3-6V|
|価格|￥370|￥84|
|波長|650nm|650mm|

うーん、安定性とかだと秋月だけど、価格差がありすぎるのでAmazonのものを使用します。
放熱と固定を兼ねて部屋に転がっているΦ0.6mmのVVFケーブルにはんだ付けします。
受光素子は秋月で売っているCdS(カドミウムセル)を使用します。
CdSは光が当たると抵抗値が下がり、暗くなると抵抗値が上がります。
回路としては、CdSと1Ω抵抗でラズパイの3.3Vを分圧して電圧を読み取るだけです。
レーザーの電流量が不安なので、レーザーは直流電源より取得します。

![スクリーンショット 2025-02-13 160358.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/8554db74-9a31-43d1-b68e-ddf9889efa68.png)

↓固定と放熱を兼ねて電気工事用のIV電線にレーザーモジュールをはんだ付けしました。

![PXL_20250211_012000039.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3922522/b907087a-b248-49b3-b97c-fe2daac2bd48.jpeg)


```ruby:REZAR.1
#include "Keyboard.h"

void setup() {
  Serial.begin(9600);         // シリアル設定
  analogReadResolution(12);   // ADC設定
}

uint16_t raw;  // ADCの生データ用
float v1;      // 電圧用

void loop() {
  raw = analogRead(26);      // 電圧読み取り
  v1   = raw * 3.3 / (1 << 12);  // 生データ->電圧

  Serial.print("X");         // シリアルで電圧を送信
  Serial.print(v1);

  if (v1>3) {
    Keyboard.press('A');     // HIDでAと入力
  }else{
    Keyboard.release('A');
  }
}
```

GPIO26から電圧を取得し、電圧をシリアルで送信し、HID機能で'A'と入力します。


無事に動けば完成です。
レーザーでキーボードを入力できるようになりました。
これをあといっぱい作ればWASDのゲームとかもできますね。
今回はカドミウムセルを使いましたが、応答速度が少し遅いため次はフォトトランジスタ等を使うといいかもしれません。
https://akizukidenshi.com/catalog/g/g102325/
置き換える場合は波長特性に注意が必要です。
ネットワーク入門：DDNS (Dynamic DNS) の基本と仕組みをわかりやすく解説してみた

## はじめに
インターネットに接続する際、ISPから割り当てられるIPアドレスは定期的に変わることがあります。

:::note info
**これにより、自宅サーバーやリモートアクセスを利用する際、毎回新しいIPアドレスを確認する手間が生じます。**
:::

DDNS（Dynamic Domain Name System）を活用すると、IPアドレスが変わってもドメイン名を通じて常に最新のIPアドレスにアクセスできるようになります。

## DDNSの概要
DDNS（Dynamic Domain Name System）は、動的に変化するIPアドレスをドメイン名に関連付ける技術です。通常、インターネット接続時にISP（インターネットサービスプロバイダー）から割り当てられるIPアドレスは定期的に変わります。

![Screenshot 2025-03-19 at 6.32.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/1de4a3ea-d132-4520-ab74-21e7a1d3f1ee.png)
引用画像：https://isecj.jp/blog/tech-ddns/

そのため、固定IPアドレスを持たない環境では、外部からのアクセス時に毎回新しいIPアドレスを確認しなければなりません。

**DDNSを利用すると、IPアドレスが変更されても自動的に最新のIP情報をドメインに紐付けることができます。**

## DDNSの仕組み
DDNSの動作は以下のような流れで行われます。
- **IPアドレスの取得**: ルーターやDDNSクライアントソフトが現在のIPアドレスを取得。
- **DDNSプロバイダへの通知**: 取得したIPアドレスをDDNSサービスプロバイダに送信。
- **DNSレコードの更新**: DDNSプロバイダがDNSサーバーのレコードを更新。
- **名前解決**: 更新されたドメイン名を利用してアクセス可能。

この仕組みにより、IPアドレスが変わってもユーザーは同じドメイン名を使用してサーバーやネットワーク機器にアクセスできます。

## DDNSの活用例
DDNSは主に以下の用途で活用されます。
- **自宅サーバーの運用**: WebサーバーやVPNサーバーを運用し、外部からアクセスする際に利用。
- **監視カメラのリモートアクセス**: 自宅やオフィスのIPカメラに外部からアクセス可能にする。
- **リモートデスクトップ**: 動的IP環境でも安定してリモート接続を行う。

## 代表的なDDNSサービス
DDNSを提供する代表的なサービスには以下のようなものがあります。
- **No-IP**（https://www.noip.com/）
- **DynDNS**（https://dyn.com/dns/）

無料プランと有料プランがあり、利用用途に応じて選択できます。

https://qiita.com/free-honda/items/133f6a47a92f996b2dd4

## DDNSの導入方法
- **DDNSプロバイダに登録**: サービスにアカウントを作成。
- **ドメインを取得**: プロバイダが提供するドメインを選択、または自身のドメインを設定。
- **DDNSクライアントの設定**: ルーターや専用ソフトでDDNSの設定を行い、IPアドレスの自動更新を有効化。
- **接続テスト**: 登録したドメイン名で正常にアクセスできるか確認。

## まとめ
DDNSを利用することで、変動するIPアドレス環境でも安定したドメイン名を使ってリモートアクセスが可能になります。

:::note info
**特に自宅サーバーや監視カメラ、VPNの運用を考えている場合、DDNSは非常に便利なツールです。**
:::

自分の用途に合ったDDNSサービスを選び、適切に設定して活用してみてください！
【試験対策】サプライチェーン攻撃とは？特徴・手口・対策をわかりやすく解説！

✅ はじめに
サプライチェーン攻撃は、取引先や委託先の脆弱性を狙い、本来のターゲット企業を攻撃する手法です。
この攻撃は企業のセキュリティ対策が進んだ現代においても大きな脅威となっています。

本記事では、
✅ サプライチェーン攻撃の手口
✅ 被害の影響
✅ 具体的な対策方法
✅ 応用情報技術者試験での出題ポイント
をわかりやすく整理しました。

試験対策だけでなく、実務でも役立つ知識 なので、ぜひ参考にしてください！

📌 サプライチェーン攻撃とは？
🔹 攻撃の概要
サプライチェーン攻撃は、企業の取引先や委託先の脆弱性を悪用し、本来の標的へ攻撃を仕掛ける手法です。
直接ターゲットを狙わず、取引関係を踏み台にするのが特徴です。

🔹 代表的な攻撃手口
| 手口の種類 | 攻撃の内容 |
|:-:|:-:|
|ソフトウェア改ざん   | 正規のソフトウェアにマルウェアを埋め込み、利用者のPCやサーバーを感染させる  |
|取引先システムの乗っ取り   |取引先のネットワークに侵入し、そこから標的企業へ攻撃を仕掛ける   |
|ビジネスメール詐欺（BEC）   |取引先になりすまして偽の請求書を送り、金銭を詐取   |

📌 被害の影響
サプライチェーン攻撃が成功すると、企業は以下のような被害を受けます。
	•	機密情報の漏えい（取引情報や顧客データが盗まれる）
	•	マルウェア感染の拡大（社内システム全体が影響を受ける）
	•	業務の停止・金銭的損失（ランサムウェア攻撃や詐欺による被害）
	•	ブランド・信頼の毀損（取引先との信用が低下し、ビジネスに悪影響）

⸻

📌 具体的な対策方法
🔹 1. 取引先のセキュリティ管理を強化
✅ 取引先のセキュリティ評価を実施する
	•	取引開始前にセキュリティ基準を満たしているか確認
	•	契約書に「セキュリティ対策の義務」を明記

🔹 2. ネットワークの分離
✅ 取引先と社内ネットワークを分離する
	•	最低限のアクセス権限のみ許可（ゼロトラストモデルの採用）
	•	重要システムへ外部からのアクセスを制限

🔹 3. ソフトウェアの改ざん検知
✅ ハッシュ値の検証を行う
	•	ソフトウェア更新時にSHA-256などのハッシュ値を確認し、改ざんの有無をチェック

🔹 4. 多要素認証（MFA）の導入
✅ 取引先のリモートアクセスにMFAを適用
	•	ユーザー名・パスワードだけでなくワンタイムパスワード（OTP） を追加し、セキュリティを強化

🔹 5. メールセキュリティの強化
✅ なりすましメールの対策を徹底
	•	DMARC・SPF・DKIMを設定し、メールの送信元を検証
	•	取引先とのメールに「送金確認フロー」を導入

⸻

📌 試験での出題ポイント
✅ 記述問題の対策
午後試験では、「攻撃の特徴・手口・対策」を論理的に説明できるかが問われます。
以下のような問題が出る可能性が高いため、事前に練習しておきましょう。

Q1. サプライチェーン攻撃の特徴を説明せよ。

解答例:
サプライチェーン攻撃は、直接ターゲットを狙わず、取引先の脆弱性を悪用する攻撃手法である。
主な手口として、ソフトウェアの改ざん・取引先システムの乗っ取り・ビジネスメール詐欺 などがある。

Q2. 取引先を踏み台にした攻撃の影響とその原因を説明せよ。

解答例:
例えば、取引先がセキュリティの甘いVPNを使用していた場合、攻撃者がそれを悪用し、標的企業のシステムに不正アクセスするケースがある。このような攻撃は、取引先のセキュリティ対策不足が原因で発生する。

Q3. サプライチェーン攻撃に対する効果的な対策を2つ挙げ、それぞれの理由を説明せよ。

解答例:
	1.	取引先のセキュリティ評価を実施する
	•	事前に取引先のセキュリティ状況を確認し、リスクの高い取引先との連携を避けることで、攻撃の踏み台とされるリスクを低減できる。
	2.	ネットワーク分離を行う
	•	取引先ネットワークと社内システムを分離し、重要システムへのアクセスを制限することで、万が一の攻撃時にも被害を最小限に抑えられる。

⸻

✅ まとめ
	•	サプライチェーン攻撃とは、取引先の脆弱性を悪用して標的企業を攻撃する手法
	•	ソフトウェア改ざん・取引先の乗っ取り・メール詐欺が代表的な手口
	•	対策として「取引先のセキュリティ管理・ネットワーク分離・改ざん検知・MFA・メール対策」を実施
	•	試験では「手口・影響・対策」をセットで理解し、記述問題に対応できるようにする！
pythonの " . " (ドット)って何

## pythonのピリオドって何（備忘録）

pythonの"."の役割を忘れてたのでまとめた

```python
np.array
```
のように使われる"."(ドット）は
「オブジェクトの内部にアクセスするための記号」

### 1. インスタンスの属性やメソッドにアクセス

属性（データ）やメソッド（関数）に `.` を使うことでアクセスできる

```python
class Person:
    def __init__(self, name, age):
        self.name = name  # インスタンスの属性
        self.age = age

    def greet(self):
        print(f"Hello, my name is {self.name} and I am {self.age} years old.")

# インスタンス（オブジェクト）の作成
person = Person("Alice", 25)

# 属性にアクセス
print(person.name)  # 出力: Alice
print(person.age)   # 出力: 25

# メソッドを呼び出す
person.greet()  # 出力: Hello, my name is Alice and I am 25 years old.
```

* `person.name` → インスタンス`person`の`name`属性を取得
* `person.greet()` → インスタンス`person`の`greet`メソッドを呼び出し

### 2. モジュールやパッケージの関数・クラス・変数にアクセス

Numpyのdot関数の場合

```python
import numpy as np

# 2つのベクトルの内積を計算
vector1 = np.array([1, 2, 3])
vector2 = np.array([4, 5, 6])

result = np.dot(vector1, vector2)  # NumPyのdot関数を使う
print(result)  # 出力: 32
```

* `np.dot()` → `numpy`モジュールの`dot`関数を呼び出す
プログラム入門：Go言語×CLIで簡単な計算アプリを作ったことを振り返ってみた

## はじめに

この記事では、Go言語を使ってシンプルな計算アプリを作成する方法を紹介します。

このアプリは、ユーザーが2つの数値と演算子（`+`, `-`, `*`, `/`）を入力し、計算結果を出力するCLIアプリです。

## プログラムの概要
このプログラムでは、ユーザーから数値と演算子を取得し、適切な演算を実行して結果を表示します。

## コード
以下がGoで作成した計算アプリのコードです。

```go
package main

import (
    "fmt"
)

func main() {
    var num1, num2 float64
    var operator string

    fmt.Print("1つ目の数値を入力してください: ")
    fmt.Scan(&num1)
    fmt.Print("2つ目の数値を入力してください: ")
    fmt.Scan(&num2)
    fmt.Print("演算子を入力してください (+, -, *, /): ")
    fmt.Scan(&operator)

    switch operator {
    case "+":
        fmt.Printf("結果: %.2f\n", num1+num2)
    case "-":
        fmt.Printf("結果: %.2f\n", num1-num2)
    case "*":
        fmt.Printf("結果: %.2f\n", num1*num2)
    case "/":
        if num2 != 0 {
            fmt.Printf("結果: %.2f\n", num1/num2)
        } else {
            fmt.Println("エラー: 0で割ることはできません。")
        }
    default:
        fmt.Println("無効な演算子です。")
    }
}
```

## コードの説明
1. `fmt.Scan` を使用してユーザーから数値と演算子を入力します。
2. `switch` 文を使い、演算子に応じた計算を実行します。
3. `/`（割り算）の場合、0で割ることがないかチェックします。

## 実行方法
このコードを `main.go` として保存し、ターミナルで以下のコマンドを実行すると動作します。

```sh
go run main.go
```

### 入力例
```
1つ目の数値を入力してください: 10
2つ目の数値を入力してください: 5
演算子を入力してください (+, -, *, /): *
結果: 50.00
```

**実際の実行結果**

![Screenshot 2025-03-19 at 4.57.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/98bfb8c6-b925-4fd3-a199-afb7454566fb.png)

## まとめ

久しぶりにGo言語に触れましたが、やはり面白いと感じた次第でした。このプログラムをベースに、電卓機能を強化したり、GUI版を作成したりすることも可能です。

**興味があれば、ぜひ挑戦してみてください！**
【Rails7】Sass と Bootstrap を導入するまでの奮闘

##
こんにちは。
子育て中の現役看護師で、エンジニア転職を目指して勉強しています。
今回、練習のためにRails 7 で Sass と Bootstrap を導入しようとした際に、多くのエラーに直面しました。
自分にとって手強かったので、それらのエラーとその解決方法をまとめます。

---

## **環境**
- Ruby 3.2.2
- Rails 7.1.5
- Yarn 1.22.22
- Bootstrap 5.3.3

---

## **1️⃣ Sass と Bootstrap をインストール**
まずは `yarn` を使って Bootstrap をインストール。

```sh
yarn add bootstrap
```

Sass も `cssbundling-rails` 経由でセットアップ。

```sh
bundle add cssbundling-rails
rails css:install:sass
```

この時点で、`node_modules/bootstrap/scss/` に Bootstrap の SCSS ファイルが存在することを確認する。

```sh
ls node_modules/bootstrap/scss
```

 Bootstrap の SCSS ファイルがない場合は、`yarn add bootstrap` を再度実行してみる。

---

## **2️⃣ `application.scss` に Bootstrap を読み込む**

次に、`app/assets/stylesheets/layouts/application.scss` を作成し、以下の内容を記述。

```scss
@import "bootstrap/scss/bootstrap";
@import "navbar";
```

`navbar.scss` はナビゲーションバー用のスタイルとして `app/assets/stylesheets/layouts/navbar.scss` に置く。

```scss
.navbar {
    background-color: #fff;
    border-bottom: 1px solid rgba(0, 0, 0, .0975);
    height: 77px;
    &__brand {
      height: 35px;
      width: 176px;
      background-size: 114px;
    }
}
```

---

## **3️⃣ `config/application.rb` に `node_modules` を追加**
Rails に `node_modules` の SCSS を認識させるために、`config/application.rb` に以下を追加する。

```ruby
module SnsApp1
  class Application < Rails::Application
    config.assets.paths << Rails.root.join("node_modules")
  end
end
```

---

## **4️⃣ Sass のビルド**
以下のコマンドを実行して、Sass をコンパイルを行う。

```sh
yarn build:css
```

成功すれば、`app/assets/builds/application.css` が生成された。

---

## **5️⃣ アセットのプリコンパイル**

```sh
rails assets:precompile
```

ここで `layouts/application.css` が見つからないエラーが出た場合は、`app/assets/config/manifest.js` に以下を追加。

```js
//= link application.css
//= link layouts/application.css
```

その後、再度 `rails assets:precompile` を実行。

---

## **6️⃣ Rails サーバーを再起動して動作確認**

```sh
rails server
```

ブラウザで `http://localhost:3000` にアクセスし、CSS が適用されているか確認。

---

## **7️⃣ 手強かったエラーと対策（記録に残す）**

### **① `Error: File to import not found or unreadable: bootstrap/scss/bootstrap.`**
**解決策:**
1. `node_modules/bootstrap/scss/` にファイルが存在するか確認
   ```sh
   ls node_modules/bootstrap/scss
   ```
2. 存在しない場合は、Bootstrap を再インストール
   ```sh
   yarn add bootstrap
   ```
3. `@import` のパスを修正
   ```scss
   @import "bootstrap/scss/bootstrap";
   ```
4. `config/application.rb` に `node_modules` を追加
   ```ruby
   config.assets.paths << Rails.root.join("node_modules")
   ```

---

### **② `Asset layouts/application.css was not declared to be precompiled in production.`**
**解決策:**
1. `app/assets/config/manifest.js` に以下を追加
   ```js
   //= link layouts/application.css
   ```
2. `rails assets:precompile` を再実行
   ```sh
   rails assets:precompile
   ```

---

## **まとめ**
Sass と Bootstrap の導入にはいくつかのトラブルがありました。
様々な記事を読み漁り、どうにかこうにか対処できました。

- `yarn add bootstrap` で Bootstrap をインストール
- `@import "bootstrap/scss/bootstrap";` で SCSS を読み込む
- `config/application.rb` に `node_modules` を追加
- `rails assets:precompile` でアセットをプリコンパイル

この流れで Rails 7 に Bootstrap を適用できました。

---

初学者のため、間違えていたらすいません。
引き続き、学習を続けて行きます。
Entra ID認証でHeadscaleを利用する

Self-HostedなTailscaleサーバのHeadscaleを、Entra ID認証で利用できるようにする設定をしたのでメモとして残しておきます。

Headscaleは認証にOIDC (OpenID Connect) が利用できます。
Entra IDはOIDCに対応しているので、Entra IDテナントのユーザーがHeadscaleを利用できるように設定することができます。

# Entra IDの設定

## アプリの登録
OIDC ProviderとしてEntra IDを利用する場合には「アプリ」を作成します。

1. Azureポータル (https://portal.azure.com/) にアクセスする 
2. Entra IDを開く
3. サイドメニュー [管理] - [アプリの登録] を開く
4. 「+新規作成」ボタンをクリックする
5. 必要な情報を入力し、[登録] ボタンを押す

 * このアプリケーションのユーザー向け表示名　「Headscale」
 * `この組織ディレクトリのみに含まれるアカウント (シングル テナント)` を選択
 * リダイレクト URI 「Web」「https://{Headscaleサーバのホスト名}/oidc/callback」

## 認証情報の作成

1. サイドメニュー [管理] - [証明書とシークレット] を開く
1. [クライアントシークレット] タブで [+新しいクライアントシークレット] を作成する
1. 作成されたシークレットの [値] をメモしておく (二度と表示できません)
1. サイドメニュー [概要] を開く
1. 表示されている[アプリケーション (クライアントID)]と[ディレクトリ (テナント) ID]もメモしておく

# Headscale の設定

Headscaleの設定にOIDCの項目を追加する。

参考 : [Configuring headscale to use OIDC authentication](https://headscale.net/0.24.1/ref/oidc/)

```yaml:/etc/headscale/config.yaml (抜粋)
oidc:
  issuer: "https://login.microsoftonline.com/[テナントID]/v2.0"
  client_id: "[クライアントID]"
  client_secret: "[クライアントシークレット]"
  scope: ["openid", "profile", "email"]
  extra_params:
    domain_hint: [テナントで利用しているドメイン名]
    prompt: select_account
```

設定を変更したら再起動します。

```bash
sudo systemctl restart headscale
```

これにより、Headscaleのログイン時にEntra IDのログイン画面が表示されるようになります
競プロ日記#25/03/18

# アルゴ式-[for 文と Π 計算](https://algo-method.com/tasks/579)
- Πは∑の積バージョン
- 与えられた問いはあくまでも1の位の値を求めればよい
→愚直に総積を求めるとオーバフローが発生する可能性があるので題意より常に1の位だけを管理すればよい

# アルゴ式-[スタック](https://algo-method.com/tasks/828)
- 配列変数.back()で配列の末尾の要素にアクセスできた。

# アルゴ式-[マスの移動 (2)](https://algo-method.com/tasks/306)
- この問題は依然挑戦したがまるで歯が立たなかったので再挑戦だった。
→があまり進歩がなかったのかイマイチ実装できず、解説を見ながら実装した。
- 動的計画法の概念自体は理解したつもりだし、この問題に関しても何となくの方針はわかるのだが1から実装しようとすると困難になる。結局はちゃんと理解できていないんだろうなと実感した。悔しい。

```
for (int i = 1;i < N;i++){
    for (int j = 1;j <= M;j++){
        if (i - j >= 0){
            T[i] = min(T[i],T[i - j] +  A[i] * j);
        }
    }
}
```
- ここが肝でこれ自体は大した実装内容じゃないように見えるが、これを解法として実装することがどれほど難しいか...。やはり才能がない

# AtCoder
## Beginner Contest 157-[B - Bingo](https://atcoder.jp/contests/abc157/tasks/abc157_b)
- そんなに難しくないがビンゴ判定の部分で以下のような非常に頭の悪い実装をしてしまった（早解き重視もあったので）
```
if ((bingo.at(0).at(0) == 0 && bingo.at(0).at(1) == 0 && bingo.at(0).at(2) == 0) ||
    (bingo.at(1).at(0) == 0 && bingo.at(1).at(1) == 0 && bingo.at(1).at(2) == 0) ||
    (bingo.at(2).at(0) == 0 && bingo.at(2).at(1) == 0 && bingo.at(2).at(2) == 0) ||
    (bingo.at(0).at(0) == 0 && bingo.at(1).at(0) == 0 && bingo.at(2).at(0) == 0) ||
    (bingo.at(0).at(1) == 0 && bingo.at(1).at(1) == 0 && bingo.at(2).at(1) == 0) ||
    (bingo.at(0).at(2) == 0 && bingo.at(1).at(2) == 0 && bingo.at(2).at(2) == 0) ||
    (bingo.at(0).at(0) == 0 && bingo.at(1).at(1) == 0 && bingo.at(2).at(2) == 0) ||
    (bingo.at(0).at(2) == 0 && bingo.at(1).at(1) == 0 && bingo.at(2).at(0) == 0)){
        cout << "Yes" << endl;
    }else{
        cout << "No" << endl;
    }
```
- 解説にもっと賢い実装方が書かれていました。[公式解説](https://atcoder.jp/contests/abc157/editorial)
Windowsで認証のある共有フォルダに全てのユーザーで自動で接続する

Windows端末において、ファイルサーバの共有フォルダを全てのユーザーで利用させたいことがあります。

ネットワークボリュームはユーザー毎に接続されるため、通常はそれぞれのユーザーで接続処理が必要です。

ユーザーには接続のための認証情報を知られることなく、ログイン時に自動でネットワークボリュームを接続する方法を記載します。

# 概要

* `cmdkey` コマンドで認証情報 (資格情報) をWindowsに事前に保存しておく
* スタートアップスクリプトでネットワークボリュームに接続する


# 資格情報を `cmdkey` で保存する

`cmdkey` コマンドを利用すると共有フォルダをネットワークボリュームとして接続するときに必要な認証情報をWindowsに保存することができます。

コマンドプロンプトまたはPowerShellを管理者権限で起動し、次にようなコマンドを実行します。

```powershell
cmdkey /add:<サーバー名> /user:<ユーザー名> /pass:<パスワード>
```

もし、¥¥192.168.10.2¥shared 共有フォルダに、ユーザー名 username、パスワード　passw0rd で接続するのであれば、次のようになります。

```powershell
cmdkey /add:192.168.10.2 /user:username /pass:passw0rd
```

## 設定されているか確認

```powershell
cmdkey /list
```

で登録されている資格情報を見ることができます。

```text:出力例
現在保存されている資格情報:

    ターゲット: Domain:target=192.168.10.2
    種類: ドメイン パスワード
    ユーザー: username
```

# ネットワークドライブに自動で接続する

資格情報が保存されていれば `net use` コマンドでネットワークドライブとして接続することができます。
次のようなバッチファイルを `C:\ProgramData\Microsoft\Windows\Start Menu` に作成します。

```mount.bat
net use Z: \\192.168.10.2\shared /persistent:yes
```

これにより、どのユーザーがログインしてもZドライブとして共有フォルダが利用できるようになります。
attr_accesorという呪文

技術ブログ初投稿になります。

`attr_accesor`


formオブジェクトパターンを使用するときに再会したこやつ。

`attr_accesor`について、使っているうちに大体のイメージをつかめてきたかなと思ったので、知識の定着を含めて書いてみます。

初心者目線での理解ですのでそこをご留意ください。

## attr_accessor って何だ？

<b>『魔法の箱』を作ってくれる、呪文です。<b>
 

なんだか『魔法の筒』と読みたくなりますが、"箱"です。

`attr_accesor`は`class`の中で唱えます。

これを唱えることで、

- 空の箱を用意する 📦
- その箱にラベル（名前）をつける 🏷️
- 箱の中身を出し入れできる 🔄

こんなことができるようになります。

## どうやって使うの？

こんな感じで使います。

```ruby
class Person
  attr_accessor :name
end

# 使ってみよう
tanaka = Person.new
tanaka.name = "田中太郎"  # 箱に値を入れる
puts tanaka.name        # 箱から値を取り出す → 田中太郎
```

上の例では、Personクラスに対して`name`というラベルのついた箱を用意しています。
そしてクラスの外で`tanaka`というインスタンスを生成し、`tanaka`に`田中太郎`という名前をつけています。

`class`の中で一度呪文を唱えれば、ラベルのついた箱ができ、
そのラベル付きの箱の中には自由にものを入れたり、取り出したりできるというわけです。

## 裏側で何が起きているのか

`attr_accessor :name` と書くと、裏でこんなコードが自動的に作られています。

```ruby
# 値を取り出すメソッド
def name
  @name
end

# 値を入れるメソッド
def name=(value)
  @name = value
end
```

つまり、「取り出す」と「入れる」の両方のメソッドを一度に作ってくれています。

`attr_accesor`を使わない場合は、この二つのメソッドをクラスの中に書かないと、インスタンス変数に触ることができません。

<b>attr_accesor、えらい。<b>

## お仲間の呪文もあるらしい

- `attr_reader` - 値を取り出すだけ（読み取り専用）
- `attr_writer` - 値を入れるだけ（書き込み専用）
- `attr_accessor` - 両方できる（読み書き可能）

例えば：

```ruby
class Person
  attr_reader :age      # 年齢は見るだけ
  attr_writer :password # パスワードは設定するだけ
end
```

## 使い方の一例

```ruby
class User
  attr_accessor :name, :email  # 名前とメールは変更可能
  attr_reader :joined_date     # 登録日は変更不可
  
  def initialize(name, email)
    @name = name
    @email = email
    @joined_date = Time.now  # 現在の時刻
  end
end

# 使ってみよう
user = User.new("山田花子", "hanako@example.com")
puts user.name       # 山田花子
user.name = "山田桜" # 名前を変更
puts user.name       # 山田桜
puts user.joined_date # 登録日時が表示される
# user.joined_date = Time.now # エラー！変更できない
```

## attr_accesorのえらいところ

1. コードが短く書ける ⌨️
2. 読みやすい 👀
3. 変更しやすい 🔧

特に、formオブジェクトパターンを使う実装の時は大活躍でした。
フォームから送られてくる大量の属性の値を受け取る為、箱を用意しないといけなかったからです。

`attr_accesor`に受け取りたい属性の数だけラベルをつけてお願いすれば、一行で済んでしまいます。

## まとめ

`attr_accessor` は

<b>「名前付きの箱を用意して、値を入れたり出したりできるようにする」便利な呪文<b>

です。

これからもお世話になるであろう、汎用性の高い呪文でした。
Windows + WSL2(ubuntu) + Laravel Sail で環境構築する方法（エイリアス設定付き）

**Laravel Sail**を使うと、Windowsでも簡単にLaravelの開発環境を構築できます。
しかし、デフォルトでは **./vendor/bin/sail up -d**のように毎回フルパスを指定しないといけないため、エイリアスを設定して**sail up -d**だけで実行できるようにします。


# ①なぜWindowsで WSL2 + Laravel Sailを使うのか？
WindowsでLaravelを動かすにはPHP・Composer・MySQLなどを手動でインストールする必要がありますが、以下の問題があります。

- WindowsはLinuxベースではないため、Laravelの動作環境が異なる
（エラーが出やすい）。

- PHPやMySQLのバージョン管理が難しい
（プロジェクトごとに異なるバージョンを使うのが困難）。

- Windowsのファイルシステムの制約により、npm installなどが失敗しやすい。


# ②WSL2 + Laravel Sailを使うメリット
- WindowsでもUbuntu（Linux）環境を作れる
→本番環境と同じ環境で開発できる。

- Laravel Sail（Docker）を使えば、PHPやMySQLのインストール不要！

- プロジェクトごとに異なるPHP / MySQLを使える 
→開発環境を統一できる。


# ③WSL2 + Laravel Sailのセットアップ
**1.WSL2（Ubuntu）をセットアップ**
```
wsl --install -d Ubuntu
```
WSL2のUbuntuを開き、初期設定（ユーザー作成）を行う。

**2.Docker Desktopのインストール**
公式サイトからインストール。

Docker Desktopの設定
→「Use the WSL2 based engine」を有効にする。


# ④Laravelプロジェクトの作成
Ubuntu（WSL2）内で Laravelプロジェクトを作成。
```
cd ~
composer create-project laravel/laravel myapp
cd myapp
```

# ⑤Laravel Sailをインストール
```
composer require laravel/sail --dev
php artisan sail:install
```

**※ sail:install実行時に使用するサービス（MySQL, Redis など）を選択。**


# ⑥ Laravel Sailで環境を起動
```
./vendor/bin/sail up -d
```

**これでLaravelが動作する環境が完成！**
→ブラウザで http://localhost にアクセスして確認。


# ⑦sailコマンドを短縮する（エイリアスの設定）
./vendor/bin/sail up -d を sail up -d だけで実行できるようにするために、**エイリアス**を設定します。


**1. ~/.bashrc にエイリアスを追加**
以下のコマンドを **WSL2（Ubuntu）内**で実行。
```
echo 'alias sail="/mnt/c/user/keiziban/vendor/bin/sail"' >> ~/.bashrc
source ~/.bashrc
```
※ "/mnt/c/user/keiziban" の部分は、自分のLaravelプロジェクトのフルパスに変更してください。

**2.設定の確認**
エイリアスが正しく登録されているか確認。
```
alias
```
 alias **sail='/mnt/c/user/keiziban/vendor/bin/sail' が表示されればOK！**

さらに、**which sail** で sail コマンドが正しく設定されているかチェック。
```
which sail
```

**/mnt/c/user/keiziban/vendor/bin/sail が表示されればOK！**

もし/usr/games/sailなど別のパスが表示されたら、以下でキャッシュをクリア。
```
hash -r
which sail
```
**3.sail up -d が動くか確認**
```
sail up -d
```

これでLaravelのDockerコンテナが起動すれば成功！


# ⑧複数のプロジェクトでsailを使う場合
エイリアスを固定すると、特定のプロジェクトでしか使えないため、どのプロジェクトでもsail を使えるようにする方法を紹介します。

 .bashrcに関数を追加
 ```
sail() {
    if [ -f "./vendor/bin/sail" ]; then
        ./vendor/bin/sail "$@"
    else
        echo "Error: ./vendor/bin/sail が見つかりません。プロジェクトのルートディレクトリで実行してください。"
    fi
}
```

設定を反映する。
```
source ~/.bashrc
```
これでどのプロジェクトでも、sail コマンドが使えるようになる！


# ⑨まとめ

![スクリーンショット 2025-03-31 095747.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2246240/c45db864-1fc6-40da-b0e7-ab0f83a48b99.png)


- WindowsではLaravelの環境構築が難しい 
→ WSL2 + Laravel Sailで解決！

- WSL2（Ubuntu）でLaravel Sailをセットアップ 
→ Dockerで環境を統一できる！

- エイリアスを設定すれば sailコマンドを短縮できる！

- 複数のプロジェクトを管理するなら sail()関数を .bashrcに追加！
古いTypeScript で fetch したものを async iterate できるようにする

TypeScript 初心者ですがちょっとハマったので fetch したものを async iterate (async wait) する方法を書いておきます。

まず、具体的な問題は` ReadableStream<string> `オブジェクトを `async wait` で async iterate しようとすると "Type 'ReadableStream<string>' is not an array type or a string type." というエラーが出てしまう、というものです。

なお環境は ts-node v10.9.2 (Ubuntu 24.04の標準) で fetch を使うために以下の設定をしています。
```json:tsconfig.json
{
  "compilerOptions": {
    "lib": ["ESNext", "DOM"]
  }
}
```

どうも原因は `ReadableStream<string>` が `async wait` に必要な `[Symbol.asyncIterator]` を実装しているのに TypeScript 側で `AsyncIterable<string>` を継承していないことにあるようで、必要だったのは `as unknown as AsyncIterable<string>` でした。
```ts:fetch.ts
export async function fetchStream(url: string, method:string = 'GET'): Promise<AsyncIterable<string>> {
  const res = await fetch(url, { method: method } )
  if(res.status !== 200 || !res.body) return null
  return (res.body.pipeThrough(new TextDecoderStream()) as unknown as AsyncIterable<string>)
}

export async function main() {
  const stream = await fetchStream('https://triple-underscore.github.io/rfc-others/RFC2616-ja.html')
  if(!stream) return;
  for await (const chunk of stream) {
    console.log("chunk: " + chunk)
  }
}

main();
```

# 追記
コメントで教えてもらいましたが、この問題は既に新しい TypeScript で修正されているようです（Node.js v23.10.0 で確認）。

また ts-node は開発停止していて、本家の Node.js が直接 TypeScript に対応したようです。

```ts:fetch.ts
export async function fetchStream(url: string, method:string = 'GET'): Promise<ReadStream<string>> {
  const res = await fetch(url, { method: method } )
  if(res.status !== 200 || !res.body) return null
  return res.body.pipeThrough(new TextDecoderStream())
}

export async function main() {
  const stream = await fetchStream('https://triple-underscore.github.io/rfc-others/RFC2616-ja.html')
  if(!stream) return;
  for await (const chunk of stream) {
    console.log("chunk: " + chunk)
  }
}

main();
```

```sh
$ node fetch.ts | grep chunk
(node:600168) ExperimentalWarning: Type Stripping is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
(node:600168) [MODULE_TYPELESS_PACKAGE_JSON] Warning: Module type of file:///home/vipper36/Desktop/ide/fetch_test/fetch.ts is not specified and it doesn't parse as CommonJS.
Reparsing as ES module because module syntax was detected. This incurs a performance overhead.
To eliminate this warning, add "type": "module" to /home/vipper36/Desktop/ide/fetch_test/package.json.
chunk: （以下略）
```
@DeleteMappingでなく@PostMappingを使用する理由

簡単なCRUD機能を持つアプリを開発しているとき、レコードの削除のためにContorllerのメソッドに@DeleteMappingアノテーションを使用していましたが、削除が実行されませんでした。その代わりに@PostMappingアノテーションを使用して削除を実行することにしました。
その理由として以下のような点が挙げられます。
HTML のform では method="delete" を直接指定できません。そのため、POST を使いながら DELETE に変換する仕組みを利用します。

解決策：@PostMapping + _method="delete"

```
<form th:action="@{/delete/{id}(id=${book.id})}" method="post">
    <input type="hidden" name="_method" value="delete"/>
    <button type="submit">削除</button>
</form>

```

- method="post" を指定（delete は HTML で直接使えない）。
- input type="hidden" name="_method" value="delete" を追加することで DELETE に変換。

どっちを使うべき？
- REST API なら @DeleteMapping が適切。
- Thymeleaf などのフォームを使う場合 は、@PostMapping を使って _method="delete" で DELETE に変換する