OmniAICreator/Qiita-1.07M huggingface dataset:
Supabaseでスケジュール実行をするためのメモ


## 環境
React
supabase
windows

## edgefunctionsに、googleスプレッドシートから情報を取得してgoogleカレンダーに追加するという処理を作成
edgefunctionsにデプロイするには、AI assistantを使うか、ローカルでdockerをつかってdeployするか。
エラーをはきまくった結果、
ai assistantで原型を作成してから、
> 1. Download the function
$
npx supabase functions download [scheduler] 
> Deploy a new version
$
npx supabase functions deploy [scheduler] 

このへんをつかって編集するのが一番確実。

テストで実行するには
curlコマンドを使う
curl -X POST "https://[myproject].supabase.co/functions/v1/[scheduler]" -H "Authorization: Bearer [your-anon-key]"




ローカルで編集したとき、Denoが名前解決できずにエラーになるが、Supabase側でdeployするので問題なし。
ちょっと気になるが。


## supabaseにスケジュールを追加
参考　https://infigate.net/supabase%E3%81%A7edge-functions%E3%82%92%E5%AE%9A%E6%9C%9F%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/

Supabaseでファンクションを毎朝9時に実行するには、PostgreSQLのcron機能（pg_cron拡張）を使用します。以下のステップで設定できます：

Supabaseダッシュボードで「SQL Editor」を開きます
次のSQLコマンドを実行してpg_cron拡張を有効化します：

sqlCopyCREATE EXTENSION IF NOT EXISTS pg_cron;

スケジュール設定を追加します。毎朝9時に実行するため、以下のSQLを実行します：

sqlCopySELECT cron.schedule(
  'daily-calendar-events',  -- スケジュール名
  '0 9 * * *',             -- cronパターン（毎日9時に実行）
  $$
  SELECT net.http_post(
    'https://[your-project-ref].functions.supabase.co/functions/v1/create-calendar-events',
    '{}',
    '{"Authorization": "Bearer [your-anon-key]"}'
  ) as request_id;
  $$
);
このコマンドで：

daily-calendar-events はスケジュールの名前です（任意の名前に変更可能）
0 9 * * * はcron表記で、毎日9時にジョブを実行します
URLの [your-project-ref] は、あなたのSupabaseプロジェクトの参照IDに置き換えてください
[your-anon-key] は、Supabaseプロジェクトの匿名キーに置き換えてください


スケジュールが正しく設定されたか確認するには、以下のSQLを実行します：

sqlCopySELECT * FROM cron.job;
この設定により、毎日朝9時にEdge Functionが自動的に呼び出され、カレンダーにイベントが追加されるようになります。
PowerShellのMeasure-Commandでリダイレクトありの計測を行う

```
mysql.exe -h host -u user -ppassword < dump.sql
```
というふうにMySQLのリストアを行う際に所要時間が知りたかった。PowerShellの**Measure-Command**で計測できるわけだが、リダイレクトのところで詰まった。
結論から言うと、**-RedirectStandardInput**を使えば良かった。
下のようにコマンドを叩けば良い。
```
Measure-Command { Start-Process "mysql.exe" -argumentList "-h host -u user -ppassword" -RedirectStandardInput dump.sql -Wait -NoNewWindow }
```
【C#】DrawLine(系)で太い線を描画するときとGraphicsPath使用時のちょっとした注意点

# DrawLine(系)で太い線を描画するときのちょっとした注意点

※DrawLine系: DrawLine, DrawLines, DrawPath, ... など(実質Draw系)

津波情報の描画にGeoJSONの`LineString`,`MultiLineString`形式の地図データを使っていますが、なぜか欠けることがある問題が起きました。

↓小笠原諸島
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3052941/517155b0-46d1-480d-b865-4251b32cde75.png)

↓上のものは後述(GraphicsPath使用時の注意点)

https://x.com/ProjectS31415_1/status/1899796497178464513

(よく見ると佐渡などで欠けている)

始点と終点は一致していますし、Penに`LineJoin.Round`、Graphicsに`SmoothingMode.AntiAlias`を設定しても変わりません。

## 解決方法
**`Point`ではなく`PointF`, `int`ではなく`float`** を使えば(たぶん)OK(サイズが小さいと欠けます)

(やり方と命名が変なのは置いといて)例がないのは寂しいので置いときます。.NET9, System.Text.Jsonです。
```csharp:例
var pointsList = new List<List<PointF>>();
if ((string)json_1_geo["type"]! == "LineString")
{
    var points = new List<PointF>();
    foreach (var json_2 in json_1_geo["coordinates"]!.AsArray())
        points.Add(new PointF(((float)json_2![0]! - 120f) * 20f, (50f - (float)json_2[1]!) * 20f));
    pointsList.Add(points);
}
else
    foreach (var json_2 in json_1_geo["coordinates"]!.AsArray())
    {
        var points = new List<PointF>();
        foreach (var json_3 in json_2!.AsArray())
            points.Add(new PointF(((float)json_3![0]! - 120f) * 20f, (50f - (float)json_3[1]!) * 20f));
        pointsList.Add(points);
    }

```


# GraphicsPath使用時のちょっとした注意点

`Multh**`形式のGeoJSONをGraphicsPathを使用して適当にやっていると、異なる地物がつながります(上の方のポストでも一部起きている)。

## 解決方法
**`GraphicsPath.Add**()`の前か後に`GraphicsPath.StartFigure();`** をするだけでOK。

# おまけ
津波情報を表示している自作ソフト

https://github.com/Ichihai1415/JmalHnd-Tsunami

~~https://github.com/Ichihai1415/QuakeMapFast~~ 編集時点未作成

https://github.com/Ichihai1415/TsunamiWarningOverlay
Gitの使い方　サマリ

# Github SSH接続方法
## 1.pubの内容、＝公開鍵情報をコピペする
```bash
pbcopy < ~/.ssh/id_rsa.pub
```

## 2. SSH接続確認
ssh -T git@github.com


応答として下記が返って来ればOK
```bash
Hi (account名)! You’ve successfully authenticated, but GitHub does not provide shell access.
```
## 3. Clone
あとはGithub上の「Clone with SSH」を使ってクローンするだけ。

```bash
git clone git@github.com:user/repository.git
```

# GitHub リモートリポジトリからブランチ作成、コミット、プッシュ、マージまでの流れ

## 1. リモートリポジトリのクローン
GitHubからリポジトリをローカルにクローンします。

```bash
git clone https://github.com/username/repository.git
cd repository
```

## 2. 新しいブランチの作成
新しい作業ブランチを作成し、そのブランチに切り替える

```bash
git checkout -b new-branch
```

## 3. ファイルを編集し、コミットを作成
編集後、ファイルをステージングし、コミットします。

```bash
コピーする
編集する
git add .
git commit -m "Add a new feature"
```

## 4. リモートリポジトリにプッシュ
新しいブランチをリモートリポジトリにプッシュします。

```bash
git push origin new-branch
```

## 5. プルリクエスト（Pull Request）の作成
GitHub上で、new-branch を main にマージするためのプルリクエストを作成します。
- GitHubリポジトリのページにアクセスし、ブランチを選択後、「New Pull Request」ボタンをクリック。

## 6. マージ
プルリクエストが承認されたら、GitHub上で「Merge Pull Request」をクリックして main ブランチにマージします。

## 7. ローカルブランチの削除（オプション）
作業が完了したら、ローカルの作業ブランチを削除できます。

```bash
コピーする
編集する
git branch -d new-branch
```

これで、リモートリポジトリからローカル作業を行い、プルリクエストを通じてリモートに反映させ、マージまでの一連の作業が完了です。
線形回帰モデルについて、あなたはどれくらい答えられますか？


---

## 🔹 基礎レベル（初級）

### Q1. 回帰問題とは何か、分類問題との違いは？

**解答例：**  
回帰問題とは連続値を予測するタスクのことで、例えば住宅価格や気温予測などがあります。  
分類問題はカテゴリを予測するタスクで、「犬・猫」「陽性・陰性」などの離散的な結果を予測します。

---

### Q2. 線形回帰モデルで最も重要な前提条件は何か？

**解答例：**  
データと目的変数の関係が線形であることです。実際は必ずしも線形でないことも多く、非線形モデルや特徴量変換が必要になります。

---

### Q3. 回帰モデルの評価指標を挙げてください。

**解答例：**  
- RMSE（Root Mean Squared Error）
- MAE（平均絶対誤差）
- R²（決定係数）
- RMSLE（Root Mean Squared Logarithmic Error）

---

## 🔎 中級レベル

### Q4. 線形回帰モデルで注意すべき前提条件（仮定）とは？

**解答例：**  
- 線形性（説明変数と目的変数の関係が線形）  
- 誤差項の正規性（残差が正規分布に従う）  
- 誤差項の等分散性（分散が一定）  
- 多重共線性がないこと（説明変数間の相関が低いこと）  
- 自己相関がない（データ同士が独立である）

---

### Q4. 過学習とは何か？回避方法は？

**解答例：**  
過学習とはモデルが訓練データに過剰に適合し、未知のデータに対して精度が悪化する現象です。

回避方法として以下が挙げられます：
- 正則化（L1/L2正則化）
- 交差検証（クロスバリデーション）
- データ量を増やす
- 特徴量の選択や削減を行う

---

## 📌 中級レベル（理論的）

### Q5. 「多重共線性」とは何か、なぜ問題か、どう検出するか？

**解答例：**  
多重共線性とは、複数の説明変数同士が高い相関を持つ現象です。  
これにより係数の推定値が不安定になり、推定精度が下がります。検出方法はVariance Inflation Factor（VIF）で、一般にVIFが10を超えると多重共線性が疑われます。

---

### Q6. 説明変数のスケーリングが回帰モデルに与える影響は？

