OmniAICreator/Qiita-1.07M huggingface dataset:
AWS重要知識(AWS-SAA,SAP対策)　〜VPC(ネットワーク系)篇〜

## 目的
VPCとその関連リソースに関する重要知識を学ぶ



## VPCのCIDRがRFC1918準拠かどうか
重要度⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️⭐️

:::note
RFC1918とは？
プライベートIPアドレスとして定められているIPアドレス範囲

RFCはインターネット技術の標準仕様をまとめた文書群のことらしい
:::

RFC1918準拠でないということはインターネット上のIPアドレスと重複している可能性がある
完全にVPC内部で完結した通信であれば問題はないが、将来的に外部システムやSaaSなどと連携した時に詰むので基本的にRFC1918は準拠がマスト

:::warn
また、内部だけだとしてもNLBのターゲットIPにはRFC1918しか指摘できないなど弊害あり
:::

AWSもVPCはRFC1918準拠を推奨している
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/vpc-cidr-blocks.html

そもそもクラウドとかAWSとかいう話ではなく、オンプレやAzureでも同じ話です。






## VPCのIPアドレスには余裕を持たせる
重要度⭐️⭐️⭐️⭐️⭐️
後々のリソースの追加はもちろんのことだがAWSでは一つのリソースが複数のIPアドレスを必要とするケースが多い。

### VPCエンドポイント(インターフェース)
VPCエンドポイントはアタッチするサブネットのIPアドレスを1つ使用する。
SSM、S3、CloudWatchなどVPCエンドポイントは基本複数あるはずなので注意。

### Auto Scalling
EC2をスケールアウトさせて可用性向上を行うサービス
このサービスはスケールアウトの台数分で追加のIPアドレスを必要とする。
追加のIPアドレスが割り当てできない場合はスケーリングが失敗する。





## セキュリティグループはステートフル
重要度⭐️⭐️⭐️⭐️⭐️

:::note
ステートフルとは？
一方向の通信が許可されていれば、戻りの通信も許可されること
:::

例えば、
セキュリティグループに「inboundの22番ポートを許可」を設定し、EC2にアタッチします。

入ってくるSSHの通信はもちろん許可されますが、EC2からクライアントへ戻っていくSSH通信は許可されていないから一見するとSSHできなさそうです。
しかし、セキュリティグループはステートフルなので実際は可能となります。


## ネットワークACLはステートレス
重要度⭐️⭐️
逆にネットワークACLはステートレスです。
入りも戻りもセットで許可しないといけません。

ネットワークACLで通信制御するケースはそこまで多くないので重要度は低いです。(というかVPC単位での制御なので細かい制御をすると事故る)





## Amazon Route53 Resolver
重要度⭐️⭐️⭐️
VPC作成時に先頭から +2 のIPアドレスにRoute 53 Resolverが作成される。
これはVPC内部のリソースが名前解決をする際の参照先となる。

Route53 Resolverを深掘りしていく。

### EC2内部
EC2を立てると自動的にRoute53 Resolver向きのDNS設定になる。

VPCのCIDR 「10.0.0.0/16」でEC2を立ててみる。
LinuxのDNS参照先設定のファイルである『etc/resolv.conf』を見る

```
cat etc/resolv.conf
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/2412632e-f3ea-2ee2-58d2-7f2a5ce5e07d.png)

「10.0.0.2」がDNSサーバーとして設定されている。
つまり、EC2は名前解決の際に一番最初にRoute53 Resolverへと問い合わせる。
Route53 Resolverはドメインが内部リソースの場合はその場で返し、外部リソースの場合はさらに別のDNSへと問い合わせを行う。

もちろん、このファイルを消したり、書き換えると終わるので注意。


### Route53 Resolverへの通信はセキュリティグループで制御不可能

Route53 Resolverとの通信には「TCP,UDP/53」の穴あけは不要。

一つ実験をしてみる。
EC2に次のセキュリティグループをアタッチして名前解決のコマンドを使用してみる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/53793ba9-55b3-bd80-7128-b5fd4b034fe9.png)
↑アウトバウンドの53番は穴あけしてないので本来は名前解決は失敗するのが普通の感覚




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/28c15140-6973-9729-0630-2a82ecb0de90.png)
↑名前解決できてしまった...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3801383/ffc1691f-dc43-2a61-ac2e-af2a79b74ab5.png)
↑さらに上位のDNSサーバーにも届いている



## AWSが所有するIPアドレスからの通信
重要度⭐️⭐️⭐️⭐️
これもセキュリティグループで制御できない(全部かどうかはわからない)

自分が出会ったケースだと、VPCフローログで送信元IPアドレスを確認している時にセキュリティグループで弾いているはずのIPアドレスからの通信がACCEPTになっているケースがあった
正直ログの中にあると怪しい通信なのか？AWSの通信なのか？を判断するのが難しい
あらかじめクエリなどでAWSの通信IPアドレスを弾くなどしておくのもありだろう

下記サイトがAWSのIPアドレスである。
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/aws-ip-ranges.html

Json形式なのでスクレイピングで取得して加工も容易



## VPCピアリングのCIDR重複

:::note
VPCピアリングとは？
別のVPC同士がエンドポイント経由で通信できるようになるサービス

アカウントやリージョンを跨いだVPCでもピアリング可能
:::

VPCピアリングで接続するVPCのCIDRは重複が許されない

VPC1 : 10.0.1.0/24
VPC2 : 10.0.0.0/16
上のような場合だとNG




## VPCフローログは作成後設定変更できない

よくあるのがカスタムログを追加したい場合やログ出力先を変えたいケース
しかし、作り直すしかない

作る前にしっかりと検討が大事
UseStateとuseReducerの違い

**useState と useReducer の違い**

React で状態管理を行う際に使われる useState と useReducer について,残しておきたく記事にしました。

# 1. useState とは？

useState は、React のコンポーネント内で状態を管理するためのフックです。シンプルな状態管理に適しており、以下のように使います。

```Typescript
import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Count: {count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}
```

**useState の特徴**

シンプルな状態管理向け

直接 setState で値を更新

関数コンポーネントのローカルな状態管理に適している

# 2. useReducer とは？

useReducer は、useState よりも複雑な状態管理を行うのに適したフックです。状態の更新ロジックを reducer 関数として定義し、それに基づいて状態を管理します。

```Typescript
import { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </div>
  );
}
```

**useReducer の特徴**

状態の更新ロジックを reducer 関数に分離

dispatch を使って状態を変更

複雑な状態管理（多くの state の組み合わせや、前の状態を考慮する場合）に向いている

# 3. どちらを使うべき？

**選択基準**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3823687/5862ab03-92b6-6371-86bb-73c09ba050e0.png)



# 4. まとめ

**シンプルな状態管理（カウンターなど） → useState**

**複数の状態が関係する、複雑なロジックがある場合 → useReducer**
シリアル接続(ポートを指定)が上手くできなくなった場合の対処法(例:ラズベリーパイPico W)

OpenPLC等でポート接続を久しぶりに行う際、以前使用したポートで
シリアル接続が出来ない場合がある。
本例だと以前はCOM8を使用していたが、今回そのポートを使用したらエラーが出た。デバイスマネージャを見たところ以前使用していたCOM8が消えていた。

(過去)
![11111111111.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827595/8cad1889-fa93-8f6d-108f-7d521e9c4d8d.png)


(現在)
![aaaaa.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827595/0ebefac2-0227-9eb3-0a15-33ba514d767d.png)

そのため、今回表示されているCOM3で改めて接続したら問題なく
ポート通信を行えた。
しかし、新しく表示されたポートを使用しても接続が出来ずエラーが出る場合がある。
このような場合は一度、ポートを接続するために使用しているソフト
(今回だとOpenPlC)をアンインストールして入れ直した上で
再度、新しく表示されたポートで接続すると問題なく接続出来る。


![111111111111111111.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827595/f9537463-673c-bbbf-8c51-539ca898bfae.png)
【Kotlin】厳密等価演算子（Identity Operator）の不思議な挙動について

Kotlinの学習で`===`を使用した際に、予想外の挙動に遭遇したのでメモ。

以下のように簡単な変数に同じ値を代入し比較したところ、両者は異なるメモリアドレスが割り当てられ厳密等価は`false`になるかと思いきや。。。

```main.kt
fun main() {
    val s = "str"
    val t = "str"
    println(s===t)  // true
}
```
結果はなんと`true`となった。

じゃあ文字列をいじったらどうなんだと思い、次のようにすると。。。
```main.kt
fun main() {
    val s = x + y
    val t = x + y
    println(s === y)  // false
    println("--------")

    val a = "abc".substring(0, 2)
    val b = "abc".substring(0, 2)
    println(a === b)  // false
    println("--------")
}
```
期待通りの結果に。

GhatGPTに尋ねたところ、「インターン化」と呼ばれる最適化が行われているとのこと。

恐らく簡単な処理だからコンパイラが同じものとして扱っているものと考えられる。
が、状況次第では期待と異なる挙動になる可能性があるので注意が必要そう。

なお開発環境は次の通り
【OS】Mac
【エディタ】Intellij

以上。
CursorのCtrl+KをVSCodeに戻す

# CursorのCtrl+KをVSCodeに戻す

## ショートカットの概略

基本的には適切なイストールを行っていれば、Cursorのショートカットは、VSCodeのショートカットも引き継いでいます。ただ、`Ctrl+K`が目玉のEditor上で起動するCursorのチャット画面となります。もともと`Ctrl+K` で実行していたコマンドは、`Ctrl+M`で実行可能です。

頻繁に使いそうなショートカットは、記事に上がっていました。[Cursor・VSCodeショートカット集（随時追加）](https://zenn.dev/motonosuke/articles/548beaa830287c?utm_source=chatgpt.com)

## ショートカットの設定変更

先程記載した通り、`Ctrl+M`を利用すれば`Ctrl+K`関連のショートカットはこれまで通り利用できます。
ですが、VSCodeの設定通り、`Ctrl+K`を利用したい場合は、以下の設定を変更することで、一括で、`Ctrl+M` → `Ctrl+K`に戻すことができます。

### `Ctrl+M` → `Ctrl+K`に戻す

1. `Ctrl+Shift+P`に"Keyboard Shortcuts"を入力してショートカット設定を開く。
2. ショートカットメニューの検索窓に`workbench.action.keychord.leader` を入力する。
3. 見つかったショートカットのキーバインドを欄を選択して`Ctrl+K` を設定する。
![ショーットカット設定](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3840737/09a5f5dc-8756-aa48-305f-5aaf5838627f.png)
:::note Cursorのチャット機能の変更
Ctrl+K以外にもどのようなコマンドがあるか調べておきたい場合は、設定画面から検索を行いコマンドを確認しておいてください。

1. `Ctrl+Shift+P`に"Keyboard Shortcuts"を入力してショートカット設定を開く。
2. ショートカットメニューの検索窓に`Cursor` を入力する。
:::

### Cursor Open Chatの設定を変更

1. `Ctrl+Shift+P`に"Keyboard Shortcuts"を入力してショートカット設定を開く。
2. ショートカットメニューの検索窓に`Cursor Open Chat` を入力する。
3. 見つかったショートカットのキーバインドを欄を選択して好みのショートカットを設定する。

### 参考にした情報など

[公式のDiscussion](https://forum.cursor.com/t/cmd-k-vs-cmd-r-keyboard-shortcuts-default/1172?utm_source=chatgpt.com) でやり取りがあり、参考になるjsonファイルの内容についても記載されています。

ちなみに、よく使うCtrl+Kにショーットカットを割り当てたことを批判されていました。（私も思います笑）
シェイプキー　

・あとからシェイプキーのベースを変えたいとき
新規で修正用のシェイプキーを追加　→　そこで調整したい個所を調整　→　ベースのシェイプキーに戻って、修正を反映したい部分を選択　→　頂点タブ→「シェイプキーからブレンド」　→　度のシェイプから統合するか聞かれるので修正用のシェイプキーを選択して決定。　修正用シェイプキーは消しちゃっていい。



・
Django4 #1

"Django4 Webアプリ開発実装ハンドブック" という参考書で Django の勉強をしています．
復習を兼ねて参考書の内容を要約してみようと思い，この記事を書きました．
勉強した内容を何回かに分けて書いていこうと思います．

:::note warn
実行環境は Mac OS です．
:::


↓参考書はこちらです．各ヘッダに対応する章を記述してあります．

https://www.shuwasystem.co.jp/book/9784798067179.html

# 仮想環境の立ち上げ(2章)
まずは， Django をインストールします．
※ Python のインストール方法は省略します．

Mac OS では pip コマンドで Python のモジュールをインストールすることができません．
apt コマンドで実行するように指示されますが，私の環境では apt コマンドで Django をインストールすることができなかったため，仮想環境内でプログラムを実行することにしました．
仮想環境は， Python のバージョン管理やモジュール管理が容易にできるというメリットがあります．

```shell
# test という名前の仮想環境を作成
$> mkdir test
$> python3 -m venv test
# 仮想環境の立ち上げ
$> source test/bin/activate

