OmniAICreator/Qiita-1.07M huggingface dataset:
IPアドレスとCIDR表記の理解：AWSでのネットワーキング

今回はIPアドレスとCIDR表記について解説します。それぞれの数字が何を示しているのか、そしてどのようにしてAWSのVPC（Virtual Private Cloud）やサブネットを設定するのかをわかりやすく解説します。
当時AWSの本を読んでいたとき、VPCのルーティングを勉強するとき「なんでこんなわかりにくい説明するんだろう」とずっと思っていたので、自分なりに図を使って解説していきたいと思います。

## IPアドレスとは

IPアドレスは、インターネット上のデバイスを一意に識別するための番号です。IPv4と呼ばれる現在主流の方式では、IPアドレスは4つの数（各々が0から255の間）によって表現されます。例えば、`192.168.1.1`などです。
<img width="300" alt="6ED892B9-C891-4C18-984A-88C1000DA3D1_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479750/129bdb12-7973-2ef9-57cf-442f1b7a5d6f.jpeg">

これらの数値は、それぞれが8ビットのバイナリ数値（2の8乗で256通り）を表しています。そして、それが4つ並んでいるため、全体としては32ビットのバイナリ数値を表現しています。これは理論的には2の32乗、つまり約43億のユニークなアドレスを指し示すことが可能です。

## CIDR表記とは

CIDR（Classless Inter-Domain Routing）表記は、IPアドレスとともに使われ、`/`に続けて数字を記述します。この数字は、IPアドレスのネットワーク部分とホスト部分を区別するために使用されます。

例えば、`192.168.1.0/24`のような表記を見たことがあるかもしれません。ここでの`/24`は、32ビットのうち最初の24ビットがネットワークを表し、残りの8ビットがホスト（つまり特定のデバイス）を表すことを意味します。

ネットワーク部分が同じIPアドレスは同じネットワーク（例えば、同じローカルネットワークやVPC）に属します。一方、ホスト部分はそのネットワーク内でのデバイスを一意に識別します。

## AWSでのネットワーキング

AWSでは、VPCを作成する際に、そのVPC用のIPアドレス範囲をCIDR表記で指定します。例えば、`10.0.0.0/21`と指定すると、`10.0.0.0`から`10.0.7.255`までのIPアドレスがそのVPC内で使用できることを意味します。この範囲内では`2^11`（すなわち2048）のIPアドレスが存在します。ただし、最初の4つと最後の1つのIPアドレスはAWSによって予約されています。

<img width="550" alt="3662E1FB-D001-4468-A7E0-E10CD318F28B_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479750/b2f2e979-dc25-d27c-8ed3-a2893099741a.jpeg">

さらに、このVPCをいくつかのサブネットに分割したい場合があります。その際には、それぞれのサブネットにもCIDR表記でIPアドレス範囲を指定します。例えば、`10.0.1.0/24`と指定すると、そのサブネットでは`10.0.1.0`から`10.0.1.255`までの256個（実際には251個）のIPアドレスが使用できます。以下の図の例では、10.0.0.0/21のVPC内に/24のサブネットを作成する例を示しました。

<img width="401" alt="9E96F90B-5C76-4B59-A72C-8D7464C6BAA2_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3479750/3acde6bf-da19-52dc-1edd-ce8a591e4a1f.jpeg">

以下にそれぞれのCIDR表記ごとの詳細を説明します：

1. **CIDRが/25の場合**

サブネット1: `10.0.0.0/25` - IPアドレス範囲は `10.0.0.0`から`10.0.0.127`まで、123個の使用可能なIPアドレス。

サブネット2: `10.0.0.128/25` - IPアドレス範囲は `10.0.0.128`から`10.0.0.255`まで、123個の使用可能なIPアドレス。

2. **CIDRが/26の場合**

サブネット1: `10.0.0.0/26` - IPアドレス範囲は `10.0.0.0`から`10.0.0.63`まで、59個の使用可能なIPアドレス。

サブネット2: `10.0.0.64/26` - IPアドレス範囲は `10.0.0.64`から`10.0.0.127`まで、59個の使用可能なIPアドレス。

サブネット3: `10.0.0.128/26` - IPアドレス範囲は `10.0.0.128`から`10.0.0.191`まで、59個の使用可能なIPアドレス。

サブネット4: `10.0.0.192/26` - IPアドレス範囲は `10.0.0.192`から`10.0.0.255`まで、59個の使用可能なIPアドレス。

3. **CIDRが/28の場合**

サブネット1: `10.0.0.0/28` - IPアドレス範囲は `10.0.0.0`から`10.0.0.15`まで、11個の使用可能なIPアドレス。

サブネット2: `10.0.0.16/28` - IPアドレス範囲は `10.0.0.16`から`10.0.0.31`まで、11個の使用可能なIPアドレス。

このような形で、CIDR表記によりそれぞれのサブネットで利用可能なIPアドレスの数が異なります。これらの値を理解することで、ネットワーキングニーズに合わせた適切なサブネットの設計が可能になります。
このように、IPアドレスとCIDR表記を理解することで、AWSでのネットワーキングがどのように動作するかがわかるはずです。それぞれの数字が何を示しているかを理解し、どのようにネットワークを設計するかについて考えることが重要です。



以上、このチュートリアルがCIDR表記とIPアドレスの理解に役立つことを願っています。
RPGMaker Unite のアップデートの仕方

# RPG Maker Unite のアップデートの仕方

0\. これまでに変更している部分があったらバックアップを取っておく<br/>

1\. Unity のモードを [Unity Editor] モードに変更する。（RPG Maker + Unity Editor モードになっている方はそのままでも大丈夫です。）<br/>
    ![Unity のモードを変更する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/fa7d9822-5621-655c-e2c6-80115f0310a5.png)
    
2\. パッケージマネージャーを開く<br/>
    ![パッケージマネージャーを選択](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/2c1eefaa-59f9-03a8-c4a0-196c786eed85.png)

3\. パッケージマネージャーの調べたいパッケージの種類を変える。上の方の[パッケージ：プロジェクト内]のプルダウンメニューを開いて[マイアセット]を選択する。<br/>
        ![パッケージの種類を変える](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/61948465-a4e6-2247-8ed5-41910a01f479.png)

3\.1\. パッケージマネージャーに RPG Maker Unite(以下RMU) があるか確認する。<br/>
    ![パッケージマネージャーを確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/fdbb1a8e-9227-da31-635b-167d999bce3b.png)<br/>
    3\.2\. パッケージマネージャーに RMU が無かった場合には下の方にある[ロード]の文字をクリックする<br/>
        ![ロードをクリック](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/7f389edc-e61b-b109-fa48-f395bde2fb75.png)<br/>

3\. パッケージマネージャーに RMU が現れるので、右上の [更新] を選択する。([再ダウンロード]とあるが、これは既に更新してしまったため)<br/>
    ![更新](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/f1c3fe47-6ed2-4c8f-85d5-ceee55b5160d.png)

<br/><br/>
4\. インポートを選び、ガイドに従って更新する。<br/>
    ![インポート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/b266d981-b3c4-1dbf-aef4-63cdb2f0b080.png)<br/>
    4\.1\. 不安だったら[すべて]を選択し、インポートする。<br/><br/>
    ![インポート](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/30a7778c-dfad-dec7-7319-108c91e188e5.png)<br/>
    4\.2\. 更新の確認が出てくる。この段階で、変更している部分をバックアップしていなかったらバックアップを取る。<br/>

![確認](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540529/4477b0ad-8c2c-cf6c-33e2-9bb7ff7310f8.png)<br/>

>訳は以下(Deeple 翻訳)[このプロジェクトのソースファイルの中には、変更されたAPIを参照しているものがあります。これらを自動的に更新することができます。更新する前に、プロジェクトのバックアップを取ることをお勧めします。<br/>
はい、これらのファイルと、後で見つかるかもしれない他のファイルについてです。]<br/>

自信がないなら一番左のボタンを押す。

以上です。
スプレッドシートをDBにそのまま入れようとしたら日付部分でエラーが出た

GoogleSpreadSheet上で作成したデータをDLしてMySQLにインポートしようとしたらつまづいたので忘れないための備忘録

### エラー文
```
conversion failed: "2023/05/10" to datetime
```

スプレッドシート上では日付は勝手に`YYYY/MM/DD`の形に修正されるがMySQLでは`YYYY-MM-DD`の形でインポートする必要があったためエラーを吐いた


### 対応
スプレッドシート上で書式なしテキストにして勝手にフォーマットされないようにする
AWSクラウドの概念　クラウドアーキテクチャの設計原理

クラウドのメリットを活かした設計を行うには、オンプレミスとは異なる設計原理がある。

# 故障に備えた設計（Design for Failure）

時間が経てば故障する、ということを認識してアーキテクチャに取り入れる。
故障に備えたメカニズムを構築しておく。

Design for Failure = 単一障害点をなくす。

1. 1つのデータセンターのみで運用しない
1. 単一のインスタンスのみで構成しない



# コンポーネントの分離

クラウドはサービス指向アーキテクチャの設計原理を踏襲する。
システムのコンポーネントを疎結合にすればするほど、スケーリングしやすくなる。

