OmniAICreator/Qiita-1.07M huggingface dataset:
Amazon SNSのUnsubscribeリンク無効化する（ + 無効化の確認まで）

# 概要
Amazon SNSのメール通知では、本文内に記載がある「Unsubscribe」をクリックすると簡単に通知が解除されてしまいます。
知らずに誰かが解除してしまい、メールが届かない事に気づかないというケースは割とあるので、この無効化リンクを解除しておきましょう。

# 項目
下記を紹介します。

1.コンソールから行う無効化
2.AWS CLIで行う無効化
3.無効化されているか確認する方法

# 1.コンソールから行う無効化

メールアドレスの新規追加時の前提で進めます。
まず、コンソールからSNSのトピックに対してメールアドレスを設定すると、設定されたメールアドレスに対して下記内容の承認メールが届きます。

件名：
AWS Notification - Subscription Confirmation

本文：
![メール1_20230513053422.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/ac118339-2e98-e6e7-cbe5-a14542c401ba.png)

本文に「Confirm subscription」というリンクがありますが、
**こちらは左クリックはせず（重要！）**、右クリックでリンクのURLを取得しておきましょう。

左クリックで先に承認してしまった場合は、コンソールでのリンクの無効化は出来なくなってしまう模様。

次にコンソールに戻ります。
対象のトピックより、新規追加したサブスクリプションを選択し、「サブスクリプションの確認」を押下。

![トピック1_20230513054310.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/30c8a101-8d15-7457-3b49-e7ce611129d8.png)


ここに先ほど取得しておいたリンクを入れ込んで「確認」を押せば完了です。

![トピック2_20230513054615.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954355/d0addb79-2ff9-1e4b-d4b5-313192f8a5ed.png)


# 2.CLIから行う無効化

こちらはコンソール手順とは違い、既に承認されているサブスクリプションに対しても（上述した左クリックをしていても）、リンクの無効化が可能です。
CloudShellから実行するのが良いでしょう。

topic-arn、tokenについては、設定対象から取得して入れ込みましょう。
取得方法は次の項目で説明します。

```
aws sns confirm-subscription \
--topic-arn arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:zenden_topic \
--token xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
--authenticate-on-unsubscribe true \
--region ap-northeast-1
```

# topic-arn、tokenの見つけ方

topic-arn、tokenは、上述の「コンソールから行う無効化」にて取得したURLを見ると確認する事ができます。
例えば下記のようなURLであった場合、このように分けられます。

> https://sns.ap-northeast-1.amazonaws.com/confirmation.html?TopicArn=arn:aws:sns:ap-northeast-?:xxxxxxxxxxxx:zenden&Token=2336xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxd8a&Endpoint=zenden@hoge.jp

・topic-arn
```
arn:aws:sns:ap-northeast-?:xxxxxxxxxxxx:zenden
```

・token

```
2336xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxxxd8a
```


# 3.無効化が行われているか確認

CloudShellにて下記コマンドを実行すると確認できます。（このまま実行でOK）
結果を確認して、行頭にTrueと出ていれば無効化されています。

```
echo '"ConfirmationWasAuthenticated","SubscriptionArn","Protocol","Endpoint"' &&\
  aws sns list-subscriptions | jq -r '.Subscriptions[].SubscriptionArn'\
  | xargs -I{} -P 5 aws sns get-subscription-attributes --subscription-arn {}\
  | jq -r '.Attributes |  [.ConfirmationWasAuthenticated,.SubscriptionArn,.Protocol,.Endpoint] | @csv'
```

# 終わりに
時と場合によりますが、特にメーリングリストの場合などは設定しておくと良いのではないかと思います。
誰かのお役に立てば。
【Mac】TSharkのインストール方法と使い方を解説