# Django のインストール
$> pip install --upgrade pip
$> pip install Django

# 仮想環境の終了
$> deactivate
```

これ以降のプログラムはこの仮想環境内で実行します．

# プロジェクトの作成(3章)

```shell
# プロジェクトの作成(3章)
$> django-admin startproject [project name]

# ファイル構成
$> tree
.
└── [directory name]
    ├── [project name]
    │   ├── __init__.py
    │   ├── asgi.py
    │   ├── settings.py
    │   ├── urls.py
    │   └── wsgi.py
    └── manage.py

3 directories, 6 files
```

# Web サーバの起動

プロジェクトフォルダの直下にある manage.py には， Web アプリの開発に必要なコマンドが収録されています．Web サーバの立ち上げも manage.py のコマンドを使って行うことができます．

```shell
$> python3 manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
February 02, 2025 - 08:19:26
Django version 5.1.5, using settings 'blogproject.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
```

ブラウザ上で http://127.0.0.1:8000/ にアクセスをすると Django が用意したトップページが表示されます．

manage.py に収録されているコマンドをいくつか紹介します．

### startapp

Web アプリ用のソースファイルを生成します．
```shell
python3 manage.py startapp [アプリケーション名]
```

ファイル構造はこのようになっています．
これらのモジュールを編集することで， Web アプリ開発していきます．
```shell
webApp
├── __init__.py
├── admin.py
├── apps.py
├── migrations
│   └── __init__.py
├── models.py
├── tests.py
└── views.py
```

### makemigration

Django には，Python のソースファイルから直接データベースを操作するための仕組みとして”マイグレーション”という仕組みが用意されています．

startapp コマンドで作成された migrations フォルダ内の \_\_init\_\_.py には，データベースとテーブルを作成するためのプログラムを記述していきます．
makemigration コマンドを実行することで編集した内容を反映したデータベースを生成することができます．

### createsuperuser

プロジェクトの管理者を作成します．
「Django管理サイト」を利用して，データベースを直接操作できます．

```shell
python3 manage.py createsuperuser
```

ユーザ名，メールアドレス，パスワードを入力すると，管理者が作成されます．

# おわりに

今回は，3章までの内容をまとめました．
次回は 4章，実際に Web アプリを作成していきます．

# 備考
不備などございましたら，教えていただけると幸いです．
Svg ファイルのバリデーション

## はじめに

本記事では、SVG ファイルに限定して、アップロード前に XSS のリスクがないかを検証し、危険なコンテンツが含まれていればアップロードを拒否する仕組みについて、私が実装した方法を紹介します。

:::note info
フロントエンドに限定して話して行きます
:::

## アップロードファイルのバリデーション

### MIME タイプの信頼性について

File API の `file.type` プロパティで MIME タイプを取得できますが、これはユーザー側で容易に偽装できるため、セキュリティの観点からは信用できません。  

`file.type` プロパティはアップロードされたファイルの拡張子から MIME タイプを推測しています。本当の MIME タイプを知るには [マジックナンバー (フォーマット識別子)](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88%E8%AD%98%E5%88%A5%E5%AD%90)) を見る必要があります。

そこで、実際のファイルバイナリから MIME タイプを判定できる [file-type](https://github.com/sindresorhus/file-type) ライブラリを利用しました。

### SVG 判定について

`file-type` では SVG ファイルの判定ができないため、文字列として読み込んだ内容が SVG であるかどうかは [is-svg](https://github.com/sindresorhus/is-svg) を利用してチェックします。

## XSS 攻撃の検出とサニタイズ

SVG ファイル内で XSS 攻撃を引き起こす典型的な手法は、`<script>` タグの利用です。  
しかし、あらゆる攻撃パターンを網羅するのは困難なため、ここでは既存のサニタイズライブラリ [DOMPurify](https://github.com/cure53/DOMPurify) の機能を活用します。

DOMPurify はサニタイズ処理時に、削除した要素や属性を `removed` プロパティに格納します。  
これを利用し、「削除対象に危険な要素（例: `<script>`）や属性（例: `onclick`、`onerror`、`onload`）が含まれているか」をチェックすることで、問題のある SVG のアップロードをブロックします。

Dompurify の https://github.com/cure53/DOMPurify/blob/main/src/tags.ts の svgDisallowed に脆弱性を引き起こす tag を配列として保持されてあったので、これをありがたく使わせていただきました。

## 実装コード例

以下は、上記の流れを実現した実装例です。

```js
const validate = async (file: File) => {
  // 1. ファイルの MIME タイプを判定する
  const fileType = await fileTypeFromBlob(file)
  if (!fileType) return file

  // 2. ファイル内容をテキストとして取得し、SVG かどうかチェックする
  const text = await file.text()
  if (!isSvg(text)) return file

  // 3. DOMPurify を使ってサニタイズ処理を実施
  const clean = DOMPurify.sanitize(text)
  const removedElms: string[] = []
  const removedAttrs: string[] = []

  // DOMPurify によって削除された要素や属性を収集する
  DOMPurify.removed.forEach((item) => {
    if ('element' in item) removedElms.push(item.element.nodeName)
    if ('attribute' in item && item.attribute)
      removedAttrs.push(item.attribute.name)
  })

  // 4. 危険と判断するタグおよび属性の一覧を定義する
  const tagVuls = ['script'] // 例: SVG 内で許可されないタグ
  const attrVuls = ['onclick', 'onerror', 'onload'] // 例: SVG 内で許可されない属性

  // 5. 削除された要素・属性に危険なものが含まれているかチェックする
  const isVul =
    removedElms.some((elm) => tagVuls.includes(elm)) ||
    removedAttrs.some((attr) => attrVuls.includes(attr))

  if (isVul) {
    throw Error('SVG エラー')
  }

  // 6. サニタイズ済みの内容で新たな File オブジェクトを生成して返却する
  return new File([clean], file.name, { type: fileType.mime })
}
```

### コード解説

1. **MIME タイプの判定**  
   `fileTypeFromBlob` により、実際のバイナリから MIME タイプを判定します。判定できなかった場合は、そのままファイルを返却します。

2. **SVG 判定**  
   `file.text()` でファイル内容をテキストとして取得し、`isSvg` で SVG であるかどうかをチェックします。SVG でなければ、そのままファイルを返します。

3. **サニタイズ処理**  
   DOMPurify の `sanitize` 関数を利用して、テキスト中の潜在的な危険なコードを除去します。

4. **削除対象の収集**  
   サニタイズの過程で DOMPurify が削除した要素や属性を `removed` プロパティから収集し、別途リストに格納します。

5. **危険な要素のチェック**  
   収集した削除対象の中に、予め定義した危険なタグ（例: `<script>`）や属性（例: `onclick` など）が含まれている場合、エラーをスローしてアップロードを拒否します。

6. **新しいファイルオブジェクトの生成**  
   サニタイズ済みの内容で新たな File オブジェクトを作成し、問題がなければ返却します。

## まとめ
この実装により、アップロード前に XSS 攻撃のリスクを検出し、安全なファイルアップロード機能を実現できます。  

本記事が同様の課題に取り組む方々の参考になれば幸いです。
【シリーズすごいぞiQ-F】「いわゆる構造化プログラミング」への道　2回目の記事

## つづきを始める前に
[「いわゆる構造化プログラミング」への道　最初の記事](https://qiita.com/fujiteruo/items/031c8bf649d574df0bba)
からのつづきになります。

GX WORKS2では
「よし、これから構造化プログラミングをするぞ」
と心構えをさせられたけど
GX WORK3では構造化プログラミングなんてマニュアルでは一言も記載が無い。

じゃあ、どうしよう。
という話です。

「いわゆる構造化プログラミング」というのは、IEC61131-3に準拠した形でGX WORKS3行えるプログラム手法を指しているつもりです。
IEC61131-3はプログラムの標準化についての提案はしていますが、必ずプログラムを構造化しなさいというものではありません。
IEC61131-3を活用するとプログラムを構造化できるというスタンスに読み取っています。

## 構造化というよりは、まずは部品化
構造化プログラムというのはBASICでパソコンプログラムを始めた頃に初めて耳にした言葉ですが、元々はGOTO命令を使わずにGOSUBなどでサブルーチンを呼び出す形のプログラミングを意味していました。
シーケンス命令にも「構造化命令」としてその手の命令が用意されています。

「いわゆる構造化プログラミング」で部品化手法として代表的なファンクションブロック（FB）はインスタンスを生成するという部分ではオブジェクト指向に近いのですが、継承などの重要な概念は導入されていないので（GX WORKS3では）オブジェクト指向とも呼べません。
（しかし、解説書の方では機能は足りていないが「FBはオブジェクト指向」と記述されていました）

CHAT GPTと相談して
「中途半端なオブジェクト指向」とか色々な呼び方を評価してもらいましたが、
「部品化」というのが実態をよく表していて適切とのお褒めをいただきました。

## 制御盤設計ではすでに普及している部品構築化設計
制御盤を設計する際、特定の機能を組み込む際にはそういう機能を持つ部品を組み込むのが普通です。
・フロートレスレベルスイッチとか
・調節計とか
・週間タイマーとか
・比較変換器とか
どちらかと言えばマグネットやリレーやタイマーで設計者が構成し実装することが多いと思われるスターデルタ回路もスターデルタユニットとして販売されています。

これと同じように、そういった何らかの機能をFB化して貼り付けてプログラミングするというのがPLCでの「いわゆる構造化プログラミング」の実際であると考えています。

こういった部品には動作モードを切り替えるための入力などが設けられているため、こういった仕様が自作FB部品を作る上でのヒントになりました。

## 「よく使う回路をFB化する」のでは無い
そもそも再利用性が低いというのが問題視されているPLCプログラムなので定型の処理以外は似ているんだけど微妙に違う回路の集合になっているのでは無いでしょうか。

なので、「よく使う回路をそのままFB化」というのは演算や信号処理など決まり切った流れの処理に限られて来ます。

私の分野では冷凍、空調制御などが主なので、有接点シーケンスで制御盤を組む場合は下記のような部品を盤内に組み込む事になります。
- サーモスタット
- デフロストタイマー
- 1時間以上遅延のオンディレイタイマー
- 送風機間欠タイマー
- 空気状態計算機
- 温度警報発生器（調節計機能の一部）
- ハイセレクタ

このような実際にも部品として存在するものからFB化してFBというもののイメージを掴みました。

その他のイメージとして、空調機相手に制御する場合は空調機側が外部入力と外部出力を持っていて、それとPLCで連携を取るプログラムを今まで組んできたわけです。
なので、送風機制御などのFBを組むときは空調機をまねて、送風機制御器にはどのような入力と出力が必要か検討しました。

データの構造化の問題もクリアしないといけないのですが、入出力を持つ装置をFB化する所まで見えてくれば、三菱の冷凍機制御で言えばクールマルチコントローラとかそういった役割を持つ比較的大規模なものもFB化出来るようになります。

## ファンクションブロックFBとファンクションFUNの違い
- ファンクションブロック（FB)
    - タイマーやカウンターなど、内部で値を記憶する処理が可能
    - したがってFUNとの比較として言えば、入力に対して同じ結果を返すとは限らない
- ファンクション（FUN)
    - 内部で値を記憶できない
    - 入力に対して必ず同じ結果を返す

GX WORKS3以外の場合はファンクションの戻り値は1つだけというのが多いのですが、GX WORKS3は複数の戻り値を設定できます。
したがって、ファンクションで使用出来ない変数の型を使用しなければ、内部で値を記録する必要が無ければファンクションブロックからファンクションへの移植も簡単です。

## FBをプログラム中に並べる＝盤図に部品を並べて書く
FBをラダープログラム中で使用するのは、まるで盤図に部品を並べて書いているのと同じ感覚です。
まさに「部品を貼り付けるだけの簡単プログラミング」です。
それでいてサブルーチン型のFBであればサブルーチンとしてプログラムが呼び出されるのでロジックに関しては回数分のプログラムステップを消費しません。
（引数引き渡しと呼び出し処理にいくらかステップを消費します）

### 同様の処理を複数回繰り返す場合を比較する

- ラダーベタ書きで処理数分の回路を書いた場合
- 1つのロジックでデバイスをインデックスで切り替えて必要回数処理した場合
- サブルーチン型のファンクションブロックを使用した場合
- ファンクションを使用した場合（内部に値を保持する処理は不可）

|項目|ラダーベタ書き|ラダーインデックス|FB  |FUN  |
|---|---|---|---|---|
|ステップ数|大  |小  |中  |中  |
|データメモリ|回数分  |組み方次第  |回数分  |1回分  |
|内部モニタ  |可能  |不可  |可能  |不可  |
|用途範囲  |広い  |狭い  |広い  |狭い  |
|回路変更  |大変  |楽？  |楽  |楽  |

※ラダーインデックスの回路変更はインデックスに絡む変更は難しい場合があるので？を追記しています

引数引き渡しと呼び出し処理にステップ数を消費することに目をつぶれるならモニタも出来るし回路変更も楽というFBの優位性が分かると思います。

## なかやすみ
私だけかも知れませんが、「よく使う回路」と思っている間は、ホントFBって何を作って良いか思い浮かばなかったんですよ。

下手に作ろうとしても、いきなり大がかりな処理をFB化しようとするものだからFBの中でグローバルラベル配列を使って、添え字部分を引数で引き渡して切り替えるとかトンチンカンなFBを組んでみたりしてました。

最近見た海外のPLC OPENの資料では発酵機を例に挙げて説明してあったのでFB化する部分についても非常に分かりやすかったし、私と考え方が近かったです。

次はデータの構造化について書いてみようと思います。


## 過去記事一覧
+ [過去記事一覧](https://qiita.com/fujiteruo/items/af2459d320e8109963db)
Power Automateのスコープに「変数を初期化する」を追加できる？いや、できないが使いどころはある。

## いまだクラシックモードでしかクラウドフローを使えない民たちへ
はい。私がその民です。どうしても新しいフローデザイナーに慣れず。最初にクラッシック画面い切り替えてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/ed57bfc7-0cb3-ea38-271e-25f5b5ec7fec.png)

こっちのほうが使いやすいと思ってしまうのですけれど、少し残念なのが、スコープの中に、「変数を初期化する」アクションを含めることができないこと。これは残念。

こちらが新しいデザイナーの画面。
「変数を初期化する」アクションをスコープの中に入れることができます。素晴らしい！
とおもったのも束の間。いざこの状態で保存しようとしたら、エラーで叱られてしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/ae8daf01-6530-d23f-e098-a5169040660a.png)

```
The variable action '変数を初期化する' of type 'InitializeVariable' cannot be nested in an action of type 'スコープ'.
```

## 所詮短い夢出あったか……（グローバル艦長風）
保存ができないのではせっかくスコープの中に入れることができても意味がないのだけれど、使いどころを考えました。
それが、ブラウザーどおしのアクションのコピー。

色々な処理をとりあえずスコープの中にまとめて、スコープごとコピーします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/f28b611e-c61c-c83e-6a19-e52805ea17a0.png)

つぎにコピー先のフローを開いて、貼り付けます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/8ccc9787-5f57-42a6-1f38-60c58fd4db0e.png)

ちゃんとコピーできました。
ただし、このままだと保存ができないので、「変数を初期化する」のアクションだけは、スコープの外に出してやります。バッチリ保存もできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285141/9ded65a0-9929-ca63-e3b2-139328f7b174.png)

ちなみに、保存したあとでクラシックモードに戻すこともできました。
ブラウザをまたいだアクションのコピーは、新しいデザイナーのほうが安定しているようです。

クラウドフローをコピーするには、フローをエクスポートすれば良いのだけれど、いちどソリューションに入れてしまうと、同じソリューションに入っている他のフローまでエクスポートしたくなかったり。

ブラウザでスコープにまとめてコピーする方法は、単純だけれど結構使えるのでは？良いクラウドフローライフを！！

## こんな人が書いてます。
職場でPower BIを使ったり困っている人のサポートをしたりしてます。[Qiitaの記事](https://qiita.com/daddydaddy)　や　[個人的なブログ](https://mocabrown.com/blog/powerautomate/)　ではPower AutomateクラウドフローについてのTIPSのようなものを作ったりしているので、良かったら読んだり「いいね！」していただけると励みになります。
「OpenRouter × Cursor × DeepSeek R1」で自動開発しました！ 🚀

![S__2859060.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/beeddb5f-69d9-6dd8-7442-a4f813056174.jpeg)

![スクリーンショット 2025-02-02 16.48.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/9665d4fc-5aee-6e51-dd96-b75c1d876f19.png)

![スクリーンショット 2025-02-02 16.48.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478895/d4031c6d-6835-117d-3ff1-3d7b2e57c445.png)


## やったこと
### ① OpenRouterでAPIキーを作成 🔑
→ OpenRouter にログインして、「Keys」 からAPIキーを発行！

### ② Cursorをインストール＆起動 💻
→ Cursor をダウンロードしてインストール、起動！

### ③ APIキーをCursorに設定 ⚙️
→ 「Settings」 > 「Providers」 で 「OpenRouter」 を選択し、APIキーを貼り付け！

### ④ DeepSeek R1を設定 🎯
→ 「Model」 に deepseek-r1 を手入力！

### ⑤ クレジットが足りなかったので購入💰
→ OpenRouterのCreditsページ で$10分購入！（手数料込み$10.9）

### ⑥ CursorでAIコーディング開始！🚀
→ DeepSeek R1を使って、コード補完＆AI支援を試した！

### 最終的にこうなった！ 🎉
#### 🔹リクエスト内容
「React.jsとHTML、CSSを使ってスマホ用の予約Webアプリを作成（最低限のページ数）」

#### 🔹モデルの利用状況
Tokens: 36.9k / 1.3k
Context: 18.0k (112%)
API Cost: $0.0327
【mac備忘録】仮想環境作成の際にシンボリックリンクとやらに助けられた話

（いったん簡単に書いておきます、後日もうちょっと詳細書くかも）

## 大悩み：デスクトップアプリでPythonを呼び出せない。

アプリから仮想環境を作成する際、Python3.9を必要としていたのですが、なぜかPythonが呼び出されない。(Python3.9 command not foundのエラーメッセージ）

ターミナルではPython3.9をダウンロードできているし、Pathもおかしくないはず。
```.PATH
/usr/local/bin/python3.9 
```


## 原因：パスがうまく設定できておらず、Pythonコマンドを見つけらていない

なんとなくこの原因まではわかっているのですが、じゃあ解決策はなんやねんと。

```試行：~/.zshrcを編集
echo 'export PATH="/opt/homebrew/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
```
`/usr/local/bin` は通常、コマンドの実行ファイルが保存されるディレクトリのため、ここにリンクを作成することが重要です。
じゃあこのパスをシェル設定に追加するのかな？と思い、上をターミナルで実行するもエラーは変わらず。


## 解決：シンボリックリンクを作成する

`/opt/homebrew/bin/python3.9` を python3.9 として認識させるため、シンボリックリンクを作成します。

``` .シンボリックリンクの作成
sudo ln -s /opt/homebrew/bin/python3.9 /usr/local/bin/python3.9
```

これにより python3.9 コマンドがシステム全体で使えるようになるとのことで、実行すると見事起動。


### シンボリックリンクってなんやねん。


シンボリックリンクは、 **「あるファイルやディレクトリを別の場所から参照できるようにする、特別な種類のファイル」** です。
通常のファイルとは異なり、シンボリックリンクは実際のファイルのコピーではなく、別のファイルやディレクトリへの参照を作成します。
ショートカットみたいなもんですね。

ターミナルでは、`ln -s`で、シンボリックリンクを作成できます。

上記の悩みはPython3.9のコマンドを認識するため、
`/opt/homebrew/bin/python3.9` という実際のファイルを、`/usr/local/bin/python3.9` という場所にシンボリックリンクとして作成するものです。これにより、システム内で python3.9 コマンドを入力すると、実際には `/opt/homebrew/bin/python3.9` を指し示すことになります。


### シンボリックリンクの特徴

- 別名：シンボリックリンクは、あるファイルやディレクトリに対して「別名」を与えるような感じ
- リンク元とリンク先：シンボリックリンクは元のファイルを指し示す「ポインタ」のような役割を果たす。リンク元（シンボリックリンク）は、リンク先（実際のファイル）へのパスを記録します。
- 動的な参照：シンボリックリンクは元のファイルやディレクトリが更新されても、それに追従します。つまり、リンク先が更新されるとシンボリックリンクもその更新を反映します。

### シンボリックリンクを使う理由

- パスを短縮：長いパスを簡単にアクセスできるようにするため。
- 一元管理：複数の場所で同じファイルを使いたい場合、リンクを作成するだけで管理が楽になります。
別の場所からアクセス：異なるディレクトリにあるファイルを、別の場所から簡単に利用することができます。
Rails × Tailwind CSS 完全ガイド｜最短4ステップで導入＆実装方法を解説

## 背景
個人プロジェクト（Ruby, Ruby on Rails）でtailwindを使った実装をすることになったため、その時の導入方法を記録として残しておきます。

## tailwindとは
Tailwind CSSは、ユーティリティファーストのCSS（カスケーディングスタイルシート）フレームワークです。ウェブページの構築やデザインで定義済みのクラスの形でHTML内にCSSを記述できます。
似たようなものですと、Bootstrapなどがあります。

> ※ユーティリティファーストのCSSとは、マークアップ（HTML）内の、定義済み機能を備えたクラスを指します。つまり、あらかじめ定義されたスタイルを持つクラスを記述するだけで、そのスタイルを要素に適用できます。

## 簡単な使い方を紹介
通常のCSSを使って実装する方法、Tailwind CSSでユーティリティクラスを使用して実装する方法は、それぞれ以下のようになります。
```
#HTML
<button class="btn">クリック</button>