コンポーネントの分離を実現するには、Amazon SQSを使ったキューイングチェーンを利用して非同期かつ疎結合にすることができる。

また、マイクロサービスアーキテクチャを用いて、システムを複数の小規模なアービスの集合体として構成することで、コンポーネントの分離を進めることができる。



# 弾力性の実装

クラウドには弾力性（Elastic）という概念がある。伸縮性とも言って、リソースの性能を柔軟にスケールアウトしたり、スケールインすることができる。

弾力性を実現する方法は3つある
1. 巡回スケーリング
    1. 一定間隔に発生する定期的なスケーリング
1. イベントベーススケーリング
    1. イベントのためにトラフィックリクエストが急増されると予想されるときに実現するスケーリング
    1. スケジュールドスケールアウトパターンを利用
        1. Auto Scalingで定時に起動を指示
1. オンデマンドの自動スケーリング
    1. 監視サービスを利用して、監視項目に基づいてスケールアウト、スケールインを行う
    1. スケールアウトパターンを利用
        1. CloudWatchでリソースを監視
        1. トラフィック増加を検知したらAuto Scalingに通知
        1. Auto Scalingがインスタンスを起動



# 並列化を考慮する

ロードバランサーを組み合わせて、並列処理を行う。


# 動的コンテンツデータをコンピュータの近くに、静的コンテンツデータをエンドユーザーの近くに保管する

クラウドでは、データをネットワーク経由で利用するため、配信のオーバーヘッドやボトルネック対策は必須。

* 静的コンテンツは外部に出して、エンドユーザの近くに保管
* 動的に処理するデータは、クラウド上のコンピューティングリソースの近くに保管
PHPの正規表現で文字列の一部のみ切り出す

# 正規表現で一致したデータの一部を取得する

[PHP: preg_match](https://www.php.net/manual/ja/function.preg-match.php)

## マッチする文字列の取得

- マッチした文字列が第三引数に入る

```php
preg_match('/Harry Potter/', 'Mr. Harry Potter', $matches);
var_dump($matches);

// array(1) {
//   [0]=>
//   string(12) "Harry Potter"
// }
```

## マッチする文字列の一部を取得

- 括弧で囲んだ部分にマッチした文字列が取得できる

```php
preg_match('/(Harry) (Potter)/', 'Mr. Harry Potter', $matches);
var_dump($matches);

// array(3) {
//   [0]=>
//   string(12) "Harry Potter"
//   [1]=>
//   string(5) "Harry"
//   [2]=>
//   string(6) "Potter"
// }

var_dump($matches[1]);

// string(5) "Harry"
```

## 例えばこういう時に便利

### User-Agentから桁数が不定なバージョン情報を取得

```php
$user_agent = 'AppVer/105/hogehoge';
preg_match('/(^AppVer\/)(\d+)(\/hogehoge)/', $user_agent, $matches);

if (version_compare($matches[2], '105', '>=')) {
    var_dump("アプリバージョンは {$matches[2]} 以上です。");
} else {
    var_dump("アプリバージョンは {$matches[2]} 未満です。");
}

// string(47) "アプリバージョンは 105 以上です。"
```
neosでlogix その141

# 概要
neosでlogixやってみる。
youtubeを見る手順。

# youtubeを見る手順。

- ctrl + V する。
- ビデオを選択する。

# 写真

![2023-06-29 05.43.29.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b2442344-3350-6f3d-15b1-d5d4f4f1e2a2.jpeg)



以上。
QiitaのAPIでいいねした投稿一覧を取得

PythonでQiitaのAPIをコールして、Qiitaのいいねした投稿一覧を取得するように実装してみました。
取得した記事はいいね数降順でソートします。

```sh
pip install pandas==1.3.5
pip install requests==2.28.2
pip install openpyxl==3.0.9
```

```get_qiita_article.py
import requests
import pandas as pd
from datetime import datetime as dt


def get_qiita_articles_by_page(page):
    """
    第何ページ目の文章を取得
    @param page ページ目
    @return 文章リストを返す
    """
    url = 'https://qiita.com/api/v2/items'
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'
    }
    params = {
        'page': page,
        'per_page': 100,
        'query': 'likes_count:=0'
    }
    response = requests.get(url, headers=headers, params=params)
    if response.status_code == 200:
        article = response.json()
        return article
    return None


def get_qiita_articles():
    """
    qiitaの文章を取得

    """
    articles = []
    for i in range(1, 9999):
        top = get_qiita_articles_by_page(i)
        if top:
            articles.extend(top)
        else:
            break
    return articles


def out_put_articels(file_name):
    """
    qiitaの文章を出力
    """
    articles = get_qiita_articles()
    # for index, article in enumerate(articles, start=1):
    #     print(f'{index}. {article.get("title")} - {article.get("likes_count")} likes')
    if articles:
        df = pd.DataFrame(articles)
        df.drop(columns=["id", "rendered_body", "body", "coediting", "comments_count", "created_at", "group", "private", "reactions_count",
                         "stocks_count", "tags", "updated_at", "team_membership", "organization_url_name", "user", "page_views_count"], axis=1, inplace=True)
        df.sort_values(by="likes_count", axis=0, ascending=False, inplace=True)
        df = df[df["likes_count"] > 0]
        df = df.reindex(columns=['title', 'url', 'likes_count'])
        df.to_csv(file_name, encoding='utf-8', index=False)
    else:
        print("文章を取得できなかった！")


if __name__ == '__main__':
    day = dt.now().strftime('%Y%m%d')
    out_put_articels(f'./result_{day}.csv')
```

更にGithubのActionを利用して、毎日定時的に実行します。

```schedule.yml
name: schedule

on:
  schedule:
    - cron: "0 8 * * *"
  push:
    branches:
      - main

jobs:
  excute-python:
    runs-on: ubuntu-latest
    env:
      TZ: Asia/Tokyo

    steps:
      - name: Checkout code
        uses: actions/checkout@v2

      - name: Set up Python
        uses: actions/setup-python@v2
        with:
          python-version: 3.x

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          pip install -r requirements.txt

      - name: excute python
        run: |
          git config --local user.email "bot@github.com"
          git config --local user.name "bot"
          git remote set-url origin https://${{ github.actor }}:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
          git pull --rebase
          python get_qiita_article.py
          git add .
          git commit -m "update by github action"
          git push
```

## 参考

https://github.com/JapanTools/qiita-tools
#04 PythonでCSV保存するときに文字化けしないようにするとエラー

### はじめに
PythonでデータをCSVとして保存しようとすると

~~~python
df.to_csv("hoge.csv")
~~~
を使うかなと思うのですが、これだとデフォルトではUTF-8でエンコーディングされてしまい、エクセル等では文字化けしてしまう。

### それでは文字コードを指定する
to_csvの文字コードはencording=""で指定できる。

~~~python
df.to_csv("hoge.csv", encoding="shift_jis")
~~~
これでいけるかとおもうと、文字コードが違う関係でうまくエンコードできない場合がある。

以下のエラーが出てしまう。
~~~
'shift_jis' codec can't encode character '\uff5e' in ~~~
~~~

### 最終的に
その場合はcp932を指定するとエラーを解決できる。

~~~python
df.to_csv("hoge.csv", encoding="cp932")
~~~
EVAL: Explainable Video Anomaly Localization

# 1. 概要
動画の中から異常行動を検出しどの方角からどのくらいのスピードで何が来るのかを検知してわかりやすく可視化した研究。従来手法と比べ異常検知の精度が大きく向上しており、またAIの解釈性(interpretability)を高めるためのUIも充実している。動画から異常検知を実施するときに問題になるのが、不審行動や異常の定義があいまいなため教師学習が成り立ちにくい点にある。この研究では、異常な状態や不審な行動自体を学習するのではなく、動画を時空間に分割したときに周囲に比べて自分のパッチがどれほどかけ離れた特徴を持っているかを調べることで実現している。

---

# 2. 新規性
1) 対象物体のクラス、2) 動作検知、3) スピード検知、4) 静止画素の割合を入力動画から同時に求めることができる。学習は個別に行われるのではなく、4つのネットワークに対して一度に実施される。対象物体のスピードや方向といった情報はオプティカルフローを教師情報として学習することでアノテーションコストがかからないようにした。静止画素の割合はパッチ単位で特徴量が算出され、固定のグリッド長に対してどれほど動作があるかを示す。例えば、周囲が絶え間なく動いている中で静止している箇所は周辺と比べて特異であるし、また周囲が静止している中で対象が動いていれば顕著点となる。

---

# 3. 実現方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/323a8e78-60ef-6baa-fa4e-3076076ffd2e.png)
動画を空間的にグリッドに区切り、時間方向のボリュームとみなして各ネットワークからの出力をグリッドの代表特徴ベクトルとして保存する。検知対象動画に対して同じ処理で各グリッドの代表特徴ベクトルを取得した時に、これまでのレコードされた特徴ベクトルと比べ最近傍探索で距離が離れていたものを異常個所とみなす。

---


