OmniAICreator/Qiita-1.07M huggingface dataset:
【langchain v0.3】ChatOpenAIの使い方メモ（画像添付）

【langchain v0.3】ChatOpenAIの使い方メモ（画像添付）
# 概要
langchain v0.3のChatOpenAIの画像添付のやり方をよく忘れるので自分用にまとめました。

# 準備

```sh
pip install langchain langchain-openai
```

環境変数OPENAI_API_KEYを指定します。もしくはプロジェクトのルートに`.env`を作成しOPENAI_API_KEYを指定します。

# コード
基本的には、HumanMessageのcontentに`{"type": "image_url", "image_url": "urlまたはbase64でーｔ"}`と指定すればよいです。（[参考](https://python.langchain.com/docs/how_to/multimodal_inputs/)）
## URL

インターネット上の画像の場合、対応しているモデルであれば、URLの直書きでいけます。

```Python
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI

image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"

model = ChatOpenAI(model="gpt-4o-mini")
message = HumanMessage(
    content=[
        {"type": "text", "text": "この画像の天気を教えて"},
        {"type": "image_url", "image_url": {"url": image_url}},
    ],
)
response = model.invoke([message])
print(response.content)
```

```
申し訳ありませんが、画像から具体的な天気を判断することはできません。ただし、晴れた青空と柔らかな雲が見られるので、穏やかな天気のように見えます。
```

URLの直書きに対応していないモデルの場合は、URLからコンテンツをダウンロードしてbase64を入力します。

```Python
import base64
import httpx
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI

image_url = "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"
image_data = base64.b64encode(httpx.get(image_url).content).decode("utf-8")

model = ChatOpenAI(model="gpt-4o-mini")


message = HumanMessage(
    content=[
        {"type": "text", "text": "この画像の天気を教えて"},
        {
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
        },
    ],
)
response = model.invoke([message])
print(response.content)
```

```
画像を直接分析することはできませんが、青空と緑の草原から、穏やかで晴れた天気のように見えます。もし天気の詳細を知りたい場合は、具体的な地域や日付を教えていただければ、一般的な情報をお伝えできます。
```

## ローカルファイル
ローカルファイルの場合はbase64に変換して入力します。
[空の画像](https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg)を"sample.jpg"という名前で保存して試します。

```Python
import base64
from langchain_core.messages import HumanMessage
from langchain_openai import ChatOpenAI

def get_base64_from_image(image_path: str) -> str:
    """
    画像ファイルを読み込み、base64エンコードされた文字列を返す関数

    Args:
        image_path (str): 画像ファイルのパス

    Returns:
        str: base64エンコードされた画像データ
    """
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode("utf-8")

image_data = get_base64_from_image("sample.jpg")

model = ChatOpenAI(model="gpt-4o-mini")


message = HumanMessage(
    content=[
        {"type": "text", "text": "この画像の天気を教えて"},
        {
            "type": "image_url",
            "image_url": {"url": f"data:image/jpeg;base64,{image_data}"},
        },
    ],
)
response = model.invoke([message])
print(response.content)
```

```
画像から直接天気を判断することはできませんが、青空と雲が見られることから、晴れているか、少し曇っている可能性があります。具体的な天気情報は、現地の天気予報を確認することをお勧めします。
```
[Google Ad Manager]動的なKey-Valueの設定と取得に向いているデータ

## Key-Valueとは？
- Google Ad ManagerのKey-Valueとはカスタムターゲティングを可能にする機能
- 独自のキー（key）と値（Value）を定義し、広告配信のカスタムターゲティングを実現する<br><br>

###### 使用例：
- ページタイトルに特定の文字が含まれる場合の広告配信
- ページURLによるターゲティング
- カテゴリ（タグ）ごとの広告出し分け
- 環境（開発・ステージング・本番）ごとのターゲティング
- 特定の内容を含む記事への広告配信制御<br><br>

  


###### Key-Valueでは２つのタイプがある
- 動的：ページURLやタイトルなど、ページごとに異なる値を使用
- 定義済み：性別など、固定された値を使用<br><br><br>

## 設定
![スクリーンショット 2025-01-23 12.26.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193285/c80253d3-361e-c3fc-50f2-1d25e789f8fb.png)
名前　　　　　　：Key-Valueのkeyに当たるもの、半角英数字で入力する
表示名　　　　　：アドマネージャー上での表示名
値のタイプ　　　：今回は動的
値のレポート　　：今回レポートで利用したいので含める
ターゲティング値：Key-ValueのValueに当たるもの、keyに対して取得したい値を設定<br><br><br>



## 設置したタグ
$Categoryにはサイト内ページのカテゴリが入る
ターゲティング値に"ニュース"と設定したらニュースカテゴリのページで以下タグにより値が取得される
````
<script>
  window.googletag = window.googletag || {cmd: []};
  googletag.cmd.push(function() {
      googletag.pubads().setTargeting("Category", "$Category");
  });
</script>
````
<br>

## 取得に向いていないデータ
取得したい値をターゲティング値に一つ一つ設定する必要があるので例えばメディアサイトの記事のような数が多い値(1つのkeyに対して設定できる値の上限は100,000個)や頻繁に変更されるような値は取得に向いていない
【2025年最新】Next.js15における、paramsの扱い方

# はじめに
Next.js15では、**パラメーター ( params ) のプロパティに直接アクセス**しようとすると、エラーが吐かれてしまいます。
このエラーを解決するのに、私自身なかなか苦労したので、備忘録としてここに書き残します。

# エラー概要
プロパティにアクセスしようとすると、以下のようなエラーが吐かれると思います。

`params` is now a Promise and should be unwrapped with `React.use()` before accessing properties of the underlying params object.

つまり、params が Promise として渡される場合、その値を使う前に `React.use()` を使って解決する必要があるということです。

# 解決方法
#### 1.　まずは、params の型定義を Promise に変更 ####
- 変更前
```src / app / [id] / page.tsx
export default function Example({ params }: { params: { id: number } }) {
    // コードを記述
};
```
- 変更後
```src / app / [id] / page.tsx
export default function Example({ params }: { params: Promise<{ id: number }> }) {
    // コードを記述
};
```

#### 2.　Promiseの params を use() を使ってアンラップ ( 加工 ) ####
- 変更前
```src / app / [id] / page.tsx
export default function Example({ params }: { params: Promise<{ id: number }> }) {
    // コードを記述
};
```
- 変更後
```src / app / [id] / page.tsx
import { use } from "react";
export default function Example({ params }: { params: Promise<{ id: number }> }) {
    const unwrapParams = use(params);
    // コードを記述
};
```

#### 3.　パラメーター ( params ) のプロパティにアクセス！！ ####
- 変更前
```src / app / [id] / page.tsx
import { use } from "react";
export default function Example({ params }: { params: Promise<{ id: number }> }) {
    const unwrapParams = use(params);
    // コードを記述
};
```
- 変更後
```src / app / [id] / page.tsx
import { use } from "react";
export default function Example({ params }: { params: Promise<{ id: number }> }) {
    const unwrapParams = use(params);
    // プロパティにアクセス
    console.log(unwrapParams.id);
};
```
# 最後に
いかがでしたでしょうか？
初めての Qiita 投稿でつたない部分もあったと思いますが、皆さんの役に立てられれば幸いです。
これからも技術発信を続けますので、是非ほかの投稿記事もご覧ください！
Databrcks の serverless compute を利用時における withColumns に空の引数を渡した際のエラーへの対応方法

## 概要

Databrcks の serverless compute を利用時に、withColumns に空の引数（`{}`）を渡した際のエラーへの対応方法を共有します。対応方法としては、空の引数の場合には実行しないようにする必要があります。

> AssertionError: 
> File <command-8962258698623039>, line 1
>       1 col_conf = {}
> ----> 2 src_df.withColumns(col_conf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/be63b2cd-11cb-3bbf-a3f5-1504b24efaa6.png)


## 通常の Databricks クラスターでの動作確認

```python
data = [{"col_1": "a"}]
src_df = spark.createDataFrame(data)
display(src_df)

col_conf = {}
src_df.withColumns(col_conf)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/819e5d0c-a9f4-b6e9-4986-b7a3b933af9e.png)

## Databrcks の serverless compute でエラーとなることを確認

```python
data = [{"col_1": "a"}]
src_df = spark.createDataFrame(data)
display(src_df)

src_df.withColumns({})
```

> AssertionError: 
> File <command-8962258698623039>, line 1
>       1 col_conf = {}
> ----> 2 src_df.withColumns(col_conf)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/be63b2cd-11cb-3bbf-a3f5-1504b24efaa6.png)

## エラーへの対応方法

```python
col_conf = {}
if col_conf:
    src_df.withColumns(col_conf)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/0eba8ea2-4e47-d65f-a566-648583dd8e7a.png)
outlook2007でメール

# 概要
outlook2007で、mailしていた。
BIGLOBEトップのマイページに入りたくて、パスワードを新規にしたら、メールが読めなくなった。

# 環境
windows11
outlook2007

# 症状
pop3 ログインできない。
smtp ログインできない。

# 対処
ログインパスワードを変更。
pop3 ログインOK。
smtp ログインできない。

# 対処２
smtp port 225 -> 587に変更
pop3 ログインOK。
smtp ログインok。