こんにちは、[yamaday0u](https://yamaday0u.net/profile/)です。


今回はTSharkというパケットキャプチャツールについてインストール方法や使い方を解説します。
※2022年から技術系の記事は個人ブログにも投稿しております。個人ブログの記事は適宜修正しておりますのでぜひこちらもご覧ください→[yamaday0u Blog](https://yamaday0u.net/category/programmer/)

- TSharkとは
- TSharkのインストール
- tsharkコマンドの例


## TSharkとは
パケットキャプチャの支援ツールであるWiresharkのコマンドライン版ツールです。

Terminal wireSHARKの略でTSharkというらしいです。（こういう略称の元の名前を知るのが好きでよく調べています。）

> tshark (Terminal wireSHARK) is the command line tool (CLI)
[Tshark | About](https://tshark.dev/setup/about/#what-is-tshark)

## TSharkのインストール
MacならHomebrewでのインストールが簡単なので、brewコマンドを使ってインストールする方法を紹介します。

他の方法でインストールしたい方は、tsharkのガイドページにいくつかのインストール方法が紹介されているのでそちらを参考にしてみてください。

```bash:ターミナル
brew install --cask wireshark
```

途中でPCのパスワード入力を求められる場合もあります。
無事にインストールが終わったらtsharkコマンドが使えるか確認します。

```bash:ターミナル
tshark -v
```

以下のようにバージョンが表示されれば成功です。

```bash:ターミナル
TShark (Wireshark) 4.0.5 (v4.0.5-0-ge556162d8da3).
```

ちなみにbrewコマンドでインストールするときに「–cask」オプションをつけたので、Wiresharkも同時にインストールされています。

## tsharkコマンドの例
ぼくがよく利用するtsharkコマンドはこんな感じです。

|コマンド|実行内容|
|:----|:----|
|tshark -D|インタフェース一覧の表示|
|tshark -i ポート番号 or ポート名|ポートを指定してログ取得開始|
|tshark -i 1 -w test.txt|ログをtest.txtファイルに書き出し|
|tshark -i 1 -w test.txt -P|test.txtファイルに書き出しながらターミナルにもログ出力|
|tshark -i 1 -f “host 192.168.1.4”|IPアドレス192.168.1.4が含まれるログをフィルタして出力|
|tshark -r ファイル|指定したファイルを開く|

上記コマンドのうち、いくつかのコマンドについて具体的に説明します。

### tshark -D
tshark -Dコマンドはパケットキャプチャするインタフェースのリストを表示します。

```bash:ターミナル
tshark -D
```

ぼくのMacで実行したところ以下の結果が出ました。
![スクリーンショット 2023-05-14 1.04.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849306/8be7d13b-a7e4-d46c-2cf6-3719c9b7af1a.png)

各インタフェースの説明は次のとおりです。

- en：イーサネット
- awdl：Apple Wireless Direct Link（ネットワーク「awdl」とは何でしょうか）
- llw：Low Latency WLAN
- utun：仮想インターフェース

### tshark -r
tshark -r “ファイル”コマンドで指定したログファイルを読み込みます。

tsharkで出力したログファイルの拡張子はpcapng（packet capture next generation）で、普通のエディタでは開くことができません。

## 参考資料
- [tshark.dev](https://tshark.dev/)
- [Wireshark](https://www.wireshark.org/)
やってしまった... ルートディレクトリで権限変更&復活劇

プロジェクトフォルダで「sudo chmod -R 777 ./」を「sudo chmod -R 777 /」と打ってしまったようだ。
suコマンドやsudoコマンドの実行、VSCodeの起動等何もできなくなってしまった。
VMのイメージのバックアップはあるので1からプロジェクトを作り直せば解決はするのだが、滅多に起きないトラブルなのでどこまで復活できるか試してみた。
# はじめに
* setuidが必要なコマンドの復旧
* sshd関係のアクセス権の修復
* VSCodeが起動しない！！
* 小ネタ

### 環境　
仮想マシン：VirtualBox
OS:CentOS (GNOME Desktop)
IDE：VSCode

### setuidが必要なコマンドの復旧
su, sudoはsetuidが必要であるがパーミッションを777に変えたことでsetuidが落ちてしまい実行出来なくなった。本来の4755に戻す必要がある。
幸いrootのログインが許可されていたのでCentOSのGNOME Desktopからrootでログインを試みた。
ログインユーザが入力できない場合Ctrl+Alt+F2でユーザ名を変更できる。
ログインできたので早速ターミナルを起動して以下のコマンドを実行。
```bash 
$ chmod 4755 /bin/su
$ chmod 4755 /bin/sudo
```
rootをログアウトし、通常のユーザでログインする。
suコマンドが使えるようになったがsudoコマンドはいくつかのファイルの権限をチェックするらしく、エラーが出て実行できない。
sudoコマンドの権限を戻していく。

```bash
$ su -
$ password:
$ chmod 755 /etc/sudoers.d
$ chmod 644 /usr/libexec/sudo/sudoers.so
$ chmod 440 /etc/sudoers
$ chmod 644 /etc/sudo.conf

 ```
sudoコマンドが使えるようになった。

### sshd関係のアクセス権の修復
system.logを確認するとSSH関係のWarningが出ているので権限を戻していく。
```bash
$ chmod #### /xx/xxkey　　←後日記載
$ chmod #### /xx/xxkey　　←後日記載
$ chmod #### /xx/xxkey　　←後日記載
```
### VSCodeが起動しない！！
開発プロジェクトに問題ないかGNOMEのランチャからVSCodeを起動。しかし、起動せずアラートすら出ない。
何かエラーがでていないかsystem.logを確認したがVSCodeに関するログはない。

今度はターミナルから直接コマンドを実行してみる。しかし、エラーメッセージも表示されず終わる。
```bash 
$ code .
$ 
```
codeコマンドにオプションをつけて実行してみるといつもの出力がされた。パスが通っていないわけではないようだ。
```bash
$ code --help
$ code -v
```

しばらく手詰まり。。。


ランチャのアプリに起動コマンドの定義があることを知った。
/usr/share/applications/に移動する。
VSCodeのアプリのアイコンを右クリックして「プロパティ」を確認。
基本タブ-起動コマンド："/usr/share/code/code --unity-launch %F"
%Fは多分ファイル名だろう。ファイル名は省略してこの1行をターミナルで実行してみる。

```bash 
$ /usr/share/code/code --unity-launch
:FATAL:setuid_sandbox_host.cc(158)] The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. You need to make sure that /usr/share/code/chrome-sandbox is owned by root and has mode 4755.
```
エラーきたー！
エラーに従って権限を戻す。
```bash
$ su -
$ password:
$ cd /usr/share/code/
$ chmod 4755 chrome-sandbox
```
VSCodeの起動を試みる。
きたー！VSCodeきたー！

### 小ネタ
/etc/sudo.confの権限を戻す前にsudoコマンドを実行すると以下のメッセージがでる。
```text
$ sudo [コマンド]
/etc/sudo.conf is world writable
あなたはシステム管理者から通常の講習を受けたはずです。
これは通常、以下の3点に要約されます！
#1) 他人のブライバシーを尊重すること。
#2) タイプする前に考えること。
#3）大いなる力には大いなる責任が伴うこと。
password:
$ 
```
滅多にお目にかかれないメッセージに遭遇してビビった。
３番目のメッセージは古くからの格言だがスパイダーマンで有名になった言葉らしい。

# おわりに
教訓　権限変更はフォルダを指定しよう。chmod -R [パーミッション] [任意のフォルダ名]

# 参照URL
suコマンドの権限変更からVSCode起動までに参考にさせていただいたページがたくさんありました。
URLを保存していなかったので紹介できませんがお礼を申し上げます。
Githubのプライベートリポジトリをsshでクローンする方法（Mac）

## 環境
- System Version: macOS 13.3.1 (22E261)
- Kernel Version: Darwin 22.4.0
- Shell: zsh

## ターミナルでsshキーを生成する
下記コマンドを入力する
```
ssh-keygen -t rsa -b 4096 -C "hogehoge@example.com"
```
:::note info
-Cはコメントを指定するオプションであり、Githubの公式ドキュメントでメールアドレスを指定するよう書かれています。
ここで指定したメールアドレスは公開鍵に埋め込まれます。

メールアドレスを公開鍵に含めるのは、他の人が利用する際に所有者を特定できることで何かあった際に連絡できるようにするという目的がありそうです。
あくまでコメントなので空白でも良いと思います。
:::

生成された公開鍵と秘密鍵は~/.ssh/に配置されます。
- id_rsa.pub: 公開鍵
- id_rsa    : 秘密鍵

## Githubで公開鍵を登録する
Settings > SSH and GPG keys にて New SSH key をクリック

Titleは自分がわかればOKなので適当に入力
Keyは先程生成した公開鍵を開いて、中身をそのままペースト

Add SSH key で登録します。

## ターミナルでSSHエージェントに秘密鍵を登録する
下記コマンドを入力する
```
ssh-add ~/.ssh/id_rsa
```

## ターミナルでSSH認証する際に使う秘密鍵を登録する
下記コマンドを入力する
```
ssh -i ~/.ssh/id_rsa git@github.com
```

>The authenticity of host 'github.com (20.27.177.113)' can't be established.
ED25519 key fingerprint is SHA256:************************.
This key is not known by any other names
Are you sure you want to continue connecting (yes/no/[fingerprint])? 

のようなメッセージがでてきて、対応を求められると思います。

これは、初めてGitHubのSSHサーバーに接続しようとしている場合に表示されるメッセージです。
SSHでは、接続先のホストの公開鍵を確認して安全な接続を確立します。しかし、初めて接続する場合、その公開鍵がローカルシステムに存在しないため、接続の安全性を確認することができません。

yesと入力して、接続を続行します。
接続先のホストの公開鍵がknown_hostsファイルに追加され、次回からは自動的に検証されるようになります。

## クローンする
Githubでクローンしたいリポジトリを開き、SSH用のURLをコピーします。
```
git@github.com:[owner_name]/[repository_name].git
```

ターミナルでクローン先のDirectoryに移動し、次のコマンドを入力します。
```
git clone git@github.com:[owner_name]/[repository_name].git
```

うまく設定できていれば、クローンできるはずです！
【Rails】namespace, scope, module


## はじめに
Rails 勉強中の👶です。
理解を深めるために日々の学びを記事にしています。
初心者の記事なので言い回しや記載に誤りがあるかも知れませんが、暖かく見守っていただけると幸いです。
<font color="gray">(よろしければ間違いをコメントいただけると学び、励みになります！)</font>

## 学んだこと
・Railsにおける namespace, scope, module

## namespaceを使用
#### route.rbの記載
```erb:routes.rb
Rails.application.routes.draw do
  # 通常(比較用)
  resources :user, only: [ :index ]

  # namespace
  namespace :admin do
    resources :user, only: [ :index]
  end
end
```

#### ルーティング確認
**グループ化されるもの:** 　Prefix、URI Pattern、Controller#Action(ファイル構造)
**グループ化されないもの:** -
```
      user_index GET  /user(.:format)       user#index
admin_user_index GET  /admin/user(.:format) admin/user#index
```


## scopeを使用
#### route.rbの記載
```erb:routes.rb
Rails.application.routes.draw do
  # 通常(比較用、併記するとエラーになります)
  resources :user, only: [ :index ]

  # scope
  scope :admin do
    resources :user, only: [ :index]
  end
end
```

#### ルーティング確認
**グループ化されるもの:** 　URI Pattern
**グループ化されないもの:** Prefix、Controller#Action(ファイル構造)
``` 
user_index GET  /user(.:format)       user#index
user_index GET  /admin/user(.:format) user#index
```

## moduleを使用
```erb:routes.rb
Rails.application.routes.draw do
　# 通常(比較用、併記するとエラーになります)
  resources :user, only: [ :index ]

  # module
  scope :admin do
    resources :user, only: [ :index]
  end
end
```

#### ルーティング確認
**グループ化されるもの:** 　Controller#Action(ファイル構造)
**グループ化されないもの:** Prefix、URI Pattern
``` 
user_index GET  /user(.:format)       user#index
user_index GET  /user(.:format) admin/user#index
```


##  ネスト構造のController・Viewを作る
namespaceなどで活用できます
```console
$ rails g controller admin/users  # namespace
```

#### 結果
```console
      create  app/controllers/admin/user_controller.rb
      invoke  erb
      create    app/views/admin/user
      invoke  test_unit
      create    test/controllers/admin/user_controller_test.rb
      invoke  helper
      create    app/helpers/admin/user_helper.rb
      invoke    test_unit
      invoke  assets
      invoke    scss
      create      app/assets/stylesheets/admin/user.scss
```

#### フォルダ構造 比較
```console
$ rails g controller users        # 通常
$ rails g controller admin/users  # namespace
```
![スクリーンショット 2023-05-13 23.20.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2736096/eab857cb-c797-5c45-5b12-0177c868322c.png)
Google Photorealistic 3D Tilesを試してみた！

## はじめに
5/11にGoogleからPhotorealistic 3D Tilesの実験的リリースが発表されました。
これにはジオ界隈でも大きな話題になっています。
現在は無料で使えるとのことなので、使ってみたいと思います。


## Photorealistic 3D Tilesとは
Googleが提供している3D Tilesです。
CesiumJSやdeck.glなどのマップライブラリを使ってレンダリングできます。

Google Earthと同じ3Dマップソースを使用しています。
対象は日本を含む49カ国、2500以上の都市です。

https://cloud.google.com/blog/products/maps-platform/create-immersive-3d-map-experiences-photorealistic-3d-tiles?hl=en


執筆当時では、Map Tiles APIを通じて無料で試すことができます。
タイル リクエストは 1 日あたり最大 250,000 件までになります。
これを超えた場合は、課金ではなくタイルリクエストを受け付けなくなるようです。

https://developers.google.com/maps/documentation/tile/usage_limits?hl=ja

## Google Maps Platform APIキー取得
すでに持っている場合は飛ばしてください。
私は持っていなかったので新規登録しました。

### 料金
Google Maps Platformでは、1か月あたり$200の無料利用枠があります。
これを超えると料金が発生します。超えそうになった時にアラートを設定できるので、必要であれば設定しましょう。

https://mapsplatform.google.com/intl/ja/pricing/

### 手順
以下のサイトを参考にAPIキーを取得します。

https://developers.google.com/maps/documentation/tile/cloud-setup?hl=ja

## マップライブラリを使った表示手順
画面キャプチャはGoogleMapsのガイドライン的にNGっぽいので、貼れません。
ご自分の環境で楽しんでください！

### Cesiumで表示
以下のサイトのサンプルコードを使います。
Cesiumでは地図の操作にマウスが必須です。

https://developers.google.com/maps/documentation/tile/3d-tiles?hl=ja

### deck.glで表示
以下のサイトのサンプルコードを使います。

https://developers.google.com/maps/documentation/tile/use-renderer?hl=ja#work_with_deckgl


## おわりに
3Dの地図といえばProject PLATEAUの3D都市モデルが有名ですが、今回GoogleがPhotorealistic 3D Tilesをリリースしたことで、ユーザが流れそうな予感がしました。

PLATEAUデータはデータ更新の頻度が自治体に依存していますが、Googleの場合は更新頻度も高そうなので魅力ですよね。
とはいえ、実際に触ってみると、Googleのほうはゴミっぽいオブジェクトが多く、この点はPLATEAUデータに軍配が上がりそうです。
PLATEAUデータはLODを使い分けることができるのもメリットですよね。

今後の動向に期待です。
Microsoft 365 + Route 53 + 独自ドメイン(GoDaddy)構成でOutlookのメールを受信できるようにする

日本ではあまり馴染みのない`GoDaddy`で取得したドメインを使って、Route 53でのレコード管理、Microsoft365のOutlookでメール受信する方法をご紹介します。

## Route53でホストゾーンを作る
以下の公式ドキュメントを参照して、独自ドメインのパブリックホストゾーンを作ります
※突然仕様変更する場合もあるので、英文ドキュメントも併せて参照してください

https://docs.aws.amazon.com/ja_jp/Route53/latest/DeveloperGuide/CreatingHostedZone.html




## GoDaddyでの設定
- Mis productos => Administrar で対象のドメインを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/2355d2b4-f9c4-d0c8-3c17-ca0ca1c8398f.png)

- `Dominio` => `Configración de Dominio` 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/6ea59ef6-dbc6-69cf-8c1f-58cf56620e8f.png)

- `Cartera de dominio`ページから、対象のドメインを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/201d9521-7832-90e6-58ee-4a658e9eeae8.png)

- `DNS` => `Servidores de nombres` => `Cambiar de servidor de nombres`で Route53のNSレコード4つ入れる
:::note warn
注意
4つのNSコードの最後尾にある`.`は入れないようにしてください
:::
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/51dfc294-47f5-5a2e-70c4-f30e62392966.png)

- しばらく待ちます。DNS伝播状況はこちらで確認できます

https://www.whatsmydns.net/

## Microsoft 365 の設定
- Microsoft 365管理センター左メニュー：`設定` => `ドメイン`を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/a7d74c50-c1cb-5bd1-8077-5fb1c9e4f5be.png)

