OmniAICreator/Qiita-1.07M huggingface dataset:
Windows版 Cursorのターミナルでmvnw.cmdが実行できない人向け

# mvnw.cmdが見つからないようなエラーになる
Cursorのターミナルでmvnw.cmdを実行しても↓のようなエラーがでる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2964854/b4c5a9b4-97ca-6bc3-d18f-c847978b9479.png)


何やら"mvnw.cmd"が見つからないとか・・・
ちゃんとあるのに・・・

### 解決方法
コマンドの前に「./」を入力しよう！
```
./mvnw.cmd [options]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2964854/cc9bfcca-9c59-65b2-89cd-484814a75125.png)

実行できた！
Route53で独自ドメインを設定してS3でWEBページをホスト

事前準備
* お名前.comで無料のドメインをGET
* 超シンプルなHTML・CSSファイルを用意

下記の図のように、フェイルオーバーも設定せずシンプルな静的WEBサイトを構築したいと思います。
![スクリーンショット 2024-01-20 8.31.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/c1a1c946-4434-5b99-56af-ef42000e3d8a.png)

参考にしたのは下記の記事です。(ありがとうございました。)
[Amazon S3 バケットの静的なウェブサイトにドメインを使用する](URL "https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/getting-started-s3.html")
[S3で静的ウェブサイトホスティングの設定をする](URL "https://blog.serverworks.co.jp/2022/09/06/212352")

手順は上記記事で丁寧に詳しく書いていただいているので、私がハマってしまったポイントだけ備忘録として書きます。

### 1.S3のバケット名とドメインを《完全に》一致させる
![スクリーンショット 2024-01-20 8.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/b4de7972-0ed0-f00b-809c-0dd3f42a7fea.png)　[ステップ 2: ルートドメイン用の S3 バケットを作成する](URL "https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/getting-started-s3.html#getting-started-create-s3-website-bucket")
と、公式にも記載してくれていて、

![スクリーンショット 2024-01-20 8.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/5671d6c6-10a6-baa7-b2f8-2096e2f727e0.png)
Route53の設定画面でもきちんと注意書きしてくれているにも関わらず！！！
私は、
下記の設定にしてしまっていてWEBページが表示されませんでした・・・
レコード名を `blog`.kwtkd.net 
S3バケット名を kwtkd.net

ここに気づかずネームサーバーの書き換えってこんなに時間かかるんだ〜と20時間くらいただ待ってました。笑　流石に自分がどこかでミスってるんだと気づき、Terminaiで下記のコマンドでネームサーバーがお名前.com発行のものからAWS発行のものに書き換わっているか確認。改めて自分の設定ミスに気づく・・・
```sh
NS dig ドメイン名
```
![スクリーンショット 2024-01-20 9.06.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/28e8dcbe-41dc-76c0-8339-b362f4b49322.png)


### 2. S3にHTMLとCSSファイルを、まとめてフォルダのまま入れではダメ
上記の設定ミスに気づき、再度、独自ドメインでアクセスしてみても次は404エラーが・・・
#### 《原因》
S3にアップロードする際にHTMLファイルもCSSも画像フォルダもぜーんぶまとめて1つのファイルでアップロードしてしまっていたから。
#### 《解決》
index.htmlは1つのファイルとして、
cssといimageは1つずつのフォルダとして個別にアップロードすべきでした。
![スクリーンショット 2024-01-20 9.41.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570384/9fef3e80-0711-5470-d496-b2e9bc5a462a.png)


#### 《感想》
解決してみれば、技術も何も本当にイージーミスなことでした笑
2度と失敗しません！




これが無事に独自ドメインでS3にてホストしているWEBページです。http://blog.kwtkd.net
Google MapのPlacesService（プレイスライブラリ）を使ってみた

Google MapのPlacesService（プレイスライブラリ）を使ってみたので、その時のメモ。

[Google Mapのキーの取得方法はこちら（https://qiita.com/sera_ramon/items/707ac5064f6e6343df05）](https://qiita.com/sera_ramon/items/707ac5064f6e6343df05)

```javascript:TestPlacesService.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>TEST PlacesService</title>
  </head>
  <body>
    <div id="map" style="width:100%; height:500px"></div>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=＜＜＜ここにキーを記載＞＞＞&libraries=places&callback=initMap&v=weekly"
      defer
    ></script>
    <script>
      function initMap() {
        alert('pause');
        _map = new google.maps.Map(document.getElementById("map"), {
          zoom: 12,
          center: { lat: 34.9875936, lng: 135.7567649 },
          mapTypeId: "terrain",
        });

        var request = {
          location: new google.maps.LatLng(34.9875936, 135.7567649),
          radius: '500',
          type: ['tourist_attraction']
        };
        service = new google.maps.places.PlacesService(_map);
        service.nearbySearch(request, callback);
      }
      window.initMap = initMap;

      function callback(results, status) {
        if (status == google.maps.places.PlacesServiceStatus.OK) {
          for (var result of results) {
            console.log(result);
          }
        }
      }
    </script>
  </body>
</html>
```

以上です。
Google Mapのキーの取得方法

Google MapのJavaScript版を使ってみました。
PlacesService（プレイスライブラリ）とDistance Matrix API（距離行列サービス）を使ってみましたが、その時のメモです。
まず最初に、APIキーの取得から。

# GoogleのAPIキーの取得

1. Google Cloudコンソールで、適当なプロジェクトを作成するか選択します。
1. 左上のハンバーガーメニューで「APIとサービス」のプロダクトを選択（固定しておくと便利）
1. 「認証情報」を選択

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/a0c41624-c90c-2c8e-58fd-0daf5a26624a.png)

1. 「APIとサービス」画面で「認証情報を作成」→「APIキー」を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/c670cda1-7d2b-2f44-025c-e99fad2c5c6b.png)

1. 「APIキー」が作成される
このキーを利用しますので、メモしておきます。後で確認することもできます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/b5d876ad-d060-54a5-ba4b-e8bf4ed00bb4.png)

1. 作成した「APIキー1」を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/537a39f5-a6fe-e958-96a2-2b3c174f6212.png)

1. キーの名前を適当につける
1. 「アプリケーションの制限の設定」は「ウエブサイト」を選択
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/90cd3dcf-bf77-8e1f-8b79-e4c23300eb31.png)

1. 「ウェブサイトの制限」の「ADD」を押して、キーの使用を許可するサイトを設定。PCでテストするので「localhost」を追加する
1. 「API の制限」は「キーを制限」を選択
1. 「Select APIs」を選択し「Maps JavaScript API」「Distance Matrix API」「Places API」をチェック
1. 「保存」を押して設定内容を保存
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/952a5e6e-567c-c4d9-60c1-d51160c1eff4.png)

# 利用料金の確認
1. 左上のハンバーガーメニューで「お支払いAPIとサービス」のプロダクトを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136795/5dfcd57e-82a6-4a81-9d74-3761abe0523d.png)


以上です。

[PlacesService（プレイスライブラリ）の使い方](https://qiita.com/sera_ramon/items/88ffacdb944deef54b20)
[Distance Matrix API（距離行列サービス）の使い方](https://qiita.com/sera_ramon/items/ea45084fa2fea320e8bb)
Salesforce Reports and Dashboards REST API 


+ [Salesforce レポートおよびダッシュボード REST API 開発者ガイド](https://developer.salesforce.com/docs/atlas.en-us.api_analytics.meta/api_analytics/sforce_analytics_rest_api_intro.htm)
+ [Salesforce Reports and Dashboards REST API Curlコマンド偏](https://qiita.com/Keiji_otsubo/items/d6ceda32fdd8fe132b60)

+ [I'm trying to use the Analytics Download API to get a PNG of my dashboard, but I'm getting errors. If we can download Lightningdashboard from Analytics Download API?](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XGkEk)

これで機能すると思ったけど、エラーだったらしい

```
https://[my_organization-dev].my.salesforce.com/services/data/v60.0/analytics/download/dashboard/01Z5h000000BxkWEAS.png
```

```Json
[
    {
        "errorCode": "NOT_FOUND",
        "message": "The requested resource does not exist"
    }
]
```

URL に /service/data/version を追加するとエラーが発生します

```
https://[my_organization-dev].my.salesforce.com/analytics/download/dashboard/01Z5h000000BxkWEAS.png
```

# 応用

+ [項目Ａがレポートで使用されている場合、項目Ｂとレポート上で置き換えることは可能でしょうか。※項目Ａは複数のレポートで使用されており、手動で置き換えるのはあまり現実的ではありません](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007YwB6j)

+ [チーム別にレポート作成が必要となると、膨大な量となり…（現在はダッシュボードに10ほどのレポートを使用しているため、10×チーム数となる。）効率的＆シンプルに作成できる方法はないかと質問させていただきました。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ahqkv)




# 未解決

+ [レポートおよびダッシュボードAPIについて](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XIcCT)
Kaggle参戦記：首の皮1枚で金メダル圏内にステイ

おはようございます。引き続きKaggleの「[AIの文章か人間の文章かを当てるコンペ](https://www.kaggle.com/competitions/llm-detect-ai-generated-text)」に参加中です。1/15にLBスコア0.972を刻んでから5日間、あまり進展がありませんでした。一方で、ランキング上位陣は徐々にスコアをあげており、私の順位は現在18位。幸い、まだぎりぎり金メダル圏内にいます。

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3666147/3353edf5-7b51-dfd1-89c7-a498334c0647.jpeg">

最後のラストスパート中のデータサイエンティストたち ([Bing Image Creator](https://www.bing.com/images/create))


締め切りは日本時間で週明けの1/23（火）8:59なので、今週末が最後の追い上げになります。締め切り前1週間はCodeも共有できなくなっていました。「[驚きの新事実](https://qiita.com/rho-guy/items/26c53dd8ecb2e50e4be7)」発覚後、いろいろと面白い観察結果も出てきたので、シェア用にCodeも書いていたのですが、コンペ終了後までおあずけです。

一方、おかげさまで先日シェアした[データセット間の関係の視覚化](https://www.kaggle.com/code/rhoguy/eda-for-llm-detection-dataset-relation)が好評で、upvoteがたまって銀メダルをいただけました。Kaggleマスターへの道は、コンペでメダルを獲得するよりも、Codeで目指した方が確実なのではないかと考え始めています。

いろいろとお話したいことはありますが、今はちょっと控えておきます。下記、簡単に今の状況だけお伝えしておきます。

- 過去の自分のAUCとLBスコアの変化を追ってみました。幸い、AUCとLBスコアに強い逆相関のようなものは見られませんでしたが、LBスコアを順調に伸ばしていった一方で、AUCの値はどうどうめぐりをしていたことが分かりました。残りの期間は「AUCを伸ばすこと」を優先して力を割いています。

- ソースコードを2つに分けました。一つはLBスコア追及版、もう一つはローカルでのAUC追及版です。ただ、これはちょっと悪手だったかもしれない。コード管理の手間が増大し、様々な場面でミスを誘発することになっています。

- マインドセットを変えました。以前は「AIの文章と人間の文章を見分けるのは難しい」と思っていたので、高いAUCスコアを見ると「これは過学習のせいに違いない」と思っていました。今は、わざわざ運営がノイズを混入させないといけないほど、「実はAIの文章と人間の文章を見分けるのは簡単」なのだと思うようにしました。これで心置きなく高いAUCを追及できます。

- プライベートLBスコア集計用の最終版は、LBスコア最高版、AUC最高版、LBスコア＆AUCバランス版の3つを提出しようと思っています。それぞれのパブリック⇒プライベートへの変化がどう出るか、楽しみです。
Perl 備忘録



# 環境
|項目|説明|
|----|----|
|OS|Windows10||
|perl|Strawberry Perl 5.36.1.1 ||

# Version
#### Strawberry Perl ***5.36.1.1*** を採用
※ 5.<b>38</b>.0.1は下記ツイートと同じ状況になったため、取り止め
>strawberry perlの最新版（5.38.0.1）って，ロケール関係の警告でる．Locale 'Japanese_Japan.932' is unsupported, and may crash the interpreterって言われちゃう．5.36.1.1ではそんなことなかったのに．powershellでロケール変更すれば動くのかもしれないけど，面倒なので，5.36.1.1でいいや．
https://x.com/Dolista/status/1717006043421827140?s=20

# 日本語の文字化け Wide character
### 手動
「テスト」をutf8 でdecode し、内部文字列を encode (今回windowsなのでsjis)
```
$str = Encode::encode('sjis', Encode::decode('utf-8', 'テスト'));
print($str."\n"); #テスト
```

### 自動
use utf8で 内部文字列化
binmode で 内部文字を cp932 encode
```
use utf8;
binmode(STDOUT, ':encoding(cp932)');
```


https://dorapon2000.hatenablog.com/entry/2022/02/23/203252

# クラスの記述方法
```perl
#!C:\Strawberry\perl\bin\perl
package hiro;
use utf8;
use strict;