以上。
社員教育で防ぐ！すぐに実践できるITセキュリティの鉄則！

## 1. はじめに 
リモートワークの普及により、企業にとってITセキュリティの重要性はますます高まっています。そこで、本記事では、インターン生の私が **「【講義動画】情報セキュリティ・個人情報保護の新人研修」という動画**を見たうえで **先輩から教わったポイント**を基に、すぐに実践できるITセキュリティの鉄則についてまとめました。

<iframe width="560" height="315" src="https://www.youtube.com/embed/I9p-NAoamhA?si=w99v4F9qs4T2rL7t" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


## 2. 先輩から教わった注意点・その他の気づき
動画で学べる対策のほかにも気をつけるべきことは多く存在します。情報漏えいは信用失墜に留まらず、最悪の場合は訴訟や解雇といった重大な結果を招く可能性があります。そのため、以下の対策も怠らずに実施しましょう。


|No　|対策  |説明  |
|---|---|---|
|1 |周囲に人がいる環境では極力作業しない| 喫茶店や公共の場で業務を行うと、ショルダーハッキングによる情報漏えいリスクが高まります。原則として、社内などの所定の作業場所で作業しましょう。やむを得ず外出先で作業する場合は、壁を背にする・覗き見防止フィルターを使用するなど、第三者に画面を見られない工夫を徹底しましょう。 |
|2 | 外出時はPCや資料を手の届く範囲で管理する |  PCや資料を手の届かない場所に置くと、盗難や置き忘れなどのリスクが高まります。喫茶店などの公共の場でPCを置いたまま席を離れる行為は避けましょう。また、電車などの移動時はPCを常に携行し、網棚を使わないなど注意を払って管理してください。|
|3|お酒を飲む場合はPCを持ち運ばない|飲酒により危機管理能力が低下し、盗難や紛失のリスクが高まります。出張先などでお客様と飲酒する場合は、PCをホテルの部屋（可能であれば金庫）に保管し、持ち歩かないようにしましょう。|
|4|USBメモリなどの外部記録媒体を許可なく使用しない|過去に、個人情報や機密情報がUSBメモリなどの外部記憶媒体を経由して不正に持ち出された事例があります。そのため、多くの企業で外部記憶媒体の利用を禁止・制限しています。利用が必要な場合は、必ず会社のルールを確認し、ルールに従って使用しましょう。|
|5|定期的にバックアップをとる|セキュリティとは直接関係しませんが、バックアップの取得は重要です。作業中のファイルは、会社で許可されているクラウドサービス（Google DriveやOneDriveなど）に保存するとリスクを低減できます。ソースコードもリポジトリなどクラウド環境で管理するようにしましょう。|
|6|メールで添付ファイルやURL認証を送信しないようにする|メールは転送されやすく、意図せず情報が拡散してしまう恐れがあります。添付ファイルやURL認証の利用は極力避け、ファイル送付が必要な場合はクラウドストレージにアップロードし、必要な相手にだけアクセス権を付与する方法を推奨します。|
|7|メール等で情報を送信する際は誤送信防止に注意する|誤送信は最も一般的な情報漏えい原因の一つです。宛先を複数回確認する、送信を遅延させる機能を活用するなど、誤送信防止策を講じましょう。|
|8|OSやウイルス対策ソフトを最新バージョンに保つ|バージョンが古いと既知の脆弱性を悪用されやすくなり、ウイルス感染のリスクも上昇します。自動アップデートを推奨しますが、会社の運用ルールによっては最新が最適でない場合もあるため、社内規定に従って実施しましょう。|
|9|URL認証は極力使わない|URLを知っている人なら誰でもアクセスできる場合があるため、機密性の高い情報を扱う際はURL認証の利用を避けましょう。|
|10|無関係な案件の情報を受け取らない|アクセス権を必要最小限にすることで、情報漏えい発生時の原因調査がしやすくなります。部外者がアクセスできる環境だと調査対象が増え、原因究明が難しくなるため、自身に無関係な情報は極力受け取らないように心がけましょう。|
|11|極力印刷をしない|紙で情報を扱う場合、紛失リスクや廃棄の手間（溶解処理等）が増えます。可能な限り印刷は控え、どうしても必要な場合は社内のプリンターを使用し、適切に廃棄してください。シェアオフィスなど社外のプリンターは印刷履歴に情報が残る可能性があるため、利用は避けましょう。|
|12|社外（カフェや電車等）で機密情報を話さない|周囲の人に聞かれて情報が漏えいするリスクが高まります。社外からオンライン会議に参加する際も、周囲に聞かれない個室などで参加しましょう。|
## 3. おわりに
リモートワークの普及により、セキュリティ意識向上の必要性が高まっています。  
そのため、本記事で紹介した内容がセキュリティ意識向上の助けとなれば幸いです。
【ネットワーク基礎】ARPについて

## ▼ARP(Address Resolution Protocol)とは
ネットワークのIPアドレスをMACアドレスに変換することができるプロトコルです。

## ▼前提：
ネットワークにあるデバイスにはIPアドレスとMACアドレスを持っています。
IPアドレスはネットワーク上の位置で変動する場合がありますが、
MACアドレスは物理アドレスなので不変です。


## ▼必要性：
#### [1].ネットワーク上でデータを送信する際、送信元デバイスは宛先デバイスのIPアドレスを知っているが、MACアドレスは知らない場合
⇒ARPでMACアドレスを取得する

#### [2].ネットワーク通信の効率化
⇒ARPテーブルにIPアドレスとMACアドレスの対応が登録されることで、再度ARPリクエストを送信する必要がなく通信が迅速になる。

#### [3].トラブルシューティング支援
⇒ARPテーブル確認して、デバイスのMACアドレス特定ができる
・データリンク層(L2)とネットワーク層(L3)の橋渡し
⇒データリンク層はMACアドレスを使用し、ネットワーク層はIPアドレスを使用するため、これらの層間での通信を可能にします。

#### 例：スイッチとルータ間の通信
⇒ネットワーク層でIPアドレスを使用し、データリンク層でMACアドレスを使用して行われる。
⇒ルータはIPアドレスを基にパケットをルーティングし、スイッチはMACアドレスを基にフレームを転送します。
⇒MACアドレスが分からない場合、ARPで特定します

## ▼ARP動作流れ
ARPリクエスト(要求)、ARPレスポンス(応答)という2種類のデータを送信しあって、MACアドレスを取得します。

#### 例：特定のデバイスにあるMACアドレスを知りたい場合流れ
①ARPリクエストをネットワーク上にブロードキャスト(1対多数)する。

②ARPリクエスト通りのIPアドレスを持つデバイスが受信した場合、自身のMACアドレスをARPパケット内に入れてARPレスポンスで返す。
　※ARPレスポンスはユニキャスト(1対1)通信です
　※一致しないデバイスは何も応答されない

③受信したARP内容はARPテーブルに保存されます
　※登録されれば何回も問い合わせ不要となる

## ～おまけ～
ネットワーク構成には、ルータ、L2スイッチ、L3スイッチ、アクセポイント(AP)のネットワーク機器が主に利用されますのでARP必要可否を分けました。
#### ・L2スイッチ、アクセスポイント：ARP登録不要
⇒通信ではARP登録不要となります。
⇒基本はレイヤ２デバイスでありMACアドレスをもとにパケット転送するため

#### ・ルータ、L3スイッチ：ARP登録必要
⇒L3スイッチはIPアドレスを使用してルーティングを行うため、ARPテーブルが必要です。
⇒ルータはL3で動作しIPアドレスを基にパケットルーティングするため、ARPテーブルが必要です。

-----------------------------------------------------------------
・L2：データリンク層
MACアドレスの通信なので異なるネットワーク間は通信不可

・L3：ネットワーク層
IPアドレスで通信、異なるネットワークで通信可能
ARP登録必要
influxDBをWSLにインストールしようとしたときのエラー

基本的には下記のサイトの通りでいけるかと思い試しました。


https://docs.influxdata.com/influxdb/v2/install/?t=Linux

最初の部分でキーのエラー
```
Err:3 https://repos.influxdata.com/ubuntu jammy InRelease
  The following signatures couldn't be verified because the public key is not available: NO_PUBKEY D8FF8E1F7DF8B07E
```
探すと下記のサイトで解消するとのこと。

https://www.influxdata.com/blog/linux-package-signing-key-rotation/

今度はpubコマンドがないとのエラー。。。。
dartのSDKに入っているコマンドなのか、、、influxDBはGO言語でできてるとのことで関係ないので、
入れたくない。

代わりに下記を実行
```
curl --silent --location -O https://repos.influxdata.com/influxdata-archive.key
echo "943666881a1b8d9b849b74caebf02d3465d6beb716510d86a39f6c8e8dac7515  influxdata-archive.key" | sha256sum --check - && cat influxdata-archive.key | gpg --dearmor | tee /etc/apt/trusted.gpg.d/influxdata-archive.gpg > /dev/null && echo 'deb [signed-by=/etc/apt/trusted.gpg.d/influxdata-archive.gpg] https://repos.influxdata.com/debian stable main' | tee /etc/apt/sources.list.d/influxdata.list
sudo apt-get update && sudo apt-get install influxdb2
sudo service influxdb start
sudo service influxdb status
sudo systemctl enable influxdb
```
下記はエラー出てたらやる
```
sudo systemctl unmask influxdb.service
```
Roo ClineでPythonのFlaskを勉強してみる