- DNSホストプロバイダーを`Amazon Web Service(AWS)`に設定(黄色ハイライト部分)
- `MXレコード`,`TXTレコード`,`CNAMEレコード`の情報をメモ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/708eb3a7-4691-af3a-8aea-687ff6b83766.png)

## Route 53にMX,TXT,CNAMEレコードを追加
- `Route 53` => `Hosted Zone` => `Create Record(オレンジのボタン)`で作成する
- **MXレコードに必要な情報**
  - レコード名(Record name): GoDaddyドメインの場合、`空白`でOK
  - 値(Value): `優先度 Exchange`のように、２つのフィールドを入れる。優先度とExchangeの間は半角スペース
  - TTL: 3600s = 1hour でOK
  - ルーティングポリシー: シンプルルーティング
- **TXTレコードに必要な情報**
  - レコード名(Record name): GoDaddyドメインの場合、`空白`でOK
  - 値(Value): Microsoft 365記載のまま
  - TTL: 3600s = 1hour
  - ルーティングポリシー: シンプルルーティング
- **CNAMEレコードに必要な情報**
  - レコード名(Record name): 記載通り
  - 値(Value): Microsoft 365記載通り
  - TTL: 3600s = 1hour
  - ルーティングポリシー: シンプルルーティング

:::note warn
ハマったポイント
MXとTXTレコード作成で「記載通りに入れればOK」なはずなのに、Microsoft 365ではいつまで経ってもエラーが吐き出される。
`レコード名`、`値末尾の「.」(ピリオド)`を削除して登録したら、エラーが解消した。
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/01de78eb-b9ce-e869-8e79-25332e274838.png)



## Outlookでの受信テストを行う
- 受信できたことを確認して終了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3227891/0c771c6e-1bab-3c8a-e12c-7f91629a1d10.png)

## 終わりに
GoDaddy + Microsoft 365 + Route53でのメール受信設定の技術情報はほとんど存在しないため、Microsoft 365でのレコード認証の部分ではだいぶ手間取ってしまいました。
おそらく日本で当記事の構成を行うことは99％ないと思うが、個人的な備忘録も兼ねて記事にしてみました。
V言語の環境構築からプロジェクト作成まで

以前から気になっていたV言語を触ってみました。

# インストール
WSL2のUbuntu 20.04上にインストール。
公式のインストール方法通りで問題ないと思います。ただ私はインストールディレクトリを指定したかったので、以下コマンドでインストール、問題なく完了。

```bash
sudo mkdir -p /opt/v
sudo chmod 777 /opt/v
git clone https://github.com/vlang/v /opt/v
cd /opt/v && make
sudo ln -s /opt/v/v /usr/bin/v
v --version     # V 0.3.4 814d682
```

上記コマンドはDocker上に構築されている以下を参考にさせていただきました。なおV言語を利用するユーザは書き込み権限まで含めて必要とのこと。
https://celtislab.net/archives/20230417/vlang-programming-environment/#toc_h42

# Hello World
プロジェクトを作成し、コーディング、コンパイル、実行までを確認します。

### プロジェクト作成
```bash
$ mkdir ~/workspace/v
$ cd ~/workspace/v
$ v init
Change the description of your project in `v.mod`
Complete!
$ ls
src  v.mod
$ ls src/
main.v
```
`v init`だとカレントディレクトリにプロジェクトを作成しますが、`v new <プロジェクト名>`だとディレクトリも作ってくれるとのこと。

### コーディング
`v init`の時点でコーディング完了してた。。。
```bash
$ cat src/main.v
module main

fn main() {
        println('Hello World!')
}
```

### 実行
```bash
$ v run .
Hello World!
```
簡単ですね！

### コンパイル
`run`のコマンドを指定せず、ファイルパスだけ指定すればビルドしてくれます。
```bash
$ v .
$ ls -lh
total 664K
drwxr-xr-x 2 shun shun 4.0K May 13 23:15 src
-rwxr-xr-x 1 shun shun 654K May 13 23:18 v
-rw-r--r-- 1 shun shun   83 May 13 23:05 v.mod
```
ん？実行ファイル654KBもあるぞ？実行ファイルのサイズはちっちゃいと昔謳ってたような気がしましたが、と思ったらリリースビルドしてませんでした。
あとガベージコレクションはデフォルトでONなようなので、一旦オフにしてみます。

```bash
$ v -prod -gc none .
$ ls -lh
total 104K
drwxr-xr-x 2 shun shun 4.0K May 13 23:15 src
-rwxr-xr-x 1 shun shun  96K May 13 23:49 v
-rw-r--r-- 1 shun shun   83 May 13 23:05 v.mod
```
96KBは思ってたより大きいですね。他にもオプションが必要なのかもしれませんがヘルプにも書かれていないオプションがあったりということでとりあえずここまで。
これから色々触っていきますが、現時点でNimと比べてどうなのかとかも評価していきたいですね。
Qiita Markdownの書き方

# はじめに
Markdown記法の練習がてら，以下を参考に書いてみる．

https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1


# 1.見出しの設定
見出しは#の数で大きさを変更可能

# 見出し
## 見出し
### 見出し

# 2.コードの挿入
「`」（バッククオテーション）3つでコードをくくる
（※「'」（シングルクオテーション）ではないので注意）

https://qiita.com/aion/items/e8508264833ff9b63bff

```
function hello(){
    return "Hello";
}
```
## コード挿入にシンタックスハイライトの追加

\```php
function hello(){
    return "hello world!";
}
\```
のように書くと，以下のようになる
"php"は"python"でも"html"でも何でも可
> Bash, C#(cs), C++(cpp), CSS, Diff, HTML, XML, Ini, Java, Javascript, PHP, Perl, Python, Ruby, SQL, 1C, AVR Assembler(avrasm), Apache, Axapta, CMake, DOS .bat(dos), Delphi, Django, Erlang, Erlang, REPL, Go, Haskell, Lisp, Lua, MEL, Nginx, Objective C(objectivec), Parser3, Python, profile, Scala, Smalltalk, TeX, VBScript, VHDL, Vala

```php
function hello(){
    return "hello world!";
}
```

# 3.リンクの挿入
・直張りタイプ
> URL

https://qiita.com/koudai_555/items/a3fd672251b77c245d71

・URLにテキストを埋め込むタイプ
> \[テキスト名](URL)

[テキスト名](https://qiita.com/koudai_555)

# 4.引用
【personal-study】binary-tree-riverse

this is personal study about binary tree riverse

## Before
```mermaid
graph TD;
    1-->2;
    1-->3;
    2-->4;
    2-->5;
    3-->6;
    3-->7;