#CSS
.btn {
  background-color: #000;
  color: #fff;
  padding: 8px;
  border: none;
  border-radius: 4px;
}
```

```
#Tailwind
<button class="bg-black text-white p-2 rounded">クリック</button>
```

Tailwind CSSの場合、これだけで通常のCSSを使用した例と同じスタイルが設定できます。使用した各クラス名にはすでにスタイルが定義されているため、外部スタイルシートにスタイルを記述する必要はありません。

## Tailwind CSSのメリットとデメリット

### メリット
Tailwind CSSを使用することで、以下のような利点があります。

- **開発プロセスが高速化できる**  
  → ユーティリティクラスを使うことで、CSSの定義不要で即座にスタイリング可能。  
- ユーティリティとコンポーネントが簡単にカスタマイズ可能 
  → `tailwind.config.js` でデザインを柔軟に変更できる。  
- **本番用のファイルサイズが常に小さい**  
  → 未使用のCSSを削除（PurgeCSS)するため、軽量なCSSを生成可能。  
- **CSSの知識があれば、簡単に習得可能**  
  → クラスを組み合わせるだけでデザインできるので、CSSに慣れていればすぐ使える。  
- **ドキュメントが充実**  
  → [公式ドキュメント](https://tailwindcss.com/docs) が詳しく、情報が豊富。  

### デメリット
一方で、Tailwind CSSには以下の欠点もあります。

- **大規模なプロジェクトではマークアップが乱雑に見える**  
  → クラスが長くなりがちで、可読性が低下することがある。  
- **CSSを十分に理解していないと、習得が困難**  
  → コンポーネント指向のCSSと異なり、CSSの概念を理解していないと学習コストが高い。  
- **すべてを1から構築しなければならない**
  → Tailwind CSSはデフォルトのCSSスタイルを削除するため、ボタンやフォームなども最初からデザインする必要がある。  

## 導入手順
導入手順は至って簡単です。

### 1. まず、Tailwind CSS を Rails に追加します。
```
bundle add tailwindcss-rails
rails tailwindcss:install
```
#### 実行後に自動で設定されるもの

・app/assets/tailwind/application.css （CSS 読み込み用）
・Procfile.devの設定を追加 （開発環境で rails server + tailwindcss:watch を実行）
```
web: bin/rails server -p 3000
css: npm run build:css -- --watch
css: bin/rails tailwindcss:watch <= 追加
```
※私はすでに別途bin/devの設定をしていましたが、下記のコードが追加されていました。
・bin/dev （開発環境の起動スクリプ設定）
```
# Default to port 3000 if not specified
export PORT="${PORT:-3000}"