# Roo ClineでPythonのFlaskを勉強してみる
Roo Clineがあまりに簡単にアプリを自動で作ってくれるので、PythonのWEBアプリフレームワークのFlaskを勉強してみようと思いました。
# 最初に行ったこと
まずChatGPT o1に以下を聞いてみました。
Q.「Flaskの学習向けの簡単なWEBアプリをたくさん紹介してください。サーバーはsakuraレンタルサーバーを使用しpythonは3.8です。」
# ChatGPT o1からの回答
以下の回答が返ってきました。
A.「Flaskの学習向けに、さくらレンタルサーバー（Python 3.8）で動作する簡単なWEBアプリのアイデアをいくつか紹介します。これらは、基本的なFlaskの機能を学ぶのに役立ちます。

## 1. メモ帳アプリ
機能: メモの追加、編集、削除
学べること: CRUD操作、SQLiteデータベース、テンプレートエンジン（Jinja2）
主な技術: Flask, Flask-SQLAlchemy, Bootstrap
## 2. ToDoリストアプリ
機能: タスクの登録、完了管理
学べること: フォーム処理、セッション管理、CSSフレームワーク連携
主な技術: Flask-WTF, Flask-SQLAlchemy, Bootstrap
## 3. 簡単なお問い合わせフォーム
機能: 名前、メールアドレス、メッセージの送信
学べること: フォームバリデーション、メール送信（Flask-Mail）
主な技術: Flask-WTF, Flask-Mail
## 4. 天気情報取得アプリ
機能: 都市名を入力して天気を取得（外部APIを使用）
学べること: API連携、非同期リクエスト処理
主な技術: Flask, requests, OpenWeatherMap API
## 5. 画像アップロードアプリ
機能: 画像のアップロード・表示・削除
学べること: ファイルのアップロード処理、Flaskのセキュリティ
主な技術: Flask-Uploads, Flask-WTF
## 6. ユーザー認証システム
機能: ユーザー登録・ログイン・ログアウト
学べること: Flask-Loginによる認証、セッション管理、パスワードハッシュ化
主な技術: Flask-Login, Flask-Bcrypt, Flask-SQLAlchemy
## 7. シンプルなブログシステム
機能: 記事の投稿、編集、削除、コメント機能
学べること: ORM、リレーショナルデータベースの使い方
主な技術: Flask-SQLAlchemy, Jinja2
## 8. チャットアプリ（WebSocket対応）
機能: リアルタイムチャット機能
学べること: WebSocket通信、非同期処理
主な技術: Flask-SocketIO
## 9. QRコード生成アプリ
機能: 入力されたテキストからQRコードを生成
学べること: 画像処理、外部ライブラリの活用
主な技術: Flask, qrcodeライブラリ
## 10. ポートフォリオサイト
機能: 自己紹介、プロジェクト一覧、問い合わせフォーム
学べること: 静的ページの作成、デザインの適用
主な技術: Flask, Bootstrap, Flask-Static-Digest

これらのアプリは、比較的簡単にセットアップでき、さくらレンタルサーバー上でPython 3.8を使って運用可能です。特に、requirements.txt で必要なライブラリを記載し、WSGI経由でアプリをデプロイする方法も学べます。興味のあるプロジェクトがあれば、具体的な実装方法を紹介できます。」
# Roo Clineへのプロンプト
挙げられた例を元にRoo Clineにプロンプトで注文するとあっという間に動くWEBアプリを作ってくれます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10836/2845a342-a7c9-6679-503d-cc2b3c17f6ad.png)

Flaskをつかったユーザー認証システムを作ってください。
フォルダは/home/garyo/project/flask/loginです。
機能: ユーザー登録・ログイン・ログアウト
学べること: Flask-Loginによる認証、セッション管理、パスワードハッシュ化
主な技術: Flask-Login, Flask-Bcrypt, Flask-SQLAlchemy

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10836/a8ac9d32-f6f1-739f-ad84-18018a73143d.png)

FlaskをつかったQRコード生成アプリを作ってください。
フォルダは/home/garyo/project/flask/QRに入れてください。
機能: 入力されたテキストからQRコードを生成
学べること: 画像処理、外部ライブラリの活用
主な技術: Flask, qrcodeライブラリ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10836/3b17f8b2-22a6-c63e-1d8e-f76f8f0ceeb2.png)

Flaskをつかったポートフォリオサイトを作ってください。
フォルダは/home/garyo/project/flask/portfolioに入れてください。
機能: 自己紹介、プロジェクト一覧、問い合わせフォーム
学べること: 静的ページの作成、デザインの適用
主な技術: Flask, Bootstrap, Flask-Static-Digest

# 結果
天気情報取得アプリだけAPIキーが上手く取れなかった以外は全てRoo Clineが作成してくれました。
# その他
AIのAPIにはDeepSeekのdeepseek-reasonerを使っています。
これだけ作っても$0.7(109円)くらいでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10836/b1c0b07c-5aca-7f82-89d0-b3daa6df395c.png)
Databricks (Spark) の SQL にて Array の値から範囲外の値を取得しようとした際のエラーへの対応方法

## 概要

Databricks にて SQL の SPLIT 関数で生成された配列に対して、範囲外のインデックスを指定した場合に発生した下記エラーへの対応方法を共有します。本エラーは、"spark.sql.ansi.enabled"の設定が"True"の場合に発生します。"spark.sql.ansi.enabled"の設定が"False"の場合と同様の対応を実施するには、 Get 関数を利用すればいいようです。


> [INVALID_ARRAY_INDEX] The index 1 is out of bounds. The array has 1 elements. Use the SQL function `get()` to tolerate accessing element at invalid index and return NULL instead. If necessary set "spark.sql.ansi.enabled" to "false" to bypass this error. SQLSTATE: 22003

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/e9d22e28-ec85-1f43-03c6-9af04b4c3dc7.png)

エラーについてドキュメントにて言及されています。

> array_col[index]: 無効なインデックスを使用している場合、この演算子は ArrayIndexOutOfBoundsException をスローします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ab312c58-b960-0727-4656-c31048450f64.png)

引用元：[Databricks Runtime での ANSI 準拠 - Azure Databricks - Databricks SQL | Microsoft Learn](https://learn.microsoft.com/ja-jp/azure/databricks/sql/language-manual/sql-ref-ansi-compliance#sql-operators)


## "spark.sql.ansi.enabled"の設定が"False"の場合の動作確認

```python
spark.conf.set("spark.sql.ansi.enabled", "False")
```

```sql
%sql
WITH src AS (
  SELECT 
    "-1" as  col_1
)
SELECT
  *,
  SPLIT(`col_1`, "[\\.]")[1]
  FROM
    src
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/1335cc08-8d9e-5503-a5c6-365610af8937.png)

## エラーの再現

```python
spark.conf.set("spark.sql.ansi.enabled", "True")
```

```sql
%sql
WITH src AS (
  SELECT 
    "-1" as  col_1
)
SELECT
  *,
  SPLIT(`col_1`, "[\\.]")[1]
  FROM
    src
```

> [INVALID_ARRAY_INDEX] The index 1 is out of bounds. The array has 1 elements. Use the SQL function `get()` to tolerate accessing element at invalid index and return NULL instead. If necessary set "spark.sql.ansi.enabled" to "false" to bypass this error. SQLSTATE: 22003

## エラーへの対応方法

```sql
%sql
WITH src AS (
  SELECT 
    "-1" as  col_1
)
SELECT
  *,
  get(SPLIT(`col_1`, "[\\.]"), 1)
  FROM
    src
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/fe5515d9-26a1-001f-2bc1-312ecb698612.png)
【Xcode】Xcodeが動かない！？落ち着け、この記事を見れば大丈夫

# Xcodeの不具合を解消するための手順まとめ

iOSアプリ開発において、Xcodeは欠かせない開発ツールですが、時折不具合や謎のエラーに悩まされることがあります。
この記事では、初心者でも分かりやすくXcodeの不具合解消に役立つ手順を具体的に解説します。

---

## 目次
1. **基本的な解決手順**
    - Xcodeの再起動
    - macOSの再起動
2. **キャッシュ関連の対処法**
    - Derived Dataの削除
    - Module Cacheの削除
3. **プロジェクト設定の確認と修正**
    - ビルド設定のクリーンアップ
    - プロビジョニングのリフレッシュ
4. **コマンドを使った問題解消**
    - `xcodebuild`コマンド
    - シミュレータのリセット
5. **その他のトラブルシューティング**
    - Xcodeの再インストール
    - クリーンインストール時の注意点
6. **おまけ：便利なリソース**

---

## 1. 基本的な解決手順
### 1.1 Xcodeの再起動
一番簡単ですが、意外と効果的です。アプリケーションの挙動が不安定な場合は、まずはXcodeを終了して再起動してみてください。

- **手順**  
  1. **`Command + Q`** でXcodeを終了します。  
  2. 再度Xcodeを起動します。

### 1.2 macOSの再起動
macOSの状態が不安定だと、Xcodeに影響を与えることがあります。