```

## After

```mermaid
graph TD;
    1-->3;
    1-->2;
    2-->5;
    2-->4;
    3-->7;
    3-->6;
```



## method

```python
def reverseTree(tree):
    if tree is None:
        return
    tree.right, tree.left = tree.left, tree.right
    reverseTree(tree.right)
    reverseTree(tree.left)
    return tree
```


#### First Step
Check current root. And change right tree,left tree to left tree ,right tree.

```mermaid
graph TD;
    1.current.see-->3;
    1.current.see-->2;
```


```python
tree.right, tree.left = tree.left, tree.right
```


#### Second Step
finally child left tree and right tree recursion.



```python
reverseTree(tree.right)
reverseTree(tree.left)
```


### reference
https://www.udemy.com/course/50-problems/
【VSCode】文字エンコードを自動判別する方法

## 文字エンコードを自動判別する方法

次の手順で設定することでファイルを開いた際に文字エンコードを自動判別できるようになります。

### ユーザー設定を開く

`command` + `shift` + `P`を入力してコマンドパレットを開きます。

`Open User Settings`と入力しユーザー設定を開きます。

![スクリーンショット 2023-05-13 23.53.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/160d17e2-4ebf-3f5a-f6ee-2a0a3f7d9857.png)

## 設定する

ユーザー設定の検索窓に`Files:Auto Guess Encoding`と入力して検索します。

ヒットした設定にチェックをつけます。

![スクリーンショット 2023-05-13 23.56.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/1aa655f5-5489-e552-4816-72a8e177fa30.png)

以上でファイルをVSCodeでファイルを開いた際に文字エンコードを自動で判別してくれるようになります。
IT知識も実務もPCも未経験でどうすれば良いか・・・

はじめまして。

退職をして独学でやっております、タイトル通り未経験・・・

前職（営業）で培った「顧客の情報を知る」ってな感じで４月下旬からとにかく、情報キャッチを行いました。結果、PCの操作からタイピング、ショートカットキー、目標の作成期間からやっと、Qiitaまでたどり着いた。

明らかに、ほかの人より出遅れてます。だって３４歳・・・。

外出が恐怖、不安、緊張、などで辛くなった。今はだいぶ良くなりました。
でも仕事しないと生活できない・・・

それは良いとして、とりあえず写経を何回も行い、今週はヘッダーの部分を習得したい。

最初作ったHPは完全にパクリで１時間以内の動画で完成していたプロの方達。私は４～５時間もかかりましたよ・・・

わからないことだらけ、でもなんか楽しい！！
新たな目標とやりがいを見つけた。

３４歳で遅すぎる業界はかなり辛い、が楽しいから絶対エンジニアに俺はなる！
Kinesis Data Streamsでデータ重複はなぜ起きるのか

## はじめに
### 概要
Amazon Kinesis Data Streams ではエラーにより、データが重複することがあります。
どのようなケースでデータの重複が発生するのか図を交えながら見ていきます。

### この記事で得られること
- Amazon Kinesis Data Streamsで重複が発生するケースについて
- 重複の対策

## Kinesis Data Streamsについて
Kinesis Data StreamsはリアルタイムでIoTデバイスやスマートフォン等のデバイスからデータを受信して、収集、処理、分析ができるサービスです。
まずは簡単に用語の説明をしていきます。

### プロデューサ
プロデューサとはKinesis Data Streamsに対して、データを送信するものです。
- IoTデバイス
- スマートフォン
- PC

といった機器があります。
これらのログやデータなどをリアルタイムにKinesis Data Streamsに送信します。

### コンシューマ 
コンシューマとはKinesis Data Streamsが受信したデータをポーリング(取得)するものです。
- Lambda
- Kinesis Data Firehose
- Kinesis Data Analytics

などがあります。

これらのサービスを使って、後続のS3やDynamoDB,RDSなどにデータを送信することが可能です。
Lambdaを経由してデータに処理を行った後、データベースへ登録する。
Kinesis Data Firehoseを使ってリアルタイムにデータをS3へ登録する。
といったことが可能です。

### レコード
データのこと。

### シャード
データを書き込むところ。
シャードはデータの書き込み量によって増減します。
一つのシャードは毎秒最大1MBのデータ書き込み、毎秒最大2MBのデータ読み込みが可能です。

### ストリーム
複数のシャードを管理する枠組み。
ストリームには一つ以上のシャードが存在します。

メインとなる用語はこのくらいです。
全体像は図のような感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/fd1d8081-27f2-f2f3-ac28-ae426ce6f832.png)

## データ重複
では、ここからデータが重複するパターンを見ていきましょう。
データが重複するパターンは、以下の2つがあります。
- プロデューサからKinesis Data Streamsへデータ送信時にエラー
- Kinesis Data Streamsにポーリングする時のエラー

### プロデューサ→Kinesis Data Streams
まずは プロデューサからデータを書き込むときのエラーです。
データの書き込みはプロデューサ側からPutRecord APIを叩く必要があります。
通常、 問題なくデータが書き込まれる場合の図を示します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/fb60ae7f-bf18-7769-e4b9-3186145110d1.png)


全体の流れは、
1. プロデューサがデータを送信
1. PutRecord APIでシャードへ書き込む
1. シャードから書き込みができたことをプロデューサへ通知
1. シャード内に書き込まれたレコードをコンシューマがポーリングする
1. ポーリングしたデータを後続のデータ配信先に配信する

という感じです。
では書き込み時にエラーが発生するとどうなるでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/8beead58-90f5-b388-e448-60337f3dc2aa.png)


プロデューサはデータを送信しますが、それに対する書き込みの通知が返って来ません。
すると、 プロデューサーは再度データを送信します。
これにより、シャードに同じデータが登録されるということが発生します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/d0e3597f-b88c-3271-86ce-b153c85c8a21.png)

この図では、シャードに同じレコードが複数登録されたことにより、コンシューマであるLambdaを通してデータベースでデータの重複が発生しています。

### Kinesis Data Streams→コンシューマ
次に、コンシューマがデータをポーリングする際にエラーが発生するパターンを見てみます。
こちらはシャード内にはレコードが登録正常に登録されています。
そのレコードをLambdaがポーリングする際にエラーが発生したケースです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/cbcfe648-c597-5507-575c-99a7c7a0c7c2.png)

エラーが発生するまでのデータは先にデータベースへ登録されます。
その後、再度Lambdaがシャード内のレコードをポーリングします。
それにより、DynamoDBでデータの重複が発生してしまいます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/7cdd99a6-5889-4ba3-3b1b-e9f8719a24a3.png)

## 対策
対策として
シャードに書き込まれる各レコードに一意のIDを割り当てるという方法があります。
これはKinesis Data Streams側ではなくプロデューサ側で実装します。
IDをDynamoDBの項目の一部として使用することで、同じレコードが二度書き込まれても、二度目の書き込みは単に既存の項目を上書きするだけとなり、結果的には同じデータが二度書き込まれても影響はありません。

これは対策の一つなので、この実装が難しい場合は他の対策を取る必要があります。

## まとめ
Kinesis Data Streamsはそれ単体では機能せず、他のサービスとの連携が重要です。
プロデューサのデータを加工する必要があるのか、リアルタイムでの収集が必要なのか、
などデータをどのように扱うかによってKinesis Data Streams移行の処理が変わってきます。
そのため、設計の段階で全体像を把握して設計する必要があります。

### 所感
Kinesis Data Streamsは聞きなれない用語が多く、DVAの試験問題で詰まることが多かったですが、用語を理解してしまえばすんなり理解できるようになりました。
ただ、実際に手を動かして動作を確認できていないので次は実際に手を動かしてみようと思います。
イベントハンドラ onKeyDown とは

`onKeyDown`は、Reactのイベントハンドラで、キーボードのキーが押されたときに発火するイベントです。このイベントハンドラは、主に入力フォームやホットキーなど、キーボードの操作に応じて特定のアクションを実行したい場合に使用されます。

例えば、テキスト入力時に特定のキー（例えば、Enterキー）が押されたときに処理を実行するコンポーネントは以下のようになります。

```jsx
import React, { useState } from 'react';

function App() {
  const [text, setText] = useState('');

  function handleKeyDown(event) {
    if (event.key === 'Enter') {
      alert(`入力内容: ${text}`);
      setText('');
    }
  }

  function handleChange(event) {
    setText(event.target.value);
  }

  return (
    <input
      type="text"
      value={text}
      onChange={handleChange}
      onKeyDown={handleKeyDown}
    />
  );
}