# クラス変数
our $count = 0;

# コンストラクタ（生成関数）
sub new {
    my($class, $name) = @_;     # 第1引数はクラス名
    my($self) = {};             # 無名参照オブジェクトを生成
    bless($self, $class);       # オブジェクトとクラス名を関連付け
    $self->{NAME} = $name;      # 属性を初期化
    $count++;                   # クラス変数を更新
    return $self;               # オブジェクト（無名参照）を返す
}

# デストラクタ（消滅関数）
sub DESTROY {
    my($self) = @_;             # 第1引数はオブジェクト
    $count--;                   # クラス変数を更新
}

# メソッド：オブジェクトの総数を返す
sub getCount {
    return $count;
}

# メソッド：NAME属性を設定する
sub setName {
    my($self, $name) = @_;
    $self->{NAME} = $name;
}

# メソッド：NAME属性を参照する
sub getName {
    my($self) = @_;
    return $self->{NAME};
}
1;          # use がエラーにならないように 0 以外の値を記述しておく
```
|項目|説明|備考|
|----|----|----|
|strict|宣言強制|our my がないとコンパイルエラーになる|
|our|グローバル変数＝パッケージとの紐付いた変数|our $count = 0;の場所でmyにするとコンパイルエラーになる。|
|my|レキシカル変数≒ローカル変数|スコープの中で有効な変数|

https://qiita.com/xtetsuji/items/e70e6b8a663dff0927a9#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%A8%E3%81%AE%E7%B4%90%E4%BB%98%E3%81%91%E3%81%8C%E7%84%A1%E3%81%8F%E3%81%AA%E3%81%A3%E3%81%9F%E3%83%AC%E3%82%AD%E3%82%B7%E3%82%AB%E3%83%AB%E5%A4%89%E6%95%B0my-%E3%81%A8-state

https://www.tohoho-web.com/perl/class.htm
Salesforce Starter and Pro Suite

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


-------------------------------

+ [Marketing Segments](https://help.salesforce.com/s/articleView?id=sf.easy_marketing_segment_reference.htm&type=5)

視聴者内のグループをターゲットにする場合、それをセグメントと呼びます。Salesforce Starter および Salesforce Pro Suite では、個人の所在地やアカウント名などのフィルタ条件を適用してセグメントを作成します。フィルター条件は、見込み客、連絡先、統合された個人に関する情報を保存するデータ オブジェクトに基づいています。

# Create A Segment- Starter Org

+ [Create A Segment- Starter Org](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007X6zxS)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/3e5f859d-6acf-4354-1b4b-2b6272529040.png)

:::note
It turns out it may be a limitation of being in a sandbox
:::

+ [Pro Suite org- Marketing- DATA STREAM REFRESH](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007X7OVISA3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c7d8031b-cb11-9224-d5e3-ada456e4229e.png)

# 400.mx.salesforce.com

+ [【ヘルプ】Salesforce Starter および Pro Suite のマーケティングに関する考慮事項](https://help.salesforce.com/s/articleView?id=xcloud.starter_prosuite_set_up_marketing.htm&type=5)

>注:詳細設定で組織全体のメールアドレスを追加すると、そのメールアドレスは、メールキャンペーンの [送信元] 項目で使用される前に、Salesforce ドメインで再フォーマットされます。たとえば、組織全体のメールアドレス name@example.com は、キャンペーンの [送信元] 項目では name_at_example.com@400.mx.salesforce.com と表示されます。Salesforce ドメインは異なる場合があり、再フォーマットするとメールの配信性が向上します。

---
+ [【ヘルプ】組織の共有メールアドレスを使用する場合の考慮事項](https://help.salesforce.com/s/articleView?id=sf.emailadmin_orgwide_addresses_considerations.htm&type=5)

組織の共有アドレスは、以下には使用できません。

+ スケジュール済みレポート
+ スケジュール済みの 1 対 1 のメール
+ ダッシュボードの更新のスケジュール設定
+ 差し込み印刷メール、一括メール、取引先責任者およびリードへのミーティング要請の送信


# 同じようなエラー

https://www.reddit.com/r/salesforce/comments/1csxhdo/marketing_cloud/

https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX00000Kg7sK0AR
【CSS】特定の要素より後の要素を指定する方法

## 「以降」

以下のように記述することで特定の要素(.targetの要素)以降の要素が指定できます。

```css
ul li.target,
ul li.target ~ li {
	color: red;
}
```

## 「より後」

以下のように記述した場合には、特定の要素(.targetの要素)を含みません。

```css
ul li.target ~ li {
	color: red;
}
```

## 「直後」

以下のように記述すると直後の要素のみを指定することができます。

```css
ul li.target + li {
	color: red;
}
```
[個人の感想] かっこいい親とは（IT業界で私はどう生きるか）

# はじめに
私の将来の夢は***かっこいいパパ***になることです。
子どもから「将来はパパと結婚する！」と言われたい。

30代になってからそんな夢を持つとは知らない青年期、何も考えずにIT業界に飛び込んでしまいました。
そこで、この業界にいながら***かっこいいパパ***になるにはどうすればいいかを考えたいと思います。


# IT業界でのかっこいい

ぱっと聞かれると、以下のような単語が思いつくかも知れません
* 外資系
* ハッカー
* 青年実業家
* 英語ぺらぺら
* ばりばりのPM
* スーパーエンジニア
* ビッグテックで働いている
* 何百人を率いるマネージャー




キラキラっぽい言葉を並べてみましたが、我ながら薄っぺらい...！
そして、能力や地位が目立ちました。これは人によっては正しい。正に人それぞれです。
では私にとってはどうなのか、私にとってのかっこいいとは・・・


# 遡って幼少期
昔はエッセンシャルワーカーに憧れていました。
両親がエッセンシャルワーカーとして働いている姿に憧れていたので、おぼろげにそういう職業に就くと考えていました。



# かっこいいとは
そういう背景があるからか、
やはり私の中では、***社会貢献***という言葉が浮かびます。
世の中を良くしようと行動している姿にかっこよさを感じます。

### （補足）社会貢献しない会社って？
ある日将来の夢を母親に聞かれた際に、「社会貢献をしたい」と伝えると、
「社会貢献していない会社はない、どんな小さな仕事でも社会の役に立っている」と名言っぽいことを言われました。基本はその通りだと思います。

でも社会に出てみて、社会貢献ではない利益のみが目的で、利益のためなら社会にマイナスなことも厭わない会社が存在することも学びました。

# かっこいいパパとは
[かっこいい](https://qiita.com/SobaNyaku/items/e934c504d90631308dba#%E3%81%8B%E3%81%A3%E3%81%93%E3%81%84%E3%81%84%E3%81%A8%E3%81%AF) + 家族のことを第一に考えて行動している人だと考えます。
* いくら社会貢献していても、家族を犠牲にしていたらダメ:no_good:
* 家族のこと第一でも、だらだらしていたり悪いことをしているようではダメ:no_good:

書くのは簡単だけど難しい...



# じゃあ結局どうすればいいの？
例外を除いて、働く場所は問わないのだと思います。
「パパって何してるの？」とそのうち聞かれると思います。
その時に「PC触ってるよ」とだけ言いたくない。「[MATANA](https://gendai.media/articles/-/109002)で働いているよ」「部長という役職だよ」「英語がぺらぺらで～」と地位や能力で伝えたくない。
キラキラした能力や役職がなくても、以下を胸を張って言えるように日々過ごしたいです。

:::note info
***『みんなのことを考えながら、次世代のために社会をより良くすることを目指して、日々努力している』***

***『それには色々な方法があるけど、パパはPC(IT)を使って影響範囲を大きくしていこうとしているよ』***

***『具体的には～』***(ここは年齢に合わせて伝える)
:::



と言おうと思います。そして、それを真に実現できる会社で働きたいと思います。
日々の働きが、日々の努力が、少しでも家族が幸せに生きることができる世界に繋がればいいと思います。

そして、きっかけ・原動力は家族ですがそれが社会全体への好影響に繋がることを切に願っていると伝えます。

### （補足）真に社会貢献ができる実現できる会社の見極め方
1. まずはMissionや経営理念に共感できる会社を探しましょう
1. ただ、どの会社もそれはそれは素晴らしいことが書いてあります。無理やりにでも社会貢献と結びつけています。
1. そこら辺の複数人の社員と話せる機会があったら、その人たちにMission/経営理念を聞いてみましょう
1. 全員が言えたら、その会社は本気だと思います。文化が浸透していて、そのMission/経営理念に向かっていけることが分かります

私は2社経験していますが、どちらも最終的に選んだ決め手は上記の通りです。（明確に社員にテストしたわけではないですが、そういう会社は向こうから勝手に言ってくることが多かったです）
両社とも文化醸成に力とお金を使っていて、みんなが同じ方向を向いて社会貢献を目指していた、とてもとてもいい会社でした。


# おわりに
最後まで見ていただき、ありがとうございます。
よかったらチャンネル登録（フォロー）と高評価（いいね:heart_decoration:）お願いします:pray:
週一で投稿目指してます。もしフォローかいいね:heart_decoration:をしてくれたら、やる気出るので、次週は投稿することを約束します。
Maven（Apache Maven）とは

# 【Mavenとは】(※読み：メイブン)
Mavenは簡単に言うと、「開発を自動化してくれる便利な物」である。
Mavenは、プログラムをビルドすることを目的として利用する「ビルドツール」のひとつで、主にJavaで書かれたプロジェクトをビルドするために利用する。Eclipseと連携して利用することが多い。



# 【Mavenを使ってできること】
①ライブラリの管理
Mavenの最大のメリットが、「プロジェクトで利用するライブラリを管理できる」という点。 Javaには多くのライブラリが存在しており、それらのライブラリを使うことで高速に開発を進めることが可能。
Mavenでは、XMLに必要なライブラリの情報を記述することで、「そのプロジェクトに必要なライブラリ」を一元管理してくれる。 また、Mavenは依存性を管理する機能も備わっている。

例えば、あるライブラリAを使いたい場合、ライブラリAは、他のライブラリであるBを利用している場合、JavaのプロジェクトにはライブラリAとライブラリBを含める必要がある。 しかし、Mavenを利用した場合には、「ライブラリA」の情報のみを記述するだけで良くなる。
Maven上に存在するライブラリAには、「ライブラリBを利用するよ（依存関係がある）」ということが明記されており、Mavenはこの依存関係を自動で吸収してくれる。 プロジェクトには「ライブラリAを利用する」と記述するだけで、ライブラリBも自動で依存関係に含めてくれる。
このように、ライブラリの管理が非常に楽になるのがMavenの大きなメリットである。

②ライブラリの自動インストール
Mavenは利用するライブラリを管理するだけでなく、それらのライブラリを自動でインストールしてくれる。 先ほど紹介した「依存関係」を自動で検出し、必要なライブラリを一括でダウンロードしてくれる。 手動でライブラリをインストールする必要がないので、複数人で開発するときにありがちな「ライブラリのバージョンが違ったので挙動が異なってしまう」というような問題も発生しなくなる。

③ビルド
コマンドを実行するだけで、下記の処理を一括で行ってくれる。
・必要なライブラリのインストール
・Javaファイルのコンパイル
・自動テスト
・パッケージ(JarやWar)の作成 


 ビルドからテストまでを一括で実施してくれることで、人の手による作業を減らす役割を担っている。
そのため、複数人で開発をするような現場であればこのようなビルドツールは必須の存在である。


（補足）
・ビルド：おおまかに言うと「ソースコードに問題（バグ）がないか解析を行い、問題がなければ実行できる形のファイルに変換し、組み立てること」を言う。※開発環境によって、少し内容が異なっている場合もある。

・ライブラリ：便利なプログラムの部品を沢山集めて、ひとまとめにしたファイルのこと。

・XML：文章の見た目や構造を記述するためのマークアップ言語の一種。HTMLの一種。データの意味に合わせて要素名を自由に定義し、データを明確に目立たせることができるのが特徴。

・Jar（ファイル）：Javaアプリケーションを実行するためのJavaクラスファイル、関連するメタデータ、リソースが1つのファイルに集約されているファイル。

・Warファイル：Webアプリケーションを開発するために必要なServlet、JSP、HTML、JavaScriptなどのファイルが含まれているファイル。



# 【Gradleとの違い】
同じく、Javaで使えるビルドツールとして「Gradle」が存在する。
実は、MavenもGradleもできることに大きな違いはない。 ただし、Gradleの方が後発であることもあり、Mavenの面倒な部分をより細かいカスタマイズができるようになっている。そのため、やりたいことによってMavenかGradleかを選ぶとよい。



# 【よく使うMavenコマンド】
・依存関係のライブラリをインストールする際には「install」コマンドを利用する。
「mvn install」

・作成したJUnitの単体テストを実行する場合には「test」コマンドを利用する。
「mvn test」

・javaファイルをコンパイルし.classファイルを作成する場合には、compileコマンドを実行。
「mvn compile」

・成果物としてjarやwarといったファイルを作成する際に実行するのが「package」コマンド。
「mvn package」

・ビルドの成果物をサーバー等へ公開する際に利用するのが「deploy」コマンド。
「mvn deploy」

・プロジェクトをクリーンし、ビルド結果を削除する場合には「clean」コマンドを利用する。ビルドに失敗した場合や、うまく動かない場合にはこのコマンドを利用する。
「mvn clean」
Bash と Caddy サーバで ActivityPub のインスタンス(12) 202 ディレクトリの整理

## 202 ディレクトリに貯まったファイルを type によって分類する
netcat で受け取った inbox へのリクエストファイルが 202 ディレクトリに貯まっているはずだが、そのファイルを receive ディレクトリを作って、その中に type に応じたディレクトリへ分類する。
```
mkdir ./receive ./receive/delete ./receive/create ./receive/announce ./receive/like ./receive/accept ./receive/follow_request ./receive/undo_follow ./receive/undo ./receive/create_done ./receive/announce_done ./receive/like_done ./receive/accept_done ./receive/follow_request_done ./receive/undo_follow_done ./receive/other ./receive/NG
```

数が多くて面倒い。/\*\*\*_done/ ディレクトリは、/***/ディレクトリに分類したファイルを処理した後にそこへ mv する。

まずは 202 のファイルを type に応じて分類したいが、何故か Mastodon や Misskey インスタンスはアクターの削除情報を大量に送ってくるのでそれを ./receive/delete ディレクトリに送る。
また、ここでそれ以外のリクエストの HTTP署名の検証を行う。それらを通過したものを type に応じた各ディレクトリへ分類する。
```bash:sort_req_file.sh
#!/bin/bash