- **手順**  
  1. macOSを再起動します。  
  2. 再起動後、再度Xcodeを起動して問題が解決しているか確認します。

---

## 2. キャッシュ関連の対処法
### 2.1 Derived Dataの削除
XcodeのキャッシュであるDerived Dataは、ビルド関連の問題を引き起こすことがあります。

- **手順**  
  1. Xcodeを終了します。  
  2. Finderで以下のパスに移動します。  
     ```
     ~/Library/Developer/Xcode/DerivedData
     ```  
  3. フォルダ内のデータをすべて削除します。  
  4. Xcodeを再起動してビルドを試してください。

### 2.2 Module Cacheの削除
モジュールキャッシュが原因でエラーが発生することもあります。

- **手順**  
  1. 以下のパスに移動します。  
     ```
     ~/Library/Developer/Xcode/ModuleCache
     ```  
  2. フォルダ内のデータを削除します。

---

## 3. プロジェクト設定の確認と修正
### 3.1 ビルド設定のクリーンアップ
- **手順**  
  1. Xcodeのメニューから **Product > Clean Build Folder** を選択します（ショートカット：`Shift + Command + K`）。
  2. 再ビルドを行い、エラーが解消されているか確認します。

### 3.2 プロビジョニングのリフレッシュ
証明書やプロビジョニングプロファイルが原因でビルドエラーが発生する場合があります。

- **手順**  
  1. **Xcode > Settings > Accounts** に移動します。  
  2. Apple IDを選択し、「Manage Certificates」で証明書を更新します。  
  3. プロビジョニングプロファイルを手動で再取得します。

---

## 4. コマンドを使った問題解消
### 4.1 `xcodebuild`コマンドでクリーン
ターミナルでXcode関連のキャッシュを削除するコマンドを実行できます。

- **手順**  
  1. ターミナルを開きます。  
  2. 以下のコマンドを実行します。  
     ```bash
     xcodebuild clean
     ```

### 4.2 シミュレータのリセット
シミュレータのキャッシュが問題を引き起こす場合があります。

- **手順**  
  1. ターミナルで以下を実行します。  
     ```bash
     xcrun simctl erase all
     ```  
  2. シミュレータを再起動します。

---

## 5. その他のトラブルシューティング
### 5.1 Xcodeの再インストール
それでも問題が解決しない場合、Xcodeを再インストールしてみてください。

- **手順**  
  1. App Storeまたは`/Applications`フォルダからXcodeをアンインストールします。  
  2. App Storeから最新バージョンのXcodeをインストールします。

### 5.2 クリーンインストール時の注意点
Xcode再インストール前に、関連フォルダを完全に削除することで不具合が残らないようにします。

- 削除対象のフォルダ：
  - `~/Library/Developer/Xcode`
  - `~/Library/Preferences/com.apple.dt.Xcode.plist`

---

## 6. おまけ：便利なリソース
- [Apple公式ドキュメント](https://developer.apple.com/documentation/)
- [Stack Overflow: iOS開発タグ](https://stackoverflow.com/questions/tagged/ios)

---

この記事が少しでも皆さんの開発環境の安定に役立てば幸いです。何か追加の手順や質問があれば、コメントで教えてください！
TabViewの使い方

# TabViewの使い方
#swiftアプリ開発の備忘録
## ソースコード
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        TabView {
            Group {
                topPage
                helpPage
            }
            .toolbarBackground(.visible, for: .tabBar)
        }
        
    }
}

// MARK: -UI
struct TopView: View {
    var body: some View {
            Text("トップページです")
                .tabItem {
                    Image(systemName: "book.pages.fill")
                    Text("トップ")
                }
    }
}

struct HelpView: View {
    var body: some View {
        Text("ヘルプページです")
            .tabItem {
                Image(systemName: "questionmark.circle.fill")
                Text("ヘルプ")
            }
    }
}
```
![スクリーンショット 2025-01-23 13.52.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109842/0941da83-4a0e-02fa-61fb-04541075a412.png)![スクリーンショット 2025-01-23 13.54.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109842/c3fbf868-d9f6-f3e7-556c-33f7689ba931.png)
設定で勝手に作成されるIAMポリシーを一括で削除するCLIワンライナー

# はじめに
AWSでちょっと検証と思い、手動でリソースを作成していたら、設定で勝手に作成されるIAMポリシーが大量に作成されてしまいました。
例: AWSLambdaBasicExecutionRole-xxx, AWSCodePipelineServiceRole-xxx, CodeBuildBasePolicy-xxx ...
IAMロールは選択式のチェックボックスがあるため、複数選択から削除が可能なのですが、IAMポリシーは選択式ではないため、手動で削除するのは大変です。
そのため、AWS CLIで一括削除する方法を調べてみました。

# 方法
:::message alert
動作確認はしましたが、意図していないポリシーを削除してしまう可能性があるため、各自検証の上、ご利用ください。
:::

```bash
aws iam list-policies --query 'Policies[?starts_with(PolicyName, `XXX`)].Arn' --output text | tr '\t' '\n' | xargs -I{} aws iam delete-policy --policy-arn {}
```
※XXXの部分は、削除したいポリシー名のプレフィックスを指定してください。
※バージョンを作成しているポリシーは削除できません。

内容としては特定のプレフィックスで始まるIAMポリシーを一覧表示し、それらを削除するためのものです。`aws iam list-policies`コマンドを使用して、条件に一致するポリシーのARNを取得し、`tr`コマンドでタブ区切りを改行に変換し、その結果を`xargs`コマンドに渡して、`aws iam delete-policy`コマンドで各ポリシーを個別に削除します。

## 実行例
例えば、`AWSCodePipelineServiceRole`で始まるポリシーを削除する場合：
```bash
aws iam list-policies --query 'Policies[?starts_with(PolicyName, `AWSCodePipelineServiceRole-`)].Arn' --output text | tr '\t' '\n' | xargs -I{} aws iam delete-policy --policy-arn {}
```

## 事前確認
削除前に対象のポリシーを確認したい場合は、以下のコマンドで一覧を表示できます：
```bash
aws iam list-policies --query 'Policies[?starts_with(PolicyName, `AWSCodePipelineServiceRole-`)].Arn' --output text | tr '\t' '\n'
```

# おわりに
AWS CLIを使用することで、特定のプレフィックスで始まるIAMポリシーを一括で削除することができます。手動での削除作業が必要な場合に比べて、大幅な時間短縮が可能です。
ただし、削除対象のポリシーを慎重に確認し、意図しないポリシーを誤って削除しないよう注意が必要です。
DOKでOllamaを実行する

[DOK](https://www.sakura.ad.jp/koukaryoku-dok/)はコンテナー型のGPUサービスで、NVIDIA V100やH100を実行時間課金で利用できるサービスです。

[コンテナー型GPUクラウドサービス 高火力 DOK（ドック） | さくらインターネット](https://www.sakura.ad.jp/koukaryoku-dok/)

今回はこのDOKを使って、Ollamaを実行してみます。ローカルにGPUがなくとも、速いレスポンスが得られます。

## Ollamaとは

Ollamaは、LLMを簡単に実行できるオープンソース・ソフトウェアです。Llama 3やMistralなど、さまざまなモデルに対応しています。CLIで利用することが多いですが、今回はWeb APIとして立ち上げて、Open WebUIから操作します。

![FireShot Capture 396 - Open WebUI - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/acf27cb8-572d-0427-938c-d7f5a2fe8430.jpeg)


## 実行する

DOKで、下記の条件でタスクを作成します。

| 項目       | 設定          |
| ---------- | ------------- |
| イメージ   | ollama/ollama |
| HTTPポート | 11434         |

実行して、しばらく待つとHTTPアクセスできるURL（ `https://UUID.container.sakurausercontent.com` のような）が発行されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/7b296aff-e6bc-6d55-0b2c-b24815cf6673.png)


## Open WebUIで操作する

ローカルで実行します。これはGPUが不要なので、Dockerさえ実行できれば、どこでも実行できます。先ほど出力されたURLを `OLLAMA_BASE_URL` として指定します。

```bash
docker run -p 8080:8080 \                                                       
-e OLLAMA_BASE_URL=https://UUID.container.sakurausercontent.com \ # 発行されたURLに置き換え
-v open-webui:/app/backend/data \
--name open-webui --restart always ghcr.io/open-webui/open-webui:main
```

そして、ブラウザで `http://localhost:8080` にアクセスします。以下のような画面が表示されます。

![FireShot Capture 394 - Open WebUI - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/776bf498-d84a-8097-ab57-abd8c7d0db86.jpeg)

## モデルの追加

設定の中にある接続設定から、モデルを追加します。今回はLlama 3.2を追加しました。ダウンロードはDOK側で行われます。

![FireShot Capture 395 - 管理者パネル - Open WebUI - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/ea5f5939-3436-ed55-4c69-916b2ec683e8.jpeg)


ダウンロードさえ終われば、チャットが利用できます。

![FireShot Capture 397 - 🌐 Sticky Header with CSS & JS - Open WebUI - localhost.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/2246a806-3c2c-66cd-f172-bffa38376182.jpeg)


## 注意点

DOK上でコンテナが実行されている限り、課金が発生します。使い終わったら、タスクを終了してください。