export default App;
```

上記の例では、`handleKeyDown`関数が`onKeyDown`イベントハンドラとして定義されています。テキスト入力でEnterキーが押されると、`handleKeyDown`が実行され、アラートが表示され、入力内容がリセットされます。
ペルシャ絨毯

あなたが思いついたかもしれない質問の 1 つは、機械のカーペット パネルがどのように生産されるのかということです。 機械製カーペットパネルの製造手順は何ですか? 機械製カーペットパネルの製造方法は何ですか?また、市場では何種類の機械製カーペットパネルが入手可能ですか? この記事では、さまざまなタイプの機械製カーペットパネルの製造手順と製造方法を検討します。

機械製カーペットは、機械製織カーペットと機械製プリントカーペットの 2 つのカテゴリーに分けられ、印刷と織の両方の方法で製造されます。 それぞれの製造工程が異なります。
機械織りカーペットパネルの製造方法

このタイプの機械カーペットの製造には機械織り機が使用されます。 これらのカーペットは 4 つの段階で準備されます。
織るための糸の準備
糸を染める
マシンカーペットパネルの質感
カーペットの織りを終えてカーペットが完成します

機械プリントされたカーペットパネル

機械プリントカーペットは、カーペット上に印刷することによって製造される、別のタイプの機械プリントカーペットです。 機械プリントのカーペットはギフトに非常に適しており、ご希望のイメージでこれらのカーペットを注文し、愛する人や友人への永遠の贈り物として贈ることができます。

プリントカーペットパネルが機械織りカーペットパネルに比べて持つ重要な利点は、より広い範囲の色をカバーできることです。 たとえば、自然の中で撮影された家族の写真には 200 色以上の色がある場合があります。 18色で最終的に織られた機械織りのカーペットパネルは、この写真には適していません。 一方、機械印刷されたカーペットパネルは、これら 200 色すべてを高品質かつ解像度でカーペットパネル上に表現できます。

プリントカーペットは機械織りカーペットに次いで普及し、生産されてきました。
機械プリントされたカーペットパネルの製造方法

印刷技術は通常同じ構造をしており、細部が異なるだけである場合があります。 たとえば、紙への印刷は布地への印刷とは異なりますし、どちらもカーペットへの印刷とは異なります。 カーペットへの印刷は非常に高品質で、耐久性があり、何年も安定しています。
カーペット印刷機

https://hidadecor.ir

カーペット印刷機

プリントマシンカーペットパネルを製造する方法は、まず白いマシンカーペットパネルをロール状に織ります。 これらの白いカーペットは、高い櫛と密度でカットされ、根が張られ、印刷に適した繊維がお客様の注文した寸法で生産されます。 この白い絨毯を生絨毯といいます。 この白いカーペットは、紙に印刷する場合、紙と同じ規則を持っています。 熱昇華印刷機を使用したカーペットデザインは、異なる色の組み合わせで高熱、圧力、重プレスを使用して、白い機械カーペット上に高品質の最終デザインを印刷します。 印刷工程では、カーペットのマットに色を印刷します。 次に、カーペットの裏面が白くならないように、同じデザインがカーペットの裏面に印刷されます。
機械印刷カーペットパネル用の白と生のカーペット

機械印刷カーペットパネル用の白と生のカーペット
機械印刷カーペットパネルの印刷方法

プリントカーペットの製造は 2 つの方法で行われます。 最初の方法では、前述のように、熱昇華機を使用してカーペットの表面とカーペットの裏面に印刷が行われます。 この方法では、カーペット内部の繊維は白く残り、繊維の表面のみにプリントが施されます。 Claris カスタム カーペット パネルと呼ばれる機械カーペット パネルの 2 番目の印刷方法では、印刷中に色がカーペットの繊維の奥深くに注入されます。 これにより、カーペットの内側と裏側の繊維が染色され、カーペットには白い繊維がなくなります。 Claris 方式でプリントされたカーペットの価格は、表面プリントされたカーペットよりも高価です。
[AWS Q&A 365][EKS]AWSのよくある問題の毎日5選 #56

# 1. AWS Step Functionsは、お客様のデータのセキュリティを確保するためにどのような対策を取っていますか？
回答：AWS Step Functionsは、データの安全性を確保するために、データの暗号化（静的および転送時）、IAMポリシーによるアクセス制御、さまざまなセキュリティ基準と規制への準拠など、さまざまなセキュリティ対策を実施しています。

# 2. AWS Step Functionsは、サービスへの不正アクセスからどのように保護されていますか？
回答：AWS Step Functionsは、ネットワークセキュリティ、アイデンティティとアクセス管理、監視とログ記録など、複数のレイヤーのセキュリティコントロールを使用して、不正アクセスから保護されています。

# 3. AWS Step Functionsは、顧客がセキュリティの状態を監視および管理するためのツールを提供していますか？
回答：はい、AWS Step Functionsは、監査とコンプライアンスのためのCloudTrail、リソースのインベントリと設定管理のためのAWS Config、脅威検知のためのAmazon GuardDutyなど、さまざまなツールを提供しています。

# 4. AWS Step Functionsは、サービスの統合のセキュリティをどのように確保していますか？
回答：AWS Step Functionsは、セキュアなAPIとプロトコルの使用、IAMポリシーによるアクセス制御、さまざまなセキュリティ基準と規制への準拠などにより、サービスの統合のセキュリティを確保しています。

# 5. AWS Step Functionsは、データ漏えいやその他のセキュリティインシデントに対してどのような対策を取っていますか？
回答：AWS Step Functionsは、定期的なセキュリティ評価と監査の実施、インシデント対応計画の実装、お客様にセキュリティ状態を向上させるためのツールとガイダンスの提供など、さまざまな対策を取っています。
[AWS Q&A 365][EKS]Daily Five Common Questions #56

# 1. What measures does AWS Step Functions take to ensure the security of its customers' data? 
Answer: AWS Step Functions implements various security measures to ensure the security of its customers' data, such as encryption at rest and in transit, access control through IAM policies, and compliance with various security standards and regulations. 

# 2. How does AWS Step Functions protect against unauthorized access to its services? 
Answer: AWS Step Functions uses multiple layers of security controls to protect against unauthorized access, such as network security, identity and access management, and monitoring and logging. 

# 3. Does AWS Step Functions provide any tools for customers to monitor and manage their security posture? 
Answer: Yes, AWS Step Functions provides various tools for customers to monitor and manage their security posture, such as CloudTrail for auditing and compliance, AWS Config for resource inventory and configuration management, and Amazon GuardDuty for threat detection. 

# 4. How does AWS Step Functions ensure the security of its service integrations? 
Answer: AWS Step Functions ensures the security of its service integrations by using secure APIs and protocols, implementing access control through IAM policies, and complying with various security standards and regulations. 

# 5. What steps does AWS Step Functions take to protect against data breaches and other security incidents? 
Answer: AWS Step Functions takes various steps to protect against data breaches and other security incidents, such as conducting regular security assessments and audits, implementing incident response plans, and providing customers with tools and guidance to improve their security posture.
【Python】CSVの住所一覧から緯度・経度を一括で取得する

Google Map APIを使ってジオコーディングする際に、大量の住所データに対応する緯度・経度データを取得したいケースがあり、「一発で取得したい！」と思った時のメモです。
Pythonのpandasとrequestsライブラリを使うと、結構簡単にできました。

## CSVデータを用意
こんな感じで、住所一覧が記載されているCSVデータ（address.csv）を用意します。
こちらのように、住所以外のデータが含まれていても大丈夫です。
「一覧データはあるけどPDFしかない…🥺」という場合は、[こちらの記事](https://qiita.com/outsider-kithy/items/0ea59246404fbca952e4 "【Python】PDFの表データをCSVに変換する")を参考に、PDFからCSVに変換してみてください。
![address.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/80c21575-7b22-40a4-24a0-856eda701a4d.png)

## pandasライブラリをインポート
後ほど住所一覧をfor文ですべて走査して処理するために、CSVを読み込んでpandasのDataFrame型のデータに変換します。

```python
import pandas as pd
data = pd.read_csv("address.csv")
data.head()
```
こんな感じのDataFrame型データが読み込まれます。
![data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/c8ed9689-112f-23d3-2bb2-2995088dcbf1.png)
このdataに、これから取得する「緯度・経度」のカラムを追加しておきます。

```python
data["緯度・経度"] = 0
```

## requestsライブラリを使って、Google Map Geocoding APIを経由して緯度・経度を取得

Pythonでhttp通信を行うためのライブラリ`requests`を使って、Google Map Geocoding API経由で緯度・経度を取得します。

APIの利用にあたって、[Google Cloud Platform](https://console.cloud.google.com/)からAPIキーを取得しておいてください。（今回の例であれば基本無料で使えると思います。）

それでは、Google Mapから全データ分の緯度・経度を取得します。

```python
import requests

api_key = '取得したAPIキー'

#dataの数だけ繰り返す
for i in range(len(data)):
    address = data['住所'].loc[i]
    #Google Map Geocoding APIにアクセスして緯度・経度を取得
    url = f'https://maps.googleapis.com/maps/api/geocode/json?address={address}&key={api_key}'
    response = requests.get(url).json()
    if response['status'] == 'OK':
        lat = response['results'][0]['geometry']['location']['lat']
        lng = response['results'][0]['geometry']['location']['lng']
        #dataの「緯度・経度」カラムに取得した値を書き込む
        data['緯度・経度'].loc[i] = f'{lat},{lng}'
    else:
        print(f'{address}:緯度・経度が取得できませんでした')