**解答例：**  
説明変数のスケールが大きく異なる場合、一部のアルゴリズム（リッジ回帰、Lasso回帰、勾配降下法を用いる回帰など）において収束が遅くなったり、精度が落ちることがあります。スケーリングを行うことで性能向上や安定性が向上します。

---

### Q7. リッジ回帰とLasso回帰の違いを説明してください。

**解答例：**  
- リッジ回帰はL2正則化（係数の2乗和を最小化）を用いて過学習を防ぎます。
- Lasso回帰はL1正則化（係数の絶対値の和を最小化）を用いて、一部の変数を完全にゼロにし、特徴選択も同時に行います。

---

### Q7. 非線形の関係性を扱うには、どのような方法があるか？

**解答例：**  
- 多項式回帰（Polynomial Regression）  
- 非線形特徴量変換（対数変換、指数変換など）  
- 非線形モデルの使用（決定木系やニューラルネットワーク）

---

## 📌 上級レベル（応用・実践的）

### Q7. 残差の分析とは何か、何がわかるか？

**解答例：**  
モデルの予測値と実際値の差を残差といい、残差を分析することでモデルがどの仮定を満たしていないか把握できます。例えば、残差にパターンがあれば非線形性の問題があり、残差の分散が一定でなければ異方分散性の問題があります。

---

### Q7. 「バイアス-バリアンスのトレードオフ」を説明してください。

**解答例：**  
- バイアス（偏り）が強いモデルは単純すぎて精度が低下（Underfitting）  
- バリアンスが高すぎるとデータのノイズにも反応し過学習に陥る  
- 最適なモデルを見つけるためには両者のバランスが重要。

---

### Q7. 変数選択の方法をいくつか挙げて説明してください。

**解答例：**  
- 前進選択（Forward Selection）：一つずつ説明変数を追加  
- 後退選択（Backward Elimination）  
- Lasso回帰（L1正則化によるスパース性を利用）  
- 再帰的特徴量削減（RFE: Recursive Feature Elimination）

---

## 上級レベル（実践的・高度な内容）

### Q8. 不均衡データは回帰モデルにどう影響するか？

**解答例：**  
目的変数に極端な値や外れ値が多い場合、モデルが特定の範囲に偏る可能性があります。外れ値の処理（対数変換、ロバスト回帰、Quantile Regression）を検討します。

---

### Q9. 回帰モデルでの欠損値の扱い方を説明してください。

**解答例：**  
- 単純削除（Listwise Deletion）  
- 平均値や中央値での補完  
- K最近傍法（KNN）での補完  
- モデルベース（MICEなど）の補完

欠損の原因を考慮して補完法を選択することが重要です。

---

### Q9. 一般化線形モデル（GLM）とは何か、回帰とどう関連するか？

**解答例：**  
一般化線形モデル（GLM）は線形回帰を拡張したモデルで、目的変数の分布が正規分布以外（ポアソン分布、二項分布など）の場合でもモデル化可能です。リンク関数を用いて線形予測子と目的変数を関連付けます。

---

## 📌 まとめ・ポイント整理

面接時に特に注目されることは：

- 回帰モデルの前提条件への理解
- 多重共線性や過学習などの問題への対応力
- 実際の分析場面での適切な評価指標やモデル選択

です。上記の質問と解答を準備しておくことで、自信をもって技術面接に臨めるでしょう。
遺伝的アルゴリズム（GA）とは？分かりやすく具体的に解説！


遺伝的アルゴリズム（Genetic Algorithm、略称：GA）とは、生物の進化を模倣したアルゴリズムで、最適化問題を解くために広く用いられます。この記事では遺伝的アルゴリズムの仕組み、具体例、他の手法との比較についてわかりやすく解説します。

---

### 遺伝的アルゴリズムの仕組み

遺伝的アルゴリズムは以下のようなステップで最適解を探索します。

1. **初期個体群の生成**：ランダムに複数の「解候補（個体）」を作成します。
2. **適応度評価**：各個体がどれほど良い解かを評価します。
3. **選択（淘汰）**：適応度が高い個体を優先的に選びます。
4. **交叉（交配）**：選ばれた個体同士を組み合わせて、新しい個体を作成します。
5. **突然変異**：一定確率でランダムに個体の一部を変更します。
6. **繰り返し**：適切な解が見つかるまで、上記のステップを繰り返します。

---

### 具体例

例えば、「荷物をトラックに効率よく積み込む問題」を考えてみましょう。

- **個体**：各個体は荷物の積み込み順序を表します。
- **適応度**：トラック内の空きスペースが少ないほど適応度が高いと評価されます。
- **交叉**：2つの順序を組み合わせて新たな積み込み順序を作ります。
- **突然変異**：順序を一部ランダムに入れ替えることで、新しい可能性を探ります。

これらの操作を繰り返すことで、最適な積み込み順序に近づきます。

---

### 他の最適化手法と比較したメリット

- **広範な探索能力**：局所最適解に陥りにくく、広い範囲から解を探索可能です。
- **問題の汎用性**：複雑で数学的な定式化が困難な問題にも適用しやすいです。
- **並列化が容易**：複数の個体を同時に評価でき、並列処理で高速化できます。

---

### デメリット

- **計算コストが高い**：複数世代の進化を繰り返すため、計算に時間がかかることがあります。
- **収束速度が遅い場合がある**：微調整や収束までに時間がかかる場合があります。
- **パラメータ調整が必要**：交叉率、突然変異率、個体数などの調整が成果に影響します。

---

### 遺伝的アルゴリズムが有効な場面

- 組み合わせ問題（巡回セールスマン問題、スケジューリング問題など）
- 複雑な関数の最適化
- 機械学習のハイパーパラメータ最適化

---

### まとめ

遺伝的アルゴリズムは、生物進化の原理を利用した柔軟で強力な最適化手法です。計算コストはかかりますが、複雑な問題で他の手法が困難な場合に効果的です。活用する際は、問題の特性に応じて適切にパラメータを調整することが重要です。

ぜひ、最適化問題の解決に活用してみてください！
【書評】イラスト図解式 この一冊で全部わかるWeb技術の基本

## 「イラスト図解式 この一冊で全部わかるWeb技術の基本」を読んだ感想

## 本書の概要
公式サイトの紹介文を引用します。

>Webの全体像から、HTTPでやりとりする仕組み、さまざまなデータ形式、Webアプリケーションの開発、セキュリティ、システムの構築・運用まで、これからWebにかかわる人が知っておきたい知識をこの一冊で丸ごと解説！
すべての項目の解説は、徹底的にイラスト図解化。
これから仕事に必要な知識を学ぶ方に、すばやく、たのしく知識を身につけていただけるよう、読みやすさ、わかりやすさにこだわって制作しています。
>・知識ゼロから全体像がつかめる！
・よく使われる用語の意味がわかる！
・技術の仕組みがスムーズに学べる！
>実務に生かせる知識が、確実に身につく、これから学ぶ人のベストな一冊です！

>＜主な対象読者＞
・これからIT系の仕事に就かれる方
・これから社内の情報システムを担当される方
・Webシステムに関連する技術と実務を、幅広く、バランスよく学びたい方

>■目次：
Chapter1 Web技術とは
Chapter2 Webとネットワーク技術
Chapter3 HTTPでやりとりする仕組み
Chapter4 Webのさまざまなデータ形式
Chapter5 Webアプリケーションの基本
Chapter6 Webのセキュリティと認証
Chapter7 Webシステムの構築と運用

まさに紹介文の通りで，知識ゼロの自分でもそこまで苦労せずに読むことができました．それでいて，広範な内容をカバーしていて，それぞれの技術や用語の全体像をつかむのに役立ちました．技術の詳細や仕組みといった部分は全くといっていいほど触れられていないので，その点は留意して読む必要があります．

## 読書の背景
web系の仕事をすることが決まり，ソフトウェアエンジニアにも興味があるので，コンピュータサイエンスを基礎から学びたいと考えました．また，web技術（HTTP，webAPI）について興味があり，これまでインターンシップなどでも触れる機会があったが，基礎的な部分が抜けていると感じたため，書籍などできちんと勉強したいと考えていました．

## 本書を選んだ理由
Webを支える技術 ―― HTTP，URI，HTML，そしてRESTという有名な本があり，常々読みたいと考えていました．しかし，その前にまずはweb技術の概観をさらりと掴もうと考え，本書を選びました．

## 感想
さらりと読み流してしまっては，すぐに忘れてしまいそうだと感じたので，読みながら適宜メモを取っていました．イラストを紙で書いたり，メモをとったりしながら読むと，飽きずに読み進められるのでおすすめです．

### 良かった点
ネットワークの基礎，web技術のトレンド，セキュリティ関連の基本的なことなど，とにかく幅広い内容をカバーしている点が良かったです．また，各ページの半分説明，半分イラスト図解という構成のおかげで，読みやすく理解しやすかったです．

### 悪かった点

仕方ないことではありますが，各項目の説明がかなり簡潔なため，概念の名前と概略だけではイメージがつかみきれないものも多々ありました．それらの項目については，適宜ネットで簡単な解説記事を調べたりしながら読み進めました．例えば，6章のOAuthの項目については，一番分かりやすい OAuth の説明を読みました．

### 次に読みたい本
満を持して，Webを支える技術 ―― HTTP，URI，HTML，そしてRESTを読みたいと考えています．

## こんな人におすすめ
公式にあるように，以下のような方におすすめです．
>- これからIT系の仕事に就かれる方
>- これから社内の情報システムを担当される方
>- Webシステムに関連する技術と実務を、幅広く、バランスよく学びたい方
【Linux】dnfコマンド

# はじめに
こんにちは。私はアメリカ在住で、独学を通してエンジニアを目指している者です。
本日は現在学習中のLinuxコマンドの1つであるdnfコマンドについてみていきたいと思います


## `dnf` とは
**dnf (Dandified Yum)** は、FedoraやRed Hat系ディストリビューションで採用されているパッケージ管理システムで、インターネット経由でソフトウェアをインストールしたり、アップデートしたりすることができます