なお、執筆時点（2025年1月現在）では、v100-32gbが無料、h100-80gbが0.11円/秒とキャンペーン中になっています（H100は2025年4月末までの価格）。

## まとめ

今回はDOKでOllamaを試しました。v100-32gbを使いましたが、より大規模なモデルを利用するならh100-80gbもあります。大規模LLMの学習や評価に使うと、ローカルのGPUを使うよりも早く結果が得られます。ぜひ試してみてください。

DOKはタスク実行用途での利用が多いですが、HTTPアクセスを使えば[Jupyter Notebookなども利用できます](https://knowledge.sakura.ad.jp/38980/)。ぜひAI・機械学習に活用してください。

[コンテナー型GPUクラウドサービス 高火力 DOK（ドック） \| さくらインターネット](https://www.sakura.ad.jp/koukaryoku-dok/)
Windowsバッチ(.bat)学習メモ　文字列加工

<br>

* (n+1)文字目以降～最後まで
    `%変数名:~n%`
    ```bat:
    set sample=123456789
    @echo %sample:~3%
    456789
    ```

<br>

* n文字目からm文字
    `%変数名:~n,m%`
    ```bat:
    set sample=123456789
    echo %sample:~3,2%
    45
    ```

<br>

* n文字目以降(末尾x文字は表示しない)
    `%変数名:~n,x%`
    ```bat:
    set sample=123456789
    echo %sample:~3,-1%
    45678
    ```

<br>

* 後ろからn文字目～最後まで
    `%変数名:~-n%`
    ```bat:
    set sample=123456789
    echo %sample:~-2%
    89
    ```

<br>

* 後ろからn文字目～最後m文字を除いたところまで
    `%変数名:~-n,m%`
    ```bat:
    set sample=123456789
    echo %sample:~-2,1%
    8
    ```

<br>

* 後ろからn文字目以降m文字
    `%変数名:~-n,-m%`
    ```bat:
    set sample=123456789
    echo %sample:~-4,-3%
    678
    ```

<br>

**※重要※**
* 文字Aを文字Bに置換する。複数文字を指定することも可能。
    `%変数名:A=B%`
    **※置換先Bに何も記述しない場合、置換元Aが削除された文字列が返される**
    ```bat:
    set sample=123456789
    
    rem 置換元「3」を削除
    echo %sample:3=%
    12456789
    
    rem 置換元「345」を「?」に変換
    echo %sample:345=?%
    12?6789
    ```
rex0220 データ生成プラグイン テーブル行集計結果からレコード生成

[データ生成プラグイン](https://qiita.com/rex0220/items/8e760adbfd69b9416b2d)で、テーブル行集計結果からレコード生成してみます。

# 概要

データ生成プラグインでテーブル内の製品別に集計して、レコード生成する例です。
計算式の関数で、テーブル集計を行いレコード生成を行います。

![2025-01-23_12h58_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/109d68fc-3ea9-a337-3705-3f6558e85aed.png)

# データ生成プラグイン設定

テーブル集計時は、テーブル欄を指定しません。

![2025-01-23_13h04_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/4e3caa99-d5d6-366d-9d48-4588b56477da.png)

- 対象アプリ条件：　レコードを識別するため伝票番号を指定

![2025-01-23_13h04_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/ce779425-20ec-0a02-a055-71992765ca07.png)

- 設定項目：　
    - ループ配列：　製品名を配列化して製品名分ループ
        - TDSIF： テーブル内項目を指定条件で重複無く配列化
        - TDSIF(製品名,製品名)： 入力済みの製品名を配列化
    - 伝票番号：　元レコードの伝票番号
    - 識別ID：　データ生成プラグイン制御用の識別ID
    - 製品名：　ループ変数 $val に、製品名が入る
    - 数量：　SUMIF で、製品別に集計
    - 単価：　金額集計と数量集計から平均単価を算出
    - 金額：　SUMIF で、製品別に集計

![2025-01-23_13h05_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/a174f88d-5854-04c2-632e-f93b99aad5e3.png)
pythonで画像を表示する

## 導入
python で画像を表示してみよう。

## 前提
フレームワークは面倒なのでガン無視して、最初なので openCV を使います。

## 拾ってきたサンプルコード
```
import cv2

img = cv2.imread('sample.png')
cv2.imshow('sample', img)
cv2.waitKey(0)
cv2.destroyAllWindows()
```
これを適当なディレクトリに image.py 等として保存します。
sample.png も同じディレクトリに用意します。

## openCV をインストールする
まず pip を使う前は、アップグレードする癖をつけましょう。
```
$ pip install --upgrade pip
```
```
$ pip install opencv-python
```
はいエラーで失敗ｗｗｗ
openssl はインストールされていましたが python くんが openssl の場所がわからないようです。

## anaconda をインストールする
いろいろ小一時間いろいろ調べて、英文と格闘した結果、まず anaconda をインストールして anaconda を使って openssl をインストールすれば解決しそうだとわかりました。

anaconda のサイトから Windows 用のインストーラを拾ってきてインストールします。このときインストールするディレクトリパスにスペースが入らないようにします。うちは cygwin 環境なのですが、PATH を使って cygwin から使いたいからです。

## 教訓
ディレクトリにスペースを使うのは Windows の独自仕様です。
Linux 等の他 OS では(cygwin も同様)、
ディレクトリにスペースを使うとろくな目に遭わないので、
絶対にやめましょう。

## openssl をインストールする
```
$ conda install openssl
```

## openCV をインストールする
```
pip install opencv-python
```
今度はすんなりインストールできました。

## ライブラリが見えるかテスト
```
$ python
Python 3.12.7 | packaged by Anaconda, Inc. | (main, Oct  4 2024, 13:17:27) [MSC v.1929 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import cv2
>>> quit()
```
エラーでません。OK です。
## 実行
```
$ python image.py
```
sample.png が表示されました。

## 次回
次は Web ブラウザに画像を表示してみよう。
(次回がいつなのかは未定)
accepts_nested_attributes_forで関連モデルを同時作成する

Orderモデルが複数のItem持っている状況を考えます。

Orderモデルに`accepts_nested_attributes_for`を追加します。
こうすることでOrderモデルは`items_attributes`属性を受け入れるようになります。

```order.rb
class Order < ApplicationRecord
  has_many :items
  + accepts_nested_attributes_for :items
end
```

実際に同時作成するときには`items_attributes`で子モデル属性の配列を渡せば良いです。

```orders_controller.rb
order = Order.new(
  customer: "田中",
  items_attributes: [
    { name: "商品A", price: 1000 },
    { name: "商品B", price: 2000 }
  ]
)
order.save
```

このときに、関連モデルのバリデーションも実行されます。
ただし、子モデルにおけるバリデーションエラーは親モデルには伝播しません。
実務でよく使うPyTorchの機能まとめ③｜modelの保存・読み込み(torch.save・torch.load)

## 基本的な用法
### torch.save
PyTorchで学習させたmodelの保存には`torch.save`を用います。

```python
import torch
# https://pytorch.org/docs/main/generated/torch.save.html

# Save to file
x = torch.tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
torch.save(x, "tensor.pt")
```

上記を実行するとカレントディレクトリに`tensor.pt`というファイルが保存されます。

https://pytorch.org/docs/main/generated/torch.save.html


### torch.load
保存させたmodelの読み込みには`torch.load`を用います。下記が基本的な実行例です。

```python
model = torch.load("tensor.pt", weights_only=True)
print(type(model), model)
```

・実行結果
```
<class 'torch.Tensor'> tensor([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
```

CPU環境で呼び出す場合は`torch.load`の引数に`map_location=torch.device("cpu")`を入れて実行します。

https://pytorch.org/docs/stable/generated/torch.load.html



## 抑えておくと良い使い方
アンサンブルとスタッキングを分かりやすく解説！初心者向けガイド

データ分析や機械学習を勉強していると、「アンサンブル」や「スタッキング」という言葉を耳にすることが増えてきます。しかし、初めて聞くと少し難しそうに感じるかもしれません。そこで今回は、初心者でも分かりやすいように、アンサンブルとスタッキングについて丁寧に解説していきます！
※この記事は、ChatGPTの出力を基に作成しています。

---

#### **アンサンブルとは？**
アンサンブルとは、**「複数のモデルを組み合わせて、より正確な予測を目指す方法」**のことです。一つのモデルだけを使うのではなく、複数のモデルの長所を活かすことで、より高い精度を目指します。

イメージとしては、「みんなで意見を出し合って最良の答えを導く」ような方法です。

---

#### **アンサンブルの種類**
アンサンブルにはいくつかの種類があります。以下が代表的なものです：

1. **バギング（Bagging）**
   - 同じアルゴリズムを使った複数のモデルを学習し、それらの結果を「平均」や「多数決」で統合する手法。
   - 例：ランダムフォレスト。
   - **特徴：安定性を高めることが目的。**

2. **ブースティング（Boosting）**
   - 弱いモデル（性能が低いモデル）を順番に学習させ、徐々にエラーを減らしていく手法。
   - 例：XGBoost、LightGBM。
   - **特徴：段階的にモデル性能を向上させることが目的。**

3. **スタッキング（Stacking）**
   - 複数の異なるモデルを組み合わせ、その出力を新たなモデルに入力して最終的な予測を行う手法。
   - **特徴：異なるモデルの強みを組み合わせて精度を上げることが目的。**

今回は、スタッキングにフォーカスして詳しく見ていきます！

---

#### **スタッキング（Stacking）とは？**
スタッキングは、**「複数のモデルの出力を新しい特徴量として組み合わせ、別のモデル（メタモデル）で最終的な予測を行う」**という手法です。

##### **スタッキングの流れ**
1. 複数のモデル（例：モデルA、モデルB、モデルC）を訓練して予測を行う。
2. 各モデルの予測結果を、新しいデータセットとしてまとめる。
3. そのデータセットを使ってメタモデル（ブレンダーとも呼ばれる）を訓練し、最終的な予測を行う。

##### **具体例**
たとえば、健康診断の結果を基に病気のリスクを予測する場合を考えます。
- **モデルA：医者の意見**
- **モデルB：心理学者の意見**
- **モデルC：栄養士の意見**
最後に、これらの意見を総合的にまとめる「家庭医」がメタモデルとなり、最終的な判断を下します。

---

#### **スタッキングと他のアンサンブル手法の違い**
| 手法           | 仕組み                                                         | イメージ                                         |
|----------------|----------------------------------------------------------------|------------------------------------------------|
| **バギング**   | 複数の同じアルゴリズムを使い、結果を平均化または多数決する       | みんなで手を上げて多数決                        |
| **ブースティング** | 弱いモデルを繰り返し訓練し、徐々にエラーを修正していく          | 少しずつ練習して成績を上げる                   |
| **スタッキング** | 異なるモデルの結果をまとめ、さらに別のモデルで最終予測を行う     | 専門家の意見をリーダーがまとめて判断する       |

---

#### **スタッキングのメリット・デメリット**
##### **メリット**
- 異なるモデルの強みを活かせる。
- 全体の予測精度が向上することが多い。

##### **デメリット**
- 計算コストが高い（複数のモデルを訓練する必要がある）。
- 設計が複雑で、適切な調整が必要。

---

#### **初心者にも分かるスタッキングのイメージ**
たくさんの専門家の意見を集め、最後にコーディネーターがそれらをまとめる、という方法を考えると分かりやすいかもしれません。

例えば：
1. Aさん：ある分野の知識が豊富。
2. Bさん：別の視点で物事を考えるのが得意。
3. Cさん：異なるデータを分析するスキルがある。

それぞれが出した意見を、最後に「まとめ役」が判断して最良の結論を出します。これがスタッキングです。

---

#### **まとめ**
- スタッキングは、アンサンブル学習の一種で、異なるモデルを組み合わせることで精度を上げる手法です。
- バギングやブースティングと比べて柔軟性が高いですが、計算コストや設計の複雑さがあります。
- 初学者の方はまず、ランダムフォレスト（バギング）やXGBoost（ブースティング）から学び、次のステップとしてスタッキングを試してみるのがおすすめです！

アンサンブル学習は機械学習の中でも非常に重要なテーマです。少しずつ理解を深めていきましょう！
IBM i 駆け出し日記：Rational Developer for i (RDi)を日本語に設定&Fixをあてる

# はじめに
最近のIBM i 開発においてはVS codeに関する記事が多いですが、VS codeで使用する拡張機能であるCode for IBM iとDb2 for IBM i は今のところ日本語設定ができません。
一方、Rational Developer for i (RDi)は日本語環境で使用できます。
英語以外の環境で安定して動作することが、RDiのメリットの1つとのことです。

今回はRDiの日本語設定方法を書いていきます。

インストールの記事はこちら：[IBM i駆け出し日記：Rational Developer for i (RDi)をインストールする](https://qiita.com/koga39chan/items/2661e962c475ab70d875)

# 使用する環境
- 筆者のPC
Mac book Air M1 

[RDi のSW/HW要件](https://www.ibm.com/software/reports/compatibility/clarity/product.html?id=DA7EB234CACE476C87F0C99EFE92DC27)を確認するとRDiはM1/M2チップMacは非対応では？との疑念ありでしたが 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/03638355-3a5f-a93b-a4c0-e74dbe44ca2f.png)

現地技術者の方に聞いたら、「そんなことはないよ、対応しています。」と言われました。
アプリケーションの稼働も安定しています。
ただ資料のアップデートがかかってないだけかもしれませんね。

- 使用したRDiのバージョン
現行：RDi 9.8.0.0
あてるFix：9.8.0.3(2024/12にリリースされたもの)


[RDiのFixリスト](https://www.ibm.com/support/pages/fix-list-rational-developer-i#9801)はここから確認できます。
RDiなくなるのでは？と言われたことありますが、かなり定期的にFix出てます。
なのでそんなことないです。

# 日本語環境に設定
Rational Developer for i (RDi)のアイコンを右クリックして、
”パッケージの内容を表示” → “パッケージの内容を表示” -> “Contents” -> “Eclipse”
をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/5432968e-5ff6-335d-0608-dc5620856890.png)

“developer_for_i.ini”に以下を追記します。

```
-Duser.language=ja 
-Duser.country=JP
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/ef9bd5f9-6806-a93f-be2b-7b987a778aaf.png)


RDiを再起動して表示言語が日本語になっていることを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/64f168eb-3903-7971-c879-6505f61faa5d.png)

Macは日本語に設定しても、上のメニューバーは英語なんですよね。
表示の半分くらいが日本語になります。

Windowsはほぼ全て日本語で表示されます。
なんならインストールの段階で日本語になるので、この操作は不要です。
もし何らかの間違いで日本語環境にならなかった際、こちらをお試しください。

# Fixをあてる
RDiのヘルプからcheck for Updatesを選択します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/052742e7-3b8d-3f84-442f-453cc704a0f1.png)
 
 更新可能なアップデート一覧が出てきます。アップデートしたいものを選択します。
今回はデフォルトの全部選択しました。
Nextボタンを押します。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/608b2924-b7ba-4ed2-2f9e-cb843a2cc5a7.png)

問題なければFinishを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/8f04a4cc-1bcf-117d-592a-7d947e173698.png)

Finish押しても応答がないので、もう一度check for Updatesを選択するとこのようなエラーが。静かにインストール操作が走っているそう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/684df427-0bb3-e99a-220f-8021c2456d27.png)

7分くらい待ってこのような表示が出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/054f0d79-c7a1-f2df-5290-1391fea72b2a.png)
Select Allを押して、右下の青くなったTrustSelectedを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/7daabc0f-7c10-7a0c-b0cb-0672b6f98735.png)
再起動するか聞かれるので、Restart nowを押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/5c62acc3-7443-8e3f-330e-2888ce938dcb.png)

再起動したRDiのバージョンを確認すると、9.8.0.3になっておりました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3212743/42d536bf-613b-aee0-0fad-764722d1196a.png)


今回はここまで！
手軽にプライバシー保護２０２５年版

# コストをかけないでパッケージ品にどこまで迫れるか
## 朝起きたらCESで人間と車のナンバーを隠すとかやっていたので、既存のモデルでやってみた

:::note info
インフォメーション
- しっかりやるのであれば、それぞれデータを集めて学習するのはわかっているんですが・・・
:::

# 人間はかんたんだが、ナンバー・文字系が難しい
**人間はDeepLabV3がPytorchにありますからね**
さて、OCRのモジュールをつっこんでみる？？

# OCRはお気楽モードではうまくいかない
## 使用したモジュール


:::note info
- 実行環境は通常のオフィスでOCRを阻害するであろう因子がてんこ盛り
- しっかりやるのであれば、それぞれデータを集めて学習するのはわかっているんですが・・・
:::

## 使用したもの
1. pytesseract
    - デバッグすると一部は読めている模様。 
    - ただし、全体が読めていないため、モザイクがかからず

2. EasyOCR
    - フレームレートが落ちた？このOCRのせいではないと思いますが 

:::note info
参考記事はこちら
:::    

https://qiita.com/ryome/items/16fc42854fe93de78a23

https://qiita.com/penguinprogrammer/items/b1d5a956768182c20ac6

# 文字を読むのではなく、文字っぽい領域をセグメンテーションする
- OCRの考えで行くと真面目にやるので手書き文字などまったく引っかからず
- かといってEMNISTみたいなセットを学習してみたが、推論がだめでした・・・
- 短い時間で作るので、今回は諦めよう！
- OCRをするとフレームレートが3,4FPSになっている

# pytesseractベースで文字単位から領域に緩くする

```python

# CUDA使います

device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"[INFO] Using device: {device}")

```

# それっぽい状態になった（要改良）

- これで実用的なフレームレートが出るようになりました。10FPS以上

![masked.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/b202b0d6-4a43-9c3e-fe74-260d6fcd3d01.png)

![number.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2155177/da28b945-4260-716b-971c-770c0b407476.png)

- 一応、ナンバーも見えない。
- ・・・実はちょいちょい外れちゃうのが、要改善

:::note info
インフォメーション
- 市販レベルで工数は趣味レベルで更新がんばります
:::

https://github.com/mi-kaneyon/person_privacy
Cloudflare WARP のログインユーザを切り替える

# 目的

Cloudflare WARP を対象の Cloudflare Zero Trust アカウントに紐付けて利用を始めるには、チーム名を指定して `Cloudflare Zero Trust にログイン` する必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a39a585c-c539-d59c-5c77-2a567638ca6b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/31672fc8-df24-6685-7cf4-fff72b85f878.png)

その際に、デプロイパラメータとして指定する方法はいくつかありますが、その方法によって Cloudflare WARP のログインユーザを切り替える方法も異なるため、動作を確認します。

https://qiita.com/khayama/items/9f675bef0a4d7e1721d7

例えば、1つの Windows ローカルユーザアカウント内で、複数のログインユーザを切り替えたい場合が想定できます。

# Cloudflare WARP のログインユーザを切り替えるには

以下の3つがアクションが必要となります。

1. ブラウザ上で IdP からログアウト
1. ブラウザ上で `https://<YOUR_TEAM_NAME>.cloudflareaccess.com/cdn-cgi/access/logout` からログアウト
1. `Cloudflare Zero Trust からログアウト` して、WARP が保持する登録情報をクリア

これらによって、WARP 登録に使うログインユーザを切り替えられます。

もし 1 の段階で IdP のログアウトエンドポイントにリダイレクト機能があれば、1 --> 2 を一度の操作で終えることも可能です。

例えば、以下のような記事の内容を参考にできます。

https://qiita.com/khayama/items/4289eef68835dfdec84a

# 1. ブラウザ上で IdP からログアウト
IdP での操作に従ってログアウトしてください。

例えば、Microsoft Entra ID の場合、https://myprofile.microsoft.com/ からサインアウトできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a70f1cae-a6da-6697-d8ba-dac23de2140d.png)


# 2. ブラウザ上で `https://<YOUR_TEAM_NAME>.cloudflareaccess.com/cdn-cgi/access/logout` からログアウト
`https://<YOUR_TEAM_NAME>.cloudflareaccess.com/cdn-cgi/access/logout` にアクセスし、ログアウトされたことを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/9d9c9273-10b1-65e8-6d46-5bb1b9d0ffcc.png)

# 3. `Cloudflare Zero Trust からログアウト` して、WARP が保持する登録情報をクリア

## GUI でチーム名を指定してログインした場合
以下の `Cloudflare Zero Trust からログアウト` ボタンを押して、WARP が保持する登録情報をクリアすることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/81d997d9-f7e0-b68c-fbeb-a81290da3f94.png)

その後、初期状態から再設定をおこなう形です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/a39a585c-c539-d59c-5c77-2a567638ca6b.png)

## `msiexec` や MDM ファイルでチーム名を指定してログインした場合
以下の `Cloudflare Zero Trust からログアウト` ボタンがグレーアウトして、GUI からは WARP が保持する登録情報をクリアすることができません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/5b08b142-d5cb-1eff-fa54-321f45468742.png)