data.head()
```
![latlng_data.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/cbfb3ab9-52d6-786d-9ed6-ac27b94d9bd3.png)

data.head()で先頭から5つのデータを表示してみると、こんな感じで緯度・経度のカラムに取得した値が書き込まれているのが分かります。
何らかのエラーで緯度・経度が取得できなかった場合は、取得できなかった住所と「緯度・経度が取得できませんでした」のメッセージが表示されるようにif文で条件分岐しています。
これでCSVの住所一覧から、緯度・経度が一括で取得できました。
（Google Mapで１件ずつ住所を検索して緯度・経度をコピペしなくて済む！やったね！）

最後に、緯度・経度カラムを新しく追加したdataをCSVとして出力して終了です。

```python
data.to_csv("latlng_data.csv", index=False)
```
【Paizaレベルアップ問題集】標準入力メニュー/行入力1000行の入力

# Paizaレベルアップ問題集
Pythonで回答
## 標準入力メニュー/行入力1000行の入力
### STEP1 1行の入力
```Python
"""
1行の入力
https://paiza.jp/works/mondai/stdin_primer/stdin_primer__read_line_step1
"""

# 文字を受け取る
string = input()

# 文字を表示する
print(string)
```


### STEP2 2行の入力
```Python
"""
2行の入力
https://paiza.jp/works/mondai/stdin_primer/stdin_primer__read_line_step2
"""

# 文字を2行受け取る
string1 = input()
string2 = input()

# 文字を2行表示する
print(string1)
print(string2)
```


### STEP3 3行の入力
```Python
"""
3行の入力
https://paiza.jp/works/mondai/stdin_primer/stdin_primer__read_line_step3
"""

# 3行文字を受け取る
string1 = input()
string2 = input()
string3 = input()

# 3行文字を表示する
print(string1)
print(string2)
print(string3)
```


### STEP4 10行の入力
```Python
"""
10行の入力
https://paiza.jp/works/mondai/stdin_primer/stdin_primer__read_line_step4
"""

# 文字を10回受け取り表示する
for i in range(10):
    string = input()
    print(string)
```


### Final問題 1000行の入力
```Python
"""
1000行の入力
https://paiza.jp/works/mondai/stdin_primer/stdin_primer__read_line_boss
"""

# 1000回文字を受け取って表示する
for i in range(1000):
    string = input()
    print(string)
```
BottomSheetDialogFragmentとDaggerFragmentを両方使う方法

BottomSheetDialogFragment・DaggerFragmentともに、使うには継承する必要があります。
ただ、Kotlinは多重継承ができないため、一見すると両方同時に使えなさそうにみえます。

結論から言うと、DaggerFragmentのコードをベースに、BottomSheetDialogFragmentを継承することで両方同時に使用できます。

``` Kotlin
open class BaseBottomSheetDialogFragment : BottomSheetDialogFragment(), HasAndroidInjector {

    @Inject
    lateinit var androidInjector: DispatchingAndroidInjector<Any>

    override fun onAttach(context: Context) {
        super.onAttach(context)
        AndroidSupportInjection.inject(this)
    }

    override fun androidInjector(): AndroidInjector<Any> {
        return androidInjector
    }

}
```

参考：
https://github.com/google/dagger/blob/master/java/dagger/android/support/DaggerFragment.java
https://gist.github.com/baruckis/279ddf998d3aae6a6b9e8c30b51b0811
PokeAPIを使用してAndroidアプリを作成 ～プロジェクト作成編～

# はじめに
この記事は、アプリ開発をするためのプロジェクト作成編です。
プロジェクトを作成し、Git連携までを行いたいと思います。
Git連携をするメリットとして、以下が挙げられます。
　・バージョン管理ができる
　・変更履歴として細かく残せる
　・バックアップできる
　・ポートフォリオとしても使える　etc.
Git連携をすることによるデメリットは一つもないので、簡単なアプリであってもGit連携することをオススメします。

# プロジェクト作成
Android Studioを起動して「New Project」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/f46fddfd-cb21-1252-e037-8e660111dd38.png)
「Empty Activity」を選択し、「Next」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/9521fc86-8c3e-6894-021a-b30f21716c6e.png)
以下情報を設定。
・Name：作りたいアプリ名を入力します。
・Package name：自分が所属するドメインとアプリ名をドットで繋げたものを入力します。
・Save location：プロジェクトの保存場所を指定します。
・Language：使いたい言語を指定します。KotlinかJavaか、好きな方を選択しましょう。ただ、今回のプロジェクトはJavaを使用します。
・Minimum SDK：必要なAPIレベルです。どのくらいのデバイスで動かせるのか、下にパーセントが表示されるので、それを見ながら選ぶと良いです。
入力が終わったら、「Finish」をクリック。
![プロジェクト作成2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/b046f8c9-24aa-3ff1-496d-2aacb0e49eb2.png)
これでプロジェクト作成は完了です。
![プロジェクト作成3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/24a28cb5-c871-4dbc-aa11-54277f7e8c73.png)

# AndroidStudioとGitHubを連携する
「VCS」->「Enable Version Control Integration...」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/58899df6-fa30-e975-af71-a7c77cbd71d4.png)
「Select a version control system to associate with PokeApplication_Java」:「Git」を選択して「OK」クリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/9a860456-f473-4e58-a96a-944d5ab7dabb.png)
「VCS」が「Git」に変わります。
「Git」->「GitHub」->「Share Project on GitHub」をクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/5735e199-c421-4071-f82b-f04f2dab131d.png)
リポジトリ名を設定して「Share」ボタンをクリック。
※ 今回は「Private」にチェックを入れていないですが、公開したくない場合はチェックを入れましょう。
※ 下記画像と違う場合、「Add account」をクリックして「Log in with Token...」をクリック。
　 GitHubでアクセストークンを取得して貼り付けてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/0020df8b-84b2-5e79-ce9c-d22ddcf888fb.png)
以下の画面が表示されるので、「Add」ボタンをクリック。
これでGitにリポジトリが作成されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/6c73e38b-2dba-39f2-af75-2717a15df514.png)
GitHubで作成されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3331610/a8f7cb58-650e-bca4-8dee-7c0e536d87a3.png)
Gitにコミットされていれば完了です。

# 最後に
今回はアプリ開発をするためのプロジェクト作成を行いました。
Git連携なども覚えておくとことで、実際の現場に携わる際にとても役立つと思います！
基本的にGitを使っていない現場はないと思います。（稀にSVNでバージョン管理している現場も、、、）


つたない文章だったと思いますが、ここまで見ていただきありがとうございます。
次回、画面レイアウト作成編でお会いしましょう。
【Python】TypingライブラリとList

## はじめに
Pythonは動的型付け言語であるため、通常は変数や関数の引数、戻り値の型を明示的に宣言する必要はない。
しかし、大規模なプロジェクトやチーム開発の際には、型を明示しておくことで、コードの読みやすさやエラーの早期発見に役立つ。

この記事は、Pythonの静的型チェックをサポートするためのtypingライブラリの`List`の解説。

## Listとは？
Listはtypingライブラリに含まれる型の一つで、リストの型を表現する。
Listはジェネリック型で、リストに格納される要素の型をパラメータとして持つ。

Pythonの型ヒントは実行時には影響を与えない = **型ヒントに違反するコードでも実行自体は可能**。

しかし、型チェッカーやIDE、linterなどが型ヒントを用いて静的なエラーチェックを行うため、
型ヒントを正しく使用することで開発効率の向上につながる。

## Listの使い方
```Python
from typing import List

def double_elements(numbers: List[int]) -> List[int]:
    return [x * 2 for x in numbers]