### dnfのインストールと基本コマンド

FedoraやRHEL系ディストリビューション（AlmaLinux, Rocky Linuxなど）では標準的にインストールされています。もしインストールされていない場合は、下記のようにインストールできます。

```bash
sudo yum install dnf
```

#### 1. パッケージのインストール

```bash
sudo dnf install <パッケージ名>
```

- 例: `sudo dnf install httpd` (Apache HTTP Serverをインストール)

#### 2. パッケージの削除

```bash
sudo dnf remove <パッケージ名>
```

- 例: `sudo dnf remove httpd`

#### 3. パッケージの検索

```bash
dnf search <キーワード>
```

- 例: `dnf search nginx`

#### 4. システムの更新

```bash
sudo dnf update
```

システム上のパッケージを一括で更新します。セキュリティアップデートやバグ修正が含まれるため、こまめに実行することが推奨されます。

#### 5. パッケージグループの操作

`dnf`では、パッケージの「グループ」単位でインストールや削除を行うことができます。

```bash
sudo dnf group install "Development Tools"
```

`"Development Tools"`は、CコンパイラやGCCなどのツールチェーンをまとめてインストールできるグループの一例です。

---

### dnfの設定ファイル

`/etc/dnf/dnf.conf` がメインの設定ファイルです。リポジトリ設定など、より詳細な設定は `/etc/yum.repos.d/` ディレクトリ内にある `.repo` ファイルを編集することで行います。

主な設定項目例：

- `cachedir`: パッケージダウンロード時のキャッシュ保存先
- `keepcache`: ダウンロードしたパッケージを更新後も保持するかどうか
- `exclude`: インストールや更新の対象から除外するパッケージ

---

### dnf の便利なオプション

- `-y` (yes): すべての操作を自動的に承認する

  ```bash
  sudo dnf -y install <パッケージ名>
  ```

- `--downloadonly`: インストールはせずにパッケージをダウンロードのみ行う

  ```bash
  sudo dnf install --downloadonly <パッケージ名>
  ```

- `autoremove`: 不要になった依存パッケージをまとめて削除

  ```bash
  sudo dnf autoremove
  ```

---

## まとめ

dnfは、FedoraやRHEL系ディストリビューションで強力なパッケージ管理を提供するコマンドです。
従来のYumコマンドをベースに、依存関係の解決速度や安定性を向上させているため、より効率的にシステムを管理することができます。
範囲チェックの重要性について

質問：「外部からの入力を受け取る設計でなければ範囲チェックはしないものですか？」
以下はChatGPTの回答．

---

範囲チェックは、外部からの入力を受け取る設計に限らず、プログラム全体の安全性を高めるために重要です。実際、外部入力以外にも、内部的なデータ処理やロジックにおいてもバッファオーバーフローや範囲外アクセスを防ぐために適切な範囲チェックを行うべきです。

### 1. **外部入力がある場合**
外部からの入力（ユーザー入力、ネットワーク経由のデータ、ファイル読み込みなど）は、予測不可能な内容を含む可能性があり、最も一般的なバッファオーバーフロー攻撃の発生源です。このような場合、範囲チェックは必須です。入力が意図した範囲内に収まっていることを確認することで、バッファオーバーフローや不正なメモリアクセスを防げます。

### 2. **内部的なデータ処理の場合**
外部からの入力を受け取らなくても、内部的なデータ処理でも範囲チェックを行うことは重要です。内部的な処理においても次のようなケースがあります：

- **配列やバッファの操作**: 例えば、プログラム内で固定長の配列にデータを格納する場合、配列のサイズを超えて書き込むことは予期しない動作やメモリ破壊を引き起こす原因になります。配列のインデックスを計算する際、バッファサイズを超えることのないようチェックを行うべきです。

- **計算結果の確認**: 例えば、計算の結果得られた値が配列のインデックスとして使われる場合、その値が範囲内であることを確認する必要があります。範囲外アクセスはプログラムの不具合を引き起こすだけでなく、セキュリティのリスクにもつながります。

- **固定長のメモリ領域**: メモリが固定サイズの場合、メモリ領域を超えてアクセスしないように、常に範囲を確認して使用することが大切です。

### 3. **なぜ内部的なデータ処理でも範囲チェックが重要か**
内部で使用するデータが外部から供給されない場合でも、範囲チェックをしないことにはリスクがあります。たとえば、次のような状況です：

- **バグの予防**: 予期しない値が計算されたり、変数の状態が意図しない形で変更された場合、範囲チェックがなければその結果がメモリ破壊につながる可能性があります。
  
- **他のコードによる誤操作**: 他の部分のコードやライブラリが、バッファや配列を誤って操作することもあります。範囲チェックがなければ、これが問題を引き起こす可能性があります。

- **将来的な変更の安全性**: 予め範囲チェックを組み込んでおくことで、後からコードを変更した際に新たな問題が生じることを防げます。特に、後から外部入力を追加する場合や、内部処理が変更される場合、範囲チェックが既に行われていれば安全性が高まります。

### 4. **結論**
範囲チェックは、外部からの入力に限らず、プログラム全体において重要なセキュリティ対策です。特に、バッファや配列などのメモリ領域を扱う場合には、範囲を超える操作を防止することが、予期しない動作やセキュリティホールを防ぐために必須です。外部からの入力がない場合でも、プログラム内部のロジックにおいて範囲チェックを行うことで、より堅牢で安全なコードを作成できます。
Cloud Runとは デプロイ先など

## ※業務のためのアウトプットなので間違いが含まれる可能性が大いにあります。


業務でGCPを触ることになったので調べたことをアウトプットしていきたいと思います。


# Cloud Runとは

Cloud Runとはなんでしょうか。全然分かりません。

ChatGPTに「中学生にもわかるように説明して」と聞いてみると、
```
Cloud Run は、アプリを動かす場所だよ。たとえば、作ったアプリを友達に使ってもらいたいとき、自分のパソコンだけで動かしていたら、友達は使えないよね？

Cloud Run を使うと、そのアプリをインターネット上に置いて、世界中どこからでも使えるようにできるんだ。しかも、使われているときだけ動いて、お金がかかるのもその分だけ。使っていないときは止まるから、無駄がないんだよ。

たとえるなら、自動販売機みたいなもの。誰かがボタンを押したときだけジュースが出てくるけど、押されていないときは何もしていないよね？ Cloud Run も同じで、リクエストが来たときだけ動くんだ。

何か作ったら Cloud Run に乗せれば、みんながインターネットから使えるようになる。すごく便利だよ！
```
と教えてくれました。


調べると、「Google Cloudが提供しているフルマネージドな、サーバーレス、コンテナ実行環境」などと出てきます。つまりどういうことでしょうか。

通常、アプリケーションを動かすためには、サーバーを用意して、その上にアプリケーションをデプロイし、必要に応じてサーバーの管理やメンテナンスを行う必要があります。

しかし、Cloud Runを使えば、その手間が大きく省けます。


# Cloud Runはどこにあるものを実行するのか


ではそんなサーバーレスなCloud Runはどこにあるコンテナイメージや言語パッケージを実行するのでしょうか。

それはGCPの中にあるArtifact Registryを使います。

Artifact Registryとは、コンテナイメージや言語パッケージ（どう動かすか、どんなパッケージを入れるかを記したものなど）を格納、共有、管理するものになります。

実際の手順としては、

1.ローカルのソースコードをコンテナ化する。


2.コンテナ イメージを Artifact Registry リポジトリに push します。

3.リポジトリからコンテナ イメージを Cloud Run にデプロイします。

---
さらに学びを深めて、コードのアウトプットなどもしていこうと思います！
ではまた！
___
- 参考サイト
:https://cloud-ace.jp/column/detail250/

:https://cloud.google.com/artifact-registry/docs/integrate-cloud-run?hl=ja
バッファオーバーフロー脆弱性の概要

質問：「バッファオーバーフロー脆弱性を狙った攻撃はどのように行われますか？」
以下はChatGPTの回答．

---

バッファオーバーフロー脆弱性を狙った攻撃は、悪意のあるユーザーがメモリに対して不正な操作を行い、プログラムの制御を奪ったり、機密情報を盗んだりするための攻撃手法です。この攻撃は、プログラムがバッファのサイズを適切にチェックしない場合に発生します。攻撃者は、バッファの範囲外にデータを書き込み、メモリ上の他の重要な領域を上書きすることで、プログラムの挙動を変更します。

バッファオーバーフロー攻撃の基本的な流れを以下に説明します。

### 1. バッファオーバーフローの発生
バッファオーバーフローは、プログラムがメモリバッファのサイズを適切にチェックせずに、ユーザーからの入力や外部データを格納する場合に発生します。攻撃者は、予め指定されたバッファサイズを超えてデータを送信することで、隣接するメモリ領域を上書きすることができます。

例えば、次のような関数があるとします：

```c
void vulnerable_function(char *input) {
    char buffer[100];
    strcpy(buffer, input);  // 入力が100バイトを超えるとバッファオーバーフロー
}
```

この関数では、`strcpy`を使用して入力をバッファにコピーしていますが、`strcpy`は長さを確認せずに文字列をコピーするため、`input`が100バイトを超えた場合にバッファオーバーフローが発生します。

### 2. 攻撃者の目的
バッファオーバーフロー攻撃の主な目的は、プログラムの制御を乗っ取ることです。攻撃者は、以下のような目的を持っている場合があります。

- **コードの実行**: 攻撃者は、バッファを上書きすることで、任意のコードをメモリに挿入し、それを実行させることができます。これは、リモートコード実行（RCE）攻撃に繋がります。
  
- **リターンアドレスの上書き**: 攻撃者は、関数のリターンアドレスを上書きし、制御フローを自分の意図したコードに変更できます。この方法を用いて、関数が戻る場所を操作し、攻撃者が指定したコードを実行させます。