この場合、以下のコマンドで WARP が保持する登録情報をクリアできます。

```shell:
warp-cli registration delete
```

その後は、MDM ファイルにチーム名の設定情報が残るため、チーム名のログインページに遷移する挙動を確認しました。

`https://<YOUR_TEAM_NAME>.cloudflareaccess.com/cdn-cgi/access/login/<YOUR_TEAM_NAME>.cloudflareaccess.com?xxx...`

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101361/4222dabc-d5dc-fdbe-9611-b5dffcf8659c.png)

# まとめ

`Cloudflare Zero Trust からログアウト` ボタンが押せない場合には、`warp-cli registration delete` をしつつ、ブラウザに残った認証 Cookie をうまく削除できれば、Cloudflare WARP のログインユーザを切り替えられることを確認できました。
Windowsバッチ(.bat)学習メモ　お決まりの文言について

目次
1. `先頭に@をつける` または `echo off`
1. `setlocal`、`endlocal`
1. `setlocal enableDelayedExpansion`

<br>

* `先頭に@をつける` または `echo off`
コマンド部分の出力をしないようにする。
コマンドの先頭に@をつけた場合はそのコマンドのみが対象となり、
`echo off`の場合は以降全てのコマンドが対象となる。
再度コマンド部分の出力をするようにしたい場合は、`echo on`を入力する。
    ```bat:コード
    rem @でコマンド部分を非表示にする
    @echo using @

    rem 何も設定しない状態だと、コマンド部分が表示される
    echo no setting

    rem @でコマンド部分を非表示にしたecho offを実行
    @echo off
    rem echo offの後なので、@を付けずともコマンド部分は非表示になる
    echo command is gone
    echo on

    rem echo onの後なので、@を付けないとまたコマンド部分が表示されるようになっている
    echo command is return
    
    @pause
    ```
    ```bat:結果
    using @
    (パス)>echo no setting
    no setting
    Command is gone
    
    (パス)>echo Command is return
    Command is return
    続行するには何かキーを押してください...
    ```
    出力結果が煩雑にならず済むため、九分九厘記述必須のキーワードだと思う。
    なお、実際は`echo off`を含めた全てのコマンドを非表示にしたい場合がほとんどなので、`@echo off`を頭に記述し、`echo on`は記述しないことがほぼ常となる。