# Let the debug gem allow remote connections,
# but avoid loading until debugger is called
export RUBY_DEBUG_OPEN="true"
export RUBY_DEBUG_LAZY="true"
```
### 2. Tailwind をレイアウトに適用
```
doctype html
html
  head
    title
      | タイトル
    meta[name="viewport" content="width=device-width,initial-scale=1"]
    = csrf_meta_tags
    = csp_meta_tag
    = stylesheet_link_tag "tailwind", "data-turbo-track": "reload"　<= 追加
    = stylesheet_link_tag "home", "data-turbo-track": "reload"
    = javascript_importmap_tags
  body
```

### 3. サーバー立ち上げ
開発環境で Tailwind CSS を監視しながら Rails を起動する。
```
bin/dev
```

### 4. Tailwind を試してみる
Tailwind のクラスを適用できるか確認。
```
p.mt-2.sm:mt-3.text-4xl.sm:text-6xl.font-bold.text-blue-600
  | Hello world!
```

上記の４ステップで簡単に導入が可能です！

## まとめ
Tailwind CSS は、クラスを直接 HTML に適用することで、素早く柔軟にデザインできる CSS フレームワークです。本記事では、rails tailwindcss:install を実行し、stylesheet_link_tag を追加、bin/dev でサーバーを起動するだけの 4ステップで簡単に導入できる方法 を紹介しています。軽量でカスタマイズ性も高く、Rails プロジェクトにスムーズに組み込めるので、ぜひ試してみてください！
pytrendでトレンドデータを取得する

## はじめに
Google Trends の非公式APIであるpytrends を使ってみました
https://github.com/GeneralMills/pytrends/blob/master/README.md

## install
```
pip install pytrends
```

## 実際に取得してみる
2つのwordに対してトレンドデータを取得してみます
最近（2025年1月末）話題になった中国AIベンチャーDeepSeekとToyotaのトレンドデータを比較します
kw_list[]でワードを、timeframeで期間を指定しています
```Python
from pytrends.request import TrendReq
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt

pytrend = TrendReq()
pytrend.build_payload(kw_list=['DeepSeek', 'Toyota'], timeframe=['2025-01-01 2025-02-01', '2025-01-01 2025-02-01'])
interest_over_time_df = pytrend.interest_over_time()

interest_over_time_df.plot()
plt.show()
```
### 実行結果
DeepSeekが急速に話題になったことが確認できます
![Figure_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2087704/def65a3f-32f2-c46f-42fe-cf6249e20f1d.png)

## まとめ
pytrends を使用してトレンドを時系列データとして表示してみました
クライアントサイドLLM:Geminiのスモールモデル「Nano」


## はじめに
- GeminiはGoogleが開発した画像・音声・動画・テキストを統合的に理解する高性能なマルチモーダルモデルである
- Transformerデコーダーをベースに改良
- Ultra/Pro/Nanoの3サイズで対応
     - Ultra：最も高度な推論タスク向け
     - Pro：コスト効率と低レイテンシーを重視
     - Nano：デバイス上での実行に最適化(1.8B/3.25Bパラメータ)

Geminiのスモールモデル「Nano」は、バイス上での実行に特化したモデルとして提供されます。

https://arxiv.org/abs/2312.11805

# Geminiのスモールモデル「Nano」の詳細

### 1. 概要
- デバイス上での実行に特化した最も効率的なモデル
- 2つのバリエーション:
  - Nano-1: 1.8Bパラメータ (低メモリデバイス向け)
  - Nano-2: 3.25Bパラメータ (高メモリデバイス向け)
- より大きなGeminiモデルからの蒸留学習で構築

### 2. 性能特性
- 要約・読解タスクで特に高いパフォーマンス
- Proモデルと比較した相対性能:
  - BoolQ: Nano-1で71.6%(0.81倍)、Nano-2で79.3%(0.90倍)
  - TydiQA: Nano-1で68.9%(0.85倍)、Nano-2で74.2%(0.91倍)
  - NaturalQuestions: 
    - Retrieved: Nano-1で38.6%(0.69倍)、Nano-2で46.5%(0.83倍)
    - Closed-book: Nano-1で18.8%(0.43倍)、Nano-2で24.8%(0.56倍)

### 3. 高度なタスクでの性能
- 推論・コーディング・STEM分野での能力:
  - BIG-Bench-Hard: Nano-1で34.8%(0.47倍)、Nano-2で42.4%(0.58倍)
  - MBPP: Nano-1で20.0%(0.33倍)、Nano-2で27.2%(0.45倍)
  - MATH: Nano-1で13.5%(0.41倍)、Nano-2で22.8%(0.70倍)
  - MMLU: Nano-1で45.9%(0.64倍)、Nano-2で55.8%(0.78倍)

### 4. 技術的特徴
- 4ビット量子化による最適化
- 効率的な蒸留学習技術の活用
- デバイス上での実行に特化した最適化

### 5. 主な用途・展開
- オンデバイスでの要約生成、テキスト補完タスク
- リアルタイムの読解支援
- マルチモーダル・多言語処理

https://zenn.dev/aidemy/articles/9171dea7017097



----

# 参照資料

https://deepmind.google/technologies/gemini/nano/

https://developer.android.com/ai/gemini-nano?hl=ja
データエンジニアってなにができりゃいいのさ

# 本記事の趣旨
私は昨年末に転職をし、かねてより憧れていたデータエンジニアとなりました。
転職理由は、データから洞察を得て業務に活かすってかっこいいなという安易なものです。正直なところ、データ使って何かするんでしょ位の理解で転職しました。
今はETLの処理を実装したりしているのですが、そのうち提案活動とか、仕事つくりに行くところをやらないといけない雰囲気があるんですよね。
そんな状況なので、データエンジニアって結局なにができるようになればいいのさ。と一回ちゃんと考えてみて、私はこんなことできないといけないんだ（できるとは言ってない）を自分なりに書き留めておこうと思います。

# そもそもエンジニアって
エンジニアってなに。ってところから考えようかと思います。エンジニアって一昔前は「プログラムが書ける人」のイメージが強かったんですがどうですかね。
時がたつにつれてプログラムが書けるだけのエンジニアって需要が減ってきている気がします。
色々なサービスが出現してきたことで、いくらでもカスタマイズができてしまうが故に、どのサービスをどの設定で使うか。みたいな検討が各クライアントで必ず必要になってくるんですよね。
この検討に納得感を持たせることが今のエンジニアの大変なところですよね。
つまり、先方の 業務課題レベル の話を理解して"適切な"サービスを組み合わせてシステムとして納める みたいな、一連の流れが今のエンジニアに求められていると思ってます。いわゆるコンサル的な動きですよね。
コンサルってよくお医者さんに例えられますよね。会社のお医者さん みたいな。
会社（患者）の課題（症状）を打合せやアンケート（問診や検査）で把握して、解決策（処置）を提示して、必要であればシステム（処方箋）を収める。
そう考えると、〇〇エンジニアと名の付く肩書って〇〇科と名の付くお医者さんと一緒なんじゃないかと思うんです。病院も科によって見れる症状が違うじゃないですか。なので、エンジニアも種類によって対応できる課題が違うんですよ。そうするとデータエンジニアってどんな課題を診れるんだと。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954605/51c97a03-9c05-f3ae-9776-5a7f5150868d.png)

# データエンジニア
### データエンジニアとは
「データエンジニア とは」で検索すると、仕事内容とか必要なスキルがたくさん出てきますよね。例えば[こんな感じ](https://cloudfit.co.jp/article/110#index_AhGIPyMk)。
>* 仕事内容
>    * データ活用の基盤作り
>    * データの加工や整理
>    * AIや機械学習のマネジメント
>* データエンジニアに求められるスキル
>    * 基本的なプログラミングスキル
>    * データベースに関するスキル
>    * インフラやクラウドに関する知識
>    * フレームワークに関する知識
>    * データ分析の知識

これって、お医者さんでいうところの「どの薬によって症状を治すか」にあたる部分だと思うのです。
この視点でデータエンジニアを考えることに何か違和感があります。お医者さんになりたい人って、風邪薬を処方したいから医者を目指すわけではないと思うんですよね。
多分、"風邪"みたいな症状を治したいからですよね。（患者だって症状を治したくて病院に来てると思います。薬を貰いたいわけではないはず。）
これと同じで、私もシステムを構築したいんじゃなくて、課題を解決できればいいなと思ってます。
どんな課題なら解決できます って言わないといけないと思ってます。
じゃあ、データエンジニアが解決できる課題ってどんなものでしょうか。

# データエンジニアが解決できる課題
クライアントがデータエンジニアに診てもらいたい課題って一言でいうと「情報をうまく活用できてない」ということです。（少なくとも、現職の今までの仕事見てみたらそうだった。）
最近になって、データ利活用 とか データドリブン みたいな言葉が一般的になってきたことによって、意思決定はデータに基づくいてないといけない という潮流からなのでしょう。
課題は抽象化するといたってシンプルです。
じゃあそれを具体化しようとしたときに問題がいろいろと起きてくるのです。
実際に業務の中で携わってきた課題としては、

> 現状は情報をエクセルで管理しているので、更新に丸一日かかる。
> しかもその情報の信ぴょう性もわからない。

とか、

> データを利用した意思決定が熟練者にしかできない。
> しかし、一般社員には何を判断材料にすればわからない。

とか。
そうすると、今の更新の運用はどうなっているのか や 熟練者がどういった情報をもとに意思決定しているのか といった課題の把握（問診）が必要になってくるんですよね。
ここにすごく労力と時間がかかるし、技術と経験が必要になってくると思うんですよね。
最後は解決につなげないといけないので、そのために聞かなきゃいけないことがあるはずなんですよ。それが今の私にはわからないし勉強していかないといけない。
つまりスキルを身につけないといけないんですが、やっぱり課題ベースに考えられるべきだと思います。スキルも課題を解決するための手段にすぎないということを頭にとどめておくべきだと思います。

# まとめ
私が将来データエンジニアとして活躍していくために、今考えていることを書き殴りました。
* 会社は抱えている課題を解決するためにお金を払っていること
* 課題を理解しない限り解決策の検討に進めないこと
    * 課題を理解するために聞いておかなきゃいけないことがあること ← ここがわからない

この意識を忘れずにいたいと思います。なんで勉強してるんだっけ？となったときに立ち返れるように。
Kotlin金額をカンマ区切りでフォーマットする方法

金額などで使用できる、カンマ区切りでフォーマットする方法です。

```strings.xml
    <string name="format">%,3d円</string>