- **スタックの操作**: 攻撃者は、関数のスタックフレームを上書きし、返り値やローカル変数を変更することで、プログラムの制御を奪います。

- **システムやアプリケーションのクラッシュ**: 攻撃者は、アプリケーションやシステムがクラッシュするようにメモリを上書きし、意図的に障害を引き起こすこともできます。

### 3. 攻撃の手法

攻撃者がバッファオーバーフローを利用して攻撃を実行する手法は、通常次のように進行します：

#### 1. **リターンアドレスの上書き**
バッファオーバーフロー攻撃の最も典型的な方法の一つは、スタックに格納されているリターンアドレスを上書きすることです。関数の呼び出し時、リターンアドレス（戻り先のアドレス）はスタックに保存されます。攻撃者は、バッファオーバーフローを利用して、このリターンアドレスを変更し、プログラムが関数を終了した後に攻撃者が指定したコードに制御が移るようにします。

#### 2. **シェルコードの挿入**
攻撃者は、バッファオーバーフローを利用して、シェルコード（攻撃者が実行したいコード）をメモリ内に挿入することができます。リターンアドレスをシェルコードが格納されている場所に変更すると、関数が戻るときにシェルコードが実行されます。

例えば、攻撃者は次のようなシェルコードを挿入することがあります：
```assembly
; シェルを起動するシェルコード
xor eax, eax
push eax
push 0x68732f2f
push 0x6e69622f
mov ebx, esp
mov al, 11
int 0x80
```

#### 3. **スタックの破壊**
攻撃者は、バッファオーバーフローを利用して、関数のスタックフレームを破壊することもあります。これにより、関数から戻る際に不正なアドレスが読み込まれるようになり、システムがクラッシュしたり、予期しない動作を引き起こしたりします。

### 4. 実行例

攻撃者がリモートバッファオーバーフロー攻撃を行う際の典型的な手順は以下のようになります：

1. 攻撃者はターゲットとなるプログラムのバッファサイズを理解します。
2. 攻撃者は、ターゲットプログラムに送る入力（データ）を構築します。この入力は、まずバッファを満たし、その後にリターンアドレスを上書きする特別なパターンを含みます。
3. 攻撃者は、リターンアドレスを悪意のあるコードが格納されている場所に設定します（例えば、シェルコードをメモリに配置して、そのアドレスに変更します）。
4. 攻撃者がこのデータをプログラムに入力させると、バッファオーバーフローが発生し、プログラムの制御が攻撃者の意図したコードに変更されます。

### 5. 防止策
バッファオーバーフロー攻撃を防ぐためには、以下の対策が重要です：

- **入力の検証**: 配列やバッファに入力を格納する際は、必ずサイズを検証し、範囲外のアクセスを防ぎます。
- **安全な関数の使用**: `strcpy`や`gets`などの危険な関数の代わりに、`strncpy`や`fgets`など、安全な関数を使用します。
- **スタック保護機能**: コンパイラやオペレーティングシステムが提供するスタックガード（例えば、`Stack Canaries`）を利用して、リターンアドレスの変更を検出します。
- **実行不可メモリ領域**: プログラムの実行中に特定のメモリ領域（例えば、スタック）を実行不可にすることで、シェルコードの実行を防止します（例：DEP、NXビット）。
- **アドレス空間配置のランダム化 (ASLR)**: メモリ領域のアドレスをランダムに配置することで、攻撃者が正確なアドレスを知るのを困難にします。

### 結論
バッファオーバーフロー攻撃は、プログラムがメモリにアクセスする際に適切な範囲チェックを行わない場合に発生します。この攻撃により、攻撃者はプログラムの制御を奪ったり、システムを不正に操作したりすることができます。適切な入力検証、セキュリティ機能の導入、最新のコンパイラ設定を使うことで、バッファオーバーフロー攻撃を防ぐことができます。
YOLOv5sで肺がん病変をCT画像から検出することは可能か？


### はじめに
肺がんは早期発見が非常に重要であり、AI技術、特に深層学習を用いた病変検出は大きな期待が寄せられています。最近人気の物体検出モデル「YOLOv5s」をCT画像から肺がん病変検出に使えるか、詳しく検討してみます。

---

### ① YOLOv5sとはどのようなモデル？

YOLOv5sは本来、「物体検出（Object Detection）」モデルです。

- **画像分類モデル（Image Classification）**では、画像全体を1つのカテゴリーに分類します。
- **特徴抽出モデル（Feature Extraction）**は画像内の特徴を数値的に抽出し、その後別のモデルやタスクに活用します。
- 一方でYOLOv5sのような**物体検出モデル**は、画像内の複数の物体を識別し、それぞれの位置を示すBounding Box（境界ボックス）とカテゴリ情報を同時に推定します。

つまり、肺がん病変をBounding Boxとして検出することは、YOLOv5sの機能に適合します。

---

### YOLOv5sで肺がん検出が難しい理由

技術的には可能ですが、実務上、以下の課題があり簡単とは言えません。

1. **CT画像の3次元データ特性**  
YOLOv5は通常、2次元画像に対して設計されているため、CTのような3D画像をスライス単位に処理する必要があります。そのため、3次元空間での情報が失われる可能性があります。

2. **病変サイズの小ささ**
肺がんの初期病変は非常に小さく低コントラストであることが多く、軽量モデルであるYOLOv5sでは十分な精度が出にくい可能性があります。

3. **データセットのラベリングの困難さ**
肺がん病変のラベリングには医師や放射線技師による専門知識が必要で、データ収集やアノテーションに高いコストと精度が求められます。

---

### LIDC-IDRIデータセットで最も精度が高いモデル

肺がん病変検出の評価で広く用いられる「LIDC-IDRI」データセットに対し、高い性能を示したモデルがいくつかあります。その中でも特に注目されているのが、以下の2つのモデルです。

- **ProCAN（Progressive Growing Channel Attentive Non-Local Network）**
  - 精度：95.28%、AUC：98.05%
  - 特徴：段階的に特徴を学習し、注意機構と非局所的特徴抽出（Non-Local）を用いて、微細な肺病変を高精度で分類。

- **DeepLung・nnDetection（3D CNNベースモデル）**
  - nnDetection（代表例）：LIDC-IDRIやLUNA16を使用した肺がん結節の検出に特化。3次元情報を有効活用。
  - DeepLung：3D CNNを利用した高精度モデル。LUNA16データセットにおいてAUC約0.97-0.98の性能を実現。

特に3D CNNベースのモデルは、病変検出精度が高く、3次元の空間情報をより適切に扱うことが可能です。

---

### 肺がん病変検出用にYOLOv5sをファインチューニングする具体的手順

肺がんの病変検出にYOLOv5sを利用する場合、次の手順で進めます。

1. **データ収集とラベリング**
   - DICOM画像（CT画像）をPNGやJPEG形式に変換し、Bounding Boxでラベリング（LabelImgやCVATなどのツールを使用）。

2. **前処理・データ準備**
   - HU値調整による肺部位抽出。
   - YOLOフォーマットでラベルを保存。

2. **環境構築**
   - YOLOv5 GitHubリポジトリのCloneと依存関係のインストール（PyTorch、CUDA）。

3. **データセットの構築**
   - train/val/testセットに画像とラベルを分割。

4. **設定ファイル（YAML）の調整**
   - YOLO用のdataset.yamlファイルでデータセットのパス指定。

3. **トレーニング**
   - 事前学習済み重みを使った学習開始。

4. **モデルの評価と推論**
   - mAP（平均適合率）を使用した精度評価。
   - 新規画像への推論。

---

### 商用利用可能な既存モデル

商用利用可能な代表的なモデルとしては、以下が挙げられます。

- **nnDetection（3D CNN）**: Apache License 2.0（商用利用可能）
- **DeepLung（3D CNN）**: MIT License（商用利用可能）

ProCANなど、ライセンスが不明瞭なものについては商用利用は慎重に行う必要があります。

---

### 結論と推奨

肺がん検出はYOLOv5sでも可能ですが、本来の用途（一般物体検出）とは異なり、高精度を出すには3次元的情報を活用するnnDetectionやDeepLungなどの専門的なモデルがより適しています。

医療現場への導入を視野に入れる場合は、上記の特化モデルの利用が推奨されます。

---

以上が、肺がん検出へのYOLOv5s適用可否、及び肺CT画像分析における既存モデルの現状と実践的なファインチューニング手順です。

ぜひ参考にしてください。
Linuxコマンド入門：touchコマンドの基本とタイムスタンプの変更・ファイル作成の方法について

## はじめに
LinuxやUnix系OSを使用していると、ファイルのタイムスタンプを変更したり、新しいファイルを作成したりする機会があります。

:::note info
**その際に便利なのが`touch`コマンドです。**
:::

本記事では、`touch`コマンドの基本的な使い方やタイムスタンプの確認方法、便利なオプションについて詳しく解説します。

## 書こうと思ったきっかけ
ファイル管理を行っている際に、タイムスタンプを変更する方法を知りたいと感じることがありました。

:::note warn
***また、`touch` コマンドにはさまざまなオプションがあるため、基本的な使い方だけでなく応用的な使い方もまとめておくと便利だと考えました。***
:::

本記事を通じて、`touch` コマンドの活用方法をより多くの人に知ってもらえればと思います。

## touchコマンドとタイムスタンプの確認方法

#### touchコマンドとは
`touch` コマンドは、LinuxやUnix系OSでファイルのタイムスタンプ（最終アクセス時間や最終更新時間）を変更するためのコマンドです。

https://eng-entrance.com/linux-command-touch

また、指定したファイルが存在しない場合、新しく空のファイルを作成することもできます。

#### 基本的な使い方

##### 新しいファイルを作成する
```
touch filename.txt
```
指定した`filename.txt`が存在しない場合、新規に作成されます。すでに存在する場合は、タイムスタンプのみが更新されます。

##### タイムスタンプを確認する
ファイルのタイムスタンプを確認するには、`ls -l` または `stat` コマンドを使用します。