# 一応 202 のファイルを 202.bak にコピーしておく
cp ./202/* ./202.bak

# リクエストファイルの type によって分類する関数
function sort_func(){
type=$(grep "{" $1 | jq .type)

case $type in

'"Create"')
mv $1 ./receive/create;;

'"Announce"')
mv $1 ./receive/announce;;

'"Like"')
mv $1 ./receive/like;;

'"Follow"')
mv $1 ./receive/follow_request;;

'"Accept"')
mv $1 ./receive/accept;;

'"Undo"')
mv $1 ./receive/undo;;

'"Delete"')
mv $1 ./receive/delete;;

*)
mv $1 ./receive/other;;
esac
}

# 202 ディレクトリのファイルがアクター削除なら単に delete へ送る
files=$(ls -F 202)
for i in $files; do
	type_of_json=$(grep { ./202/$i | jq .type)
	if [ "$type_of_json" = '"Delete"' ]; then
		mv ./202/$i ./receive/delete
	fi
done

# Delete 以外なら署名検証して、OK なら sort_func で分類。NG なら NG ディレクトリへ
files=$(ls -F 202)
for i in $files; do
	if [ "$(bash ./scripts/verify.sh ./202/$i)" = "Verified OK" ]; then
		sort_func ./202/$i
	else
		mv ./202/$i ./receive/NG
	fi
done

# Undo のうち、follow の Undo なら follow_undo へ
files=$(ls -F ./receive/undo)
for i in $files; do
	type=$(grep "{" ./receive/undo/$i | jq .object.type)
	if [ "$type" = '"Follow"' ]; then
		mv ./receive/undo/$i ./receive/undo_follow
	fi
done
```

以降、各ディレクトリの内容を処理し、./receive/***_done ディレクトリへ送る。
WindowsでDevcontainerを構築した際にすべてのファイルがgitの変更履歴にあがってきてしまう

# TL;DR

WindowsでLinuxのDevcontainerを生成している場合、
gitの設定で`core.autocrlf=false`があるか確認しましょう。

# 環境

ホスト　：Windows
コンテナ：Linux
エディタ：Visual Studio Code

# 問題の発生

WindowsマシンでDevContainerを構築しようとコンテナを作成した際、ソースコード内の全てのファイルがGitのファイル変更リストに表示される問題が発生しました。
Windowsにインストールしてある「GitHub Desktop」や「Sourcetree」には変更があがってこないので、最初はコンテナ生成時にgitの変更履歴が同期されていないと思い、以下の点を疑って調べていました。

* GitのSSH関連設定の同期（そういう記事も多かったし…）
* .gitフォルダの同期（変更履歴情報があるから）
* devcontainer.jsonやdocker-compose.ymlファイルの設定

# 原因の特定

「docker等の同期設定が問題ではないのであれば、本当にファイルが変更されているのでは？」と思い、ファイルが勝手に変更される要因を考えてみたところ、Gitが自動的に改行文字を変更する設定があることを思い出しました。

`git config --global -l`でgitの設定一覧を確認したところ、やっぱり改行文字の自動変換設定である`core.autocrlf=false`の項目がありませんでした。
この項目がないとWindowsからDevcontainer内のLinuxにファイルを同期させた際に改行文字が自動で変換されてしまいます。

※プロジェクト生成をLinuxや他のDevcontainerなどで行ってもWindowsのローカルにクローンした際に変更されてしまいます

# 解決策

1. `git config --global -l`でgitの設定一覧内に`core.autocrlf=false`という項目があるかを確認
1. なければ`git config --global core.autocrlf false`で設定項目を追加
1. Devcontainerをリビルド

※**設定を追加したのに**改善しない場合はコンテナを削除したり、`docker builder prune`でdockerのビルドキャッシュを削除してみてください

## まとめ

初歩的なミスですが、すぐには気付けずハマってしまったので、同じ轍を踏む人が少しでも減るように記事としてあげてみました。
[Linux]cpuの諸元等を調べる方法

## 要　旨
Linuxにおいて、CPUの諸元等を調べる方法を記述します。
## 実施要領
CPUの諸元を調べるコマンド
```linux
cat /proc/cpuinfo
```
```linux
lscpu
```
システムで、利用可能なCPUのコア数の表示
```linux
nproc
```
CPUのメモリ数を調べるコマンド
```linux
lshw -short -C memory
```
## 結　言
今回は、Linuxにおいて、CPUの諸元等を調べる方法を記述しました。
本当は dialog.open() にしたかった話

# 1. 背景
ダイアログ要素のcloseメソッドを読み漁っていた際に知ったことです。

以下のdocumentの```We use show/close as the verbs for dialog elements, as opposed to verb pairs that are more commonly thought of as antonyms such as show/hide or open/close, due to the following constraints```の所を和訳します。

https://html.spec.whatwg.org/multipage/interactive-elements.html#the-dialog-element:~:text=We%20use%20show/close%20as%20the%20verbs%20for%20dialog%20elements%2C%20as%20opposed%20to%20verb%20pairs%20that%20are%20more%20commonly%20thought%20of%20as%20antonyms%20such%20as%20show/hide%20or%20open/close%2C%20due%20to%20the%20following%20constraints%3A

# 2. ダイアログ要素の動詞として反意語として一般的に考えられている動詞ペア
- show/hide
- open/close

## 2.1. ダイアログを非表示にすることと、閉じることの違い
ダイアログを非表示にすることは、ダイアログを閉じることとは異なります。
### ダイアログを閉じる
そのダイアログに戻り値を与えたり、イベントを発生させたり、他のダイアログのためにページのブロックを解除したりします。
### ダイアログの非表示
純粋に視覚的な特性であり、hidden属性やopen属性を削除することで既にできることです。

## 2.2. ダイアログを開くことと表示することの違い
### ダイアログを開く
ダイアログを作成し、表示することです。
### ダイアログを表示する
すでにDOMにあるダイアログ要素を取り込み、それをインタラクティブにしてユーザーに見せることです。

# 3. dialog.openプロパティと衝突
dialog.open()メソッドにしたかったですが、dialog.openプロパティと衝突してしまいます。

# 4. 結論
ダイアログを見せたり閉じたりするような対になる動作が持つ意味合いを、必ずしもコードでも同様に反意語として表現できるとは限らないです。

# 5. 最後に
APIのメソッドの命名の背景を知れる良い機会になりました。
GithubにSSH接続する方法

ローカルからGitHubにアクセスする方法を記載する。
※ここでいうローカルとはブラウザーからGitHubにログインではなく、「ローカルのリポジトリ」からGitHub(リモートリポジトリ)にアクセスする際の認証のこと。

2021年8月以降、password認証負荷となった、

今回は、SSH接続について備忘録。

SSH＝よりセキュアな方法でサービスにログインできる認証方法

## ■SSH接続設定の大まかな流れ

①SSHキーをローカルに作成

②SSHキーをGitHubに登録


## ①SSHキーをローカルに作成
ローカル環境でターミナル上で以下コマンド叩く

```
$ ssh-keygen -t ed25519 -C "GitHubに登録したメールアドレス"  
Generating public/private ed25519 key pair.
Enter file in which to save the key (/c/Users/yuzo/.ssh/id_ed25519):
/c/Users/yuzo/.ssh/id_ed25519 already exists.
Overwrite (y/n)? y
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /c/Users/yuzo/.ssh/id_ed25519
Your public key has been saved in /c/Users/yuzo/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
The key's randomart image is:

```
上記コマンドをたたくことで、/c/Users/yuzo/.sshフォルダ配下に２種類のSSHキーが生成される。

```
$cd ~/.ssh
$ ls
id_ed25519  id_ed25519.pub 
```
公開鍵：id_ed25519.pub　※ 自分以外の人に見せてもいい鍵
秘密鍵：id_ed25519 ※他の人に共有してはいけない鍵

ssh-agentを起動させる
```
$ eval "$(ssh-agent -s)"
Agent pid XXXX
```

ホームディレクトリ配下の.ssh/configファイルを編集する
→このconfigファイルでSSHの設定をする

VScodeで当該configファイルを開く

```
$ code ~/.ssh/config
```

以下のようにconfigファイルを修正する

```:~/.ssh/config
Host *
    AddKeysToAgent yes
    UseKeychain yes
    IdentityFile ~/.ssh/id_ed25519 
```
上記configを設定することで、GitHubにログインする時に先ほど生成した秘密鍵（.ssh/id_ed25519）を利用してログインすることができる。

SSHキーをssh-agentに登録する

```
$ ssh-add -k ~/.ssh/id_ed25519
Identity added: /c/Users/yuzo/.ssh/id_ed25519 (メールアドレス)

```
これでローカルにSSHキーを作成した。

今度はGitHubに公開鍵を登録する。

## ②SSHキー（公開鍵）をGitHubに登録

まず公開鍵をクリップボードにコピー
```
 clip <~/.ssh/id_ed25519.pub
```
ブラウザーでGitHubを開き、setting→SSH and GPG keys→New SSH keyで先ほどの公開鍵の中身を張り付けGitHubに登録終了。

あとは、このSSHキーを使って、ローカルからリモートリポジトリにアクセスする。












以下リンク参照
https://datawokagaku.com/github_ssh/
python 親子を分けて並列でDB処理する

pythonで並列処理する方法を探すと色々情報が出てくるんですが、
親子でファイルを分割して処理させるようなサンプルがなかったので、
メモをしておこうと思います。

▼環境
Python 3.12.1

```python:ParentJob.py
import concurrent.futures
from ChildrenJob import ChildrenJob

class ParentJob:

	def main(self):
		res = []
		with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
			def __exe_children_job(tid, val):
				o = ChildrenJob()
				r = o.main(tid, val)
				return r

			futures = []
			for tid, val in enumerate(["3","2","1"]):
				futures.append(executor.submit(__exe_children_job, tid+1, val))

			for future in futures:
				res.append(future.result())

		return res

o = ParentJob()
r = o.main()

print("--- 結果 ---")
print(r)
```


```python:ChildrenJob.py
from DB import DB

class ChildrenJob(DB):

	def __init__(self):
		super().__init__()

	def main(self, tid, val):
		print(f"Thread-{tid} start")

		res = []
		with self.conn.cursor() as cur:
			cur.execute("select * from sample001 where id = %(id)s", {"id":str(val)})
			res = cur.fetchall()

		print(f"Thread-{tid} end")

		return res
```

```python:DB.py
import psycopg2

class DB:
	dsn = "dbname=postgres host=localhost user=postgres password=postgres"

	def __init__(self):
		self.conn = psycopg2.connect(self.dsn)

	def __del__(self):
		self.conn.close()
```

```
# ParentJob.pyを実行した結果

Thread-1 start
Thread-1 end
Thread-3 start
Thread-3 end
Thread-2 start
Thread-2 end
--- 結果 ---
[
    [('3', 'r3-c1', 'r3-c2', 'r3-c3')], 
    [('2', 'r2-c1', 'r2-c2', 'r2-c3')], 
    [('1', 'r1-c1', 'r1-c2', 'r1-c3')]
]
```
アカン！z-indexが効かへん！！(Tailwind CSS)

![2c97092e.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497237/08c3adb5-ad86-bbf1-7300-c1283170fc6d.jpeg)

# ....z-indexが効かん！
### 現在インターン先で取り組んでいるプロジェクトで、z-indexが効かないでドブカスになっており、困ったのですが簡単なところで解決策が見つかりました。
### 今回の使用技術: Next.js TypeScript Tailwind CSS　
#### どの要素がどのように重なるかというのは奥が深かったりします。
#### 今回は効かない理由について書きますが、z-indexについてよく知っておくことをお勧めします。
absolute、relative、fixedなどstaticではない要素は、 デフォルトのstaticな要素よりも記述順番に関係なく 必ずZ軸上で手前に描画される
staticな要素にはz-indexが指定できない
opacityが指定されてるとz-index:0同士でもその要素が上に来る
スタックコンテキスト
などいろいろありますが、ここら辺はググれば神達が記事を書いてくれております。

#### ！今回はTailwind CSSでz-indexが効かなかった時に解決した方法です。通常のz-indexが効かなかった場合とは違うパターンです。

 ## 原因: Tailwindがデフォルトで設定している値ではなかった
![スクリーンショット 2024-01-19 15.32.27（2）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497237/6fc007de-debd-d4a2-7991-d69813211cbf.png)
この画像がTailwindの対応するz-の値です。つまり、z-0~50までは10刻みで指定できますが、60や70になると指定してもスタイリングは適用されません。
この場合、tailwind.config.ts(js)ファイルにzIndexプロパティを追加してあげる必要があります。
なので適当に530000とか打っても意味がないわけです。

## 設定方法
```
// tailwind.config.js
theme: {
    ...
    extend: {
     zIndex: {
        "60": "60",
        "70": "70",
       "90": "90",
      },

```
このように指定してあげれば、60,70,90のz-indexが適用可能になります。
また、configに適用しなくともarbitrary valuesを使えば無理やりスタイリングできます。
```
<div className = "z-[100]">hoge</div>
```
tailwind.config.tsの場合はd.ts形式の型ファイルがtailwindcssディレクトリにあるはずなのでみて見てください。その型に従った方法でプロパティを追加しましょう。
基本上記の例でうまくいきます。


# 結論
## Tailwindやっぱめんどくせえなあ...個人でしか使いたくないゅ🥺
MXレコードにIPアドレス設定でも、Gmailとのメール送受信可能だった。

インターネット出願システムで話題となった、「MXレコードにIPアドレス設定」のメールサーバとGmail送受信を実際に行ってみた。

# MXレコードにIPアドレス設定でもメールは届くかも？との情報

https://twitter.com/Kawakami_Kento/status/1747203198455361544
>MXレコードにIPアドレスが入っている事が話題ですが、sendmailなど一部のclientではIPアドレスが入っていても動作する事が知られています。https://cr.yp.to/im/ip.html

# MXレコードにIPアドレス設定ができるところを探した
ほとんどのサービスでは、MXレコードにIPアドレス設定が行えないようになっていた。（AWS Route53 は諸事情で試せず）

:::note info
Azure DNS で設定できた。
:::
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/37c8d5e5-ff43-f0cf-e9b3-1b320028eda5.png)


# 受信側サーバは、利用しているさくらのレンタルサーバにドメイン追加
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/5fd970c0-0982-15fd-9775-03bd9db64e9e.png)

# DNS確認
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/e78dc917-8140-bb28-e06d-0af6497b9643.png)

:::note warn
設定時はないが、digの結果には表示されている、MXレコードのIPアドレスの最後の 「.」（ドット）は、下記リンクなどから、MXレコードはFQDNが設定されることが想定されているためDNSの「ルート」を表す「.」と推測しています。
:::
https://www.nic.ad.jp/ja/basics/terms/fqdn.html

（追記 2024年1月22日 4時 以下記事追加）

https://qiita.com/umeyon/items/aa816629b2a6e7ecb9f4

# Gmailからの受信結果
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/02ac64a0-b60a-6d6f-a0a8-2540ef4019f3.png)

:::note info
Gmail から受信できた。
（MXがIPアドレスでも、Gmailから受信できた）
:::

# Gmailへの送信結果
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/fbfebcf4-690d-a86a-7e29-b3c5a5a54aa4.png)

:::note info
Gmail に送信できた。
（Gmailは受信時にMXは参照していないと推測できる）
:::

（2024年1月22日 22時追記） START TLSは使わなかったので、赤（暗号化なし）のマークとなっています。
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/354637/041f9355-a901-87b6-d3a5-756e9fa0ab9c.png)



:::note warn
送受信を実際に確認後、それぞれキャプチャしたため、画像の時間が前後しています。ご了承ください。
:::

:::note warn
2024年1月21日 0時追記
SPF を送信サーバと受信サーバを別を想定した設定 "v=spf1 ip4:(219.94.163.2XX以外) -all" にしても、送受信できました。
:::
JavaでEnumのメソッドを作成する

# 1. はじめに
* JavaでEnumのメソッドを使ってみたい

# 2. 開発環境
* java

# 3. サンプルコード
```java:
  // Enumの定義
  public enum enumMonth {
    October("A", "10"), November("B", "11"), December("B", "12");

    // フィールドを定義
    private String code;
    private String value;

    // コンストラクタを定義
    private enumMonth(String pCode, String pValue) {
      this.code = pCode;
      this.value = pValue;
    }

    // メソッド
    public static String getValueByCode(String pId) {
      for (enumMonth month : enumMonth.values()) {
        if (month.code.equals(pId)) {
          return month.value;
        }
      }

      return "0" + pId.substring(0, 1);
    }
  }
```

# 4. 実行サンプル
```
// Enumのテスト
String month_0 = enumMonth.getValueByCode("0");
String month_1 = enumMonth.getValueByCode("1");
String month_2 = enumMonth.getValueByCode("2");
String month_3 = enumMonth.getValueByCode("3");
String month_4 = enumMonth.getValueByCode("4");
String month_5 = enumMonth.getValueByCode("5");
String month_6 = enumMonth.getValueByCode("6");
String month_7 = enumMonth.getValueByCode("7");
String month_8 = enumMonth.getValueByCode("8");
String month_9 = enumMonth.getValueByCode("9");
String month_A = enumMonth.getValueByCode("A");
String month_B = enumMonth.getValueByCode("B");
String month_C = enumMonth.getValueByCode("C");
System.out.println("0:" + month_0);
System.out.println("1:" + month_1);
System.out.println("2:" + month_2);
System.out.println("3:" + month_3);
System.out.println("4:" + month_4);
System.out.println("5:" + month_5);
System.out.println("6:" + month_6);
System.out.println("7:" + month_7);
System.out.println("8:" + month_8);
System.out.println("9:" + month_9);
System.out.println("A:" + month_A);
System.out.println("B:" + month_B);
System.out.println("C:" + month_C);
System.out.println("0:" + month_0);
```
eoでpostfixのrelayが動かなくなっていた件

## 自宅でubuntuサーバーを動かしていて、いつのまにか動かなくなっていたので調べてみた

### いつまで動いていたのか？
　不明。なんか、去年eoからメールのセキュリティうんたらってメールが来ていた気がするが、スルーしていた。（そもそも、それが原因かも不明）

最初、上記が原因かと考え、いきあたりばったりで、今まで587ポートでアクセスしていたのを465ポートに切り替えてみたりアクセスしてみたが、なんか、うまくいかない。
で、よくよくlogを見てみると「warning: smtpauth.eonet.ne.jp[xxx.xxx.xxx.xxx]:587 offered no supported AUTH mechanisms: 'LOGIN PLAIN'」との警告が。最初、eoがLOGIN PLAINを提供していないよって、思っていたが、逆で、自宅のubuntuサーバーが使っているAUTH mechanismが何か（結果的にはcram-md5って設定してたみたい）だけど、eoはLOGIN PLAINしか提供していないよ。
　自宅サーバーのつもりになって書くと、「eoは、僕がサポートしていない、LOGIN PLAINのAUTH mechanismsだけ提供しているよ。アクセスできないよ」ってことだった。

## 対策
~~smtp_sasl_mechanism_filter = cram-md5~~
smtp_sasl_mechanism_filter = plain,login
に修正すると動くようになりました。

## 結論
ログはしっかり読め

でした
ESP32-C3-WROOM-02のピッチ変換基板を自作してJLCPCBに発注する

# はじめに
[**ESP32-C3-WROOM-02**](https://akizukidenshi.com/catalog/g/gM-17493/)とは[**ESP-WROOM-02**](https://akizukidenshi.com/catalog/g/gM-09607/)の後継に当たり、サイズは全く同じですが、Wi-Fiに加えてBLEやUSBも利用できるESPマイコンです。同じようにArduino開発環境が使えます。秋月電子通商だと単体なら310円で購入できるため、他のESPマイコンよりも安価です。しかし、ピン配置がESP-WROOM-02とは異なるため、秋月電子通商で販売されているピッチ変換基板が使えそうで使えません。そこで、今回はESP32-C3-WROOM-02専用のピッチ変換基板をKiCadで設計し、JLCPCBに発注してみました。送料も含め、5枚のプリント基板が420円くらいで購入できたのでむしろ既製品を購入するよりも安く済みました。
![picture.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/d676ed2f-6468-f4fb-4cb2-e7e9663f0a47.jpeg)
# KiCad
今回のプリント基板は4層で設計しました。2層よりも設計の自由度が増し、配線の交差を回避できるので小型化できました。内層は配線層、外層はプレーン層となるように設計しています[^1]。
![schematic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/43fdd2f5-7ac9-66bf-686a-4887858c6dc3.png)
ガーバーファイルは[**こちら**](https://drive.google.com/file/d/1AnUJKztSi0IaISeNneapEskXfnx07qJN/view?usp=sharing)からダウンロードできます。
![rendering_front.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/71784330-1514-eda9-a2f0-9c1c05a161bf.png)
![rendering_back.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/17463cae-84f7-684b-03b0-74010816386f.png)
# JLCPCB
配送業者は`OCS NEP`を選びました。1月11日に発注し、1月19日に到着。送料は0.96$で最も安い選択肢となります。乾燥剤と共に真空パックされた状態で届き、品質も十分でした。
![jlcpcb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2951963/383167b0-e273-4444-51be-73193083776c.jpeg)
# おわりに
自作したピッチ変換基板を使い、色々とESP32-C3-WROOM-02を活用していきたいです。また、今回はプリント基板をJLCPCBに発注してみましたが、とにかく安く、品質も安定しているみたいなので安心しました。便利な世の中です。
[^1]:https://www.atmarkele.com/articles/138
疑似要素で見出しの下線を作る

![スクリーンショット 2024-01-19 234509.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3666066/eab46644-b413-4fac-882e-fe691b7201a0.png)
以下はSCSS
.section-title{ /*要素と要素の位置*/
    font-size: 48px;
    font-weight: 700;
    text-align: center;  
    padding-bottom: 12px;
    position: relative; /*28pxは$::afterの4pxを含めている*/
    font-family: $font-en;/*英語だから、英語のfontを使う*/

    &::after{
        content: "";
        position: absolute;
        left: 50%;
        transform: translateX(-50%);
        bottom: 0;
        width: 60px;
        height: 4px;
        background: $color-main;
説明：positionを使用することで、疑似要素は親要素（基準）の中にあります。
　　　bottom:0ということは、親要素の下境界線の内側にくっついている状態です。
　　　Cardというテキストと疑似要素の間の距離は12px-4px = 8px
JavaScript全く分からん→Next.jsで遊んでみようになるまで

# はじめに
つい2年前、私は全くJavaScriptでコードを書けない人でした。
もちろんJavaScriptのフレームワークに関する知識など全くありませんでした。それどころか、DOM？何それ？な状態でした。

# JavaScriptの入門書を読むところから始める
読んだ入門書は「スラスラわかるJavaScript 新版」です。
https://amzn.asia/d/6YIH7Zm

この本を知ったきっかけは、エンジニア転職チャンネルの動画「未経験・1年目のWeb/ITエンジニアに必読の書籍17選」でした。
JavaScriptの文法の基礎的なところから、DOMとは何ぞや？みたいなところもこの書籍で学習しました。
ちなみに、非同期処理(async/await)がこの書籍には載っていますが、これをしっかり勉強したのは、もう少し後の話...。

# 初めてモダンなJavaScriptフレームワークに触れる
またしても、「未経験・1年目のWeb/ITエンジニアに必読の書籍17選」をきっかけに、「モダンJavaScriptの基本から始めるReact実践の教科書」を購入しました。
https://amzn.asia/d/0XhMPbG

Reactの基本的な書き方を学習できて、良い書籍でした。そして、学習したことを参考に実際にReactで実際に遊んでいました。これが以降に個人開発でのReact選定に繋がっていきます。

# Vue.js + TypeScript
時系列的には、前セクションからしばらく後、何ならここ数ヶ月です。
業務でVue.jsとTypeScriptを使ってフロントエンド開発をしています。
実は、JavaScriptの基礎を学ぶ前にVue.jsに興味を持ち、書店で書籍を眺めて「何これ分からん」状態になったことがあるのですが、実際にVue.jsでコードを書いたのは初めてでした。
何も知らないのはマズいと、付け焼き刃的に購入したのが、「Vue.jsポケットリファレンス」でした。開発を始めて最初の頃は、すごくお世話になりました。
https://amzn.asia/d/0NZWccd

propsやemit、v-***の概念はこの書籍でサラッと学習しました。

また、TypeScriptでしっかりコードを書いたのもここが初めてでした。「JavaScript + 静的型付け」くらいのことは知っていましたが、実際にどう書いていくのか？は全く知らない状態で開発に入りました。
最近、TypeScriptを本格的に学習すべく、「プロを目指す人のためのTypeScript入門」を購入し、絶賛学習中です。
https://amzn.asia/d/fckZOsH

併せて、「JavaScript 第７版」を購入しました。この書籍は、文法のリファレンスのような感覚で使っています。配列の処理や非同期処理の書き方なんかはこの書籍にかなり助けられました。
https://amzn.asia/d/g5pIB8p

# Next.js (今ここ)
Reactに飽き足らず、ついにNext.jsを使ってみることにしました。
npx create-next-appで何となくTypeScript+Tailwind CSS...と設定していたら何も知らずにApp Routingを選択していましたね...。
全てpage.tsxになるんだ、これが最初の学びです。

Next.js、Tailwind CSSを使うのに併せて、以下の書籍を購入してみることにしました。
・Tailwind CSS実践入門
https://amzn.asia/d/dBLgxMu
・TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発
https://amzn.asia/d/9a3vtx5

# 終わりに一言
また２冊積書が増えました...。
PythonでExcelの表にデータ入力する方法をChatGPTに教えてもらう

今回は、ChatGPTに教えてもらいながら、pythonでExcelにデータを入力していきます。

この内容なら検索した方が早そうですが、練習も兼ねてChatGPTと対話しながら進めていきます。

### 開始

* データ入力の方法をChatGPTに質問する

![スクリーンショット 2024-01-19 222551.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679771/459a5b7f-911f-f50f-abdb-2543abeae5be.png)
![スクリーンショット 2024-01-19 222602.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679771/854dd904-95ee-dee7-62c1-e01fbdfd9f50.png)
![スクリーンショット 2024-01-19 222617.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679771/6d452e92-ebfe-3a3e-76cc-b8d810f017d9.png)


ライブラリはopenpyxlやpandasを使用するのが一般的らしく、今回はファイルの作成から保存までを簡単にできそうなopenpyxlを使用します。
<br>
* コードを書いてもらう

![スクリーンショット 2024-01-19 223029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679771/9244ab6f-9ca1-23e2-bd1f-a8681a23363c.png)

↓生成されたコード
```
import openpyxl

# 新しいワークブックを作成
workbook = openpyxl.Workbook()

# デフォルトで作成されるシートを取得
sheet = workbook.active

# 列のヘッダーを書き込む
sheet['B1'] = '業務内容'
sheet['C1'] = '勤務地'
sheet['D1'] = '求人サイト'

# 会社とデータの対応関係
company_data = {
    'CompanyA': ('プログラミング', '東京', 'Indeed'),
    'CompanyB': ('デザイン', '大阪', 'Glassdoor'),
    'CompanyC': ('営業', '名古屋', 'LinkedIn'),
    # 他の会社データを必要に応じて追加
}

# データを表に書き込む
for row_index, (company_name, data) in enumerate(company_data.items(), start=2):
    sheet.cell(row=row_index, column=1, value=company_name)  # 会社名
    sheet.cell(row=row_index, column=2, value=data[0])  # 業務内容
    sheet.cell(row=row_index, column=3, value=data[1])  # 勤務地
    sheet.cell(row=row_index, column=4, value=data[2])  # 求人サイト

# ワークブックを保存
workbook.save('company_job_list.xlsx')

```
<br>

* コードを実行する
```
pip install openpyxl
```
openpyxlをインストールし、生成されたコードをpythonファイルにコピペして実行すると、作業ディレクトリに.xlsxファイルが作成されます。

### 作成したファイルの確認
![スクリーンショット 2024-01-19 223921.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679771/fd8ac2f3-c43a-1447-cc08-3e050b31292f.png)
無事にデータが入力できているので成功です。

### 最後に
ChatGPTでコードを簡単に生成できるというのは知っていましたが、実際にやってみると修正する必要もなく動いたので驚きました。

この記事は私の初投稿であり、読みづらいにもかかわらず最後まで見ていただきありがとうございました。
質の高い記事が書けるように、これからも更新していきます。
Jinjaのselectattrが返すのはジェネレータであることにハマった

# あらまし
[Jinja](https://jinja.palletsprojects.com/)の[selectattr](https://jinja.palletsprojects.com/en/3.1.x/templates/#jinja-filters.selectattr)フィルターにハマったのでメモ。


# 困ったこと
~~~ python
import jinja2
params = [
    {
        'class': 'A',
        'name': '太郎',
    },
    {
        'class': 'B',
        'name': '花子',
    },
]
env = jinja2.Environment()
tmpl = env.from_string('''
    {%- if params | selectattr('class','==','C') %}
        Cクラスの人はいますね
    {%- endif %}
''')
print(tmpl.render(params))
~~~
とすると、`Cクラスの人はいますね` と表示されてしまう。


# なぜこうなるのか
`selectattr` が返すのはジェネレータであるため。
~~~ python
tmpl = env.from_string('''
    {{ params | selectattr('class','==','C') }}
''')
print(tmpl.render(params))

<generator object select_or_reject at 0x000001DBFB6A3140>
~~~
`if` は空リストであれば偽と判定するが、
今回の場合はジェネレータオブジェクトを渡しており、これ自体は偽と判定されない。
(ジェネレータであることと、ジェネレータが何も要素を返さないのは別の話)


# 対策
`list` フィルターに通すのがいいかと思う。
これで`selectattr`の結果要素が見つからなかった場合は空リストになり、
`if`で偽と判定できる。
~~~ python
tmpl = env.from_string('''
    {%- if params | selectattr('class','==','C') | list %}
        Cクラスの人はいますね
    {%- endif %}
''')
print(tmpl.render(params))
~~~
⇒何も表示されない。


# 別解
独自の [test](https://jinja.palletsprojects.com/en/3.1.x/templates/#tests) を実装してもいいかも。
~~~ python
def existing(itr):
   try:
      next(iter(itr))
   except StopIteration:
      return False
   else:
      return True
env.tests['existing'] = existing
tmpl = env.from_string('''
    {%- if params | selectattr('class','==','C') is existing %}
        Cクラスの人はいますね
    {%- endif %}
''')
print(tmpl.render(params))
~~~


# 今見てみたら
ドキュメントに「Similar to a generator comprehension such as:」とか書いてあった・・・
でもこれで`selectattr`が返すのはジェネレータだと気付くのは無理じゃない・・・？


# 今後のために
普段のPythonコーディングで気にしていることだが、
Jinjaにおいても型を意識することは重要である。
コストをかけずにWebサービスを公開するための構成例

## はじめに
個人でフロントエンド(react)、バックエンド(node.js)、データベース(postgreSQL)を利用したWebサービスを公開したいと考えていました。
まずはテスト的に無料で外部公開できるサービスがないか調査しましたが、2022年8月に有料化されたHerokuの記事ばかりヒットしてしました。
結果的には無料で使用できる構成があり、実際にテストプログラムを動作させることができましたので構成例として記載しておきます。
※無料なので比較的厳しい条件も含まれていたりするのでそれぞれのサービスを確認お願いします。
例えばsupabaseは数日間利用がないとインスタンスが一時停止して手動で起動させないといけないなどがあります。

## 今回試したサービス
できるだけ同じサービスに集約したいと考えていましたが、実際にはフロントエンド、バックエンド、データベースはそれぞれ異なるサービスになってしまいました。
ここは無料なので仕方がなさそうです。
簡単な構成は以下の構成図のようになっています。
・フロントエンド　vercel
・バックエンド　　render
・データベース　　supabase

一部シンガポールリージョンしか選択できないサービスもありましたが、テスト的に動かすだけであれば特に困っていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/253f6643-7518-6645-59bf-a9b57c57802b.png)


## Github連携が簡単にできる
私が知らなかっただけかもしれませんが、こんなに便利なのかと感じたのがGithub連携です。
Vercel、RenderどちらもGithub連携をするだけで追加でアカウント発行の手間がなく、すぐに始めることができました。
また、どちらのサービスも何も設定しなくてもソースをGithubにプッシュすると自動的にビルドが走ってそのままデプロイまでしてくれます。


### vercelのデプロイ履歴画面
デプロイの履歴画面ですがプッシュしただけで勝手にビルドが始まりready状態になったことがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/c3fdaebb-5776-7be8-4a2a-6839aa506f6e.png)


### renderのデプロイ履歴画面
こちらも同様にrenderのデプロイ履歴画面ですが「Auto-Deploy」の表記があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/86ed8b57-da36-70cb-c740-a59f40b7764e.png)