# 4. 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/a39c5eb6-5087-1237-f0eb-d106522069df.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/51590ecc-a2c8-ddbb-91d2-cff9438781ad.png)
固定カメラを対象にした複数のデータセット(Street Scene/CUHK Avenue /ShanghaiTech/UCSD Ped1,2)で効果を検証しており、従来手法に比べて大幅な改善を確認した。
また、DNNで抽出した各種異常兆候を示す代表特徴は可視化されて直感的にユーザーにフィードバックされる。検出した対象がどのクラスでどちら向き方向にどれくらいのスピードで動いているのか、またそれは前景・背景のいずれの可能性が高いか、などが一度に確認できる。

---

Paper URL: <https://openaccess.thecvf.com/content/CVPR2023/papers/Singh_EVAL_Explainable_Video_Anomaly_Localization_CVPR_2023_paper.pdf>

last updates: June 22 2023
大学3年春: 応用情報技術者試験に受かったので何をやったか書く

# 前提
- 基本情報は受けていないです
- 早稲田大学 基幹理工学部 情報理工学科でCSを専攻しています

# モチベ
- 資格試験を受けたことがなくTOEIC程度しか資格欄に書く内容がないため
- 早いうちに取った方がかっこいい
- 網羅的に知識をインプットしたかった
- 高度試験の午前I試験免除

# 勉強スケジュール
## 一ヶ月前
応用情報合格教本という分厚い本をちまちまと読んでいました。最終的には全部読み終わりました。
応用情報合格教本なのですが、正確さ重視で難しい言い回しが多く、**お気持ち**の書いてある参考書が好きな僕からすると面白みがなかったので、集中力を持続させるのが大変でした。CSにどんな分野があるのか再認識できるため勉強にはなりました。

## 3日前
気づいたら3日前になっていました。さすがにまずいと思い、過去問道場（午前）に取り組み始めました。全範囲一気にやると、概念別にインプットするのが難しいと思うので**小単元ごとに取り組みました**。
間違えた問題は最低2回くらい正解するまでやるのがいいと思います。
結局、全部合わせて80問しか解いていません。

## 前日、当日
午後問題に関しては、セキュリティ、ネットワーク、プログラミング、組み込みシステム開発、システムアーキテクチャを本番で解く予定だったので、そこだけ過去問道場で勉強しました。

### 午後問題: 特徴
- セキュリティ・・・必須なので頑張るしかないです。ネットワークセキュリティの問題が多い。10分で終わる時もあるけど高得点は難しい。知識問題が多く、最近はファイアウォールばかり出ています。
- ネットワーク・・・セキュリティの問題やるだけでも少しは知識がつくと思います。インフラに日頃触っていると容易かもです。2進変換問題やプロトコル聞かれたりは頻出。
- プログラミング・・・競プロやったことがあるならやりましょう。数学が得意な人もやりましょう。でもたまに激ムズ。
- 組み込みシステム開発・・・プログラミングの問題と似ているときが多いです。UMLに慣れていると楽だと思います。ハードウェアに少しでも触ったことがないと難しいかも。ビット数計算やデータ転送速度など。算数のような大問が出るときあります。
- システムアーキテクチャ・・・クラウドやIoT、mm1モデルや稼働率などの計算。何度も同じ問題が出ています。ネットワークやDB関連も多いです。10分で終わる時もあります。ネットワークの勉強にもなります。簡単な部類です。稼働率計算は過去問通り。よっぽど計算が苦手でない限りはおすすめ。

# 試験中の戦略（理想）
- 先に設問把握
どうでもいい記述も割とあるので先に問題は読んだ方がいいです。
- 1問30分
全体で150分なので1問30分には抑えたい。基本は余裕だと思いますが、一題くらい沼ると考えておいた方がいいです。

# 実際の試験でどうだったか
- 午前問題は難化したな〜と感じましたが、過去問と系統が違っただけの様な気もします。
- 午後問題は結局以下を解きました。
    - 情報セキュリティ
    - 経営戦略（初めて解いた）
    - システムアーキテクチャ
    - 組込みシステム開発
    - 情報システム開発（初めて解いた）

- つまり全然予想通りに進みませんでした
- プログラミングの大問で途中で数式があっているか不安になり、芋づる式に全部落とすと悲惨なことになるため、情報システム開発を解くことにしました。（Gitの問題だったので簡単でした）
- また、ネットワークも解いたには解いたのですが、正答率が低い自信があり、経営戦略を眺めていたら、国語力を問う設問だったのでゴリ押しました。本当に暗記なしの国語力勝負です。文系の方は絶対解いた方がいいと思うくらい。

# 結果
思ったよりは余裕のある点数でしたが、3日前に過去問始めるのはさすがにやばいので、1週間前にははじめよう。
![スクリーンショット 2023-06-29 15.42.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790537/273bd5e3-01a5-e370-03b4-874d3296ce5c.png)
![スクリーンショット 2023-06-29 15.42.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1790537/fdf52d49-c821-7ce8-8c91-dce69d056799.png)

# 過去問道場をやろう
応用情報を受けて思ったのですが、おそらくIPAの試験は過去問駆動学習が最適だと思います。（IPAに限らずですが）
近い内にセキスペ（情報処理安全確保支援士試験）も受けようと思っているので、そのときも過去問から入ろうかなーと思ってます。（2024/9/1追記: [セキスペも過去問からで大丈夫でした](https://qiita.com/re_shu/items/96617eb4e468903e2297)）

午後問題の勉強をすることで午前の知識も身につきます。
Generalist: Decoupling Natural and Robust Generalization


# 1. 概要
ニューラルネットワークを用いた画像認識のシステムの入力にわずかなパッチやノイズを加えてシステムの認識系を狂わせる手法を敵対的攻撃(Adversarial Attacks)といい、これを防御するための学習手法を敵対的トレーニング(Adversarial Training)という。ここで、データセットに対してモデルがどれだけ正確に予測できるかを示す指標をNatural Accuracyと呼び、一方で敵対的な攻撃に対してモデルがどれだけ頑健かを示す指標をRobust Accuracyと呼ぶが、敵対的トレーニングを行うとNatural Accuracyが低下するのが問題だった。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/2f01eb70-4f37-e339-17bd-8c0b5c954836.png)

---

# 2. 新規性
この研究では、これまでトレードオフの関係にあったNatural AccuracyとRobust Accuracyをどちらも担保することに成功している。ネットワークを共有してと学習を同時に行うとトレードオフの関係から抜けられなくなるため、正常画像認識用のネットワークと敵対的攻撃耐性用のネットワークを用意し、Generalistと名付けた第三のネットワークによって二つのネットワークを同時に学習させつつそれぞれの識別能力が劣化しないようにハンドリングする。Generalistは初期状態が最適化されていないのでそのまま勾配を伝播させると学習が困難になる。そこで、ある一定のエポックの間の勾配情報にEMA(Exponential Moving Average)をかけて現在のエポックに最も高い重みを与えながら勾配情報を伝播させることで解決した。

---

# 3. 実現方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/02fbc8f6-994b-3ec0-d712-597801bf603a.png)
1) 正常画像用のネットワークを更新する
2) 敵対的攻撃判別用ネットワークを更新する
3) 1と2の重みを加重平均してGeneralistネットワークを構築する
4) Generalistネットワークから、一定のエポックの時差を含ませて勾配を1と2のネットワークに伝播させる
5) 1と2のネットワークの重みを更新する
*一定エポックの時差はハイパーパラメータになっている
---

# 4. 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/cc254d05-eadd-f011-2ffa-12dd5f8ec617.png)
正常画像の認識率を保ちながら、敵対的画像を判別する能力もかなり高い頑健性を維持できるようになった。

---

Paper URL: <https://openaccess.thecvf.com/content/CVPR2023/papers/Wang_Generalist_Decoupling_Natural_and_Robust_Generalization_CVPR_2023_paper.pdf>

last updates: June 22 2023
Interactive Segmentation As Gaussion Process Classification


# 1. 概要
ユーザーのクリック動作によって前景と背景を分離するバイナリーセグメンテーションの研究。従来手法では、クリック情報をニューラルネットワークのセグメンテーションネットワークに効果的に伝播できていなかったため、うまく前景と背景を分割することが難しかった。

---

# 2. 新規性
ガウス過程(Gaussian Process)を使って、画像中のピクセル単位で二値分類モデル化してクリックされているピクセルの前景予測情報をクリックされていない領域に伝播させることで、非常に複雑なシーンでも前景背景分離ができるようになった。

---

# 3. 実現方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/9c2dca21-fc95-7583-9ed1-5e7f34138b64.png)
前景と背景のそれぞれにユーザーがクリックしてアノテーションを行う。入力画像からDNNを用いて高次元特徴を取得し、クリックしていない未分類のピクセルを高次元空間で前景に近いか背景に近いか、ガウス過程の分布から予測する。ここで、クリックしてあるピクセルの高次元特徴の分布が前景らしさ・背景らしさを示すガウス確率に従うように学習することで、理論的にユーザーのクリック情報が正確な予測に反映されるようにしている。
また、ユーザーのクリックに応じて分類結果がアップデートされる構造になっており、追加情報を与えていくことでどんどん高精度なマスクが出来上がる。

---