```
```.kt
   getString(R.string.format, 10000)
```

簡単にカンマ区切りすることができました。
新卒２年目でIT資格１１個取得した話

# 新卒2年目でIT資格11個取得した話

2023年に新卒で電機メーカーに入社し、SEとして1年半勤務した後、SIerに転職。現在2年目までに合計11個のIT資格を取得しました。本記事では、取得した資格の一覧、取得時期、そして勉強法について紹介します。これから資格取得を目指す方の参考になれば幸いです。

## 取得した資格一覧と取得時期
![IMG_2626.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000068/0a6339e0-b36d-41ab-8dd0-9571790d512e.jpeg)
![IMG_2625.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000068/fd914065-f841-1a93-2ca2-28c6953106f7.jpeg)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4000068/ec4d0e90-42fe-4670-addd-64d430924cff.png)


| 資格名 | 取得時期 |
|--------|---------|
| 基本情報技術者試験 | 2023年8月 |
| AWS Certified Solutions Architect – Associate | 2023年12月 |
| AWS Certified SysOps Administrator – Associate | 2024年2月 |
| AWS Certified Developer – Associate | 2024年3月 |
| AWS Certified Solutions Architect – Professional | 2024年5月 |
| AWS Certified Security – Specialty | 2024年6月 |
| AWS Certified DevOps Engineer – Professional | 2024年8月 |
| 応用情報技術者試験 | 2024年10月 |
| GCP Professional Cloud Architect | 2024年12月 |
| HashiCorp Certified: Terraform Associate (003) | 2024年12月 |
| Certified Kubernetes Application Developer (CKAD) | 2025年3月 |

## どのように勉強したか

### 1. 目的を明確にする

資格取得の目的を明確にすることで、モチベーションを維持しやすくなります。
- **基本情報技術者・応用情報技術者試験** → ITの基礎知識を固めるため
- **AWS関連資格** → 新卒で入社した企業でAWSを使っており、実務で活用するため
- **GCP・Terraform・Kubernetes資格** → ２社目(現職)でGCPとTerraform、Kubernetesを使っており、実務で活用するため

### 2. スケジュールを立てる

1つの資格につき、**1〜2ヶ月**を目安に学習計画を立てました。
- 平日：仕事後に1〜2時間学習
- 休日：3〜5時間学習
- 試験1週間前：総復習と模試を解く

### 3. 効果的な勉強法

| 勉強法 | 内容 |
|--------|------|
| 公式ドキュメントの精読 | AWS/GCP・Kubernetesなどの公式ドキュメントを読み込む |
| 模擬試験・過去問を解く | AWS/GCPはCloud License、IPA資格は過去問道場、Kubernetesはkiller.sh。 |
| Udemy・YouTube動画学習 | 動画で理解を深め、知識の定着を図る |
| 実機演習（AWS/GCP環境構築） | 実際にクラウド環境を構築しながら学ぶ |
| ハンズオン学習 | Terraformの資格は実際にコードを書いて学習。Kubernetesの資格はコマンドをひたすら打ち、必要に応じてマニフェストファイルを編集して学習。 |

### 4. 試験直前の対策

- 直前1週間は、模擬試験を重点的に実施
- 間違えた問題の解説を確認し、弱点補強
- 可能な限りアウトプット（手を動かす、ChatGPTに説明する）

## まとめ

新卒2年目で資格を11個取得するために、**計画的に学習し、効率的な勉強法を実践**してきました。

資格取得はあくまで手段であり、**実務で活かすことが最も重要**です。今後も資格を活かしながらスキルアップを目指していきます。

もし資格取得を考えている方がいれば、**目的を明確にし、無理なく継続できる学習スタイル**を見つけることが大切です。この記事が参考になれば嬉しいです！
テスト時のインスタンス変数

特別なインスタンス変数
> Special instance variables

`ActionController::TestCase`はテストで使用する以下のインスタンス変数も自動的に供給する

>  ActionController::TestCase will also automatically provide the following
>   instance variables for use in the tests:

テストするコントローラーインスタンス
>  @controller
>   :   The controller instance that will be tested.

`ActionController::TestRequest`は今のhttpリクエストを代理する。httpリクエスト送信の前にオブジェクトを修正できる。例えば、GETリクエスト送信前にセッションプロパティを設定していいかもしれない
>   @request
   :   An ActionController::TestRequest, representing the current HTTP request.
       You can modify this object before sending the HTTP request. For example,
       you might want to set some session properties before sending a GET
       request.

`ActionDispatch::TestResponse`オブジェクトは最後のhttpレスポンスの応答を代理します。上の例では`@response`は`post`を呼び出した後、有効になります。いつくかのassert methodsが十分でないなら、詳細にhttpレスポンスを調べるためにこのオブジェクトを使うといいかもしれません
>   @response
   :   An ActionDispatch::TestResponse object, representing the response of the
       last HTTP response. In the above example, `@response` becomes valid after
       calling `post`. If the various assert methods are not sufficient, then you
       may use this object to inspect the HTTP response in detail.
  
https://github.com/rails/rails/blob/1dcfe2316b4b239e2cf6cadd4efb7af4b4345e35/actionpack/lib/action_controller/test_case.rb#L296C2-L315C4


>   Basic example
機能テストは次のように記述する
>   Functional tests are written as follows:

`get`, `post`, `patch`, `put`, `delete`,  `head`メソッドはhttpレスポンスをシミュレートします
>   1.  First, one uses the `get`, `post`, `patch`, `put`, `delete`, or `head`
       method to simulate an HTTP request.

期待された現在の状態かどうかを判断します。状態はコントローラーのhttpレスポンス、データベースのコンテンツなどなんでも構いません
>   2.  Then, one asserts whether the current state is as expected. "State" can be
       anything: the controller's HTTP response, the database contents, etc.
  
```rb
  # For example:
  #
  #     class BooksControllerTest < ActionController::TestCase
  #       def test_create
  #         # Simulate a POST response with the given HTTP parameters.
  #         post(:create, params: { book: { title: "Love Hina" }})
  #
  #         # Asserts that the controller tried to redirect us to
  #         # the created book's URI.
  #         assert_response :found
  #
  #         # Asserts that the controller really put the book in the database.
  #         assert_not_nil Book.find_by(title: "Love Hina")
  #       end
  #     end
  #
  # You can also send a real document in the simulated HTTP request.
  #
  #     def test_create
  #       json = {book: { title: "Love Hina" }}.to_json
  #       post :create, body: json
  #     end
  ```
## 感想
* @controllerはhttpリクエストを送る前に設定しておく。
* httpメソッド宣言されないと @responseは有効にならない。
公称的型付けと構造的型付け

## 公称的型付けと構造的型付け

プログラミング言語では、型の区別と互換性の判定に際して、主に二つのアプローチがあります。

- 公称的型付け（Nominal Type System）
- 構造的型付け（Structural Type System）

みなさんは、自分が使用しているプログラミング言語はどちらのアプローチを採用しており、また、それぞれのアプローチがどういうものなのか理解しているでしょうか？
かくいう私もそんなに意識せずに使用していました。

改めて「型の互換性の判別」「型の階層関係の判別」という二つの観点から両者を比較しつつ、理解を深めてみようと思います！

## 公称的型付け
公称的型付けでは、その名の通り「型の名前」を見て型の区別と互換性を判定します。
このアプローチを採用している代表的な言語は、java、PHPなどです。

### 型の互換性
型の互換性は、名前を見て決める
```java
class Cat {}
class Dog {}

class Main {
	public static void main(String[] args) {
		Cat cat = new Cat();
		Dog dog = cat; // エラーが発生する
	}
}
```

### 型の階層関係
型の階層関係の判定は、`extends`キーワードで宣言する（`java`の場合）
```java
class Animal {}
class Dog extends Animal{}

class Main {
	public static void main(String[] args) {
		Dog dog = new Dog();
		Animal animal = dog; // OK
	}
}
```

`extends`で宣言されていない場合、両者の親子関係は判別されない。
```java
class Animal {}
class Dog {}