<br>

* `setlocal`、`endlocal`
変数のスコープ範囲を、`setlocal`～`endlocal`間に限定する。
つまりここで定めた範囲内における変数への変更は、範囲外では反映されない。
    ```bat:コード
    @echo off

    set a=1
    echo %a% @point1

    rem 1つ目のスコープ開始
    setlocal
        echo %a% @point2
        set a=2
        echo %a% @point3

        rem 2つ目のスコープ開始
        setlocal
            echo %a% @point4
            set a=3
            echo %a% @point5
        endlocal
        rem 2つ目のスコープ終了
        
        echo %a% @point6
    endlocal
    rem 1つ目のスコープ終了

    echo %a% @point7
    ```
    ```bat:結果
    1 @point1
    1 @point2
    2 @point3
    2 @point4
    3 @point5
    2 @point6
    1 @point7
    続行するには何かキーを押してください...
    ```
    スコープを出ると、スコープ突入直前の値に回帰していることがわかる。
    
    >※なお`endlocal`は、記述せずともバッチファイル終了時に必ず勝手に実行されるようになっている。
    >そのためスコープのネストをしなければ、実際は`setlocal`の記述だけで事足りる場合が多い。
    >しかし、可読性のためにも`endlocal`は明記しておくに越したことはないと思う。
    
    なお環境変数に変更を加えたとしても、末尾の暗黙的な`endlocal`によってその変更は全て破棄されるので、不必要な影響を与えてしまわないかという心配は無用。

<br>

* `setlocal enableDelayedExpansion`
変数は、通常その変数が記述されている **"行"** が読み込まれた瞬間に、一気に展開される。
しかしこれを記述すると、変数はその変数が記述されている行が読み込まれた瞬間には展開されず、 少し遅れて **"命令(コマンド)"** が読み込まれた瞬間に一気に展開されるようになる。
    ```bat:コード
    @echo off
    
    set a=1
    if %a% == 1 (
        set /a a+=1
        rem if文に入った時点のものが展開されるため、
        rem 1+1は反映されず、1が表示されることになる。
    	echo %%a%% in if is %a%
        rem ただし内部的に計算は完了しているので、
        rem 文外で再度表示させれば、反映後の結果が表示される。
    )
    echo %%a%% out if is %a%
    
    setlocal enableDelayedExpansion
        set b=11
        if %b% == 11 (
            set /a b+=1
            rem enableDelayedExpansionが設定されている時に、
            rem 「%」ではなく「!」で変数を囲むことにより、
            rem 展開タイミングの遅延が発動する。
        	echo %%b%% is %b%
        	echo ^^!b^^! is !b!
        )
    endlocal
    
    pause
    ```
    ```bat:結果
    %a% in if is 1
    %a% out if is 2
    %b% is 11
    !%! is 12
    ```
    これが輝くのは、if文やfor文などを使う時。
    if文やfor文は、始まりのカッコ`(`から終わりのカッコ`)`までが1行と見なされる。
    よって文中で変数に対しどのような操作を行ったとしても、これを設定していなければ文に入った時点のもので置換されてしまうことになるため、
    if文やfor文での変更を即時反映させて扱いたい場合は、設定が必須となる。
インシデントを起こりにくくするために気を付けていること

SIerに所属しており、普段Microsoft Teams、SharePoint、Azure Portalなどを利用して複数の企業の複数の案件に対応しています。案件によりますが、自社テナントのアカウントを客先のテナントにゲスト招待頂きそのアカウントにて対応するケースがあります。
そんな時にいつも危ないなと思いながら作業しているのが、意図とは異なるのお客様のTeams、SharePointに投稿したりファイルをアップロードしてしまうことです。

幸い今のところ、メール誤送信なども含めたインシデントは人生で起こしていないのですが、常に明日は我が身でいつ起こしてしまってもおかしくないと思っています。
そのリスクを0にするは難しいですが、私が普段からそのリスクを少なくするために行っていることを紹介します。他にもこんなことやっているなどあれば是非教えてほしいです。

- Teamsのウェブ版は顧客Teasm専用、アプリ版は自社Teams専用で利用
    - Teamsの開き方は主にアプリ、ウェブの2つになりますが、それぞれで自社、顧客を開くと混乱してインシデントが起こるリスクが上がります。私は常にアプリ版は自社、顧客はウェブで表示、なおかつ普段からTeamsのウィンドウの場所を固定することで対策しています。