```

関数double_elementsは、整数のリストnumbersを引数に取り、その各要素を2倍にした新たなリストを返す。
引数と戻り値の型としてList[int]を指定することで、この関数が整数のリストを扱うことを明示している。

#### 使用例
以下のコードではdouble_elements関数に文字列のリストを渡しているが、このコードは実行時にはエラーになる。

```Python
result = double_elements(["one", "two", "three"])  # TypeError at runtime
```
しかし、double_elements関数の引数の型としてList[int]が指定されているため、このコードは型チェッカーによって型ヒントが違反されていると指摘される。このように、型ヒントを活用することで、実行前にエラーを検出できる可能性が高まる。

## Listを使う場面
Listを使う場面は主には以下の通り。

- 関数の引数や戻り値がリストであることを明示したい場合
- リストに格納される要素の型を明示したい場合

特に、大規模なプロジェクトやチームでの開発では、型を明示することでコードの理解を助け、バグを防ぐ助けになる。

## 注意点
Listには、リストの要素の型を一つだけ指定することができる。
そのため、異なる型の要素を含むリストを表現するには、
```Python
List[Union[Type1, Type2, ...]]
```
のようにUnionを使うか、
```Python
List[Any]
```
のようにAnyを使う必要がある。

## まとめ
typingライブラリのListは、Pythonの型ヒントの一部としてリストとその要素の型を明示的に表現するために使用される。
コードの可読性を向上させ、開発効率を向上させる。

しかし、Pythonの型ヒントはあくまでヒントであり、実行時の挙動に影響を与えるものではない。
ファイルを読み込んで順番に和音を出力していくPGM

<h3>ファイルを読み込んで順番に和音を出力していくPGM</h3>
コードリストファイル、楽譜ファイルをロードして、ボタンをクリックしていくことで
順番に和音を出力していくPGMを作りました。
<hr>
githubURL: https://github.com/NanjoMiyako/outputChord.io
<br>
サンプルページURL: https://nanjomiyako.github.io/outputChord.io/

<hr>
<h4>開発の手順</h4>
以下の手順でPGMを作りました。

1:サイトAの和音一覧の画像をpowershellでダウンロードするPGMを作る
サイトA:<a href="https://www.ady.co.jp/song-chord/chorditiran.htm">コード一覧</a>

2: 1で取得した画像をpowershellからwindows標準のペイントを起動し、jpeg形式で自動保存しなおすPGMを作る
(PGM名: ImageDownload2.ps)


3: 2で作成した画像から各画像の隣り合う黒鍵と白鍵の差分x座標をPGM上の変数で初期化しておく
(書き込みPGM名: KenbanHanbetu2.py、設定変数名:DiffWidth)

4: 2で作成した各画像から、先頭コード1文字目と次に'sharp'の文字が続いているものとそうでないものでグループごとの画像で分けて、各コードの左端にある黒鍵あるいは白鍵の種類と位置をファイルに入力し保存する
(書き込みファイル名:CodeImgPos.txt)

5: 3と2と4で入力した内容から各コードの構成を自動で読み込んでファイルに
保存するPGMをpythonで作る
(PGM名: KenbanHanbetu2.py)(保存ファイル名: codeCompose1.txt, codeCompose2.txt)


6: 5で作成したファイルと楽譜ファイルをロードすることで和音を順番に出力していくPGMをJavaScriptで作る
(PGM名: PlayCodeIndex.html、playCodeJS.js)

<hr>
<h4>参考にしたサイト</h4>

<a href="https://www.ady.co.jp/song-chord/chorditiran.htm">コード一覧</a><br>

<a href="https://qiita.com/kenta1984/items/169e5dcbdbf0b4c8af27">【Python】データ型とキャスト - Qiita</a><br>
<a href="https://camp.trainocate.co.jp/magazine/python-new-line/">【Python入門】改行コードの使い方！出力・削除・置換方法まとめ | プログラミングを学ぶならトレノキャンプ（TRAINOCAMP）</a><br>
<a href="https://qiita.com/cat2151/items/d6c2bf0dd3e5f441ad69">Tone.jsで音を鳴らす手順（2021年5月版） - Qiita</a><br>
<a href="https://www.wizard-notes.com/entry/javascript/web-audio-api-chrome-user-interaction">Chromeで Web Audio API の音が鳴らない現象への対処 (Warning: The AudioContext was not allowed to start) - Wizard Notes</a><br>
<a href="https://www.i-ryo.com/entry/2019/06/12/235650">【Tone.js】PolySynth()で和音を鳴らす（3コード楽器を作る） - クモのようにコツコツと</a><br>
【Flutter学習 #2】環境構築　その２

# はじめに
この記事はFlutter初心者の筆者が学習のために書いている記事です。
間違っていたら温かくご指摘いただけるとありがたいです。


[前回の記事](https://qiita.com/takashi_web_eng/items/15d5943c9dea7aaeb90d)では、MacにFlutter SDKインストールして使えるようにするところまで準備したので、今回はプロジェクトを作成して実行していきます。

# 動作環境
* PC：Macbook
* CPU：Intel
* OS：MacOS Ventura 13.3.1

# プロジェクトを作成
Flutterのプロジェクト作成はとても簡単です。

以下のコマンドを実行します。
プロジェクト名は自由に付けてください。（私はflutter_appという名前で作成しました。）
```
# 事前にプロジェクトを作成する場所に移動する
cd [プロジェクトを作成する場所]

# プロジェクトを作成する
flutter create [プロジェクト名]
```

成功すると、指定した名前のプロジェクトフォルダ直下に様々なフォルダやファイルが出来上がっていることが確認できます。

# プロジェクトを実行する

* ### Chromeで実行
プロジェクト直下で以下のコマンドを実行します。

```
# プロジェクト直下に移動
cd [プロジェクト直下]

# Flutterプロジェクトを実行する
flutter run
```

ビルドに少し時間がかかりますが、完了したらChromeでflutterプロジェクトが実行されます。
![スクリーンショット 2023-05-13 21.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3344066/b330961b-8d77-9f3e-45b1-a46415432c71.png)

* ### iOSシュミレータで実行
まず、iOSシュミレータを実行します。

```
open /Applications/Xcode.app/Contents/Developer/Applications
```
上のコマンドを実行するとFinderが開くので、開いたディレクトリ直下にあるSumulator.appを実行します。

シュミレータが起動してホーム画面が表示されたらFlutterプロジェクトを実行します。

```
# プロジェクト直下に移動
cd [プロジェクト直下]

# Flutterプロジェクトを実行する
flutter run
```

ビルドが完了したらiOSシュミレータでflutterプロジェクトが実行されます。
![スクリーンショット 2023-05-13 22.05.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3344066/79c59abc-d7ac-7f19-ac0f-36c601db2bc3.png)

* ### Androidエミュレータで実行する
まずAndroidエミュレータを実行します。

```
# インストールされている仮想デバイスを確認します。
~/Library/Android/sdk/emulator/emulator -list-avds

# 上のコマンドで表示された仮想デバイスを指定して実行します。
~/Library/Android/sdk/emulator/emulator -avd [仮想デバイス名]
```

エミュレータが起動してホーム画面が表示されたらFlutterプロジェクトを実行します。

```
# プロジェクト直下に移動
cd [プロジェクト直下]

# Flutterプロジェクトを実行する
flutter run
```

ビルドが完了したらAndroidエミュレータでflutterプロジェクトが実行されます。
![スクリーンショット 2023-05-13 22.28.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3344066/c75fc680-3ff6-84ec-4cf5-c949e7229dc6.png)


# 最後に
無事Flutterプロジェクトの作成と3つの環境での実行ができました！
1つのプロジェクトで複数環境のアプリを作れるのは本当にすごいですね。今回はWeb、iOS、Androidだけでしたが、他にもデスクトップアプリとしても実行できるようです。これは流行っているのも納得です。
Calckeyのアップデート方法

Calckeyのインストール方法は最近よく見るけどアップデート方法の記事がなかったので書いてみました。
基本的には[Calckey](https://codeberg.org/calckey/calckey)の[Release](https://codeberg.org/calckey/calckey/releases)のページにあるコマンドを入力すればOKなんだけど初見では分かりにくいところもあると思うので参考になれば。
インストール方法は以下のような記事を参考にしてみてください。

- [VPS借りてCalckeyでおひとりさまサーバーを建ててみた｜まなさす](https://note.com/thetalemon/n/naff410ae049e) 

## 前提
Kagoya VPS Ubuntu 22.04 LTS スタンダード2コア2GB
Docker非使用
[Calckey/Ubuntu-bash-install](https://codeberg.org/calckey/ubuntu-bash-install)で簡単インストールをしているもののbeta版の最新版にアップデートしたくなった人向け

## 前準備
### 1. Swapを2GB以上確保
swapが1GBではpnpm iの途中で強制終了するので最低でも2GBに設定しておくこと
`free -m`コマンドでSwapのfreeのところが2000以上ある場合はスキップしてOK

```
$ free -m
               total        used        free      shared  buff/cache   available
Mem:            1975         942          66          96         965         744
Swap:           2047          34        2013
```

```
$ swapoff -a
$ sudo fallocate -l 2G /swapfile
$ ls -lh /swapfile
$ sudo chmod 600 /swapfile
$ sudo mkswap /swapfile
$ sudo swapon /swapfile
```
引用：[How To Add Swap Space on Ubuntu 22.04 | DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-add-swap-space-on-ubuntu-22-04)

### 2.Rustインストール
v13.2.0-beta4以降のインストールの場合は事前にRustのインストールが必要

```
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```

### 3. Calckey を実行するユーザーに切り替え
Calckeyを実行するユーザーのホームディレクトリの中にcalckeyディレクトリがあり、そこに移動してからgitを実行する必要がある
```
$ su - calckey
$ cd calckey/
```

## アップデート

+ 最新版のbetaブランチに変更をマージ
```
$ git fetch origin beta:beta
```

+ 作成したbetaブランチに移動する
```
$ git checkout beta
```

+ 切り替え出来ているか確認
```
$ git branch -vv
* beta c836bcfd0 no imports
  main 6616f246a [origin/main] docs: cleanup apache
```

branchの切り替えが一度出来た後でbeta版アップデートをする場合は以下の手順のみでOK

+ 最新の変更をリモートリポジトリから取得し、ローカルリポジトリに反映させる
```
$ git pull origin beta
From https://codeberg.org/calckey/calckey
 * branch                beta       -> FETCH_HEAD