```
ls -l filename.txt
```
このコマンドでは、ファイルの最終更新時刻を確認できます。

```
stat filename.txt
```
このコマンドを使用すると、アクセス時間（Access）、修正時間（Modify）、変更時間（Change）などの詳細なタイムスタンプ情報を確認できます。

**実際のターミナル画面**

![Screenshot 2025-03-13 at 11.21.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/c1379e5c-fad6-4c3e-9fd8-1184857c6363.png)

#### touchコマンドの主なオプション

##### 1. タイムスタンプを特定の日時に変更する
```
touch -t YYYYMMDDhhmm filename.txt
```
例：
```
touch -t 202403121530 filename.txt
```
このコマンドは `filename.txt` のタイムスタンプを 2024年3月12日 15:30 に設定します。

**実際のターミナル画面**

![Screenshot 2025-03-13 at 11.22.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/423cf1b3-4d5a-429d-96e4-8d4df327e3c2.png)

##### 2. 参照ファイルのタイムスタンプをコピーする
```
touch -r reference.txt filename.txt
```
このコマンドは、`reference.txt` のタイムスタンプを `filename.txt` に適用します。

##### 3. アクセス時間のみを変更する
```
touch -a filename.txt
```
このオプションを使用すると、アクセス時間（atime）のみが変更されます。

##### 4. 更新時間のみを変更する
```
touch -m filename.txt
```
このオプションでは、更新時間（mtime）のみが変更されます。

##### 5. 存在しないファイルを作成しない
```
touch -c filename.txt
```
このオプションを使用すると、`filename.txt` が存在しない場合でも新規作成せずにスキップされます。

##### 6. 現在時刻のタイムスタンプを変更せずに維持する
```
touch -d "YYYY-MM-DD HH:MM:SS" filename.txt
```
例：
```
touch -d "2024-03-12 15:30:00" filename.txt
```
このコマンドは、`filename.txt` のタイムスタンプを指定した日時に設定します。

## まとめ
`touch` コマンドは、ファイルの作成だけでなく、タイムスタンプの変更にも便利なコマンドです。

:::note info
***`stat` コマンドと組み合わせることで、詳細なタイムスタンプ情報を確認しながら管理できます。***
:::

用途に応じて適切なオプションを使いこなしましょう。
nodenv local が効いていないときに確認する

２つの原因が重なっていて解決まで時間食ってしまったので、メモ。

## 方法：Doctorコマンドを使いながら対応していく

```zsh:Doctorコマンド
curl -fsSL https://github.com/nodenv/nodenv-installer/raw/master/bin/nodenv-doctor | bash
```

```zsh:nodenvのバージョン
nodenv -v
nodenv 1.4.1
```

## `nodenv init` ができてない
セットアップのときにしたはずなんだが、と思いながら指示されているので `nodenv init`しました。ちょいモヤ。

```zsh
Checking for `nodenv' in PATH: /opt/homebrew/bin/nodenv
Checking for nodenv shims in PATH: not found
  The directory `/Users/your-name/.nodenv/shims' must be present in PATH for nodenv to work.
  Please run `nodenv init' and follow the instructions.

Checking `nodenv install' support: /opt/homebrew/bin/nodenv-install (node-build 5.3.14)
Counting installed Node versions: 24 versions
Auditing installed plugins: OK
```


## `opt/homebrew/bin` より前にPATHを設定している


```zsh
Checking for `nodenv' in PATH: /opt/homebrew/bin/nodenv
Checking for nodenv shims in PATH: found at wrong position
  The directory `/Users/your-name/.nodenv/shims' is present in PATH, but is listed too late.
  The Node version found in `/opt/homebrew/bin' will have precedence. Please reorder your PATH.

Checking `nodenv install' support: /opt/homebrew/bin/nodenv-install (node-build 5.3.14)
Counting installed Node versions: 24 versions
Auditing installed plugins: OK
```


`node -v` すると `v23` という新しめのバージョンが出て、はて？どこかでインストールしたっけと思いつつ色々しらべてると、

「**herokuのCLIツールをインストールした際にグローバルにnodeがインストールされていた**」 

`zshrc`の書き方も相まってnodenvより先にグローバルのnodeが使われてしまう状況になっていました。


以下のように brew install されたnodeより前にPATHを追加するように対応しました。
```diff
- # NODENV
- export PATH="$HOME/.nodenv/shims:$PATH" 
- eval "$(rbenv init - zsh)"

export PATH="/opt/homebrew/bin:$PATH" 

+ # NODENV
+ export PATH="$HOME/.nodenv/shims:$PATH" 
+ eval "$(rbenv init - zsh)"
```

:::note warn
`.nodenv/bin` と説明されているサイトが多かったですが、どこかのバージョンから `.nodenv/shims` に切り替わってそうです（詳細未調査）
:::

### チェックOK :+1:
```
Checking for `nodenv' in PATH: /opt/homebrew/bin/nodenv
Checking for nodenv shims in PATH: OK
Checking `nodenv install' support: /opt/homebrew/bin/nodenv-install (node-build 5.3.14)
Counting installed Node versions: 24 versions
Auditing installed plugins: OK
```
Builder

Builderは構造を持ったインスタンスを組み上げていく。Builderクラスはインスタンスを作成するためのインターフェース。cconcreateBuilderクラスはBuilderクラスを継承した具体的な実装をしているクラス。DirecterクラスはBulderクラスのインスタンスを生成しBuilderクラスのメソッドを使う。ClientクラスはBuiderパターンを利用する。
dataform-assertions をさくっと試す

# 概要
自分が所属する組織では dataform の assertion の実装が割と後回しにされがち。
なかなかキレイに書けないのでモチベーションが沸かないのかもしれないが、品質を保証する大事な作業なのでなんとかしたい。
と思って調べたら dataform-assertions という良いものを見つけたので軽く試す。

ref. https://github.com/devoteamgcloud/dataform-assertions

# 試す
dataform の version 3 以降は `workflow_settings.yaml` で dataform core の version を指定してやればコンパイルするときに勝手に dataform core もインストールされるのだが、他に依存するライブラリがあれば `package.json` を使う必要がある。

ref. https://github.com/dataform-co/dataform/releases/tag/3.0.0

`workflow_settings.yaml` から「dataformCoreVersion: 3.0.8」の行を消し、version 3 にする際に削除した package.json を復活させる。

```yaml:workflow_settings.yaml
defaultLocation: asia-northeast1
defaultDataset: dataform
defaultAssertionDataset: dataform_assertions
```
dataform core の version 通常は `workflow_settings.yaml` に記述するのだが、`package.json` を使う場合はそちらに記述する。

```json:package.json
{
    "name": "data-analytics-dataform",
    "dependencies": {
        "@dataform/core": "3.0.8",
        "dataform-assertions": "https://github.com/devoteamgcloud/dataform-assertions/archive/refs/tags/v2.0.0.tar.gz"
    }
}
```
そしてインストール。
```
$ dataform install
 
Installing NPM dependencies...
 
Project dependencies successfully installed.
```

以下のコードは `fact_orders` というテーブルに対して、`order_date` が前日以降のデータを対象に、`order_id` のカラムに null が含まれていないかテストする内容。

:::note warn
globalAssertionsParams.database / schema は assertion 実行時に作成される view が格納される先を設定する箇所で、default_database / schema を置き換えるものではないことに注意。
:::

```javascript:assertions.js
const commonAssertions = require("dataform-assertions");
 
const commonAssertionsResult = commonAssertions({
    globalAssertionsParams: {
        // If not provided, the default Dataform project config will be used
        "database": "data-sandbox",
        "schema": "dataform_assertions",
        // "location": "bigquery-location",
        "tags": ["global-assertions-tag"],
        // "disabledInEnvs": ["dv"] // Check match with 'dataform.projectConfig.vars.env' value
    },
    config: {
        "data_component": {
            "fact_orders": {
                "where": "order_date >= current_date() - 1"
            }
        }
    },
    rowConditions: {
        "data_component": {
            "fact_orders": {
                "order_id_not_null": "order_id is not null",
            }
        }
    }
});
```

実行してみる。
```
$ dataform run --tags global-assertions-tag --default-database data-sandbox
Compiling...
 
Compiled successfully.
 
Running...
 
Assertion passed:  dataform_assertions.assert_order_id_not_nulldata_component_fact_orders
```
すばらしい。
結局GASで引数あり関数をどうデバッグするのか

# デバッグ専用の関数を作り，そこから呼ぶ
結局のところ難しいのってトリガイベントによって実行される関数を，どうやってトリガ情報を任意の値に設定してデバッグ実行するかだと思います．

今の所のベストプラクティスは単純ですがトリガ部分をメイン関数と分離させ，トリガ部分に相当するデバッグ用の関数を別に用意し内部で変数をベタ打ちする方法です．


例として以下のコードはフォームに新しい回答が送信された時に回答に対して何らかの処理を行うコードの一部です．


## 元コード
デバッグしたい処理はonFormSubmit(e)内に配置されており，引数eを指定する方法がGoogleAppScriptのコンソールには無いため任意タイミングでの実行は不可能でした．
(eを指定できたとしてもgetActiveSheet等が動くのかも不明)
```javascript:original_code.gs

function onFormSubmit(e) {
  var sheet = e.source.getActiveSheet();
  var lastRow = sheet.getLastRow();
  var data = sheet.getRange(lastRow, 1, 1, 10).getValues()[0];  
  var mail = data[0];
  ....

```
## 改善後コード
実際にデバッグしたい処理の本体をmain関数に隔離し，トリガによって起動する関数とデバッグ時に任意タイミングで実行する関数を用意しました．
debugOnFormSubmit内にてmainで必要な変数をベタ打ちで用意しているのでトリガに依存せず任意の値を渡した動作をデバッグできます．
ここまで用意したらあとは適当にbreak pointを設定してdebug consoleでデバッグ用関数を指定し実行するだけです．
```javascript:debug_friendly_code.gs

// トリガ起動用
function onFormSubmit(e) {
  var sheet = e.source.getActiveSheet();
  var lastRow = sheet.getLastRow();
  var data = sheet.getRange(lastRow, 1, 1, 10).getValues()[0];
  main(data);
}

// デバッグ専用
function debugOnFormSubmit(){
  // デバッグで使用するデータを固定する
  var docId = 'YOUR_SHEET_ID_FOR_DEBUG';
  var spreadsheet = SpreadsheetApp.openById(docId);
  var sheet = spreadsheet.getActiveSheet(); 
  var targetRow = 100;
  var data = sheet.getRange(targetRow, 1, 1, 10).getValues()[0];
  main(data);
}

function main(data) {
  
  var mail = data[0];
  ....

```
![Screenshot 2025-03-13 at 10.12.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1756017/7e1b940d-b538-45f0-a484-c5fa4d19c5fd.png)