# 4. 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/515b93a0-b139-a786-f095-907275e51231.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/83709dfc-d7b3-7169-4336-009dbf1a6aa6.png)
複数のデータセットに対して評価実験を実施しており、従来手法のセグメンテーションアーキテクチャに提案手法を組み込むことで、少ないクリック数で高精度な前景抽出が可能なことを確認した。

---

Paper URL: <https://openaccess.thecvf.com/content/CVPR2023/papers/Zhou_Interactive_Segmentation_As_Gaussion_Process_Classification_CVPR_2023_paper.pdf>

last updates: June 22 2023
Open Vocabulary Semantic Segmentation With Patch Aligned Contrastive Learning


# 1. 概要
テキスト入力に対応する画像領域を正確に求めることを目的としてPACL(Patch Aligned Contrastive Learning)を提案している。この研究では、画像特徴とテキスト特徴の高次元の特徴の対応の仕方を学習しているため、与えられたテキスト入力に対応する画像パッチの予測が可能となりゼロショットでセグメンテーションできるようになった。特に、未知のクラスへの対応能力を示すOpen Vocabularyのタスクでもセマンティックセグメンテーションが実現できている。

---

# 2. 新規性
CLIP(Contrastive Language-Image Pretraining)のモデルの改良版としてPACLを提案し、ViT(Vision Transformer)から得られる画像の部分情報となるパッチトークンと、BERTなどから得られるテキストトークンとを高次元空間で対応付け、そのマッピング方法を学習した。

---

# 3. 実現方法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/405b966a-766c-6252-e1bd-29c971cdb252.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/b391514d-8ff9-84fc-ae22-bf0bec31971a.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/eac6714f-9e0a-a678-a8c7-86a1511d9da9.png)
CLIPでは画像と言語のクラストークン(CLS token：文全体の意味を表す)が対応付けされるが、画像のパッチレベルでクラストークンと特徴の対応付けが行われているわけではないことを明らかにした。その上で、CLIPの画像パッチトークンとテキストトークンの関係を学習できるよう対照学習のロス(contrastive loss)を改変し、Patch Alighned Contrastive Learning(PACL)とした。パッチ単位でクラストークンとの対応付けが行えるようにしたことで、パッチ単位のクラス分類性能が劇的に上昇し、テキスト入力の指し示す内容が画像中から高精度に予測できるようになった。

---

# 4. 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158742/84455c2b-e2a6-8f95-fab6-218a68981e1e.png)
大規模なセグメンテーションデータセット(Pascal VOC/Pascal Context/COCO Stuff/ADE20K)に対して評価実験を行い、未知のクラスに対してもゼロショットでセマンティックセグメンテーションができることを確認した。

---

Paper URL: <https://openaccess.thecvf.com/content/CVPR2023/papers/Mukhoti_Open_Vocabulary_Semantic_Segmentation_With_Patch_Aligned_Contrastive_Learning_CVPR_2023_paper.pdf>

last updates: June 22 2023
IaC入門のメモ：Terraformを使ってみよう　第２回（API Gatewayの設定とAppSyncをエクスポートしたい）

# はじめに

座学では知っている物の、実体験をもってCloudFormationのテンプレ化をしてこなかったので、既存リソースをテンプレート化する所までを、「やってみた！」系のメモ書き(第２回)です。

TerraformとTerraformerのセットアップについては、前回の記事を参照ください。

https://qiita.com/Syoji_Yonemoto/items/24401e8b55aacdc0a85a

# 初期化の実行

実行カレントに、main.tf(スクショの実行環境では、Work直下にmain.tfを保存）を置いて、コマンドを実行する。

```winbatch
terraform init
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/b4da2ba5-d769-e882-3e5e-1cc3b48186c3.png)

# 公式ドキュメント

https://github.com/GoogleCloudPlatform/terraformer/blob/master/docs/aws.md

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/7e7e0b20-7e70-9637-2c11-9108335a493c.png)

対象としたいリソースは、この辺りです。


# ポリシー用意

 **API Gateway用の読み取り専用ポリシー**
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "apigateway:Get*"
            ],
            "Resource": "*"
        }
    ]
}
```

 **AppSync用の読み取り専用ポリシー**
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "appsync:List*",
                "appsync:Get*",
                "appsync:EvaluateCode",
                "appsync:EvaluateMappingTemplate"
            ],
            "Resource": "*"
        }
    ]
}
```


# エクスポート

 **API Gateway用のエクスポートコマンド**
```winbatch
terraformer import aws --resources=api_gateway --regions=ap-northeast-1
```

 **AppSync用のエクスポートコマンド**
```winbatch
terraformer import aws --resources=appsync --regions=ap-northeast-1
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281768/198a05bb-56f5-4d8e-ee0a-d59cb86c0159.png)

配下に 

+ generated - aws - api_gateway 
+ generated - aws - appsync

のフォルダ階層が作成されて、各種 tfファイルが出力されました。

# まとめ
出力したTFファイルを確認してみたところ、API Gatewayの方は設定している大部分の情報を出力できているようです。
対して、AppSyncは、出力内容が、まだまだ足りないな、、、という感じでした。（今後のバージョンアップに期待）

# AWSの相談・お困りごとありましたら、、、

AWSの活用方法や、お困りごとの相談、随時、お仕事の受付しております。

https://www.cs-cloud-aid.com/
Leetcode 20. Valid Parentheses

# Problem
対応する括弧が適切に開かれて閉じられているかを判定する問題です。
> Given a string s containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid. 


InputとOutputの例は次になります。
```
Input: s = "()[]{}"
Output: true

Input: s = "(]"
Output: false
```

https://leetcode.com/problems/valid-parentheses/description/

## Key Idea
Stackを利用します。対応する括弧が適切に開かれて閉じられているかを確認するために、Stackに開始括弧をプッシュし、終了括弧が出現したときに最後に開いた括弧と比較します。

## Approach #1 Stack
手続き的で冗長な書き方ではありますが、Approach #2の前準備として記載します。PythonではlistをStackとして利用することができます。`push`は`list.append()`、`peek` は、`list[-1]`、`pop`は`list.pop()` で実装できます。参考までに、実務においては `collections.deque` を使うと、listよりも高速なスタック操作が可能です。

```Python
class Solution:
    def isValid(self, s: str) -> bool:

        stack = []
        for char in s:
            if s[i] in [')','}',']']:
                if len(stack) == 0:
                    return False

                if char == ')':
                    if stack[-1] == '(':
                        stack.pop()
                    else:                        
                        return False

                if char == '}':
                    if stack[-1] == '{':
                        stack.pop()
                    else:                        
                        return False

                if char == ']':
                    if stack[-1] == '[':
                        stack.pop()
                    else:                        
                        return False
            else:
                stack.append(char)
                
        if len(stack) == 0:
            return True
        else:
            return False
```


## Approach #2 Stack + Hashmap
括弧の種類の違いによる処理が冗長なので、Hashmapを使って、Approach #0をよりスッキリさせています。

```Python
class Solution:
    def isValid(self, s: str) -> bool:

        stack = []
        hashmap = {')':'(', '}':'{', ']':'['}
        for char in s:
            if char in hashmap:
                if len(stack) == 0:
                    return False

                if stack[-1] == hashmap[char]:
                    stack.pop()
                else:                        
                    return False
            else:
                stack.append(char)
                
        if len(stack) == 0:
            return True
        else:
            return False
                
                
            
```

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。すべての文字を1文字ずつscanします。Scan中にstackにpushとpopを行うのは最悪の場合でも文字列の長さに比例します。

- Space complexity: O(n)。最悪の場合、すべての文字が開き括弧である場合にスタックにすべての文字が追加される可能性があります。

## Reference
https://www.youtube.com/watch?v=WTzjTskDFMg
【Golang】echo + air でシンプルなREST APIをつくる



ファイル構成
<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/6fac0611-4a30-0972-46d3-7f45d423cc07.png">

```bash:shell
# モジュール初期化
$ go mod init example.com/hello

# echo
$ go get github.com/labstack/echo/v4  
```

```yaml:docker-compose.yml
version: '3'
services:
  app:
    build: .
    ports:
      - '3030:3000'  # ローカルの3030番ポートでコンテナの3000番ポートに接続
    volumes:
      - .:/app       # ローカルとコンテナのディレクトリをマウント（同期）
      - go_path:/go  # パッケージやバイナリファイルのインストール先（$GOPATH）を永続化
volumes:
  go_path:
```

```dockerfile:Dockerfile
FROM golang:1.18

# コンテナの作業ディレクトリにローカルのファイルをコピー
WORKDIR /app
COPY . /app

# 必要なパッケージをインストール
RUN go mod tidy

# インストール
RUN go install github.com/cosmtrek/air@v1.27.3
RUN go get -u github.com/go-delve/delve/cmd/dlv 
RUN go get github.com/labstack/echo/v4/middleware

# airコマンドでGoファイルを起動
CMD ["air"]
```

```golang:main.go
package main

import (
	"net/http"
	"github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func rootHandler(c echo.Context) error {
	var records [3]string = [3]string{"1st", "2nd", "3rd"}
	return c.JSON(http.StatusOK, records)
}

func main() {
	// echo
	e := echo.New()
    e.Use(middleware.Recover())
	e.Use(middleware.Logger())

	// ルーティング
	e.GET("/", rootHandler) // ルートアクセスでrootHander実行

	// ポート:3000でサーバー起動
	e.Logger.Fatal(e.Start(":3000"))
}
```