- Teamsのウェブ版とTeamsのアプリ版テーマの色を分ける
    - 顧客用で使用しているウェブのTeamsとアプリ版のTeamsのテーマの色を分けています。それによって今どの顧客テナントのTeamsなのか自社のテナントなのか見分けがつきます。注意する必要があるのは、顧客ごと(テナントごと）でTeamsの背景は現状変えられないのであくまで自社か顧客かがわかるのみで、顧客間は注意する必要があります。個人的にはテナントごとに色を変えられる機能を期待しています
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269528/83c4f125-8c11-8bfe-d51f-f8398e3238ac.png)

- SharePointのフォルダはエクスプローラーに表示しない
    - SharePointのフォルダはエクスプローラに表示することができ、それによっていちいちTeamsの[ファイル]から開かずにすみ便利なのですが、少しの手違いで意図しないフォルダにアップロードしてしまったり、フォルダの名称がわかりずらく意図ところなるフォルダにアップロードしてしまうといったケースも考えられるので、私はエクスプローラーに表示しないようにしています。ファイルアップロード時は面倒ですがTeamsのチャンネルの[ファイル]からたどって、テナント名があっているよねなど確認してアップロードしています。
- Azure Portalのテーマをディレクトごとに分ける
    -Azure Portalはディレクトリごとに色のテーマや外観を変えられます。テーマの数は少ないですが。。私は[メニューの動作]と[テーマ]をうまく掛け合わせてやりくりしています。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269528/10c1499b-c915-6632-ac6e-18f546564f7a.png)
とりあえず動かしてみて、後から理解していくタイプの方におススメの記事

2025年、ラインワークスのAPIを使って楽をしたいと勉強中です。
色々あるドキュメントの中で良かったものをメモしておきます。
・とにかく楽にススっと先に進んだもの
・ゴールには辿り着けなかったけど自分自身の為によかったなと思うもの

# 初心者の私でも一応それなりに動かせた実践系

 [【LINE WORKS】LINE WORKS API 2.0をPostmanで手っ取り早く試してみる【サンプルあり】](https://qiita.com/mmclsntr/items/eee8d8f3546410fe6652)

https://qiita.com/mmclsntr/items/eee8d8f3546410fe6652

一番最初にトライしてみました。２つある認証方法のうち「User Account 認証でAPIリクエスト」でPostman経由でLINE WORKSのトークルームにbotからメッセージを送るというところまでは私でも出来ました。一度なんとなくAPIが動く！というところ体感してみたい方にはおススメです。
こちらが動いたとしても、その後にPostman以外の別の何かからAPIを呼びたいってことになると思うのですが、そこは別の高い壁しか見えませんでした。このなんとなく動くけど、ゴールには程遠い感が、勉強にはなりました

[[GAS x LINE WORKS] GoogleAppsScriptでLINE WORKSのチャットBOTを作る(API2.0 ver)](https://qiita.com/kunihiros/items/4cdec5784f21598cfee0)

https://qiita.com/kunihiros/items/4cdec5784f21598cfee0

本当はVBAからAPIを呼び出したかったのですが色々読んでトライしてみたものの挫折して心が折れた時に、至る所で見かけるGASをググってみたら「Google Apps Script」あぁ～と正体がわかり、こちらの方がイマドキなのでVBAより参考文書や先人の方のライブラリなども非常に充実しており、こんなに楽してしまっていいんだろうかとモヤモヤするほど充実していて有難くコピーさせて頂きました。本当は出来上がるチャットBotはオウム返しになるそうなのですが、私の設定がどこか間違っているんだと思うのですが、何故かオウム返しになってくれなかったので、少し書き換えて固定文言を送るようにしてみたら、LINE WORKSへはメッセージが送れたので、一旦、これでよしということにしました。また改めてチャレンジしてみたいと思います。

# 後から読みたい知識系
[一番分かりやすい OAuth の説明](https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be)

https://qiita.com/TakahikoKawasaki/items/e37caf50776e00e733be

【おススメ理由】
PostmanでAPIを動かしてみた後にたまたま辿り着き読んだのですが、認証部分のモヤモヤが図解でイメージしやく説明されていてすごくわかりやすかった。
【電脳少女プログラミング2088-壊レタ君を再構築-】SとAを解いてみた

# はじめに
なぜか、ゴルフイベント、pythonで3位スコア出したのに、ランキングに入らない、緑コーダーです

まあ感想でも書きますか(書かないと趣旨がおかしい)

# A問題の感想
見える範囲のいれずかに、行く時の移動回数の最小値と、言い換えられるので、そちらの方針で実装する
まあ普通にBFSすればいいので、実装したら、ACしました(語彙力ない)

ACコード
```py
from collections import deque

MOVES = [(0, 1), (0, -1), (1, 0), (-1, 0)]
H, W = map(int, input().split())
S = [list(input()) for _ in [0] * H]
ax, ay = -1, -1
bx, by = -1, -1

for i in range(H):
    for k in range(W):
        if S[i][k] == "A":
            ax, ay = i, k
            S[i][k] = "."

        if S[i][k] == "B":
            bx, by = i, k
            S[i][k] = "."

B = [(bx, by)]

for mx, my in MOVES:
    x, y = bx, by

    while 0 <= x + mx < H and 0 <= y + my < W:
        x += mx
        y += my

        if S[x][y] == "#":
            break

        B.append((x, y))

Q = deque()
used = [[1 << 60] * W for _ in [0] * H]
used[ax][ay] = 0
Q.append((ax, ay))

while Q:
    x, y = Q.popleft()

    for mx, my in MOVES:
        nx, ny = x + mx, y + my

        if not (0 <= nx < H and 0 <= ny < W):
            continue

        if used[x][y] + 1 >= used[nx][ny]:
            continue

        if S[nx][ny] == "#":
            continue

        used[nx][ny] = used[x][y] + 1
        Q.append((nx, ny))

ans = 1 << 60

for x, y in B:
    ans = min(ans, used[x][y])

print(-1 if ans == 1 << 60 else ans)
```

# S問題の感想
これは、単調性があるかつ、最大化問題なので、二分探索が適当
でも、他の縄張りの場所と自分の縄張りを、シュミレートすると、二分探索しても$O(HW^2 * log HW)$ぐらいになって、間に合わない
だけど、言い換えると、他の縄張りと接触しない条件は、マンハッタン距離が、縄張りの範囲+自分の範囲以下なら、接触すると言い換えられる、これを使えば、毎回、座標を探索しなくてよくなるので、$O(H \cdot W \cdot M  \cdot log HW)$ぐらいになって、十分間に合うって感じでした。

ACコード
```py
H, W, M = map(int, input().split())
L = [list(map(int, input().split())) for _ in [0] * M]

ans = -1

for i in range(H):
    for k in range(W):
        ng, ok = -1, (H * W) + 1

        while ok - ng > 1:
            mid = (ok + ng) // 2

            for r, c, s in L:
                r -= 1
                c -= 1

                if abs(r - i) + abs(c - k) <= s + mid:
                    break
            else:
                ng = mid
                continue

            ok = mid

        ans = max(ans, ng)

print(ans)

```

# 最後に
S問題はなかなか、面白かったです
プログラミング問題は埋められそうですけど、sqlは、D問題でも無理でした

:qa!
VSCodeベースのAIエディタでコンテナがアタッチできない問題

## 解決策
:::note info
 **ベースイメージ変えてみよう**
:::

## ことのはじまり
私は Node-alpine イメージでほぼあれこれしてる人です．

今話題のAI搭載エディタである，CursorやWindsurfを使ってなんかやってみてぇ～と思い，ダウンロード．いつも通り，dockerを立ち上げ，コンテナ拡張機能からコンテナにアタッチするも...

**Server returns 404** となってしまいコンテナにアタッチできない．
VSCodeではアタッチできるので，エディタ依存なのは間違いないです．

## 別のイメージでは？
Node-alpineイメージでしかやってなかったので，他のディストリビューションやベースイメージで試してみました．cursorでしか試してないけど，windsurfも同じだと思う

| イメージ | 結果 |
|:-----------|------------:|
| node:18.20-alpine       | できない       |
| alpine:3.14     | できない      | 
| ubuntu:22.04       | できる        |
| debian:bullseye         | できる          | 
| node:18.20-bullseye       | できる       | 

ディストリビューションがalpineの場合，私の環境ではコンテナにアタッチすることができませんでした．VSCodeではアタッチもできるし，開発もできます．

## 原因がわかったので
VSCodeベースのエディタでコンテナアタッチできない原因が分かったので，Dockerfileを書き換えました．

```
FROM node:18.20-alpine
```
から
```
FROM node:18.20-bullseye
```
に

それに伴ってイメージサイズも 150MBぐらいから 1GBちょっとにサイズアップしました．
軽量のAlpineイメージすごいや

### デプロイとか考えるなら
Nodeに限った話でいくと，開発段階ではDebianベースのイメージを使って，コーディングを行いテスト段階やデプロイ直前にベースイメージをAlpineにするとかが良さそうなのかな？
または，Alpineでやるならばコンテナにsshでアクセスして開発するかの二択かなと思います．
コンテナのsshちょっとめんどくさそうなのでベースイメージ変えるほうが早いのでは？