敬具
コンピュータサイエンス学び直し -プリミティブ型について-

# 1. はじめに
エンジニアとして3年が経過しようとしている中、技術を使ってより高度な問題解決をしていくためには、フレームワークや言語に依存しない基礎となる知識が必要だと感じたため、CSを勉強し直しています。
その学習内容を備忘録として発信します。
今回は**プリミティブ型**についてです。

# 2. 言語別のプリミティブ型

プログラミング言語には、基本的なデータ型（プリミティブ型）が定義されています。以下の表は、主要な言語におけるプリミティブ型を整理したものです。

| 言語       | ブーリアン型 | 文字型 | 文字列型 | 整数型 | 浮動小数点型 |
|------------|------------|--------|--------|--------|------------|
| Ruby       | true/false | なし (String を使用) | String | Integer | Float |
| PHP        | bool       | なし (string を使用) | string | int    | float |
| Python     | bool       | なし (str を使用) | str    | int    | float |
| JavaScript | boolean    | なし (string を使用) | string | number (整数としても扱える) | number |
| Java       | boolean    | char   | String | byte, short, int, long | float, double |

# 3. Javaで char 型と String 型を区別している理由

Javaでは `char` 型と `String` 型を明確に区別しています。これにはいくつかの理由があります。

## メモリ効率の向上
- `char` は **2 バイト（16ビット）** の固定サイズ。
- `String` は **オブジェクト** であり、可変長のデータを持つため、1文字を `String` で扱うと無駄なメモリを消費する。

## 処理速度の向上
- `char` はプリミティブ型であり、**直接メモリ上の値を比較** できるため、高速。
- `String` はオブジェクトであり、比較時に `equals()` メソッドを使う必要があるため、**オーバーヘッド** が発生する。

## 意図の明確化
- `char` を使用すると **「1文字を扱う」** という意図が明確になる。
- `String` は **複数文字を扱う場合** に使用され、コードの可読性が向上する。

## 不変性（Immutable）の違い
- `String` は **変更不可（immutable）** であり、新しい値を代入すると新しいオブジェクトが作成される。
- `char` は単なる値なので、変更してもオブジェクトの作成は発生しない。

# 4. Java以外の言語で char 型と String 型を区別していない理由

一方で、**Ruby, PHP, Python, JavaScript** などの言語では `char` 型を独立したプリミティブ型として用意していません。その理由は以下の通りです。

## 文字を特別扱いする必要がない
- これらの言語では **文字も単なる短い文字列** として扱う。
- 文字列操作が頻繁に行われるため、`char` と `String` を統一したほうがシンプルになる。

## オブジェクト指向の設計が優先
- **Python や Ruby** では、すべてのデータがオブジェクトであり、プリミティブ型をできるだけ減らす方針。
- **文字も文字列オブジェクトの一部** として扱うほうが一貫性がある。

## パフォーマンスの最適化が自動化されている
- **JavaScript** では **JIT（Just-In-Time）コンパイラ** によって、必要に応じて最適化が行われる。
- **Python や Ruby** でも内部的に効率化されており、`char` 型を独立させるメリットが少ない。

# 5. 処理のオーバーヘッドとは

## オーバーヘッドの定義
**オーバーヘッド（overhead）** とは、本来の処理を実行するために発生する **追加の処理負荷** のことを指します。プログラムの実行速度やメモリ使用量に影響を与える要因となります。

## オーバーヘッドの具体例

### 1. オブジェクトの参照によるオーバーヘッド
`char` は直接値を持ちますが、`String` はオブジェクトなので、**メモリ上のデータを参照する処理** が発生します。

```java
char a = 'A';
char b = 'B';
if (a == b) { // 直接比較できる
    System.out.println("Same");
}

String s1 = "A";
String s2 = "B";
if (s1.equals(s2)) { // 参照をたどって比較（オーバーヘッドあり）
    System.out.println("Same");
}
```

### 2. メソッド呼び出しによるオーバーヘッド

メソッドを呼び出すと、**スタックメモリの操作** が発生し、処理が遅くなります。

```java
public static int add(int a, int b) {
    return a + b; // オーバーヘッドが少ない
}

int result = 10 + 20; // メソッドを使わないことでオーバーヘッド削減
```

### 3. ガベージコレクション（GC）のオーバーヘッド

大量の `String` オブジェクトを生成すると、**GC（ガベージコレクタ）** が頻繁に動作し、プログラムの動作が遅くなります。

```java
for (int i = 0; i < 100000; i++) {
    String s = new String("Hello"); // GC の負担増大
}
```

## オーバーヘッドを減らす方法

| **オーバーヘッドの原因** | **改善策** |
|------------------|--------------------------------|
| **オブジェクトの参照** | **プリミティブ型を使用する** (`char` など) |
| **メソッド呼び出し** | **シンプルな処理は直接記述（インライン化）** |
| **メモリ管理（GC）** | **`StringBuilder` を使い、不要なオブジェクトを減らす** |

Javaでは **`char` と `String` を明確に区別** し、オーバーヘッドを抑えることで効率的な処理が可能になります。  
一方、他の言語では **言語設計や最適化技術** によって、`char` 型を区別する必要がなくなっています。
Androidの「戻るボタン」処理をイベント送信パターンで整理する

## はじめに

Android開発では、「戻るボタン」が押された際に画面状態に応じて処理を切り替える場面が頻繁にあります。例えば、
- 条件Aのときはダイアログを表示して確認を促す
- 条件Bのときは確認なしに画面を終了する
- 条件Cのときは何も処理を行わない

などのシナリオです。

シンプルなケースであれば問題ありませんが、状態の組み合わせが増えてくるとif文が増え、コードの見通しが悪くなります。

今回は、このような状況でイベント送信パターンを導入し、責務を明確に分離することでコードの可読性と保守性を改善した事例を紹介します。

## Before：Viewで直接状態を管理した場合の問題点

以下はよくある実装例です。

``` kotlin
override fun onBackPressed() {
    if (!isDialogVisible && isDataAvailable) {
        showDialog()
    } else if (!isDataAvailable) {
        finish()
    }
}
```

### このコードの課題点

- 画面の状態（isDialogVisibleやisDataAvailable）がView側に直接書かれているため、Viewが状態を把握・管理する必要があり、責務が曖昧になる
- 状態のパターンが増えるほど、if分岐が複雑になり、可読性が低下する
- 後々の変更に弱く、保守しづらい

## After：イベント送信パターンで責務を分離したコード

イベント送信パターンを導入すると、コードは次のように改善できます。

### ViewModel側で状態に基づいたイベントを発行

``` kotlin
fun handleBackPressed() {
    val event = when {
        shouldShowDialog -> UiEvent.ShowDialog
        shouldCloseScreen -> UiEvent.CloseScreen
        else -> null
    }
    event?.let(::sendEvent)
}
```

状態は以下のようにシンプルに整理できます。

``` kotlin
val shouldShowDialog = !isDialogVisible && isDataAvailable
val shouldCloseScreen = !isDataAvailable
```

### View側はイベントを受け取って処理を行うだけ

``` kotlin
viewModel.eventFlow.collect { event ->
    when (event) {
        UiEvent.ShowDialog -> showDialog()
        UiEvent.CloseScreen -> finish()
    }
}
```

- ViewModelが画面の状態を判断し、具体的な処理はイベントとして通知
- Viewはイベントを受け取り、それに応じた処理を実行するのみでよい

こうすることで、ViewとViewModelがそれぞれの役割に集中でき、コードの可読性が飛躍的に向上します。

## Afterの改善ポイントまとめ

|改善前|改善後|
|:---:|:---:|
|Viewが状態を直接管理|状態管理はViewModelが担当|
|状態と具体的な処理が混在|Viewは受け取ったイベントに反応するだけ|
|状態が増えるとコードが複雑化|イベント送信するだけになりシンプルを保てる|

## イベント送信パターンを取り入れるメリット

- 責務が明確に分離され、ViewはUI処理に専念、ViewModelはロジックと状態管理に専念できる
- イベントの送信処理を一箇所にまとめることで、変更に強いコードになる
- 新しい状態や処理が追加されたときも、自然に拡張可能になる

ぜひ試してみてください！！！
[ServiceNow] 拡張されたテーブルへClassを変更するScriptの実証

# はじめに

ServiceNowでは、Task（task）やBase CI（cmdb）テーブルは、それぞれを頂点に子ととして様々な拡張テーブルを持っています。例えば、Incident（incident）やProblem（problem）はTaskを拡張したテーブルです。
ここでは、上位テーブルに作成したレコードを下位テーブルに移すScriptを検証します。

# 前提

Hardware（cmdb_ci_hardware）テーブルは、Base CIテーブルから見て子孫のテーブルの一つですが、さらに多くの子孫テーブルを持ち、CIでも大きくハードウェアに分類されるものが登録されるテーブルです。このテーブルにあるレコードを下位テーブルであるComputer（cmdb_ci_computer）に、Scriptで移してみましょう。