<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3412108/82d6773c-7915-0908-8841-507f7fbff6bb.png">
PHP、データベースを使ったときの注意メモ

# 記事の趣旨
今までC#とかC++触ってて「PHPとかデータベースだとこんな仕様があるんやなー」って思ったことのメモ書きみたいなもの

## データベースにNullは作れない
未実装のデータベースを探索することはできない
既に実装されているものにUPDATEするのが正しい

![2023_0629_1454.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3236298/fd258e64-43d4-ea05-b499-10b56d3ea15c.png)

こんなデータベースでIDが255のものを探すのは現実的じゃない

## 0はスキップされる(らしい)
今のところは不具合は確認できてないが、有識者曰く「0は消失する可能性があり、1から処理をするのが好ましい」らしい

## UPDATEのカンマについて
$pdo->query("UPDATE `IdList` SET Name = '任意文字列', Score = 0 , WHERE ID = $id");

これは間違いで

$pdo->query("UPDATE `IdList` SET Name = '任意文字列', Score = 0 WHERE ID = $id");

が正しい
WHEREのあとにカンマをつけるとエラーが出るから気を付けよう(3時間くらいロスした...)

## 文字列の数がとりたいとき
strlen($hoge)

これでとれる

## データベースから取得した値の文字列を取りたい

``` PHP
$data = $pdo->query("SELECT * FROM `IdList` WHERE ID = $id");
foreach ($data as $row) 
{
    $getName = $row['Name'];
}
```

こんな感じで任意のキーをとれる
Leetcode 125. Valid Palindrome

# Problem
この問題は、与えられた文字列が回文（前から読んでも後ろから読んでも同じになる文字列）かどうかを判断するというものです。
> A phrase is a palindrome if, after converting all uppercase letters into lowercase letters and removing all non-alphanumeric characters, it reads the same forward and backward. Alphanumeric characters include letters and numbers.

InputとOutputの例です。
```
Input: s = "A man, a plan, a canal: Panama"
Output: true
Explanation: "amanaplanacanalpanama" is a palindrome.
```

https://leetcode.com/problems/valid-palindrome/description/


## Key Idea
2つのアイデアがあります。
1つ目のアイデアは、回分ならば文字列を逆にしても同じ文字列となるはず、というものです。
2つ目のアイデアは、2つポインタを使って、左からと右から一要素ずつ比較していく、というものです。

## Alphanumeric characters
この問題は、回分判定の前段階として、文字中の英数字のみを考慮します。これには、Pythonでは、ビルトインの`isalnum()`関数を使う方法と、正規表現を使う方法があります。
正規表現では、`re.sub(r'[^a-z0-9]', '', s)`と書くことができます。`a-z`もしくは`0-9`にマッチしない文字(`^`)の置換を行います。
Leetcodeの他の方の回答を見た印象では、`s.isalnum()`関数を使う方が一般的なのかもしれません。

## Approach #1 Compare with Reverse
最初に、非英数字の文字を取り除き、すべて小文字に変換します。その後、文字列がその逆順と等しければ、それは回文であると判定します。リストの逆順は、`list[::-1]`で表現できます。

```python
class Solution:
    def isPalindrome(self, s: str) -> bool:

        new_str = ''
        for c in s.lower():
            if c.isalnum():
                new_str = new_str + c

        # One linerでこのように書くことも可能です
        # new_str = ''.join(c for c in s if c.isalnum()).lower()

        reversed_str = new_str[::-1]
        return new_str == reversed_str
```

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。1)lower関数、2)文字列の変換、3) 文字列の逆順化 4) 2つの文字列の比較のそれぞれがO(n)の時間を必要とします。ここで、nは文字列の長さです。

- Space complexity: O(n)。1)lower関数、2)文字列の変換、3) 文字列の逆順化 のそれぞれでO(n)のメモリを必要とします。文字列の比較には追加のメモリは必要ないため、O(1)です。

## Approach #2 Two Pointers
2つのポインタ（一つは先頭から、もう一つは末尾から）を使用して文字列をスキャンし、各ステップでポインタが指す文字が等しいか確認することができます。この場合メモリ使用量を削減することができます。

```python
class Solution:
    def isPalindrome(self, s: str) -> bool:

        left, right = 0, len(s) - 1

        print(s)
        while left < right:
            while (left < right) and (not s[left].isalnum()):
                left += 1

            while (left < right) and (not s[right].isalnum()):
                right -= 1

            if s[left].lower() != s[right].lower():
                return False
            left, right = left + 1, right - 1

        return True

```

`while (left < right) and (not s[left].isalnum())` で `left < right`の条件を忘れないようにする必要があります。文字列の左右からスキャンしている際に、左のポインタが右のポインタを追い越さないようにするためです。ここで `left < right`の条件を忘れると、ポインタが文字列の範囲外に移動しエラーが発生する可能性があります。これは、与えられた文字列のすべてが非英数字の文字で構成されている場合などに発生します。このエラーを防ぎ、両ポインタが適切な範囲内に留まることを確保します。

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。1) 非英数字のスキッピングと `while (left < right) and (not s[left].isalnum())` のそれぞれがO(n)の時間を必要とします。ここで、nは文字列の長さです。

- Space complexity: O(1)。Approach #2では、文字列の変換も文字列の逆順化もおこなっていません。また、文字列の比較やlower関数の利用もも1文字１文字実施しています。


## Reference
https://www.youtube.com/watch?v=jJXJ16kPFWg
Leetcode 1. Two Sum

# Problem
リスト `nums` と特定の値 `target` が与えられ、`nums` の2つの要素を合計すると`target`になる要素のindexを返すという問題です。
> Given an array of integers nums and an integer target, return indices of the two numbers such that they add up to target.

InputとOutputの例は次になります。
```
Input: nums = [2,7,11,15], target = 9
Output: [0,1]
Explanation: Because nums[0] + nums[1] == 9, we return [0, 1].
```

https://leetcode.com/problems/two-sum/description/

## Key Idea
返す値がindexというのがポイントになります。"補数"（targetから現在の数を引いたもの）が既にリストの以前の部分に存在するかどうかを確認します。
リストで走査した値の管理には、Hashtable(PythonではDictionary)を使います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/99549/0609393e-e81b-b984-c6cd-efe335c2eadc.png)


## Approach #1 : Brute Force
まずは、Brute Force 手法を記載します。
```python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(i+1, len(nums)):
                if nums[i] + nums[j] == target:
                    return [i, j]
```

この解法では、計算量は下記の様になります。

- Time complexity: O(n^2)。二重ループを使っています。ここで、nは`nums`の要素数です。

- Space complexity: O(1)。必要なメモリは、`nums`の長さに依存しません。

## Approach #2 : Hashmap
Key Ideaで言及した、補数とHashmapを利用した方法です。
```python
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d = {}

        for i, num in enumerate(nums):
            complement = target - num

            if complement in d:
                return [d[complement], i]
            else:
            
            d[num] = i

```

この解法では、計算量は下記の様になります。

- Time complexity: O(n)。リスト全体を1回しか走査しないためです。

- Space complexity: O(n)。最悪の場合、すべての要素をハッシュテーブルに保存する必要があります。

## Reference
- https://www.youtube.com/watch?v=KLlXCFG5TnA
Leetcode 242. Valid Anagram

# Problem
2つの文字列が与えられ、その２つがアナグラムかどうか (文字の順序を変えて、別の単語になる)を判定するプログラムを書くという問題です。
> Given two strings s and t, return true if t is an anagram of s, and false otherwise.

InputとOutputの例は次になります。
```
Input: s = "anagram", t = "nagaram"
Output: true
```

https://leetcode.com/problems/valid-anagram/description/

## Key Idea
2つの解法が考えられます。
一つはHashmap (Dictionary)を利用する方法、もう一つはSortを利用する方法です。
最後に、面接では使えないが実務的には有効な方法も紹介します。

## Approach #1 : Hashmap
`{a:3, n:1, g:1, m:1}` といったように、文字列をdictionaryに変換した後に比較する方法です。get関数を使うと、dictionaryにkeyが存在しなくてもerrorではなく `None`や指定した値を返してくれるのでスッキリとしたコードにすることができます。

```python
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:

        if len(s)!= len(t):
            return False

        d1, d2 = dict(), dict()

        for i in range(len(s)):
            d1[s[i]] = 1 + d1.get(s[i], 0)

            # 上記のようにgetを使った一文は、下記のif文と同じ挙動です
            # if s[i] in d1:
            #     d1[s[i]] += 1 
            # else:
            #     d1[s[i]] = 1 

            d2[t[i]] = 1 + d2.get(t[i], 0)

        for key, value in d1.items():
            if d2.get(key) != value:
                return False

        return True
```
この解法では、計算量は下記の様になります。

- Time complexity: O(n)。各文字列を1回だけ走査します。n は文字列の長さです。

- Space complexity: O(1)。問題文中に文字列sとtはアルファベットという制約があるため、O(1)となります。