class Main {
	public static void main(String[] args) {
		Dog dog = new Dog();
		Animal animal = dog; // エラーが発生する
	}
}
```

このように公称的片付けでは、`extends`を使用したクラスの継承によって、階層関係を表現します。
これを***公称的部分型***と呼びます。

## 構造的型付け
構造的型付けでは、名前ではなく、「型の構造」を見て型の区別と互換性を判定します。
「構造を見る」とは、型が持つプロパティやメソッドの構造によって型同士の区別、互換性の判定を行うということです。
このアプローチを採用している代表的な言語は、TypeScript, Goなどです。

### 型の互換性
型が同一かどうかは、型の構造を見て判定する
```typescript
class Cat {
  name: string
  walk() {}
}
class Dog {
  name: string
  walk() {}
}

const cat = new Cat();
const dog: Dog = cat; // エラーにはならない
```

公称的型付けの時はクラス名が違えば区別されてエラーになりましたが、構造的型付けでは、クラス名が違っても構造が同じであれば互換性が認められます。

### 型の階層関係
型の階層関係の判定は、型の構造を見て判定する
```typescript
class Animal {
  walk() {}
}

class Dog {
  name: string
  constructor(name: string) {
	  this.name = name;
  }
  walk() {}
}

const animal: Animal = new Dog("pochi");
```

公称的型付けの場合は、`extends`キーワードがない場合は構造が同じでも継承関係が認められませんでした。
構造的型付けでは「型の構造」に着目し、`Dog`クラスが`Animal`クラスを部分的に実装しているため、だ`Animal`型の変数に`Dog`型のインスタンスを代入できます。
これを、***構造的部分型***といいます。

## まとめ
|| 公称的型付け | 構造的型付け |
| - | - | - |
| 型の互換性 | 名前を見て判定 | 構造を見て判定 |
| 型の階層関係 | `extends`で宣言 | 構造を見て判定 |

ありがとうございました！
PineScriptで5種類の移動平均を実装する



## 概要  
本記事では、TradingViewにおける[PineScript](https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0i-tradingview)を用いて代表的な5種類の移動平均を実装する方法について解説する。それぞれの移動平均の特徴を理解し、トレード戦略に応じた適切な選択ができるようになることを目的としている。移動平均はシステムトレードにおいて非常に重要なツールであり、その多様性を活用することで分析精度の向上が期待できる。  

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0i-tradingview

## 対象読者  
本記事は以下の方々を対象としている。  
- PineScriptにおける移動平均の実装方法を学びたい方  
- トレード戦略に移動平均を組み込みたい方  
- 各種移動平均の違いを知り、選択肢を広げたい方  

---

## 移動平均とは  
移動平均とは、一定期間の価格データの平均値を算出し、価格のトレンドを平滑化するための指標である。以下に示す5種類の移動平均は、トレーダーに広く利用されている。  

### 1. 単純移動平均（SMA: Simple Moving Average）  
指定期間内の価格データの単純な平均値を算出する。最も基本的な移動平均である。  

### 2. 指数移動平均（EMA: Exponential Moving Average）  
最近のデータにより大きな重みを与えることで、価格の変動を迅速に反映する。  

### 3. 加重移動平均（WMA: Weighted Moving Average）  
期間内のデータに対して線形的な重みを付けることで、直近の価格に重点を置く。  

### 4. Hull移動平均（HMA: Hull Moving Average）  
WMAを基に、価格の滑らかさとレスポンスの速さを兼ね備えた指標である。  

### 5. 三角移動平均（TMA: Triangular Moving Average）  
SMAを二重に適用することで、データをさらに平滑化した移動平均である。  

---

## PineScriptでの実装  

以下のコード例では、上述の5種類の移動平均を計算し、それぞれをチャートに描画する方法を示す。  

```pinescript
//@version=5
indicator("5 Types of Moving Averages", shorttitle="5MA", overlay=true)

// パラメータ設定
length = input.int(14, title="Length", minval=1)

// 1. 単純移動平均（SMA）
smaValue = ta.sma(close, length)

// 2. 指数移動平均（EMA）
emaValue = ta.ema(close, length)

// 3. 加重移動平均（WMA）
wmaValue = ta.wma(close, length)

// 4. Hull移動平均（HMA）
hmaValue = ta.wma(2 * ta.wma(close, length / 2) - ta.wma(close, length), round(math.sqrt(length)))

// 5. 三角移動平均（TMA）
tmaValue = ta.sma(ta.sma(close, length), length)

// チャートへの描画
plot(smaValue, color=color.blue, title="SMA")
plot(emaValue, color=color.red, title="EMA")
plot(wmaValue, color=color.green, title="WMA")
plot(hmaValue, color=color.orange, title="HMA")
plot(tmaValue, color=color.purple, title="TMA")
```  

---

## 実装時の注意点  

### 1. パフォーマンスへの配慮  
移動平均はデータポイントを多く処理するため、計算に時間がかかる場合がある。特にHMAやTMAのような複雑な計算を含む指標を用いる際には、スクリプト全体のパフォーマンスを確認する必要がある。  

### 2. 期間の選択  
移動平均の期間（length）は、短すぎるとノイズが多くなり、長すぎるとトレンドへの反応が遅れる可能性がある。適切な期間を選択することが肝要である。  

### 3. 複合的な利用  
複数の移動平均を組み合わせてトレード戦略を構築することが一般的である。それぞれの特性を理解し、相互補完的に利用することが望ましい。  

---

## 結論  
本記事では、PineScriptを用いて5種類の移動平均を実装する方法を解説した。それぞれの移動平均には独自の特性があり、トレード戦略や目的に応じて適切に選択することが求められる。本記事を参考に、移動平均を活用した分析やトレード戦略の精度向上を目指していただきたい。  

読者諸氏のトレード活動が一層実り多いものとなることを祈る。  

---

APIドキュメント：

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0i-tradingview

---

## 免責事項  

本記事に記載されている内容は、筆者がTradingViewおよびPineScriptを用いて学び得た知識と経験を基に執筆したものである。内容の正確性および完全性については可能な限り配慮しているが、必ずしもその保証をするものではない。  

自動売買Botの構築や運用、またそれに関連する投資活動は読者自身の判断と責任に基づいて行われるべきであり、筆者および本記事を掲載するプラットフォーム（Qiita）は、それによって生じたいかなる損失や損害に対しても一切の責任を負わないものとする。  

特に、トレードに関する意思決定は市場リスクを伴うため、実運用前に十分な検証とリスク評価を行い、必要に応じて専門家への相談を推奨する。  

読者各位の責任において本記事をご活用いただければ幸いである。
PineScriptで自動売買アルゴリズムを組み立てる  



## 概要  
本記事では、TradingViewにおける[PineScript](https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0c-tradingview)を活用し、自動売買アルゴリズムの基礎的な構築方法について解説する。自動売買は感情的な判断を排除し、効率的なトレードを実現する手段として広く採用されているが、その実現には慎重な設計と検証が不可欠である。本記事を通じて、読者が基礎的なアルゴリズムを理解し、システムトレードの第一歩を踏み出す一助となれば幸いである。  

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0c-tradingview

---

## 自動売買アルゴリズムの基本構造  

PineScriptを用いた自動売買アルゴリズムは以下の要素によって構成される。  

1. **エントリー条件**  
   売買シグナルの生成ロジックを定義する。移動平均線、RSI、MACDなど、テクニカル指標がよく用いられる。  

2. **エグジット条件**  
   ポジションを決済する条件を設定する。利益確定や損切りの条件を明確に記述することが重要である。  

3. **バックテスト**  
   過去のデータを用いてアルゴリズムの有効性を検証する。  

4. **パフォーマンスの評価**  
   勝率、リスクリワード比、最大ドローダウンなどの指標を確認する。  

---

## 実装手順  

以下では、移動平均線を用いたシンプルなクロスオーバー戦略を例に挙げて説明する。  

### 1. スクリプトの作成  

```pinescript
//@version=5
strategy("Simple MA Crossover", overlay=true)

// パラメータの設定
fastLength = input.int(10, title="Fast MA Length", minval=1)
slowLength = input.int(50, title="Slow MA Length", minval=1)

// 移動平均線の計算
fastMA = ta.sma(close, fastLength)
slowMA = ta.sma(close, slowLength)

// チャートへの描画
plot(fastMA, color=color.blue, title="Fast MA")
plot(slowMA, color=color.red, title="Slow MA")

// エントリー条件
longCondition = ta.crossover(fastMA, slowMA)
if (longCondition)
    strategy.entry("Long", strategy.long)

// エグジット条件
shortCondition = ta.crossunder(fastMA, slowMA)
if (shortCondition)
    strategy.close("Long")