# Script

検証ですので、ScriptはScripts - Backgroundで実行します。
実行するScriptは以下のとおりです。
今回はCIの名前が「Computer100」であるものをハードコードで指定しています。

```javascript:Script
var targetName = 'Computer100';

var gr = new GlideRecord('cmdb_ci_hardware');
gr.addQuery('name', targetName);
gr.query();
 
if (gr.next()) {
    gs.info('レコードを更新します: ' + gr.sys_id);
    gr.sys_class_name = 'cmdb_ci_computer';
    gr.sys_class_path = '/!!/!2/!(';
    gr.update();
    
	gr.initialize();
	gr.addQuery('name', targetName);
	gr.query();
    if (gr.next()) {
		gs.info('レコードが更新されました: ' + gr.sys_id);
	}
} else {
    gs.info('該当するレコードが見つかりませんでした。');
}
```

Scriptの出力結果は以下のとおりです。
念の為、レコードの更新前後で、sys_idが変わっていないことも確認できます。

![スクリーンショット 2025-02-28 18.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/26dc1878-cfa8-46de-9dbd-74c346ad93af.png)

# 実際のレコードで確認する。

変更前と変更後で、無事Classが変わっていることがわかります。

(変更前)
![スクリーンショット 2025-02-28 18.15.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/80b4d136-dab8-4dd5-868f-e949567942ad.png)

(変更後)
![スクリーンショット 2025-02-28 18.16.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3490802/a364f9cb-6478-4254-8923-20fd23533e47.png)
Flutter "Unresolved reference" エラーで以前ビルドできていたプロジェクトのビルドに失敗した際の対処法

# 事象
Flutter で開発しており、Android 向けに以前ビルドできていたプロジェクトのビルドが `Unresolved reference` エラーで失敗する
```
e: file:///C:/Users/{your username}/AppData/Local/Pub/Cache/hosted/pub.dev/image_gallery_saver-2.0.3/android/src/main/kotlin/com/example/imagegallerysaver/ImageGallerySaverPlugin.kt:21:48 Unresolved reference 'Registrar'.
```

# 原因
`image_gallery_saver` パッケージが Flutter の最新バージョンで削除された API に依存していたためだった。
パッケージのソース内に下記記述があり、`io.flutter.plugin.common.PluginRegistry.Registrar` を調べたところ最近の Flutter アップデートで削除されていた。
```kotlin
import io.flutter.plugin.common.PluginRegistry.Registrar
```

# 解消方法
方法1. `image_gallery_saver` パッケージをforkして、新しい API を使用するよう修正する
方法2. Flutter のバージョンを下げる

最新の `image_gallery_saver` パッケージ(2.0.3)がまだ古い API を参照したままだったので、`image_gallery_saver` のバージョンを上げても解決しない。<strike>知らずに Flutter のバージョンアップがされてしまっていたようなので</strike>iOSビルド時にFlutterのアップデートを促されアップデートしてしまったので、私は 2 の方法で解消した。

### 1. 現在のバージョン確認
```
$ flutter --version
Flutter 3.29.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 09de023485 (12 days ago) • 2025-02-28 13:44:05 -0800
Engine • revision 871f65ac1b
Tools • Dart 3.7.0 • DevTools 2.42.2
```

### 2. ダウングレード
```
$ flutter downgrade
Downgrade flutter to version 3.27.1
? [y|n]: y
Success
```

ダウングレード後のバージョン確認
```
$ flutter --version
Checking Dart SDK version... 
Downloading Dart SDK from Flutter engine cb4b5fff73850b2e42bd4de7cb9a4310a78ac40d... 
Expanding downloaded archive with PowerShell...
Building flutter tool... 
Running pub upgrade... 
Resolving dependencies... (1.4s)
Downloading packages...
Got dependencies.
Flutter 3.27.1 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 17025dd882 (3 months ago) • 2024-12-17 03:23:09 +0900
Engine • revision cb4b5fff73
Tools • Dart 3.6.0 • DevTools 2.40.2
```

### 3. 依存関係の更新
```
$ flutter clean # 実行結果省略
$ flutter pub get # 実行結果省略
```

### 4. ビルド
```
flutter run --debug
```

# おわりに
今回は `image_gallery_saver` と Register API だったが、他のパッケージと API でも同様のことは起こりえるので、`Unresolved reference` エラー発生時はパッケージの依存している Flutter API が廃止されていないか調べるとよさそう。

# 参考
- https://appwrite.io/threads/1334415894394306571
- https://github.com/ekasetiawans/flutter_background_service/issues/496
jsonのリアルなテストデータを大量に作れるアプリを作った話

## リポジトリ（ほぼAIで作成）↓
https://github.com/Ucchi0301/generate_testcase

## 作成の経緯
昨年開発のインターンにて、DjangoRESTフレームワークを使用した。
その際に、複数回テストケースを作成したが面倒だった

## 🚀 主な機能
1. **AIによるデータ生成**（OpenAI API連携）
2. **ランダムデータ生成**（UUID/数値/真偽値）
3. **静的な値の設定**
4. **ネストされたオブジェクト生成**
## 入出力例
入力 : 
```
{
    "count": 20,
    "fields": {
      "uuid": {
        "source": "random",
        "type": "uuid"
      },
      "name": {
        "source": "ai",
        "prompt": "ありそうなユニークな日本人の名前"
      },
      "company": {
        "source": "object",
        "fields": {
          "name": {
            "source": "ai",
            "prompt": "ありそうな日本の会社名"
          },
          "address": {
            "source": "ai",
            "prompt": "日本のありそうな住所"
          }
        }
      },
      "売上": {
        "source": "random",
        "type": "num",
        "range": [1, 500]
      },
      "is_active": {
        "source": "random",
        "type": "bool"
      },
      "launch_year": {
        "source": "random",
        "type": "num",
        "range": [2010, 2025]
      },
      "メモ（固定値）": {
        "source": "static",
        "value": "めもめも"
      }
    }
  }
```

出力例:

![output.json - テストデータ生成AI - Visual Studio Code 2025_03_13 9_15_47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3905869/40b0c9b1-8ec7-490a-ad55-c5c3f6048d37.png)

countの個数分データを作成します！
Linuxコマンド入門：Linuxコマンド「mv」と「cp」の使い方とオプション解説してみた

## はじめに
Linuxでファイルを管理する際に欠かせないコマンドに「mv」と「cp」があります。
`mv` はファイルを移動・名前変更するコマンド、`cp` はファイルをコピーするコマンドです。

## 書こうと思ったきっかけ
多くの人がLinuxの基本コマンドを使う中で、オプションの使い方を知らないまま利用していることが多いと感じました。

:::note info
**`mv` や `cp` を適切に使いこなすことで、作業効率が向上し、不要なミスを防ぐことができます。**
:::

そこで、基本的な使い方と最低限知っておきたいオプションについて解説します。

## mv コマンド

### 概要
`mv` コマンドは、ファイルやディレクトリを移動（または名前を変更）するためのコマンドです。

### 基本的な構文
```bash
mv [オプション] <元のファイル/ディレクトリ> <移動先のディレクトリ>
```

### 使用例
1. **ファイルを移動する**
   ```bash
   mv file1.txt /home/user/documents/
   ```
   → `file1.txt` を `/home/user/documents/` ディレクトリに移動

2. **ファイル名を変更する**
   ```bash
   mv old_name.txt new_name.txt
   ```
   → `old_name.txt` の名前を `new_name.txt` に変更

### よく使うオプション
| オプション | 説明 |
|------------|--------------------------------------------------|
| `-i` | 移動先に同じ名前のファイルがある場合、確認を求める |
| `-v` | 実行中の処理を詳細に表示する |

**参考文献**

https://atmarkit.itmedia.co.jp/ait/articles/1606/13/news024.html

---

## cp コマンド

### 概要
`cp` コマンドは、ファイルやディレクトリをコピーするためのコマンドです。

### 基本的な構文
```bash
cp [オプション] <コピー元ファイル/ディレクトリ> <コピー先ディレクトリ>
```

### 使用例
1. **ファイルをコピーする**
   ```bash
   cp file1.txt /home/user/documents/
   ```
   → `file1.txt` を `/home/user/documents/` にコピー

2. **ディレクトリごとコピーする**
   ```bash
   cp -r dir1 /home/user/
   ```
   → `dir1` ディレクトリを `/home/user/` にコピー

### よく使うオプション
| オプション | 説明 |
|------------|--------------------------------------------------|
| `-i` | コピー先に同じ名前のファイルがある場合、確認を求める |
| `-r` | ディレクトリを再帰的にコピーする |
| `-v` | 実行中の処理を詳細に表示する |


**参考文献**

https://atmarkit.itmedia.co.jp/ait/articles/1605/31/news019.html

---

## まとめ
`mv` は「移動または名前変更」、`cp` は「コピー」を行うコマンドです。

| コマンド | 主要なオプション | 目的 |
|----------|----------------|-----------------------------|
| `mv` | `-i, -v` | ファイルやディレクトリの移動・名前変更 |
| `cp` | `-i, -r, -v` | ファイルやディレクトリのコピー |

適切なオプションを組み合わせて、安全かつ効率的にファイル管理を行いましょう！
家計簿アプリを作る＃１５

![スクリーンショット 2025-03-13 083752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/8679e653-88be-4387-9435-f77747281ac7.png)
AppBarは、HTMLのヘッダーと同じ要素になります。

![スクリーンショット 2025-03-13 083900.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/ce77468c-5ea3-4a95-a038-145e0f9dd3c0.png)
その中には、ツールバーというものがあり、

![スクリーンショット 2025-03-13 083945.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/39f832e1-3379-49d5-a38a-7fc69f5af4c0.png)
その中に、IconボタンとTypographyというものがあります。

![スクリーンショット 2025-03-13 084113.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/3c42e064-8774-4e2c-9673-b8031b60213b.png)
IconボタンのMenuIconは、こちらになります👆
MenuIconをIconボタンで囲むことによって、Iconをボタン要素として、扱うことができます。