### supabaseのデータ管理画面
supabaseはGUIでデータを確認できる画面が用意されています。
こちらでテーブルの作成やデータの編集ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439918/abc94081-8cb2-02ba-6f20-1543c1a60be9.png)
Amazon Fire TVにAPKファイルからアプリをダウンロードする方法

# MacをFire TVに接続する

Windowsに関しては下記のサイトを参照のこと

[ADBを使用してFire TVに接続する方法 - amazon appstore](https://developer.amazon.com/ja/docs/fire-tv/connecting-adb-to-device.html)

## ADBコマンドのパスを通す

最初にAndroid Studioを起動し、SDK Managerまでのパスを調べる

Example : `/Users/<ユーザー名>/Library/Android/sdk`

上記の末尾に`/platform-tools/`をつけ、以下のコマンドを実行する

```sh
$ echo 'export PATH=$PATH:/Users/<ユーザー名>/Library/Android/sdk/platform-tools/' >> ~/.bash_profile

```

実行後、`adb`コマンドにパスが通っていることを確認する

```sh
$ adb --version
Android Debug Bridge version 1.0.41
```

## ADBコマンドを用いてFire TVに接続する

Amazon Fire TVの[設定]から[My Fire TV] > [バージョン情報] > [ネットワーク] と進み、IPアドレスを確認する。バージョンが異なる場合異なる場所にIPが存在する場合があるため、IPが確認できない場合は、上述のような公式サイトを参照のこと  
`<ipaddress>`に上で調べたIPを指定する
`<port>`には、5555～5585の範囲でポート番号を指定できる  

```sh
% adb connect <ipaddress>:<port>
```

Fire TVの画面に「USBデバッグを許可しますか？」という画面が表示されるため、承認を行う
実行後、デバイスが追加されていることを確認する

```sh
$ adb devices
List of devices attached
10.49.172.51:5555	device
```

# APKファイルからアプリをダウンロードする

コマンドライン以外による方法は以下のサイトを参照のこと

[アプリをインストールして実行する方法 - amazon appstore](https://developer.amazon.com/ja/docs/fire-tv/installing-and-running-your-app.html)

`<path-to-apk-file>`にAPKファイルまでのパスを入れるだけでいい

```sh
$ adb install <path-to-apk-file>
```
作業用スクリプトファイルをClojureで書く

# 作業用スクリプトファイルをClojrueで書く

~~スクリプトファイルとして実行させられることはできたのですが、Clojure自体の立ち上がりが遅いので実用性はあんまりありません...~~

2024/05/19 追記
jokerというツールを使えば、高速に起動できることが分かったので、[別記事](https://qiita.com/hylanger/items/80d4a317d7cb5a8d64be)でまとめました

## はじめに

手元の環境はMacなので、Macベースで記述していきます。

## インストール

Clojureの[公式サイト](https://clojure.org/releases/downloads)から最新版の以下の3ファイルをDLします。

- clojure-1.11.1.jar
- core.specs.alpha-0.2.62.jar
- spec.alpha-0.3.218.jar

この3ファイルをどこでもいいので場所を決めて配置します。
私の環境では以下のように`/opt`下にディレクトリを作成して置きました。

```sh
sudo mkdir /opt/clojure
sudo chown -R ユーザ名 /opt/clojure
mv clojure-1.11.1.jar /opt/clojure/
mv core.specs.alpha-0.2.62.jar /opt/clojure
mv spec.alpha-0.3.218.jar /opt/clojure
```

## スクリプトファイル作成

Haskellの拡張子は`.clj`なので、`sample.clj`というファイルを作成する。

```clj
#^:shebang '[
  CLOJURE_HOME=/opt/clojure
  CP1=$CLOJURE_HOME/clojure.jar
  CP2=$CLOJURE_HOME/core.specs.alpha-0.2.62.jar
  CP3=$CLOJURE_HOME/spec.alpha-0.3.218.jar
  exec java -cp $CP1:$CP2:$CP3 clojure.main "$0" "$@"
]

(use '[clojure.java.shell :only (sh)])

;; 引数の取得(文字列の配列)
(let [args *command-line-args*]
  (println args))

;; OSコマンド実行
(defn run-cmd [cmd]
  (let [res (sh cmd)]
    (println "[Exit code]")
    (println (:exit res))
    (println "[Output]")
    (println (:out res))
    (println "[Error]")
    (println (:err res))))

(run-cmd "ls")

;; 実行が完了しないので明示的に終了させる
(shutdown-agents)
```

この状態で以下のコマンドを実行してファイルに実行権限を与える

```sh
chmod +x sample.clj
```

あとは以下のように実行すればOK

```sh
sample.clj
```

## 参考

- https://tnoda-clojure.tumblr.com/post/24969285880/clojure-scripting
- http://simplesandsamples.com/arg.clj.html
- http://simplesandsamples.com/system.clj.html
- https://sunday-programming.hatenablog.com/entry/2014/02/11/010305
TeamsとWorkatoで打刻漏れ対策！勤怠システムと連携もできる！

# こんな人に参考にしてほしい
- ### 社員の打刻漏れが多くて困っている
###
- ### 管理者として勤怠状況をしっかり確認したい
###
- ### Teamsを使って業務効率化したい！
###

Workatoを利用し、Teamsで打刻漏れの対策をすることができます。
打刻依頼メッセージを送信することで、打刻をするきっかけを作ります。

WorkatoはiPaaS製品です。
クラウド上でアプリケーションと連携することができます。

勤怠システムと連携することができれば、
出勤の時は、社員にTeamsから、打刻させることが可能になります。

メールサービスと連携することができれば、
遅刻の時は、社員にTeamsから、メールで管理者へ報告させることも可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/31bce169-68a2-468f-e477-717b6d6c304c.png)

Workatoはローコードで開発できるiPaaS製品です。条件分岐や順次処理などの基本的な知識があるとよりカスタマイズができます。

例えば
- 起動する時間に応じて処理を分ける(「出勤」「退勤」）
- 社員が入力できる項目を設ける（遅刻理由など入力）
- 勤怠システムと連携し残業アラートを出す

Workatoで作成したレシピ(ワークフロー)を紹介します。
レシピは、出勤の打刻依頼メッセージを送信して、選択に応じて処理を開始するレシピです。

全体の流れがわかるように、だいぶ省略して説明しています。
アクションの詳細な説明は行っていません。要点だけ伝えることができたらと思っています。

# Workatoのレシピ
2つのレシピを用意します。

- 定期的に打刻依頼メッセージを送信するレシピ
- 選択に応じた処理が開始するレシピ

### 定期的に打刻依頼メッセージを送信

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/3564a0ca-fc1e-6352-0b0c-32b4232bc85b.png)

3つのアクションを設定します。
1. 「毎週平日の午前8時50分」とトリガー設定
2. 「送りたいチャット」を設定
3. Workbot（ロボット）がメッセージを送信

メッセージには、**ラジオボタンに値の設定**をします。
出勤が選択された場合は「1」、退勤が選択された場合は「2」とします。
さらに**Bot command の設定で【送信ボタン】と【コマンド名】を設定**します。

### 選択に応じた処理が開始

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570089/0f05ea0e-8084-6fc1-fb90-ff9fa998f197.png)

トリガーには**さきほど設定した【コマンド名】を選択** します。

Teamsに送信された打刻依頼メッセージの、【送信ボタン】が押下されるとラジオボタンの値に応じて処理が開始されます。
- 出勤を選択時：Google Sheetsの出勤簿に登録、Teamsで登録完了メッセージ
- 遅刻を選択時：Gmailで関係者へメールを送信、Teamsで送信完了メッセージ

サンプルとしてGoogle SheetsとGmailを用いていますが、Workatoと連携している他のアプリケーションに置き換えることもできます。

### アクションの説明は別記事で紹介

全体の流れだけを簡単に説明させていただきました。
**Workbotがメッセージを送信する**ことや、
**定期的にメッセージ送信するスケジュール実行**などに関しては別記事で紹介しているので、参考にしてみてください。

[・Workbot for Microsoft Teams の設定から簡単なアクションまで実行してみた](https://qiita.com/ueno_bvt/items/5d8ee9f5278a5c65eb69)

[・Teams有効活用！予約メッセージを設定する方法！Workatoでは定期実行が可能](https://qiita.com/ueno_bvt/items/4e96d89c438ce780ae4b)

# 終わりに

冒頭にも書かせて頂きましたが、Workatoはローコードで開発できるiPaaS製品です。自動化したい業務フローにあわせてWorkatoのレシピを作成することができます。

基本的なプログラミングの知識があるとよりカスタマイズができます。
弊社では他の記事も紹介しています。あわせて参考にしてみてください。
[→会社概要と記事一覧はこちら](https://qiita.com/organizations/bstylevt/profile)
pythonでbar_chart_raceを使った際に、japanize_matplotlibがインポートできない

## きっかけ
Youtubeで見たことあるグラフを作ってみたい！
なんとなく最後まで見てしまうグラフを作ってみたく、試行錯誤した際にハマったので、困った人用に載せておきます。

## ラベルに日本語を使用し、対応しているjapanize_matplotlibをimportするとエラーが発生
こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/9dca4d4e-9418-44d3-838b-623450f96b5b.png)

```error
例外が発生しました: ModuleNotFoundError
No module named 'distutils'
  File "C:\xxxxxxxxx\python_project\T0001\T0001.py", line 3, in <module>
    import japanize_matplotlib
ModuleNotFoundError: No module named 'distutils'
```

## 解決方法

Pythonのバージョンの問題です。
3.12系 では、japanize_matplotlib が使用しているモジュール「distutils」が使えません。

廃止されました。
詳しくはこちら：
https://docs.python.org/ja/3.10/distutils/index.html

bar_chart_race で日本語のラベル使用したい場合は、Python 3.11系以下を使用しましょう。

以上

## 感想
色々試行錯誤してる最中に、pip が壊れたりして、３時間ハマりました。
分かってしまえば大したことありませんが、ピンポイントで指摘する記事がなかったので、書いておきます。

他に助かる人がいれば幸いナリ。
ネットに繋がっていないはずのVPC Lambdaをどうして呼び出せちゃうんですか

# はじめに
VPC Lambdaをプライベートサブネットに配置し、手元のPCのターミナルからaws lambda invokeコマンドを実行すると呼び出すことができます。Lambdaがネットに繋がってないのになんで叩けるんや...と思ったので少し調べて見ました。

# VPC Lambdaの構造

VPC Lambdaとは言いつつ、Lambdaが実行されるのは**ユーザーが作成したVPC内ではありません**。
AWS Lambda Service VPC というLambda Service管理のVPCがあり、そこにLambdaが配置されています。かわりにユーザーが作成したVPCにはENIが作成されます。LambdaはENIを経由して、ユーザーが用意したVPC内のリソースにアクセスします。
このENIのことをHyperplane ENIと言うそうです（なんかかっこいいですね）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/51eb67a6-0a13-0379-1184-294e7d155a11.png)

https://aws.amazon.com/jp/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/foundation-networking.html#foundation-nw-eni

VPC Lambdaを作成する際に、VPC, サブネット, セキュリティグループを指定する必要があります。Hyperplane ENIはこの時指定したサブネットに配置されるようです。各サブネットとセキュリティグループの組み合わせの数だけHyperplane ENIは作成されます。

>Lambda は、各サブネットでセキュリティグループの固有のセットごとにネットワークインターフェイスを作成します。同じサブネットとセキュリティグループの組み合わせを共有するアカウント内の関数は、同じネットワークインターフェイスを使用します。


# invoke APIを実行するとなぜVPC Lambdaが実行できるのか

まず前提として、VPC Lambdaの設定上、プライベートサブネットが設定されているとします。

この状況で手元のPCからAWS CLIを使ってinvoke APIを実行したら、私は手元のPCからENIにアクセスする方法がないので、Lambdaの実行はできないものだと考えていました。しかし、実際は冒頭でも述べたようにLambdaを起動させることができます。

この理由は、invoke APIはENIを通してLambdaを呼びだしていないからだと思われます。
公式ドキュメントにも目を通したのですが、AWS Lambda Service VPC に直接アクセスしていることを言及している箇所を見つけることはできませんでした（見落としているだけだったら本当にごめんなさい）。代わりにstackoverflowで、本件に関連している質問を見つけ、その中で言及されていました。

https://stackoverflow.com/questions/41559577/why-can-i-call-an-on-vpc-aws-lambda-from-an-off-vpc-aws-lambda-but-not-vice-vers

>In order to trigger a Lambda function, all that's required is for the caller to have outbound access to the Invoke AWS API. It is not necessary for the invoked Lambda function to have any open inbound ports, or any public Internet access.

つまり、Lambdaを呼び出す側がInvoke APIにアクセスすることができれば、Hyperplane ENIの設定とは無関係にAWS Lambda Service VPCの関数を呼び出すことができます。
一方で、Lambda関数から外部のリソースにアクセスする場合はHyperplane ENIを経由するので、設定したサブネットやセキュリティグループの影響を受けます。そのためVPC LambdaがVPC内やインターネットにアクセスする場合には、セキュリティグループの設定や、NATゲートウェイの配置などを適切に行う必要があります。