```  

### 2. バックテストの実行  
上記のコードをTradingViewに貼り付け、「Add to Chart」をクリックすることで、過去のデータに基づいたバックテスト結果を確認できる。  

### 3. パフォーマンスの評価  
TradingViewの「Strategy Tester」タブを開き、以下の指標を確認する。  
- 勝率  
- 総利益および総損失  
- 最大ドローダウン  
これらの数値を基に戦略の改善を行う。  

---

## 注意点  

### 1. 過剰最適化の危険性  
バックテストにおいて最適なパラメータを追求しすぎると、実運用では想定通りの結果が得られない「過剰最適化」に陥る可能性がある。慎重に検証を行い、過去のデータだけでなく異なるマーケット環境での挙動を確認することが重要である。  

### 2. 実運用のリスク  
自動売買は完全にリスクを排除するものではない。予期せぬマーケットの動きやシステムの障害に備え、適切なリスク管理を徹底するべきである。  

### 3. データの制約  
TradingViewの無料プランでは、バックテスト可能なデータ量に制限がある。これにより、一部の戦略が十分に検証できない場合がある点に留意されたい。  

---

## 結論  
PineScriptを用いた自動売買アルゴリズムの構築は、システムトレードの基礎として極めて有用である。本記事で提示した移動平均クロス戦略はシンプルであるが、カスタマイズや改良の余地が大いにある。読者が独自のアルゴリズムを設計し、トレードの可能性を拡げる一助となれば幸いである。  

今後もさらなるアルゴリズムの工夫やテクニカル指標の応用を学びながら、TradingViewを最大限に活用していただきたい。  

---

APIドキュメント：

https://www.tradingview.com/pine-script-reference/v6/?aff_id=112991&source=qt0c-tradingview

---

## 免責事項  

本記事に記載されている内容は、筆者がTradingViewおよびPineScriptを用いて学び得た知識と経験を基に執筆したものである。内容の正確性および完全性については可能な限り配慮しているが、必ずしもその保証をするものではない。  

自動売買Botの構築や運用、またそれに関連する投資活動は読者自身の判断と責任に基づいて行われるべきであり、筆者および本記事を掲載するプラットフォーム（Qiita）は、それによって生じたいかなる損失や損害に対しても一切の責任を負わないものとする。  

特に、トレードに関する意思決定は市場リスクを伴うため、実運用前に十分な検証とリスク評価を行い、必要に応じて専門家への相談を推奨する。  

読者各位の責任において本記事をご活用いただければ幸いである。
/var/log/secureを分類・整理する

インターネット上のsshを公開しているので、sshのアクセスログを分析する。
secureログには、アクセスしたユーザ名、接続元IPアドレスが残っているので、これを分類整理する。

## アウトプットイメージ
![スクリーンショット 2025-02-02 16.47.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/384104/44a89ab9-62be-0ad1-7da8-6bf1c27e1fea.png)

## sshdの設定。デフォルトのまま
```conf:/etc/ssh/sshd_conf
# Logging
#SyslogFacility AUTH
#LogLevel INFO
```
## secureログのサンプル
- ユーザ名「admin」,接続元IPアドレス「92.255.85.107」を正規化したCSVファイルを作成する
```:/var/log/secure
2025-02-02T00:03:56.881822+09:00 indigo sshd[375538]: Invalid user admin from 92.255.85.107 port 47890
2025-02-02T00:03:57.171420+09:00 indigo sshd[375538]: Connection reset by invalid user admin 92.255.85.107 port 47890 [preauth]
```

## ソース
[gist](https://gist.github.com/harasakih/ca68c0e3131d4ba03956043dcd400d0e)

- sec01.sh リモートホストから、/var/log/secureを取得するシェル
- sec02.sh secureを分類・整理するシェル。sec_001.plを起動
- sec03.sh sec02.shで作成した、secure.tsvをカウントするシェル
- sec_001.pl secureを分類・整理するPerl
- secTSV.pl secureをTSV化するPerl
- Secure.pl 部品集（secureを分解する）
- Dbglog.pl 部品集（レベル分けしてSTDERRにログ出力する）

PATH_TO_PERLのディレクトリに *.pl を配置する。シェルは任意の場所でOK。
- 入力ファイル：SECURE="secure"
- 出力ファイル：SECTSV="secure.tsc"
    - 出力ファイルはTAB区切り


```bash:sec02.sh
#!/bin/sh
PLBIN=/PATH_TO_PERL

## 001.pl
[ ! -f "$SECURE" ] && echo "!!ERR not found $SECURE" && exit 1
echo "!!INF, Count secure by MSG-TYPE, sec_001.pl IN:$SECURE OT:$SECTSV"
$PLBIN/sec_001.pl --inf=$SECURE --otf=$SECTSV
#
```
Aurora Serverless v2をRDS Proxyと併用するときのコストの落とし穴

開発環境用のAuroraインスタンスで`db.t3.medium`を使っていたのですが、`CPUUtilization`(CPU使用率)が10 %前後とリソースをかなり持て余していました。

各インスタンスの料金を比べてみたところ、ACU(Aurora Capacity Unit)が最小容量(0.5)近くで運用されていれば、Serveless v2の方が安くなりそうだということがわかり、インスタンスを変更してみました。

**インスタンス料金(Aurora Standard, Tokyo)**
- `db.t3.medium`: 0.125 USD/hour
- Severless v2: 0.15 USD/ACU

## なんかコストが上がった..
インスタンス変更後、ACUの使用状況を確認するために`ServerlessDatabaseCapacity`メトリクスを確認したところ、変更直後は2 ACU近くまで上昇しましたが、その後は安定して0.5 ACU付近で稼働していました。

![ServerlessDatabaseCapacityのグラフ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/15ef166f-2e67-940b-43f3-87c6809e489e.png)

おっしゃ！想定通りコスト下がった！と思い、Cost Explorerを確認してみたところ、なぜか7 USD/dayくらいコストが上がっていました..

![Cost Explorerのグラフ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/27c0c19a-6c21-4b02-751b-6f567ee8e843.png)

## コスト増の原因
Cost Explorerで「使用タイプ」ごとにグループ化して料金の内訳を確認したところ、`APN1-RDS:Proxy-ASv2-Usage`が約10 USD/dayものコストを占めていることがわかりました。

![Proxyコストの内訳](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/797c3b66-dcdb-cd4f-37e6-14687ca54d4f.png)

そもそもインスタンス変更前は`APN1-RDS:ProxyUsage`という表示だったのに、Serverless v2に変更後は `APN1-RDS:Proxy-ASv2-Usage`という異なる項目になっていました。

公式ドキュメントでRDS Proxyの料金を確認してみたところ、Aurora Serverless v2では「最低8 ACU分の料金が発生する」という記載を発見しました。

![RDS Proxy料金のスクリーンショット](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569054/7d84e55a-f6c4-abdb-9aea-7cd10b2f0684.png)

https://aws.amazon.com/jp/rds/proxy/pricing/

実は、「Lambda + RDS Proxy + Aurora」構成から「ECS + Aurora」構成へ移行する過渡期だったため、RDS Proxy をそのまま残して運用していました。これがコスト増加の原因でした..

## コスト比較

- `APN1-InstanceUsage:db.t3.medium`: 約3.00 USD/day
- `APN1-Aurora:ServerlessV2Usage`: 約2.21 USD/day
- `APN1-RDS:Proxy-ASv2-Usage`: 約10 USD/day

インスタンスコストだけで比較するとServerless v2の方が約1 USD安くなっていました。RDS Proxyを削除し、Aurora Serverless v2単体で運用することで、コストを最適化することができました。

## 補足: Auroraバージョンによるさらなるコスト最適化
今回使用したAurora MySQLのバージョンは3.07.0でした。このバージョンではACUの最小容量が0.5ですが、3.08.0以降では最小ACUが0に設定可能とのことです。

これにより、アイドル時にはさらにコストを削減できそうです。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html
個人的な備忘録：Pythonのリスト内包表記で偶数リストを抽出し、振り返ってみた

## はじめに

Pythonには、リスト内包表記（List Comprehension）という便利な構文があります。

:::note info
**これを使うことで、リストの生成や条件を満たす要素の抽出を簡潔に記述できます。**
:::

今回、リスト内包表記を使って1から20までの偶数を抽出するコードを実装し、その流れや仕組みを解説します。

## 書こうと思ったきっかけ
プログラムを書く際、リストのフィルタリング処理をforループとif文の組み合わせで記述することがよくあります。

:::note warn
***しかし、Pythonではリスト内包表記を使うことで、簡潔かつ可読性の高いコードを書くことができるため、習得する価値があります。***
:::

実際に書いて動作を確認しながら、リスト内包表記の便利さを実感したかったので、このコードを書きました。

## 完成したコード

```test.py
numbers = list(range(1, 21))
even_numbers = [n for n in numbers if n % 2 == 0]
print(even_numbers)
```

### コードの流れ

- 1から20までの数値を含むリストを作成
- リスト内包表記を使い、偶数のみを抽出
- 抽出した偶数リストを出力

## 実際に実行してみる
まず、以下のコマンドを実行して作成したコードの動作を確認します。

```bash
python test.py
```

**実行結果**

```bash
➜  Desktop git:(main) ✗ python test.py
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
```

## コードの解説

### 1.1から20までの数値をリストとして作成

```py
numbers = list(range(1, 21))
```

- `range(1, 21)` を使用し、1から20までの連続した整数を生成。  
- `list()` で `range` オブジェクトをリストに変換。  
- これにより `numbers` には `[1, 2, 3, ..., 20]` が格納される。  

### 2.偶数を抽出するリスト内包表記

```py
even_numbers = [n for n in numbers if n % 2 == 0]
```

- `for n in numbers` で `numbers` の各要素 `n` を順番に取得。  
- `if n % 2 == 0` で偶数のみを抽出（`n` を2で割った余りが0のもの）。  
- 結果として、`even_numbers` には `[2, 4, 6, ..., 20]` が格納される。  

### 3.抽出した偶数リストを出力

```py
print(even_numbers)
```

- `even_numbers` の内容を出力し、リスト内包表記によって偶数のみが抽出されたことを確認。  

## まとめ
ここまで読んでいただきありがとうございました。***リスト内包表記を使うことで、リストの作成とフィルタリング処理をシンプルに記述できることがわかりました。***

今後もこのような基礎的な部分については丁寧にまとめていこうと思っています。