Typographyはヘッダーに表示されている文字のことです。
JavaScriptの基礎（3）

※この記事は初学者の毎日のアウトプット用に作成している記事です

## データ型
JavaScriptには8つの型がある
7つのプリミティブ型と1つのオブジェクト型が存在する

### プリミティブ型
null型 ー 値がない
undefined型 ー 値が定義されていない
Boolean型 ー 真偽値
Number型 ー 数値
Biglnt型 ー Numberよりも大きいor小さい数を扱う
String型 ー 文字列
Symbol型 ー シンボル

### オブジェクト型
オブジェクト型 ー 関連するデータなどをまとめたもの

### 違い
プリミティブ型のデータが代入されている変数には`値そのもの`が保存されているが、オブジェクト型のデータが代入されている変数には値が保存されている`メモリーの場所`が保存される


```javascript
// プリミティブ型 (number)
let a = 10;
let b = a; // 値がコピーされる (値そのものを代入)

// 値を書き換える
b = 20;

console.log(a); // 10 (aの値には影響なし)
console.log(b); // 20

// オブジェクト型
let obj1 = { value: 10 };
let obj2 = obj1; // メモリのアドレスがコピーされる (参照が渡される)

// 値を書き換える
obj2.value = 20;

console.log(obj1.value); // 20 (obj1の値も影響を受ける)
console.log(obj2.value); // 20

```
<br>

参考書籍：

https://www.amazon.co.jp/%E3%81%93%E3%82%8C%E3%81%8B%E3%82%89%E3%81%AEJavaScript%E3%81%AE%E6%95%99%E7%A7%91%E6%9B%B8-%E7%8B%A9%E9%87%8E-%E7%A5%90%E6%9D%B1/dp/481561802X
Web APIシリーズその5(全5回)：APIサーバをどう配置するか


## Webアプリケーションに必要なサーバ機能

1. 静的ファイル配信
  HTML/JS/CSSなど
2. API

----
## 機能毎に求められるサーバスペックは異なる

- 静的ファイル配信
   - とにかく決められたコンテンツを素早く返す
   - CPUパワーはさして重要でない
   - キャッシュが有効
- API
   - DBやストレージとのやり取りと計算
   - APIリクエストは頻繁に生じるためCPUとメモリ両方を潤沢に使いたい
   - どちらかと言えばCPUパワーがより重要（DBはメモリが大事）

----
## アーキテクチャパターン

- APIサーバ独立パターン
- 同居パターン
- サーバーレスパターン

※私がこのスライドのために勝手に名付けたのであり、一般に浸透している用語ではありません。

----
## APIサーバ独立パターン(1/2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10225/1e5a199e-b961-45f5-9088-8152392c6d03.png)


----
## APIサーバ独立パターン(2/2)

- (+)それぞれのサーバでスペックを変えられるので最適なスペックを追求できる
- (-)CORSが必要

----
## 同居パターン(1/2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10225/689c1ad2-43fe-4b6b-b564-3fd7e835b6d5.png)

----
## 同居パターン(2/2)

- (+)デプロイプロセスや運用がシンプル
- (-)静的ファイル配信が多くなった時にどうなるか・・・？

----
## サーバーレスパターン(1/2)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/10225/eb53caea-ce1c-4a38-a266-409ef868d698.png)

----
## サーバーレスパターン(2/2)

- (+)前述の２パターンの欠点を克服
- (+)コスト最適
- (-)実現が複雑。事実上、専用のサービスを使うことになる
   Static Web App(Azure)/Amplify(AWS)

----
## サーバーレスパターン補足
- 理想的に思えるが、難点はある
   - 開発プラットフォームが限定される
   - AWSベンダにロックインされる

----
## 最後に
- どのパターンも一長一短
- 選択肢を複数持っておくことが大事
#0071（2024/03/12）Lazy loading

# PythonにおけるLazy Loading（遅延読み込み）のトライ

Pythonでデータ処理や画像処理を行う際、「Lazy Loading（遅延読み込み）」という手法を使うと、効率的にメモリを管理し、大規模なデータ処理を快適に行えるようになります。本記事では、Lazy Loadingの概要と、一括読み込みとの違いを実際のテスト結果をもとに解説します。

## 🔹 Lazy Loadingとは？

Lazy Loading（遅延読み込み）とは、必要になるまでデータをメモリに読み込まない処理方式です。すべてのデータを一度にメモリ上に展開する「一括読み込み」とは対照的で、メモリ効率が良く、大規模データや大量の画像ファイルを扱う際に有効な手法です。

## 🔹 一括読み込みとの違い

- **一括読み込み:** 全データを一度にメモリ上に読み込み、処理を開始します。メモリ使用量が非常に多くなり、大量のデータを扱うとメモリ不足になる可能性があります。
- **Lazy Loading:** 必要なデータを逐次的に読み込むため、メモリの消費を抑えられます。メモリ使用量が少なく、大量のデータ処理にも対応できます。

## 🔹 PythonによるLazy Loadingの実例

画像を用いたサンプルコードでLazy Loadingと一括読み込みの違いを検証します。

### サンプルコード

```python
import os
import tempfile
from PIL import Image
from memory_profiler import profile

def create_mock_images(num_images, image_size=(100, 100), directory=None):
    if directory is None:
        directory = tempfile.mkdtemp()
    image_paths = []
    for i in range(num_images):
        img = Image.new("RGB", image_size, color=(i % 256, (i * 2) % 256, (i * 3) % 256))
        path = os.path.join(directory, f"mock_{i}.jpg")
        img.save(path, "JPEG")
        image_paths.append(path)
    return image_paths

def load_images_lazy(image_paths):
    for path in image_paths:
        with Image.open(path) as img:
            img.load()
            yield img.copy()

def load_images_all(image_paths):
    images = []
    for path in image_paths:
        with Image.open(path) as img:
            img.load()
            images.append(img.copy())
    return images

@profile
def process_images_lazy(image_paths):
    for img in load_images_lazy(image_paths):
        _ = img.size

@profile
def process_images_all(image_paths):
    images = load_images_all(image_paths)
    for img in images:
        _ = img.size

if __name__ == "__main__":
    num_images = 100000
    image_paths = create_mock_images(num_images)
    print(f"Mock images created in directory: {os.path.dirname(image_paths[0])}")

    print("Processing images with lazy loading:")
    process_images_lazy(image_paths)

    print("Processing images with all-at-once loading:")
    process_images_all(image_paths)
```

## 🔹 実行結果（メモリ使用量比較）

### Lazy Loadingの場合
```
Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
    36     53.4 MiB     53.4 MiB           1   @profile
    39     53.6 MiB      0.2 MiB         101       for img in load_images_lazy(image_paths):
    41     53.6 MiB      0.0 MiB         100           _ = img.size
```

### 一括読み込みの場合
```
Line #    Mem usage    Increment  Occurrences   Line Contents
=============================================================
    43     53.6 MiB     53.6 MiB           1   @profile
    46     57.5 MiB      3.9 MiB           1       images = load_images_all(image_paths)
    47     57.5 MiB      0.0 MiB         101       for img in images:
    48     57.5 MiB      0.0 MiB         100           _ = img.size
```

## 🔹 Lazy Loadingのすごさまとめ

Lazy Loadingを使用すると、

- 一度にメモリを大量に消費することなく、安定した処理が可能になる。
- 特に画像や大規模データを大量に扱う際、メモリ不足を避けられる。
- スケーラブルで効率的な処理が可能になる。

大規模データ処理を行う際はLazy Loadingの活用を検討すると、効率的で安定したアプリケーションを構築できます。
Slack のトレイルヘッド


+ [Unable to complete the Trail - Build a Bolt App for Slack](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000PWD0H)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5d78c3e5-5130-41e8-b012-452b754d9109.png)

 :::note
Managed to fix the issue I spotted via Glitch tools app.js debugging capabilities and figured out that under App Home in Features we need enable the Messages Tab for Say Hello bot to be able to tell us whenever we are hitting the "Click Me" button


 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/b3f5e2b4-1181-4465-a9c7-6e70d4765085.png)

 
 The above screen-shot is from the Slack App configured/setup via the api.slack.com website.
 :::
 

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2ac6feb9-9019-a12e-93f2-04ae22bedb53.png)
新しいプレイグランドで対応
Databricksアカウントにおけるパーソナルアクセストークンの監視

こちらのアップデートです。

[アカウントにおけるパーソナルアクセストークンの監視と取り消し](https://docs.databricks.com/aws/ja/release-notes/product/2025/march#monitor-and-revoke-personal-access-tokens-in-your-account-public-preview)

> トークンレポートがパブリックプレビューになりました。トークンレポートによって、アカウント管理者はアカウントコンソール上でパーソナルアクセストークン(PAT)の監視と取り消しが行えるようになります。Databricksでは、セキュリティ強化と利便性のためにPATではなくOAuthアクセスを使用することをお勧めしています。[個人用アクセス トークンの監視と取り消し](https://docs.databricks.com/aws/ja/admin/access-control/tokens#monitor-account-tokens)をご覧ください。

[アカウントコンソール](https://accounts.cloud.databricks.com/)にログインします。

**プレビュー**で**Access Token Report**が有効化されていることを確認します。

![Screenshot 2025-03-13 at 6.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/7c56543b-900a-45bb-aaff-675cf4522f00.png)

**設定**から**トークンレポート**にアクセスします。アカウント上で発行されているパーソナルアクセストークンを確認できます。

![Screenshot 2025-03-13 at 6.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/bd1e5906-d524-410d-900b-2c5a0f2bcce2.png)

作成日時や有効期限を確認することができ、トークンを取り消すことも可能です。

![Screenshot 2025-03-13 at 6.35.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/f8dd453b-5f7d-428d-9a32-caa0e7196224.png)

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)