ただし、Follow up questionで言及されているように、sとtがUnicodeの全範囲の文字を含む可能性があるとすると、最悪のシナリオでは、sとtがすべて異なる文字から成る場合、ハッシュマップのサイズは文字列の長さに比例します。したがって、このようなシナリオでは、Space complexityはO(n)となります。

## Approach #2 : Sorting
2つの文字列がアナグラムであるためには、文字列をソートした場合、同じ文字列になるはずです。

```python
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return sorted(s) == sorted(t)
```

Sortingの計算量は、言語や関数に依存します。Pythonのsorted関数は、Timsortというアルゴリズムを使用しており、最悪ケースでもTime complexity がO(nlogn)、Space complexityがO(n)となることが保証されています。

## Approach #3 : Counter
Counterクラスを利用する方法は、アナグラムの定義を考えると直感的な方法です。Interviewでは適切ではないかもしれませんが、実務においては有用です。`Counter('mississippi')` と実行すると、`Counter({'i': 4, 's': 4, 'p': 2, 'm': 1})` に変換されます

```python
class Solution:
    def isAnagram(self, s: str, t: str) -> bool:
        return Counter(s) == Counter(t)
```

実際、Leetcodeのテストケースを実行すると、Approach #1, #2よりも良いRuntime, Memory performanceの結果になりました。

## Reference
- https://www.youtube.com/watch?v=9UtInBqnCgA
- https://note.nkmk.me/python-collections-counter/#collectionscounter
JavaScriptとTypeScriptの選定基準

##  アジェンダ
この記事では、JavaScriptとTypeScriptの間で選択をする際の基準を私なりに調べてまとめさせて頂きます。