Already up to date.
```

+ pnpmをアップデートするために以下のコマンドを実行
このコマンドは pnpm を最新のバージョンにアップデートするために必要な corepack パッケージをインストールし、pnpm をアクティブにする。
```
$ corepack prepare pnpm@latest --activate

Preparing pnpm@latest for immediate activation...
```

+ パッケージをインストールする
```
$ pnpm i
```

```
$ NODE_ENV=production pnpm run build && pnpm run migrate
```
ここで長々とインストールされてエラーが出なければ大丈夫

```
$ sudo shutdown -r now
```
あとはサーバを再起動すればアップデートが反映されている筈です。
なんか反映されてないなって時はブラウザのキャッシュを削除してみましょう。
RubyでAtCoder ABC260(A, B, C)を解いてみた

# はじめに
Webエンジニアを目指して、RubyやRailsをいじってます。
今回は、RubyでAtCoder ABC260のA, B, Cを解きました。備忘録として解き方をまとめていきたいと思います。

# A - A Unique Letter
https://atcoder.jp/contests/abc260/tasks/abc260_a
```ruby:a-260.rb
s = gets.chomp.chars.tally.invert
puts s[1] ? s[1] : -1
```
## 解説
与えらた文字列を連想配列にして、invertメソッドによりkeyとvalueを入れ替えています。

# B - Better Students Are Needed!
https://atcoder.jp/contests/abc260/tasks/abc260_b
```ruby:b-260.rb
n, x, y, z = gets.split.map(&:to_i)
a = gets.split.map(&:to_i)
b = gets.split.map(&:to_i)

students = []
n.times do |i|
  students << [a[i], b[i], i + 1]
end

ans = []
students.sort_by!{ |a, b, i| [-a, i] }
x.times do |i|
  ans << students[i][-1]
end

students = students[x..].sort_by{ |a, b, i| [-b, i] }
y.times do |i|
  ans << students[i][-1]
end

students = students[y..].sort_by{ |a, b, i| [-(a + b), i] }
z.times do |i|
  ans << students[i][-1]
end
puts ans.sort
```
## 解説
sort_byメソッドを使って、「数学の得点が上位X位」「合格していない人のうち、英語の得点が上位Y位」「合格していない人のうち、数学と英語の合計得点が上位Z位」の人をそれぞれ調べ最後に昇順にして出力することで実装することができます。

# C - Changing Jewels
https://atcoder.jp/contests/abc260/tasks/abc260_c
```ruby:c-260.rb
n, x, y = gets.split.map(&:to_i)
r = Array.new(n + 1, 0)
b = Array.new(n + 1, 0)
r[n] = 1
n.downto(2) do|i|
    r[i - 1] += r[i]
    b[i] += r[i] * x
    r[i - 1] += b[i]
    b[i - 1] += b[i] * y
end
puts b[1]
```
## 解説
動的計画法を使って解くことができます。r[i]:=レベルiの赤い宝石がいくつあるか、b[i]:=レベルiの青い宝石がいくつあるかと定義しておきます。すると、条件文の通りr, bそれぞれに対して順に値を足していくことで実装することができます。

https://qiita.com/shoya15/items/50fd17e37d7c64f2b166
Autoencoderを利用して属性推定を構築しよう

物体検出の精度を上げていこうとすると、検出した領域での属性推定がほしくなる。例、顔検出の精度を上げていこうとすると、マスクをつけた人の画像も欲しくなる。髪の毛が前に垂れていて眼の領域を隠している画像も欲しくなる。マスクの有無判定、眼領域オクルージョンの有無の判定が欲しくなる。


# Autoencoder
オートエンコーダ（自己符号化器、英: autoencoder）とは、機械学習において、ニューラルネットワークを使用した次元圧縮のためのアルゴリズム。2006年にジェフリー・ヒントンらが提案した。[オートエンコーダ](https://ja.wikipedia.org/wiki/%E3%82%AA%E3%83%BC%E3%83%88%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%80)

autoencoderで符号化されたベクトルを利用して、属性推定に利用することができる。

>こうした考えに基づく初期の研究では，Neural Network を用いて複数属性を認識する手法が挙げられる．Cottrell ら [117] は，現在使われている Autoencoder に相当する特徴抽出用のNeural Network を用いて学習した顔画像特徴量を元に，識別用の Neural Network によって顔，感情，性別の認識を行っている．
それぞれの属性認識器で認識した結果を元に，それらの結果を統合して最終的な属性認識結果を再計算したり，別の属性を求めるアプローチとしては，属性認識器の出力結果を特徴量として分類する手法 [73] や，Bayesian Network を利用したものが挙げられる。

[サーベイ論文：画像からの歩行者属性認識] (https://www.vislab.is.i.nagoya-u.ac.jp/~murase/pdf/1300-pdf.pdf)

autoencoderを用いて属性推定を行うことは、入力画像から属性推定すること、属性推定の結果から画像を生成する（生成画像と入力画像の差分を小さくする）処理の一部だと考えられる。

# 仮説：autoendcoderと属性推定込みの物体検出とを構築することは、物体検出だけを学習させるよりも、精度の高い検出を実現する。

## 判断の理由：
- 属性のラベリングをすることは、検出枠の情報だけを与えることよりも多くの情報を与えて検出の学習をさせていることになる。
- 例：　顔の検出に対して、マスクの有無の属性を付与する。
- マスクありの属性があれば、鼻や口に由来する特徴量がなくても顔検出を判定できることに確証を与える。
- マスクありの属性の有無は、本来なら鼻や口が見える領域に、マスクらしいもので覆われている場合に、その特徴量を学習して判定することを可能にすると見られる。


## 属性推定を物体検出に付随して実行することは、そんなに難しくないはずだ。



### 歩行者の属性推定の実装の１例
github https://github.com/dangweili/pedestrian-attribute-recognition-pytorch
- 学習用のデータのダウンロード　　上記のリポジトリのREADME.md に記載がある。
- 学習の手順 https://github.com/dangweili/pedestrian-attribute-recognition-pytorch/blob/master/script/experiment/train.sh の実行

[Multi-attribute Learning for Pedestrian Attribute Recognition in Surveillance Scenarios](https://www.researchgate.net/publication/283484818_Multi-attribute_Learning_for_Pedestrian_Attribute_Recognition_in_Surveillance_Scenarios)

![Screenshot from 2023-05-05 23-15-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83761/9943709f-dc08-c4a9-a3de-e549b76394e0.png)

図　上記の論文中にある属性認識の属性

PETA dataset [Pedestrian Attribute Recognition At Far Distance](http://mmlab.ie.cuhk.edu.hk/projects/PETA.html)

-----
github [HydraPlus-Net: Attentive Deep Features for Pedestrian Analysis](https://github.com/xh-liu/HydraPlus-Net)
[pdf](https://arxiv.org/pdf/1709.09930v1.pdf)

---
以下のgithub [Pedestrian-Attribute-Recognition-Paper-List](https://github.com/wangxiao5791509/Pedestrian-Attribute-Recognition-Paper-List)

を読むことで、最新の動向をつかもう。


## 属性推定は、監視カメラに対して実用的な使い方がある。
- [NEC、カメラ映像を分析し曖昧な外観属性情報から特定の人物を高速・高精度に検索する技術を開発 ～商業施設における迷子捜索などに活用可能～](https://jpn.nec.com/press/202305/20230519_02.html)
【Python】PDFの表データをCSVに変換する

PDFなどの非構造化データを、分析や機械学習に利用可能な構造化データに変換し、CSVとして保存したい時ってありますよね。
こんな感じの、表形式のPDFファイル「address.pdf」があるとします。

![address.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/307e4d12-5c18-7de9-ae69-f4b22288a4d7.png)

これをCSV形式に変換するために、`tabula-py`というライブラリを使用します。

## tabulaのインポート

```
pip install tabula-py
```

```python
from tabula import read_pdf
df = read_pdf("address.pdf", pages="all")
```

tabulaは読み込んだPDFをpandasのDataFrame型オブジェクトとして返してくれるので、`df[0]`のようにインデックスで各表データにアクセスできます。

```python
df[0]
```

こんな感じでデータ一覧が表示されます。
![df[0].png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2781928/f16c2bd0-c9c8-972c-eba1-0c50bd25feb9.png)

これで、PDFデータの読み込みが完了しました。
ただ、よく見るとPDFをそのまま読み込んだだけなので、不必要なカラムや名称を変更したい行があったりします。
そういった部分を削除・修正して、データを整形していきます。

## データの整形
整形したデータを格納する変数「export_data」を用意し、ここにdf[0]を修正した結果を代入していきます。

```python
export_data = df[0]
#不必要なカラムの削除
export_data = export_data.drop("番号", axis=1)
#カラム名の変更
export_data = export_data.rename(columns={"公式サイト":"URL"})
#先頭から5行目までのデータを表示
export_data.head()
```

dropとrenameを適用しつつ、目的の形にデータを整形していきます。
データを整形できたら、CSV形式で保存します。

```python
export_data.to_csv("address.csv", index=False)
```

これで、address.pdfをaddress.csvに変換できました。