## JavaScript
JavaScriptは、ウェブの開発における[デファクトスタンダード](https://wa3.i-3-i.info/word15280.html)です。ほとんどのブラウザがJavaScriptをネイティブにサポートしており、サーバーサイド開発にも使用されることがますます多くなっています。

### JavaScriptの利点
:::note info
- **普及度**: JavaScriptはほとんどのブラウザでサポートされています。そのため、互換性や可用性の問題がほとんどない。
- **フレキシビリティ**: JavaScriptは動的型付け言語で、そのフレキシビリティは開発者に大いに評価されている。
:::

### JavaScriptの欠点

:::note alert
- **エラー検出**: 型システムがないため、開発の初期段階でエラーを検出することが難しい場合がある。
- **大規模プロジェクト**: 型安全性の欠如は、大規模なコードベースでは管理が難しくなる可能性がある。
:::

## TypeScript

TypeScriptはJavaScriptの[スーパーセット](https://anken-hyouban.com/blog/2021/09/09/superset/)であり、静的型付けとその他の機能をJavaScriptに追加します。

### TypeScriptの利点
:::note info
- **型安全性**: TypeScriptは静的型付けを提供し、コンパイル時にエラーを検出することができます。
- **大規模プロジェクト**: 型情報が存在するため、大規模なコードベースでも管理が容易になります。
:::

### TypeScriptの欠点
:::note alert
- **学習コスト**: JavaScriptの経験がある開発者でも、TypeScript特有の機能を学ぶ必要がある。
- **コンパイル時間**: TypeScriptはJavaScriptにトランスパイルされるため、コンパイルに時間がかかる可能性がある。
:::

## 選定基準

JavaScriptとTypeScriptの選定基準では、以下のような要素が挙げられると考えます。

:::note info
- **プロジェクトの規模**
- **チームのスキルセット**
- **開発スピードと品質のバランス**
- ラ**イブラリやフレームワークの互換性**
:::

## まとめ
**規模が大きく、長期的なメンテナンスが必要なプロジェクト**では、**TypeScript**の型安全性が有利になる可能性があります。一方、**小規模なプロジェクトやプロトタイピング**では、**JavaScript**のフレキシビリティが速度を優先する場合に有利になるかもしれません。

## 参考
- [【React.js／Next.js】TypeScript OR JavaScriptの選定基準](https://zenn.dev/kakio/articles/7dd35326619c68)
JavaScriptでルービックキューブGUIを作る

# はじめに
　[過去の記事](https://qiita.com/ob_nullpo/items/d04ceaf84ea212d27f47)で簡易的な3D表現をJavaScriptで実現する方法を紹介しました。理屈の紹介と、単に立方体が回転するだけでは退屈なので拡張してルービックキューブのGUIを作成します。

完成品はこのように動きます。

![picture_pc_c6546de805d0c0c1f35bdc249a267d62.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364169/278a6fc2-6921-0616-bbd7-b059ae1ae507.gif)

# ルービックキューブGUIを作成する際の課題
　ルービックキューブのGUIを作成する際、解決しなければならない課題がいくつかあります。
- 構成するオブジェクトが多い
- レンダリングが複雑
- パーツの移動の表現が複雑

このくらいでしょうか。それぞれについての解説と、採用した解決方法を紹介します。

# 構成するオブジェクトが多い
　ルービックキューブはシンプルなパズルではありますが、構成部品が多く、26個の立方体で構成されています。26個の立方体を全て6面体として扱うと156個の面を持ち、管理しなければならない頂点の数は208個にも及びます。ここに回転の表現が加わると、行列積を用いた場合は、頂点1か所あたり33回の乗算、24回の加減算が行われます。
　※四元数を用いる方法で計算の回数を少し減らすことができます。
　コンパイル言語の場合はこの程度の計算量は問題になりませんが、スクリプト言語の中でも、特に算術演算が遅い言語を選ぶとこの計算量が目に見えるようになります。ですが、今回使用しているJavaScriptは算術演算が非常に高速なため、計算負荷としては問題になりません。

　構成部品が多い特徴は計算機的な問題点もありますが、全く別の問題も含んでいます。とてもシンプルで、**コーディングが辛い**、という問題があります。理論的にはシンプルでも、作らなければならない物量が多いため、出来上がるソースコードの大半は**定義行**になります。この類の作業はどうしても時間がかかるので、時間の都合でこういったアプリケーションが作れない方は多いと思います。

# レンダリングが複雑（1）
　ルービックキューブの構成部品を26個の立方体として実装すると、全てを6面体として扱うと156個の面があることは先述の通りです。しかし、実際に目に見える面は、高々表面の27面、何か操作を加えている最中であれば高々28面しか見えません。条件によっては9面しか見えない場合もあります。この、面が見えるか見えないか、の判定でレンダリングすべき面を選定する処理はかなり複雑になります。しかし、今回はこの複雑な処理を考える必要はありません。JavaScriptが高速な言語だからです。カメラから遠い順に全ての構成パーツをレンダリングしてしまえば帳尻が合います。表面を透明色で面の辺だけをレンダリングするとこうなります。
![picture_pc_d08cbde55461645e7d3286f1acefdaa0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364169/d0cbbb4f-93e1-2914-d405-98567c9b7c38.png)

　なかなかすごい景色です。レンダリングが遅い言語でこのような雑なアルゴリズムを採用するとフレームレートが一気に落ちます。高速なJavaScriptであっても、処理が若干重くなっているのが筆者の環境では体感できました。ですが、そんなに高いフレームレートでレンダリングすることを目的とはしていなかったため、この問題は扱わないことにしました。

# レンダリングが複雑（2）
　レンダリングの課題はもう一つあります。キューブに対して何か操作を行っている最中は、キューブが凸多面体ではなくなり、カメラから遠い順にレンダリングする、という横着が破綻します。
![picture_pc_950c2f9fbee707fb744584b17996ef40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364169/8b62fe11-f708-df92-3092-7e5d34f1c644.png)
このように表示が乱れる現象が発生します。ですが、解決方法はシンプルで、9個の立方体を含む直方体、17個の立方体を含む直方体、の2つの直方体として考え、どちらの直方体が先にレンダリングされるか、を判定してレンダリングすれば上記の表示の乱れを回避することができます。

# パーツの移動の表現が複雑
　ルービックキューブに対して回転動作を作用させると、構成部品が物理的に移動します。青〇で印をつけたキューブが
![picture_pc_4c4909b5660a6e708d4779764bb043ac.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364169/a559f0d5-dd50-80e1-d7b3-5b89bf45c9eb.png)
ここにある場合と、
![picture_pc_5fff22057cfd45fcef08692f9446def3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364169/b96209df-d1f9-80a4-f42f-d873befd1d1e.png)
ここにある場合とで、作用させることが可能な動作が変化します。この変化を実装するのは大変です。この課題に正面からアタックすると大変ですが、横着できます。大事なのは、**見た目が動いたように見えていれば良い**、ということです。今回採用した方法は、**色だけ入れ替えて座標を変えないという方法です**。こうすれば、パーツが移動してしまうことはないので、作用させせる動作の定義も少なくて済みます。汎用3Dエンジンで実装しようとした際、

このキューブがここにあるときは、xxxとyyyとzzzの動作ができて...ここにあるときはaaaとbbbとcccの操作ができて...

のようなことをやり始めると考慮するパターンの多さにうんざりします。

# まとめ
　今回はルービックキューブのGUIを作成する際に生じる課題と解決方法を紹介しました。大きな課題を正面突破しようとすると非常にコストがかかる場合でも、横着して辻褄を合わせることができることは多々あります。今回の題材はルービックキューブでしたが、実際の業務でも似たような現象によく遭遇します。課題に対する解決策は様々であり、どの方法が最適かは状況に依存します。

[ソースコード](https://github.com/HirokiHayakawa/javascript3d/tree/master/rubiks_cube)
GrafanaでDocker Desktopのコンテナを監視する

現在、業務の方でGrafanaというソフトウェアを使っています。
Grafanaの公式ブログで、[「Grafanaなら簡単にDocker Desktopの監視ができるぜ」という趣旨の記事](https://grafana.com/blog/2023/06/07/easily-monitor-docker-desktop-containers-with-grafana-cloud/)を見かけました。
家ではたまにDockerを動かす機会があり、折角なので試してみることにしました。
概ね上記の記事の通りにやっていきます。興味がある方はそちらもご覧ください(英語)。

## 軽く用語説明
GrafanaとDockerについて、簡単に説明します。
[Grafana](https://grafana.com/)は運用監視の統合ソフトウェアです。メトリクス – 例えばCPU使用率やネットワークのトラフィックといった時系列データを可視化したり、閾値を設定してアラートを発報したりできます。
[Docker](https://docker.com/)はコンテナ技術による仮想化ソフトウェアです。所謂VMってやつですが、Dockerで動かすVMは専らコンテナと呼ばれてます。

## 実践
### Grafanaにサインアップ
家のPCではGrafanaを導入してないので、まずはGrafanaの導入から。
今回はGrafana CloudというSaaSを使ってみます。なんと無料です。
GrafanaアカウントかSSOでサインアップして、インスタンス名を入れるだけ。
![スクリーンショット 2023-06-13 203837_mod.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/e5afef37-6f6d-6725-db9d-30181ace9f70.png)

これで、Grafanaが使えるようになりました。すごい！

### Docker Desktop監視の追加
ではここからDocker Desktopの監視を導入していきます。

GrafanaのConnectionsの追加で、”Docker Desktop”を選択します。”Docker”で検索すると2つヒットするので注意。
![スクリーンショット 2023-06-13 204752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/ae92a694-1280-525f-7dc7-f96c1d4a2070.png)

選択後、指示の通り、Docker DesktopにGrafana拡張機能をインストールします。
説明文のリンクから飛べます。インストールしたらGrafana側の”Install”を押します。

![スクリーンショット 2023-06-13 204827.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/d856adbe-3ba8-c8b9-cf81-e3a39820f4f6.png)

![スクリーンショット 2023-06-13 204240.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/6d822c15-d73a-2688-8873-c3390482371d.png)

Docker DesktopとGrafanaの連携をするため、APIトークンの生成をします。

適当に名前をつけて”Create API token”をクリック。下にAPIトークンが表示されます。
その下にはDocker Extention側に入力する設定値が表示されます。

![スクリーンショット 2023-06-13 205057_ed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/123dc1e0-29f2-243e-f5a9-2641865cb197.png)

下側の設定値をDocker Desktop側の所定の場所(Connection Variables)にコピペします。
貼り付けたら、”Connect to Grafana Cloud”をクリック。
![スクリーンショット 2023-06-13 205129_ed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/02ea300c-c646-ab7e-cdcc-7d980a3c5836.png)

“Sending data to Grafana Cloud” と出たら成功です。これでGrafana側にメトリクスが送信されるようになり、連携は完了です。
![スクリーンショット 2023-06-13 205259.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/d2462838-8cd3-6b60-70ac-1c04a190c579.png)

### ダッシュボードについて
Dashboardの方に進むと、3つのダッシュボードが作成されています。
* Docker Desktop - Docker Overview
    * Dockerコンテナのメトリクス。CPU使用率、メモリ使用率などなど。
* Docker Desktop - Docker Logs
    * Dockerコンテナのログの情報…のはずなんですが筆者の環境ではコンテナのログが取れず。内容としてはログ件数やワーニング・エラー数など。
* Docker Desktop - Node Exporter
    * Dockerホストのメトリクス。コンテナ側と概ね同じ。


Minecraftのコンテナを動かしている時のOverviewはこんな感じです。

![2023-06-13 21.30.48 hogehoge.grafana.net b54b41d40986.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3347403/b63e0d2d-395d-5e35-6818-d201cbe141a1.png)

上部にDockerインスタンスやコンテナの絞り込み機能があるように、複数のDocker環境を一元管理できるのでしょう。大規模な環境でも俯瞰で見れるので業務での活躍もできますね。
KotlinプロジェクトでGatlingを実施する

# はじめに
負荷試験ツールとしてGatlingを初めて使用したので、インストールからGatling実行結果を確認するまでの手順をまとめました。

# Gatlingとは
Gatlingはオープンソースの高性能負荷テストツールで、主にHTTPプロトコルを使用したWebアプリケーションを対象にしたものです。その設計により、高度なシナリオを記述し、テストの結果を分かりやすい形で表示できます。これにより、大量のユーザートラフィックを扱う能力がサーバーに備わっているか確認することが可能となります。

GatlingではScalaというプログラミング言語が利用されており、DSL（ドメイン特化言語）を使って負荷テストシナリオを定義します。このため、複雑なシナリオでも読みやすく、メンテナンスしやすいコードを書くことが可能となります。

# Kotlinプロジェクトの構築について
Gatling自体はScalaをベースにしていますが、他のプログラミング言語でも使用可能です。KotlinとGradleを使用したプロジェクトであるgatling-gradle-plugin-demo-kotlinです。

https://github.com/gatling/gatling-gradle-plugin-demo-kotlin


このプロジェクトは、Kotlinで記述されたGatlingのシナリオを実行するデモンストレーションとなっています。Gradleプラグインを使用することで、Gatlingのシミュレーションを簡単に実行することが可能です。

1.クローン
```bash
git clone https://github.com/gatling/gatling-gradle-plugin-demo-kotlin.git
```

2.ディレクトリへの移動
```bash
cd gatling-gradle-plugin-demo-kotlin
```

3.Gatlingシミュレーションの実行
```bash
./gradlew gatlingRun
```

上記のコマンドを実行すると、GradleとKotlinを用いてGatlingのシミュレーションが実行されます。./gradlew gatlingRunコマンドはプロジェクト内の全てのGatlingシミュレーションを実行します。

# Gatlingの負荷試験結果について

Gatlingの負荷試験が完了すると、詳細なレポートがHTML形式でresultsフォルダに生成されます。このレポートは非常に分かりやすく、パフォーマンスの各指標を視覚的に理解することが可能です。

以下に示すのは、典型的なGatlingの結果レポートのスクリーンショットです。

![スクリーンショット 2023-06-25 18.49.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330132/4d178e30-7385-51ad-2d5b-643a7f65e532.png)

このレポートには以下の情報が含まれています。
・Response Time Ranges
　レスポンス時間の範囲（レンジ）ごとにリクエストの数を集計したものです。
・Number of requests
　負荷テスト全体で何回のリクエストが行われたかを示す数値です。
・Response Time X percentile
　計測したデータの全体のX%に位置するレスポンスタイム(ms)
・Cnt/s
　"counts per second"の略で、1秒あたりのリクエスト数を示しています。

以上の詳細なレポートにより、Gatlingを用いた負荷試験の結果を深く理解し、それに基づいてアプリケーションのパフォーマンス改善を行うことが可能となります。
Watson Discovery：Content Miningの相関値をAPIで取得してみた

Watson Discovery の Content Miner で Relevancy（相関）の値を取得する API を試してみました。

# やりたいこと
以下の「Relevancy」（右側のオレンジは黄色の値）の値をAPIで取得したい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/5838e901-1543-363b-1dab-6fabacd149ec.png)

# 結果
こうすればできました。
```python:relevancy:true
response = discovery.query(
  project_id=project_id,
  query='オイル漏れ',
  aggregation='term(field:通称名,relevancy:true,count:100)',
  count=2
).get_result()

for relevancy_data in response['aggregations'][0]['results']:
    print(relevancy_data['key'] + " : " + str(relevancy_data['relevancy']))
```
結果のイメージ図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148302/da0f9c49-d6f5-d57e-7c87-acfd8a515aff.png)

# 参考情報
製品マニュアル
`aggregation` パラメータの `relevancy` を `true` にすれば良いだけでした。
[クエリAPIの構文](https://cloud.ibm.com/docs/discovery-data?topic=discovery-data-query-aggregations#term-syntax)

# お断り
このサイトの掲載内容は私自身の見解であり、必ずしも所属会社の立場、戦略、意見を代表するものではありません。 記事は執筆時点の情報を元に書いているため、必ずしも最新情報であるとはかぎりません。 記事の内容の正確性には責任を負いません。自己責任で実行してください。
PostgreSQLのダンプ(pg_dump）、リストア(pg_restore）をAWS S3でやってみた

PostgreSQLのダンプツール(pg_dump）、リストアツール(pg_restore）を使おうと思ったら
データがでかいと、ローカルPCにダンプファイル作れない！！と困った。
それなら、AWS-S3にダンプファイル作ればよくないか？と思ったら出来たので、やり方を書きます。

## 前提
AWS CLIを使うことが前提です。

## ダンプ pg_dump

```
pg_dump -h ホスト -d データベース名 -U ユーザー -a -v -Fc  | aws s3 cp - s3://BUCKET名/ダンプファイル名
```

データがかなりでっかい（ファイルサイズが50G超えると）と
```
An error occurred (InvalidArgument) when calling the UploadPart operation: Part number must be an integer between 1 and 10000, inclusive
```
と、エラーになります！！

このエラーが発生したときは --expected-size オプションを指定します。
S3のcliはマルチパートアップロードっていう方法でアップロードします。
速くアップロードするためにファルを分割してパラレルアップロードするようなイメージです。
しかし、分割数は最大で10000までと決まっています。
なので、事前にアップロードするファイルサイズを--expected-sizeで指定しておくと、分割数を10000個以内になるように、うまいぐあいに分割してくれます。
なので、100Gのファイルをアップロードする場合は
100 * 1024 * 1024 * 1024 = 107,374,182,400を指定すればOKです。

--expected-size
```
pg_dump -h ホスト -d データベース名 -U ユーザー -a -v -Fc  | aws s3 cp - s3://BUCKET名/ダンプファイル名 --expected-size 107374182400
```

## リストア pg_restore

```
aws s3 cp s3://BUCKET名/ダンプファイル名 - | pg_restore -h ホスト -d データベース名 -U ユーザー -a -Fc -v
```

ダンプファイルの一部のテーブルだけrestoreしたい場合

```
aws s3 cp s3://BUCKET名/ダンプファイル名 - | pg_restore -h ホスト -d データベース名 -U ユーザー -a -Fc -v -t リストアしたいテーブル名
```

と-tでテーブル指定しますが、この場合
```
[Errno 32] Broken pipe
```
とエラーが発生します。
ですが、これは無視してもOKです。

エラーになる理由は
-t指定して一部のテーブルだけをリストアする場合、そのテーブルのリストアが完了するとpg_restoreコマンドは終了します。
ですが、まだダンプファイルには続きがある場合、s3のcliコマンドはファイルのダウンロードを続けます。
この時、続けようとしたが「|」先のpg_resotreコマンドが終わっているので「|」がおかしい。となっただけので、リストア自体には問題ありません。
新人、優秀すぎて草

# はじめに

6月ももう終わりですね。今年から入ってきた新人の方達は少しずつ業務に慣れてきた頃でしょうか？
私の会社にも、5月からエンジニアの新人が入ってきました。
うちの場合新人がいきなり実務に入ることはなく、まずは研修の一環として「仮想プロジェクト」というものに取り組んでもらいます。どんな研修なのか具体的に知りたい方は<a href="https://qiita.com/Terao-Takumi/items/d2b02a4cf0470675107e" target="_blank">こちら</a>。

そんな仮想プロジェクトに取り組んでいる新人たちを見ていて感心することが何度もあったので、今回の記事でまとめていこうと思います。

# 仕事の取り組み方編

これを読んでいる新人のあなたは、まずはこういうことを意識して働いてみるといいと思います。

## 質問がシンプルで具体的

「〇〇ってなんですか？」「どうすればいいですか？」みたいな脳死質問、新人の方はやりがちなんじゃないでしょうか(てか私もめちゃくちゃやってた)。
こういう聞き方をされると、答える側はとっても困りますよね。どこからどこまで説明すればいいのか分かりませんから。
一方今年の新人たちからは、基本的に漠然とした質問が飛んできません。自力で限界まで調べた上で、それでも分からないことや自分たちでは判断できないようなことだけ質問されたという印象です。
記憶に鮮明なのはこんな質問。

「〇〇の処理をしようと思ってて、gemが必要そうなので入れようと思ってます。(メモを見せながら)調べてみた感じこの3つのgemがよく使われているようなのですが、どれを使った方がいいとかありますか？」

これに対して私、見せられたメモの中から「実務で使うことになると思うのでこれ使ってください」と指差して質問対応終了。
質問受けながら、内心「うお〜〜いいね〜〜〜」とニヤついてました。
これ以外の質問も、基本的に抽象度が低いから答えやすい。時間を持っていかれない。先輩の時間をなるべく取らないようなやり方で質問しているのが素晴らしいですね。私も見習おうと思いました。

## アウトプットのレベルが高い

ここでいう「レベル」とは、内容というよりも体裁のことです。
「いやいや、内容の方が大事でしょ」って思ったそこのあなた。ええ、もちろん内容も超大事です。
ですが、見た目も引けを取らないくらい大事です。これは他人のアウトプットをレビューする側になって初めて気づきました。
例え内容が素晴らしかったとしても、見た目が汚い(フォーマットや文字サイズが揃っていない、無駄に色が多いなど)と変なところに気を取られてそもそも肝心の内容が入ってきません。
先輩に何かをレビューしてもらうときは、「自分がそれをレビューする立場だったら一目見てうんざりしないか」を確認するようにしましょう。この辺の美的感覚がない人は、同期に一度見てもらうことをおすすめします。

## 余裕を持って質問してくる

仮想プロジェクトでは最初に自分たちでリリースまでの計画をたて、基本的にはその計画に沿って開発を進めることになります。
で、今回の新人たちは、予定のだいたい二日前くらいにはそのことについての質問をしてきました。例えば、「明後日からテストに入る予定なんですけど、どんな感じで進めていくのがいいのでしょうか？」みたいな。
前日までに準備をしておくことで、当日にはいきなり本題に入ることができる状態になっているわけですね。こういうスタンスを常に持っていたおかげで、彼らのプロジェクトはほぼオンスケ(なんなら常に1〜2日くらい巻いてた)でリリースまで進むことができていました。
これは面倒を見る先輩の立場からしても非常にありがたいです。こっちがあれこれ考えて伝えたり教えたりしなくても、きた質問に答えてればそれでスムーズに進んでいってくれるんですから。

書いてて思いましたが、これら3つ全てに「先輩の時間を奪わない配慮」みたいなものが感じられますね。

# 技術編

おまけです。未経験の新人にこんなこと期待していないので、これらができていないからといって落ち込む必要はありません。

### 気づいたらレスポンシブ対応されていた

ちな、誰も頼んでないです

### CSS設計になぜかFLOCCSSが採用されていた

`super_small_pic_2`みたいなclass名を量産していた新人時代の私とは

### なんかpartialとか使っちゃってる

partialに関して一切質問されていなのでおそらく独学です

### SQL減らしてパフォーマンスめちゃめちゃ向上させてた

本当に新人だおね、？(⌒-⌒; )

# 最後に

自分これできてるかも！と思ったそこのあなた、油断は禁物だゾ♡
Voltaでpnpmを固定したい

:::note warn
この記事はVoltaのバージョンが1.1.1のときに記述しました。実験的な機能に言及しているので機能差分が考えられますので注意してください。
:::
[Volta](https://volta.sh/)はJavaScriptのツール管理を行うライブラリです。`package.json`を用いてNodejsはもちろん[npm](https://docs.npmjs.com/cli/v9)、[yarn](https://yarnpkg.com/)のようなパッケージマネージャーのバージョンを固定できます。
```json:package.json
  "volta": {
    "node": "20.2.0",
    "npm": "9.6.6"
  }
```
Voltaについての詳細な説明は[こちらの記事](https://qiita.com/KokiSakano/items/1bfcad79a0ba5e549186)で書きました。

近頃はパッケージマネージャーの新たな選択肢として[pnpm](https://pnpm.io/)がよく使われるようになっています(ライブラリの紹介でもよくpnpmがデフォルトになっているのを見かけます)。しかし、現行のVoltaではpnpmのバージョン固定が実験的な機能としてサポートされているだけなので、npmやyarnとは異なりいくつかの手順を踏んで利用する必要があります。この記事ではそのために必要なことを紹介します。

## バージョンを1.1.1に
pnpmをサポートするバージョン1.1.1までVoltaのバージョンアップを行います。
バージョンアップはインストールした時と同様の手段を用いることで完了します。

## 既存のVoltaとpnpmの設定を切る
多くの人は一度`volta install pnpm`を試していると思うので、ここで`volta uninstall pnpm`をして後続の手順をスムーズに進めるようにすることをお勧めします。私の場合はこれだけでは既存のVoltaとpnpmとの繋がりが完全に切れなかったので、Voltaのアンインストールと環境変数の削除を行なって改めてVoltaのインストールを行いました。最後まで手順を進めてうまく動作しなかった場合はこちらも検討してください。

## 環境変数で実験的機能を有効に
pnpmのバージョン固定を行う実験的機能を有効にするために環境変数を設定します。
UNIX系であれば起動スクリプトに設定を追加してフラグを立てます。
zshを用いている場合は`~/.zshrc`に以下のように一行追加することで有効になります。変更後は`source ~/.zshrc`などで設定を更新してください。
```sh
export VOLTA_FEATURE_PNPM=1
```
Windowsではシステム環境設定で`VOLTA_FEATURE_PNPM`を`1`に設定することで有効になります。

## pnpmのバージョン固定
pnpmのバージョン固定を行いたいNode環境に移動して`volta pin pnpm@latest`とすることで最新のpnpmを`package.json`に固定することができます。