OmniAICreator/Qiita-1.07M huggingface dataset:
負荷試験でlocustを使ってみる


#locustについて
- シナリオをPythonで書ける
- テストの状況をリアルタイム表示することができるWeb画面がある
- 冗長構成にすることができる
- https://locust.io/
- https://docs.locust.io/en/stable/index.html

#試してみる

###前提
- Docker、docker-composeがインストール済み

###環境構築
locustのコンテナと、試しに負荷をかけてみるコンテナを作ります。

```yaml:docker-compose.yml
version: '3.7'

services:
  master:
    image: locustio/locust
    ports:
      - "8089:8089"
    volumes:
      - ./:/mnt/locust
    # 負荷をかける環境のドメインを指定する
    command: -f /mnt/locust/main.py -H http://test_web:80

  # お試し用の負荷をかけられるコンテナ
  test_web:
    image: httpd
    tty: true

```



###テストシナリオ
テストシナリオを作ります。

```python:main.py
from locust import HttpUser, task, constant_pacing

class StressTestUser(HttpUser):
    wait_time = constant_pacing(1)

    @task
    def top_page_access(self):
        # 負荷をかける対象のパスを指定する
        self.client.get("/")
```
ユーザクラスを作ります。ユーザクラスは1人のユーザーが行う行動をwait_timeやtaskなどで定義していきます。
https://docs.locust.io/en/stable/writing-a-locustfile.html#wait-time-attribute
###起動
コンテナを起動します。

```console
docker-compose up
```

###実行
1. `http://localhost:8089` をブラウザで開く
2. `Number of total users to simulate` に同時アクセスを行う最大ユーザ数を入力する
3. `Spawn rate` にユーザ数の増加速度を入力する
4. `Start swarming` をクリックする
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152521/47053020-56e4-3d7c-7ce9-68be6db09a72.png)

###テスト状況
テストを実行すると状況が確認できます。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152521/50377567-6592-7922-1faf-913ffee3c6c4.png)
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152521/3024a792-563f-b53e-45a1-f602767a744a.png)
renderにおけるlocalsとcollectionについて

 localsとcollectionのオプションについての理解を深めようとこの記事を書くことにしました。
##1.localsについて

仮にposts_controllersに以下の記述があるとして

```posts_controllers.rb
def show
  @post = Post.find(params[:id)
end
```

```posts/foobar.html.erb
<%= render partial: 'post_partial', locals: { post: @post } %>

または省略形で
<%= rendner 'post_partial', post: @post %>
```

```posts/_post_partila.html.erb
<%= post.title%>
<%= post.body %>
```

```公式
公式(省略形)
<%= render 'パーシャル名', ローカル変数: インスタンス変数名 %>
```

つまりlocalsオプションを使用することで
`@post`というインスタンス変数を`post`というローカル変数に変換することができる。

##2.collectionについて
仮にposts_controllersに以下の記述があるとして

```posts_controllers.rb
def index 
  @posts = Post.all
end 
```

```posts/index.html.erb
<%= render partial: 'each_post', collection: @posts %>

応用形 asオプションでローカル変数を指定することができる
<%= render partial: 'each_post', collection: @posts, as: :post%>

```

collectionオプションを使用しなかった場合は以下の記述になるが

```posts/_each_post.html.erb
#collectionを使わなければ
<% @posts.each do |post| %>
  <%= post.body%>
<% end %>
```

collectionオプションを使用するで
eachメソッドを省くことができるため簡潔に記述することができる

```posts/_each_post.html.erb
#collectionを使用することで
<%= post.body%>
```
文字列のなかで変数を使いたい

html.erb形式にて、
文字列のなかに変数を含めたい

例えばpost変数の作成日を書くとき、

```
<%= "作成日:#{post.create_at}"  %>
```


___
コメントでもいただいたように、もちろん下記でもok

```
作成日:<%= post.create_at %>
```
試しにAWSのEC2にwordpressを設置してみた

#前提
データベースが必要であり、そのデータベースを設置するために2つのAZが必要になります。ここではap-northeast-1a,1cを使用します。データベースはap-northeast-1aに設置します。以下の構造を作ります。

#注意
あくまで試しに作る環境なので、環境を作って動作を確認したら課金が発生する前に環境を削除したほうがいいです。

ap-northeast-1a(AZ)
 PublicSubnet1 10.0.0.0/24
 PrivateSubnet1 10.0.2.0/24 ここにデータベースを設置します

ap-northeast-1c(AZ)
 PublicSubnet2 10.0.1.0/24
 PrivateSubnet2 10.0.3.0/24 ここにデータベースを設置します

#手順
1)以下のようにVPCを作成する。
 Name: MyVPC
 IPv4 CIDR: 10.0.0.0/21 このネットワークを手順2)で分割します

2)作成したVPC内に下記のサブネットを作る。
 PublicSubnet1 10.0.0.0/24
 PublicSubnet2 10.0.1.0/24
 PrivateSubnet1 10.0.2.0/24
 PrivateSubnet2 10.0.3.0/24

3)EC2を作成する。
 OS: AmazonLinux2
 インスタンスタイプ: t2micro
 ネットワーク: MyVPC1
 サブネット: PublicSubnet1
 自動割り当てパブリックIP: 有効
 ストレージボリューム: とりあえず8GB(デフォルト)
 タグ付け(任意)
 セキュリティグループ設定でhttp通信を許可する。必要であれば、httpsも許可する。因みにサーバーにping応答させたければ、ICMPを許可してください。
 キーペア: 既存のキーペアがあれば、それを使い、まだキーペアがなければ、キーペアを作成してください。

4)インターネットGWを作成し、VPCへアタッチする。

5)PublicSubnet1のルートテーブルに以下を追加してください。
ルート: 0.0.0.0/0
ターゲット: 手順4)で作成したGW

6)データベースのサブネットグループを以下のように作成してください。ここで以降の手順で作成するデータベースをどのAZのどのVPCのどのサブネットに割り当てるかを決定します。
 名前: MysubnetGroup
 説明: MysubnetGroup
 VPC: MyVPC1
 AZ: ap-northeast-1a,1c(前提として2つのAZが必要です。)
 サブネット: PrivateSubnet1,2

7)以下のようにデータベースを作成してください。
 データベース作成方法を選択: 標準作成
 エンジンのオプション: MySQL
 テンプレート: 開発/テスト
 マスターユーザー名: wordpress
 パスワード: 任意のパスワード
 DBインスタンスサイズ: バースト可能クラス
 可用性と耐久性: 「スタンバイインスタンスを作成しないでください」を選択する
 接続: MyVPC1
 追加の接続設定
  サブネットグループ: MysubnetGroup
  パブリックアクセス可能: なし(「あり」にするのは非常に危険です)
  VPCセキュリティグループ: 新規作成
   新しいVPCセキュリティグループ名: RDS-SG-1
   AZ: ap-northeast-1a
 追加設定
  最初のデータベース名: wordpress
 
他の設定項目はデフォルトで大丈夫です。

8)RDSセキュリティグループのインバウンドルールで接続元をwebサーバーからのみに限定してください。
 もともと設定されている接続元のIPアドレスを消去する
 「ソース」の検索窓でsgと入力する
  Web-SG-1という名前のセキュリティグループを選択する
  「保存」を押す

9)作成したEC2環境にターミナルでログインし、apacheとphpをインストールしてください。

 管理者権限にスイッチする
 ```sudo su -```
 
パッケージを最新状態にアップデートする
 ```yum -y update```
 
 phpをインストールする
 ```amazon-linux-extras install php7.2 -y```
 
 apacheとphpに必要なものをインストールする
 ```yum -y install mysql httpd php-mbstring php-xml gd php-gd```
 
 apacheがサーバー起動後に自動で起動するように設定する
 ```systemctl enable httpd.service```
 
 apacheを起動する
 ```systemctl start httpd.service```
 
 apacheのapacheが起動しているかを確認する
 ```systemctl status httpd.service```
 
 wordpressの最新パッケージをカレントディレクトリにダウンロードする
 ```wget http://ja.wordpress.org/latest-ja.tar.gz ~/```
 
 カレントディレクトリにlatest-ja.tar.gzがあるかを確認する
 ```ll```
 
 latest-ja.tar.gzを展開する
 ```tar zxvf ~/latest-ja.tar.gz```
 
 wordpressというディレクトリが存在していることを確認する
 ```ll```
 
 wordpressを/var/www/htmlにコピーする
 ```cp -r ~/wordpress/* /var/www/html/```
 
/var/www/html/配下のフォルダの所有者をapacheに変更する
```chown apache:apache -R /var/www/html```

以上でwordpressの閲覧が可能になります。

#最後に
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com

<a href="https://twitter.com/iuiikk">follow me</a>
djangoでKeyError: ('app_label', 'self.model_name_lower')が出た時の対処方

#発生タイミング
モデルの一部変更を行い、makemigration実行した際に発生

#エラーの意味
調べたところKeyErrorとはpythonの辞書型のエラーというものらしい。
実際のエラー文を一部抜粋すると以下のような形になっていた。

```python:エラー文、terminal
 model_state = state.models[app_label, self.model_name_lower]
KeyError: ('アプリ名', '項目名')

```

上段の文章から考えるとアプリの中の、項目名がおかしいよとのこと。

最初はモデル設計が違うのかと該当箇所を調べ、項目名等を修正したが直らず。
そもそもmodels.pyの中に該当の項目名すら無いのに発生してしまいました。

調べていくとmigrationファイルが悪さをしている可能性があるということがわかったので、一旦マイグレーションファイルの履歴を確認することにしました。

#マイグレーションの履歴を確認

```terminal:
% python manage.py showmigrations
```

すると以下のような結果に

```python

app_name
 [ ] 0001_initial
 [ ] 0002_auto_20201221_1907
 [ ] 0003_auto_20201231_0005
 [ ] 0004_auto_20210125_1430
 [ ] 0005_auto_20210126_0951
 [ ] 0006_auto_20210213_2037
 [ ] 0007_auto_20210223_1819
 [ ] 0008_auto_20210228_1527
```
[　]が空白になっているところは実行されていないということらしいので、再度migrateを実行すると案の定エラーが発生。

```python

  Applying app_name.0002_auto_20201221_1907... OK
  Applying app_name.0003_auto_20201231_0005... OK
  Applying app_name.0004_auto_20210125_1430... OK
  Applying app_name.0005_auto_20210126_0951... OK
  Applying app_name.0006_auto_20210213_2037... OK
  Applying app_name.0007_auto_20210223_1819... OK
  Applying app_name.0008_auto_20210228_1527...Traceback (most recent call last):
  File "manage.py", line 22, in <module>
    main()  以下エラー文
```
これでエラーを起こしているマイグレーションファイルが特定できました！

該当のマイグレーションファイルを見ると

```pyrex

operations = [
        migrations.RenameField(
            model_name='クラス名',
            old_name='古い項目名',
            new_name='新しい項目名',
        ),
```

どうやら以前modelの項目名を変更を行い、makemigrationを行った際に既存のモデル名からリネームする処理のファイルが出来てしまっていたようです。

その後、モデルのクラス名そのものを変更してしまった為、起こったエラーでした。

該当のマイグレーションファイルを削除し再度実行した結果無事に解決出来ました！
【Rails6】RSpecの導入からテスト実施するまでの手順書

#はじめに
モデル、及びコントローラーごとに単体テストを実施すると、テスト実施ファイルを作成するためのコマンドを実行する必要があります。

毎回、手順を見返すのは面倒で、参考書であれば説明文等があるので、目で追うのに少し戸惑うときもあるかと思います。

そこで、テスト実施ファイル作成までの手順をまとめていれば、作業を効率化してテストを実施できるのではないかと考え、本記事を作成しました。

#概要
テスト実施前の準備手順とテスト実施コマンドについて記述しております。

#バージョン
rubyのバージョン　ruby-2.6.5
Railsのバージョン Rails:6.0.0
rspec-rails 4.0.0

#全体像
①gemの追加
②RSpecの導入

**モデルの単体テストコード**
③モデルのテストファイルを作成
④FactoryBotを導入し、テストを実行
⑤テストコードを実行するコマンド

**コントローラーの単体テストコード**
⑥コントローラーのテストファイルを作成
⑦テストコードを実行するコマンド

**結合テストコード**
⑧結合テストのテストファイルを作成
⑨テストコードを実行するコマンド

※インストール完了している場合は③からお進みください。

#①gemの追加
Gemfileに以下の記述追加してください

```Gemfile

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]

#〜省略〜

  gem 'rspec-rails', '~> 4.0.0'
  gem 'factory_bot_rails'
  gem 'faker'
end

#〜省略〜
```

開発中のアプリのディレクトリに移動してから、bundle installを実行します。

```
$ bundle install
```

#②RSpecの導入

RSpecをインストールします。

```
$ rails g rspec:install
```

.rspecに設定を追加します。

```/.rspec
--require spec_helper
--format documentation #←追加します

```

#③モデルのテストファイルを作成
以下のコマンドを実行して、モデルのテストファイルを生成します。

```
$ rails g rspec:model モデル名（単数形）
```

#④FactoryBotを導入し、テスト実行
FactoryBotを用いてインスタンスをセットする。

その後、rspec内のモデルに、テスト内容を記述していきます。

##④の補足
※初めは手動でspecディレクトリの中に、factoriesディレクトリを作成し、さらにfactoriesディレクトリの中に、FactoryBotのファイルを作成する必要があります。

しかし、その後はrails g rspec:model モデル名（単数形）実行後、自動で生成されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1052793/8559f7f8-6097-3816-d203-20d7205bf78d.png)


#⑤テストコードを実行するコマンド

```
$ bundle exec rspec spec/models/モデル名_spec.rb
```

#⑥コントローラーのテストファイルを作成

以下のコマンドを実行し、コントローラーのテストファイルを作成します。

```
$ rails g rspec:request コントローラー名（複数形）
```

#⑦テストコードを実行するコマンド

```
$ bundle exec rspec spec/requests/コントローラー名_spec.rb
```

#⑧結合テストのテストファイルを作成

```
$ rails g rspec:system オブジェクト名（複数形）
```

#⑨テストコードを実行するコマンド

```
$ bundle exec rspec spec/system/オブジェクト名_spec.rb
```

以上です。
AWS Lambda + API Gateway POSTのパラメータ取得でハマった

フロントエンドからPOST通信でアクセスするAPIをLambda＋APIGatewayで作っていた時にハマった話を備忘録

申し込みフォームで登録後に完了メール送信を行うロジックを作っていた。

```react
     const onSubmit = async () => {
       const params = {
        to: email,
        name: name,
        email: email,
        tel: tel,
        zipcode: zipcode,
        address: prefecture + " " + address,
        message: message,
      };

      const res = await axios.post(
        "https://sample/send",
        params,
        {
          headers: { "Content-Type": "multipart/form-data; charset=UTF-8" },
        }
      );
    }

```

Lamda側でeventの中身をのぞいてみると。。。
リクエストbodyにJSON形式で渡されると思いきや、エンコードされた状態でパラメータが渡っていたため
Lambda側でどのようにパラメータ取得を行えばよいかわからず調べること1時間...

```python
{
 'body': 'eyJ0byI6InNhbXBsZUBnbWFpLmNvbSIsIm5hbWUiOiLlkI3liY0iLCJlbWFpbCI6InNhbXBsZUBnbWFpLmNvbSIsInRlbCI6Ijk5OTk5OTk5OTk5IiwiemlwY29kZSI6IjIxMDAwMDgiLCJhZGRyZXNzIjoi5p2x5Lqs6YO9IOS9j+aJgDHkuIHnm64iLCJtZXNzYWdlIjoi55Sz44GX6YCB44KK5LqL6aCFIn0=', 
 'isBase64Encoded': True
}
```

base64モジュールによりデコード処理を行うことで解決できることがわかった。

```python

def send_mail(event, context):

    
    body = event["body"]
    #bodyのエンコードされた文字列をJSON文字列にデコードし、辞書型に変換
    params = json.loads(base64.b64decode(body).decode('utf-8'))

    TO        = params["to"]
    name      = params["name"]
    email     = params["email"]
    tel       = params["tel"]
    zipcode   = params["zipcode"]
    address   = params["address"]
    message   = params["message"]
    
    ##以下割愛

```

HTTPの仕組みは奥が深い....
POSTするさいのHTTPヘッダーのContent-Typeも重要であることが分かった。
何がどう異なるのかは調べなければ...
Rustの魅力

#目的
Rustの魅力について大雑把に把握する

#まとめ
以下が実践Rustプログラミング入門に書かれていた特徴
それぞれについて自分で調査。

①とにかく実行速度が速い
→[Rustの実行速度が速い理由](https://qiita.com/asparagasu/items/d6078de68fc10a2a86bc)
②安全性が協力に担保されている
→[メモリ安全](https://qiita.com/asparagasu/items/1efc918abb535ee1213a)、[スレッド安全](https://qiita.com/asparagasu/items/c25c7e9b2e5389daee8a)、[基本文法のいいところ](https://qiita.com/asparagasu/items/8cc9f06a672bb02931ed)
③モダンな文法が一通り入っている
④ＯＳからＷＥＢアプリケーションまで幅広く実装できる
⑤ツール群がとても充実している
→[cargo](https://qiita.com/asparagasu/items/29bc4a11909ee3d004a7)
⑥エディションという考え方によって互換性を担保している
ドメイン名をミスタイプしてＬＤＡＰインストールに苦戦した話

ブログで掲載している内容から一部抜粋。

Debian(bullseye/sid)でLDAPサーバーの構築中に少しハマりました。

インストール時にパスワードの設定をすると以下のエラー
>入力された設定は無効です。DNS ドメイン名が有効な文法になっていること、組織名のフィールドが空になっていないことと、管理者パスワードが合っていることを確認してください。設定を再試行しないと、LDAP サーバはセットアップされません。あとで再試行するときには、"dpkg-reconfigure slapd" を実行してください。

![ldap_error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372363/cc2a9b16-17df-6450-0361-32e39d15df40.png)

パスワードの再入力を間違ったとも思わなかったのでとりあえず＜いいえ＞で進むと、エラー発生。
いろいろ試しましたが、結果から言うと、ドメインの設定に間違いがありました。
まさか初期セットアップ時からミスしているとは思わなくて気が付くまでしばらく時間を使いました。

slapdの削除　apt remove --purge slapd
/etc/hostsを修正した後にslapdの再インストールで無事解決しました。

以下で構築したときのことまとめています。
https://tamu-labo.net/posts/2021/02/28/ldap.html
CordovaとReact Nativeの比較

## はじめに
最近アプリ開発を行うにあたり、CordovaとReact Nativeについて調べる機会があったので、自分用のメモとしてまとめてみました。
CordovaとReact Nativeの違いやこういう場合はこっちがいいとかあったら誰か教えて欲しいです...

## CordovaとReact Nativeの比較
CordovaとReactNativeを比較するとこんな感じではと思います。

| | Cordova    | React Native |
|-----------|------------|--------------|
| 開発言語 | JavaScript | JavaScript   |
| UI　| HTML | JSX |
| 実行エンジン | WebView | JavaScript |
| パフォーマンス | ○ | ◎ |
| レンダリング時間 | 長い | 短い |
| パッケージサイズ | 小 | 大 |
| 学習コスト | ○ | △ |


### パフォーマンス
パフォーマンスについてはCordovaよりもReact Nativeの方が良いようです。
CordovaはWebView上で動作するため、どうしても表示速度や実行速度においてReact Nativeに劣るようです。
そのため、パフォーマンスや表示時間が要求されるようなアプリを開発する場合は、Cordovaを避けた方が良いかもしれません。

### 学習コスト
CordovaについてはWeb開発経験があり、HTMLやJavaScriptに慣れている人であれば、それほど難しくないのではと思います。
React NativeについてはReactを使って開発をしたことがあれば、容易ではないかと思いますが、Reactについて知らない場合は学習コストが発生します。

### どちらが人気があるか
Googleトレンドで見てみるとReact Nativeが人気がある(使用されてる？)のではと思います。
![screen-shot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119286/5e39b299-7428-a099-eefc-890b108d9c7c.png)

## 参考
[React Native / Cordova / Monacaの違い](https://press.monaca.io/atsushi/4809)
[PowerShell] 自分のIPアドレスを調べる 

# Invoke-WebRequest

```powershell
(Invoke-WebRequest -Uri "https://ipinfo.io/ip").Content
```

# 参考
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/invoke-webrequest?view=powershell-7.1
https://docs.microsoft.com/ja-jp/learn/modules/azure-sql-high-availability/3-exercise-restore-point-in-time
amplifyの作法 その7

#概要

amplifyの作法、調べてみた。
pyqubo使ってみた。

#サンプルコード

```

from pyqubo import solve_qubo
import dimod
import math
from pyqubo import Array, LogEncInteger
from pyqubo import Constraint
from amplify import (BinaryPoly, BinaryQuadraticModel, gen_symbols, Solver, decode_solution, )
from amplify.client import FixstarsClient

W = 100
w = {
	0: 21,
	1: 11,
	2: 15,
	3: 9,
	4: 34,
	5: 25,
	6: 41,
	7: 52
}
c = {
	0: 22,
	1: 12,
	2: 16,
	3: 10,
	4: 35,
	5: 26,
	6: 42,
	7: 53
}
N = len(w)
x = Array.create('x', shape = N, vartype = 'BINARY')
y = LogEncInteger("y", (0, W))
key1 = max(c, key = lambda k: c[k])
B = 40
A = 10 * B * c[key1]
HA = Constraint(A * (W - sum(w[a] * x[a] for a in range(N)) - y) ** 2, label = 'HA')
HB = -B * sum(c[a] * x[a] for a in range(N))
H = HA + HB
Q = H
model = Q.compile()
sp = ["x[0]", "x[1]", "x[2]", "x[3]", "x[4]", "x[5]", "x[6]", "x[7]", "y[0]", "y[1]", "y[2]", "y[3]", "y[4]", "y[5]", "y[6]"]
qubo, offset = model.to_qubo()
Q = {}
for i in range(15):
  for j in range(15):
    if ((sp[i], sp[j]) in qubo):
      Q[(i, j)] = qubo[(sp[i], sp[j])]
f = BinaryPoly(Q)
model0 = BinaryQuadraticModel(f)
solver = Solver(client)
result = solver.solve(model0)
solution = result[0].values
print(solution)
print("ナップサックの容量 : " + str(W))
print("荷物の数 : " + str(N))
treasures = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I']
weight = 0
cost = 0
for k in range(N):
	if solution[k] != 0:
		print("荷物 " + treasures[k])
		weight += w[k]
		cost += c[k]
print("合計の容量 : " + str(weight))
print("合計の重さ : " + str(cost))



```

以上。
AndroidStudio Flutter で Device File Explorer が表示されない

AndroidStudio でデバイスファイルエクスプローラーがない
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/24737711-6b44-f678-5757-e336060aef2d.png' width='40%'>

起動時に表情される構成を実行します
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/ebe51954-7c65-6920-575b-2136c15ad561.png' width='50%'>

表示されました
<img src='https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253995/6564af91-e4e5-364b-f3ef-e5d9887b3519.png' width='40%'>

短い記事です。
どこにも載っていなくて何度も再インストールしたりしてハマりました。
これを見た人がすぐ解決できれば嬉しいです。
Rustの実行速度が速い理由

#目的
Rustの実行速度が速い理由を知る。

#まとめ
①直接機械語にコンパイルされる。
②ゼロコスト抽象化
③GCがない

#Rustの実行速度
[様々なアルゴリズムでの速度比較](https://benchmarksgame-team.pages.debian.net/benchmarksgame/which-programs-are-fastest.html)
左からC++、Rust、C
数値が低いほど早い。RustはC,C++と同程度に速いとされている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/2143235e-abee-1d19-8644-5d16f1cacccf.png)

[Rustのコンパイラ](https://prev.rust-lang.org/ja-JP/faq.html)

#Rustのコンパイル
RustはC、C++同様に直接機械語を生成している。Rustのコンパイラは機械語生成にLLVMを使用している。
[Rustについて](https://proc-cpuinfo.fixstars.com/2019/09/rust-wins-cpp/)

pythonは実行時にバイトコード（中間コード）を生成し、仮想マシンPVM(python virtual machine)で実行するため遅い。
[参考](https://sho-wiki.com/2020/06/24/%E3%80%90python%E5%9F%BA%E7%A4%8E%E3%80%91python%E3%81%AE%E7%89%B9%E5%BE%B4/)


#アセンブラの確認
cargo rustc --release -- --emit asm　で最適化されたアセンブラを出力可能。
\target\release\depsに.sファイルが作成される。

#ゼロコスト抽象化
抽象化のコスト（実行速度の低下やメモリ使用量の増加）を限りなくゼロにしているため速い。
もとはC++の概念。（ゼロオーバーヘッド原則）

静的ディスパッチで事前に対応する関数などを生成しているためオーバヘッドがなくなる、インライン化など最適化しやすい。
動的ディスパッチにも対応しているため、実行時に型が決まる場合にも対応可能。

```rust:qiita.rs
//共通のメソッドを実装するように促す仕組み
//これがないと同じ名前の関数は使用できない
trait  Show{
  fn show(&self);
}

struct Car;
struct RacingCar;

//implで構造体にメソッドを持たせる
impl Show for Car{
  fn show(&self){
    println!("Car");
  }
}

impl Show for RacingCar{
  fn show(&self){
    println!("RacingCar");
  }
}

fn main() {
  let car=Car{};
  car.show();//静的ディスパッチ

  let caa=RacingCar{};
  caa.show();//静的ディスパッチ
  
  let Car_vec:Vec<Box<dyn Show>>=vec![Box::new(Car),Box::new(RacingCar)];
  for i in Car_vec{
    i.show();//動的ディスパッチ
  }

}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/680528/dfa729d5-c1a5-e964-cb67-380f5f504c43.png)

pythonは動的型付き言語であるため、最適化がしにくく遅い。[なぜpythonが遅いのか](https://postd.cc/why-is-python-so-slow/)

#ゼロコスト抽象化の効果の確認
[参考](https://blog.rust-jp.rs/tatsuya6502/posts/2019-12-zero-cost-abstraction/)

#ガベージコレクション（GC)がない
ガベージコレクションとは：プログラムが使用しなくなったメモリ領域を自動的に解放して他のプログラムが使えるようにすること。

GCがある言語はメモリの管理を考えずにコードを書ける代わりに、ＧＣが行われることで処理が停止するため、実行速度が遅くなる。

[JavaのGC:世代別ガベージコレクション](http://itdoc.hitachi.co.jp/manuals/link/cosmi_v0951/03Y0450D/EY040138.HTM)

[GCまとめ](http://sharply.hatenablog.com/entry/2018/03/31/233222)


どうやってガベージコレクションをなくした？
→[所有権と借用の仕組みによる。](https://qiita.com/asparagasu/items/1efc918abb535ee1213a)
Railsのenumの可読性をあげる

## はじめに
Rails(ActiveRecord)でenumを扱おうとすると、db上のデータはintegerとして扱うことが多いと思います。
しかしこれだとdb上のデータが何を意味しているかわかりづらく、可読性が下がります。
そこで今回はMySQLを使うことを前提に、MySQLのENUM型を定義する方法をメモしておこうと思います。

## 環境
ruby 3.0.0
rails 6.1.1
MySQL 5.7

## 手順
```ruby
class CreateAnimals < ActiveRecord::Migration[6.1]
  def change
    create_table :animals do |t|
      t.string :name
      t.column :animal_type, "ENUM('dog', 'cat', 'bird')", null: false

      t.timestamps
    end
  end
end
```

` t.column :animal_type, "ENUM('dog', 'cat', 'bird')", null: false`
この部分で定義しています。
`t.column`でMySQLの`ENUM('dog', 'cat', 'bird')`という構文を直接実行できます。


途中からカラムを追加するには少し工夫が必要です。
`change_table`で追加できますが、rollbackできないので`def up`で定義しましょう。

```ruby
class ChangeAnimals < ActiveRecord::Migration[6.1]
  def up
    change_table :animals do |t|
       t.column :animal_type, "ENUM('dog', 'cat', 'bird')", null: false
    end
  end

  def down 
    remove_column :animals, :animal_type
  end
end
```


途中でENUMを拡張

```ruby
class ChangeAnimals < ActiveRecord::Migration[6.1]
  def up
    change_table :attendance_punches do |t|
      t.change :animal_type, "ENUM('dog', 'cat', 'bird', 'fish')", null: false
    end
  end
end
```

~~ENUMの型を増やすことはできますが、減らしたり、名称を変更しようとするとエラーになるので注意が必要です。~~ 
→すでに該当のENUMを持つデータが存在する場合に、そのENUMの種類を消すことはできないようです。（例：animal_type: dogを持つデータが存在した場合、dogを消すようなスキーマ変更はできない。）

##### enumerizeも使えます
https://github.com/brainspec/enumerize

```ruby:animal.rb
class Animal
  extend Enumerize

  enumerize :animal_type, in: [:dog, :cat, :bird],
                          predicates: true,
                          scope: true
end
```

```terminal
animal = Animal.new

animal.dog?   # => false
animal.cat? # => false

animal.animal_type = 'dog'

animal.dog?   # => true
animal.cat? # => false

Animal.with_animal_type(:bird)
# SELECT "animals".* FROM "animals" WHERE "animals"."animal_type" IN ('bird')
```


## おわりに
カラム名を`type`にしたらエラーが出てmigrateできませんでした。どうやら予約語になっているらしく、`type`をカラム名にすることはできないようです。
【Laravel】Formの項目が多い場合にsessionに保存したエラーメッセージが表示されない問題

# 背景
LaravelでRequestFormを使ったバリデーションを実装中、

空のFormを送信するとバリデーションにひっかかって正しくリダイレクトされるが、

FormRequestに設定したエラーメッセージが表示されない問題が発生。

原因を切り分けてみるとFormRequestの設定に問題はなく、対象のformの項目数を減らすと正しくエラーメッセージが表示されたので、

項目が一定数以上あるフォームで発生するのは分かったのですが、


根本的な原因が分からずに詰まってしまったのでその原因と解決策をメモ。

# 結論
`/config/session.php`の`'driver'`の項目に**file**を指定することで解決しました。
.envの環境変数で指定している場合は対象の値を**file**に変更すると設定できます。
(※Dockerを利用している場合はDockerfileの環境変数の設定も確認)

# 結論(詳細)

こちらに似たような質問と答えが載ってました。
[stackoverflow - Laravel form validation issues (session size limit?)](https://stackoverflow.com/questions/59785406/laravel-form-validation-issues-session-size-limit)

RequestFormのエラーメッセージはsessionに保存されてviewに渡されており、

sessionドライバーに**cookie**を指定しているとcookieの容量の上限で保存できないのが原因のため、sessionドライバーに**file**を使うと解決するとのことでした。

sessionドライバーの指定は`/config/session.php`の`'driver' `の項目で指定できるので、`cookie`を使っているとを`file`に書き換えて読み込み直すと変更できます。


```php:/config/session.php

<?php

use Illuminate\Support\Str;

return [

    /*
    |--------------------------------------------------------------------------
    | Default Session Driver
    |--------------------------------------------------------------------------
    |
    | This option controls the default session "driver" that will be used on
    | requests. By default, we will use the lightweight native driver but
    | you may specify any of the other wonderful drivers provided here.
    |
    | Supported: "file", "cookie", "database", "apc",
    |            "memcached", "redis", "dynamodb", "array"
    |
    */

    'driver' => env('SESSION_DRIVER', 'file'),

    /* ~~~~~ 省略 ~~~~~~ */
];

```

.envの環境変数で指定してる場合はそちらの値(僕の場合は`SESSION_DRIVER`)に`file`を指定すると変更できます。


```.env
SESSION_DRIVER=file
```



# 余談
僕の環境の場合、上記のサイトのように`/config/session.php`と`.env`の`SESSION_DRIVER`の値はどちらもfileを指定していたのですが、Dockerfileの環境変数の設定で`SESSION_DRIVER`に`cookie`を指定していたため、反映されずに詰まってました。

# 引用
https://stackoverflow.com/questions/59785406/laravel-form-validation-issues-session-size-limit
App Store Connectにアップロードする動画のサイズ

App Store Connectにアップロードする動画のサイズ

6.5インチ用　886x1920
5.5インチ用 1080x1920
12.9インチ用 1200x1600

```
//6.5inch
ffmpeg -i "X:/Download/src.mov" -filter:v scale=886:1920 -r 30 "X:/Download/dst65.mov"
ffmpeg -i "X:/Download/dst65.mov" -f lavfi -i aevalsrc=0 -c:v copy -map 0:0 -map 1:0 -shortest -ac 2 -strict -2 "X:/Download/dst65_nosound.mov"

//5.5inch
ffmpeg -i "X:/Download/src.mov" -filter:v scale=1080:1920 -r 30 "X:/Download/dst55.mov"
ffmpeg -i "X:/Download/dst55.mov" -f lavfi -i aevalsrc=0 -c:v copy -map 0:0 -map 1:0 -shortest -ac 2 -strict -2 "X:/Download/dst55_nosound.mov"

```

参考記事
https://qiita.com/geese_saikyou/items/8fd98a4876c6eba5afc8
ADOのデータ型一覧

# ADOのデータ型

自分用にまとめたものです。
（サイズや扱える範囲などは、詳細な文献が無かったため間違っているかもしれません。）

|定数|値|サイズ|データ型|扱える範囲など|
|---|---|---|---|---|
|adTinyInt|16|1byte|バイト型（符号付き）|-128 ～ 127|
|adSmallInt|2|2byte|整数型（符号付き）|-32,768 ～ 32,767|
|adInteger|3|4byte|長整数型（符号付き）|-2,147,483,648 ～ 2,147,483,647|
|adBigInt|20|8bite|長長整数型（符号付き）|-9,223,372,036,854,775,808 ～ 9,223,372,036,854,775,807|
|adUnsignedTinyInt|17|1byte|バイト型（符号なし）|0 ～ 255|
|adUnsignedSmallInt|18|2byte|整数型（符号なし）|0 ～ 65,535|
|adUnsignedInt|19|4byte|長整数型（符号なし）|0 ～ 4,294,967,295|
|adUnsignedBigInt|21|8byte|長長整数型（符号なし）|0 ～ 18,446,744,073,709,551,615|
|adSingle|4|4byte|単精度浮動小数点型|有効桁数7桁の実数（おおよそ）|
|adDouble|5|8byte|倍精度浮動小数点型|有効桁数15桁の実数（おおよそ）|
|adCurrency|6|8byte|通貨型（符号付き）|-922,337,203,685,477.5808 ～ 922,337,203,685,477.5807|
|adDecimal|14|(12byte)|十進型|固定の精度および桁数を持つ正確な数値（10進数で最大28桁?）|
|adNumeric|131|-|NUMERIC型|固定の精度および桁数を持つ正確な数値（19byte?）|
|adVarNumeric|139|-|NUMERIC型|数値（可変長）|
|adDate|7|8byte|日付/時刻型|1899-12-30 00:00:00 ～ （倍精度浮動小数点数型）|
|adFileTime|64|8byte|ファイルのタイムスタンプ|1601-01-01 00:00:00 ～ （100ナノ秒単位）|
|adDBDate|133|-|日付型|日付値 (yyyymmdd) |
|adDBTime|134|-|時刻型|時刻値 (hhmmss) |
|adDBTimeStamp|135|-|日付/タイムスタンプ型|yyyymmddhhmmssおよび10億分の1桁までの分数|
|adBSTR|8|-|BSTR文字列型|nullで終わる文字列（Unicode） |
|adChar|129|-|文字列型|文字列値|
|adWChar|130|-|文字列型|nullで終わるUnicode文字列（ワイド文字）|
|adVarChar|200|-|文字列型|文字列（可変長）|
|adLongVarChar|201|-|長い文字列型|長い文字列（可変長）|
|adVarWChar|202|-|文字列型|nullで終わるUnicode文字列（可変長・ワイド文字）|
|adLongVarWChar|203|-|長い文字列型|nullで終わる長いUnicode文字列（可変長・ワイド文字）|
|adBoolean|11|1bit|真偽型|True / False|
|adBinary|128|-|バイナリ型|バイナリ値（最大512byte?）|
|adVarBinary|204|-|バイナリ型|バイナリ値（可変長）|
|adLongVarBinary|205|-|ロングバイナリ型|ロングバイナリ値（可変長）|
|adIDispatch|9|-|ポインタ型|COMオブジェクトのIDispatchインターフェイスへのポインタ|
|adIUnknown|13|-|ポインタ型|COMオブジェクトのIUnknownインターフェイスへのポインタ|
|adEmpty|0|-|-|値を指定しない|
|adError|10|4byte|エラーコード|32ビットエラーコード|
|adVariant|12|-|バリアント型|オートメーションバリアント型 （Variant） |
|adGUID|72|16byte|グローバル一意識別子|16進数32桁|
|adUserDefined|132|-|ユーザー定義型|ユーザー定義の変数|
|adChapter|136|4byte|adChapter型|子行セットの行を識別する4バイトチャプター値|
|adPropVariant|138|-|PROPVARIANT構造体|オートメーションPROPVARIANTを示す|
|AdArray|0x2000|-|配列|別のデータ型定数と組み合わされ、その配列を示すフラグ値|

**参考サイト**
・[データ型の比較](https://docs.microsoft.com/ja-jp/office/vba/access/concepts/error-codes/comparison-of-data-types)
・[DataTypeEnum](https://docs.microsoft.com/ja-jp/office/client-developer/access/desktop-database-reference/datatypeenum)
（10分IoT）ESP32をwifi接続して温度・湿度をグラフ化(Ambient)

#目的
Iot入門として温度・湿度をサーバーにて可視化できるようにします。

#使う機材・サービス
マイコン：ESP32
温度・湿度測定：DHT11
可視化サービス：Ambient

[ESP32-DevKitC - プログラミング入門](https://qiita.com/freezeeyes/items/16cd5a18ef6f0c2294c4)
[Arduino ESP8266で温度・湿度を測定し、Ambientに送ってグラフ化する](https://ambidata.io/docs/esp8266/)

#結線図
![IMG_0834.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/9b15d091-9e2f-4bb6-0e9c-7221aecce8ec.jpeg)

#コード
※DHTなどのライブラリはインストールしておいてください※

```java

#include <WiFi.h>
#include <Ambient.h>
#include <DHT.h>

#define channelId XXXX  // 生成したAmbientチャネルID
#define writeKey "XXXXXXXX"  // Ambient のライトキーをセット

WiFiClient client;
const int PIN_DHT = 4;
DHT dht(PIN_DHT,DHT11);
Ambient ambient;

//WiFiのIDとPASS
const char *ssid = "XXXXXX";  //wifiのssid
const char *password = "XXXXXXX";  //wifiのパスワード

void setup() {
  Serial.begin(115200);
  // WiFiに接続
  Serial.println(ssid);
  Serial.print("Waiting for Wi-Fi connection");
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");


  ambient.begin(channelId, writeKey, &client);  //  チャネルIDとライトキーを指定してAmbientの初期化
  dht.begin();
}

void loop() {
  // put your main code here, to run repeatedly:
    // DHT11から読み込み
    float t = dht.readTemperature();
    float h = dht.readHumidity();
    delay(200);
    if (isnan(t) || isnan(h)) {
      Serial.println("Failed to read from DHT sensor!");
      return;
    }
    //シリアルモニターに温度・湿度の表示
    Serial.println("Temperature: " + String(t) + "C   Humidity: " + String(h) + "%");

    //Ambientに温度と湿度を送る
    ambient.set(1, t);   //データセット          
    ambient.set(2, h); 
    ambient.send();   //  Ambientにデータを送信  
    //データ取得頻度
    delay(1000*20);  //1000ミリ秒＝1
}
```



#結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342722/e79e0114-a2a9-f59b-682d-f2e2eeebaa4e.png)
[c#] ConcurrentDictionaryを作って学ぶマルチスレッドデザインパターン

#概要
スレッドセーフといった単語を聞いたことはありますか？？
聞いたことはあっても、それがどういう状態かはっきりわかっているとは言えないなぁと思っているそこの __あなた__ に向けた記事です。
今回の記事を読めば、スレッドがどういうもので、スレッドセーフとは何かがわかるようになるはずです。
今回の目標としてはスレッドセーフなDictionary、つまり標準ライブラリのConcurrentDictionaryを作ることです。
今回、採用する言語としてc#を選びました。
c#は言語レベルでマルチスレッドプログラミングをサポートしている言語で、`async`や`await`、`Task`などはc#erなら聞いたことや使ったことがあると思います。
これらの動作の根底にはマルチスレッドデザインパターンが使用されています。
コラムとしてこれらの動作について、スレッドレベルでほんわかと解説したいと思います。

今回の記事は[Javaで学ぶマルチスレッドデザインパターン](https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82%E7%89%88-Java%E8%A8%80%E8%AA%9E%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%B6%E3%82%A4%E3%83%B3%E3%83%91%E3%82%BF%E3%83%BC%E3%83%B3%E5%85%A5%E9%96%80-%E3%83%9E%E3%83%AB%E3%83%81%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E7%B7%A8-%E7%B5%90%E5%9F%8E-%E6%B5%A9/dp/4797331623)　を読んでc#バージョンをやろうと触発された結果なので、興味があればこの本もぜひ読んでみてください。
この記事でもちいている用語は、基本的に上の本からの引用です。
#記事一覧
1. [スレッドとは何かコンピュータの動作レベルから納得する](https://qiita.com/hidekikangeki/items/faef0b07fe1f460766e6)
2. [スレッドセーフとは何か](https://qiita.com/hidekikangeki/items/4ea684b3971ab00e9aff)未完成
3. [Dictionaryをスレッドセーフにする](https://qiita.com/hidekikangeki/items/c411f2365ebb6543f689)未完成
4. [Dinctionaryをより効率的にスレッドセーフを実現する]未完成(https://qiita.com/hidekikangeki/items/708d01e986234b00e74d)
5. [async,await,taskの動きを理解する](https://qiita.com/hidekikangeki/items/29bd1fb1464a726830a1)未完成
スレッドセーフとは何か

[[c#] ConcurrentDictionaryを作って学ぶマルチスレッドデザインパターン](https://qiita.com/hidekikangeki/items/534a2a366ae8729585b7)の記事です。
未執筆
#次の記事
[Dictionaryをスレッドセーフにする](https://qiita.com/hidekikangeki/items/c411f2365ebb6543f689)
Dictionaryをスレッドセーフにする

[[c#] ConcurrentDictionaryを作って学ぶマルチスレッドデザインパターン](https://qiita.com/hidekikangeki/items/534a2a366ae8729585b7)の記事です。
未執筆
#次の記事
[Dinctionaryをより効率的にスレッドセーフを実現する](https://qiita.com/hidekikangeki/items/708d01e986234b00e74d)
Dinctionaryをより効率的にスレッドセーフを実現する

[[c#] ConcurrentDictionaryを作って学ぶマルチスレッドデザインパターン](https://qiita.com/hidekikangeki/items/534a2a366ae8729585b7)の記事です。
未執筆
#次の記事
[async,await,taskの動きを理解する](https://qiita.com/hidekikangeki/items/29bd1fb1464a726830a1)
AWS BatchでJavaのコンテナをLambda経由で起動する時にシステム環境変数を渡す

# この記事の対象
Spring Boot
EC2コンテナ
AWS Batch
AWS Lambda (node.js 14)

# 概要
Spring Bootで作成したバッチアプリケーションをAWS Batchに登録。
ジョブをLambda関数経由で呼び出す際にコンテナ起動パラメータを渡す方法です。

# なんでそんなことを？
Batch用に作成したJavaコードに、共通処理が多いため、複数のジョブ起動が実装されており、システムプロパティ(@ConditionalOnPropertyアノテーション)を利用して、実行時に起動するジョブを選択できるようにしました。

その際に、Lambda関数側でJavaのシステムプロパティを渡す方法です。

# 詳細
サンプルはAWS Lambda(node.js 14)です。

``` sample.js
const AWS = require('aws-sdk');

module.exports = async function (param) {
    var batch = new AWS.Batch({
        httpOptions: {
            timeout: 1200000
        }
    });

    try {
        const result = await batch.submitJob({
            jobName: 【AWSバッチのジョブ定義名】,
            jobDefinition: 【AWSバッチのARN】,
            jobQueue: 【ジョブキューのARN】,
            containerOverrides: {
                environment: [
                    // オーバーライドするJavaシステムプロパティを設定
                    {name: 'JAVA_OPTS', value: '-Dbatch.execute=ExecuteJob001 -Dfile.encoding=UTF-8'}
                ]
            }
        }).promise()
        console.log(result)
    } catch (err) {
        console.log("submitJob error: " + err)
        return { statusCode: 500 }
    }
};
```

肝は、containerOverridesパラメータです。
コンテナ起動時の環境変数をオーバーライドすることが出来ます。
このパラメータにJAVA_OPTS環境変数を定義する事で、起動するバッチアプリを選択できるようになります。

上記の例は、Javaコードで

```
@ConditionalOnProperty(value = {"batch.execute"}, havingValue = "ExecuteJob001")
```

と定義したアプリを起動する場合の引数指定方法になります。

# 最後に
他にも色々やり方はあるんですが、コンテナイメージを生成する際に

```
mvn spring-boot:build-image
```

を利用して安易にコンテナイメージを生成しているため、こういった方法を取りました。
Boolean型からString型にする方法


#問題
bにboolean型でtrueかfalseが与えられる時、string型に変更せよ。

```
def boolean_to_string(b)
  return
end
```

##解答1
```
def boolean_to_string(b)
  b ? "true" : "false"
end
```

三項演算子なるほど。

##解答2
```
def boolean_to_string(b)
  b.to_s
end
```

##解答3
```
def boolean_to_string(b)
  b.inspect
end

```
inspect使ったことないですができるんですね！


## 感想

`Codewars`は他の人が書いたコードが読めるのですごく勉強になりますね！
[HTML5+JavaScript]入れやすい住所入力欄を、欄を作りながら考える

[本記事は、自分サイトのこの記事と同一内容です。](https://hagiayato.github.io/my-site/jekyll/update/2021/02/28/AddressForm.html)
# はじめに
様々なサイトで見かける住所入力欄。
今後フロントエンド系の仕事をすれば一度は関わることがあるのではと思いますので、入力しやすい住所入力欄を実際に実装しながら考えてみます。
なお今回は、ライブラリとしてBootstrap v5.0.0 を使用します。
ソースコード：[HagiAyato.github.io/practice/address/](https://github.com/HagiAyato/HagiAyato.github.io/tree/master/practice/address)
動作確認できるページ：[入れやすい住所入力欄を、欄を作りながら考える](https://hagiayato.github.io/practice/address/index.html)

## １．一番シンプルなフォーム
住所をテキストボックスに入れるだけ。
開発初心者が作りそうなフォームで、色々と住所を入れにくいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/3e2743af-6dc0-974f-ee30-957a9f20fcbc.png)

問題点：

- 入力欄・入力欄に入れる文字が長くなる
- 住所は住所でも、何を入れればいいかが分からない
- 住所を空欄にしたまま"決定"される可能性がある

## ２．入力欄を分けたフォーム
住所入力欄を細分化し、何を入れればいいかを分かるようにしました。
しかしこれだけでは入力を間違えてもなにも警告が出ず、間違えたまま"決定"処理を行えます。
これでは入れやすいか以前の問題。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/1ca4dfc9-5829-ccd4-46c6-c78a1473a5e9.png)

解決した問題：

- 入力欄・入力欄に入れる文字が長くなる
- 住所は住所でも、何を入れればいいかが分からない

新たな問題・未解決の問題：

- 住所を空欄にしたまま"決定"される可能性がある
- 住所各項目の入力チェックをしていない(郵便番号の桁数・ハイフン、都道府県名・市区町村名)

## ３．入力チェック付きフォーム(HTML5)
HTML5のpattern属性による、入力チェックを実装しました。
また郵便番号については、"２．"の段階でハイフン有り無しの記載が説明になかったので、追記を行いました。
誤り入力をなくす意味ではこれで十分ですが、今回は入れやすい住所入力欄を作るのが目的です。
できれば他所の入力ミスを自動修正したい…
《注意》HTML5非対応環境を考慮する場合、およびエラーメッセージをカスタマイズしたい場合は、JavaScript等でこれ以外の実装方法を採用する必要あり。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/aeb3a7ad-cec2-da5a-faa6-40d43ba3a252.png)

解決した問題：

- 住所を空欄にしたまま"決定"される可能性がある
- 住所各項目の入力チェックをしていない(郵便番号の桁数・ハイフン、都道府県名・市区町村名)

新たな問題・未解決の問題：

- 郵便番号からの住所自動入力機能が欲しい
- 郵便番号の数字入力を、自動で半角・ハイフン抜きにしたい
- 郵便番号の英数字・片仮名入力を、自動で全角にしたい

## ４．入力補助付きフォーム
AjaxとAPIにより、郵便番号による住所自動入力を実装しました。
また、JavaScriptで、入力補助を実装し、英数字・片仮名の半角⇔全角揃えを実装しました。
ここまでくれば、よくサイトにある入力しやすい住所入力欄と同じ機能と言ったところでしょうか。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/655112/84378d58-4343-fdc4-4d55-71af3635ff1c.png)


解決した問題：

- 郵便番号からの住所自動入力機能が欲しい
- 郵便番号の数字入力を、自動で半角・ハイフン抜きにしたい
- 郵便番号の英数字・片仮名入力を、自動で全角にしたい

# 実装の結果
結論：入れやすい住所入力欄は、単に住所を入力するだけでなくその誤りチェック・自動入力・誤り修正を行えるものである。

ただここまでくると、1つの入力欄だけでも実装に必要なコード行数が多くなります。
(今回はHTML：63行+JavaScript：107行=170行)
一つ一つ住所入力欄を実装する際にこれだけのコードを書くのは手間がかかるので、
コードをライブラリのように保存して、使いまわしができるようにすべきだと感じました。
通知機能

#参考にしたサイト

https://qiita.com/nekojoker/items/80448944ec9aaae48d0a#%E5%AE%8C%E6%88%90%E5%BD%A2%E3%81%AE%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8

https://railsdoc.com/page/model_distinct

https://railsdoc.com/page/model_update_attributes
KotlinのChar型のtoInt()に引っかかった

## はじめに
Kotlinで文字列を数値に変換した際に詰まった時のメモ

## 問題発生の経緯
Kolinで文字列を数値に変換した際に発生

- 該当のコード

```
fun main() {
    var input = readLine()?: throw Exception()
    for (n in input){
        println(n.toInt())
    }
}
```

123を標準入力で受け取る。

- 想定標準出力

```
1
2
3
```

がしかし、
このコードで出力されるのは、以下である。

- 実際の出力

```
49
50
51
```

！？！？！？！？！？！？！？！？！？！？
## 解決した方法
上記のコードでは、String型の値をfor式で回し配列として扱っているので（String型はCharSequence型でもある）、nに入っている値の型はChar型(String型ではない)になる。
また、公式ドキュメントによると、

>fun toInt(): Int
Returns the value of this character as a Int.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char/to-int.html

Char型のValueをInt型で返すとのこと。

解決法としては、Character.getNumericValue（char）を使うと、charの文字を数値に変換してくれる。


```
fun main() {
    var input = readLine()?: throw Exception()
    for (n in input){
        println(Character.getNumericValue(n))
    }
}
```

もしくは、Charのvalueから'0'(48)を引けばいい。

```
fun main() {
    var input = readLine()?: throw Exception()
    for (n in input){
        println(n.digitToInt())
    }
}
fun Char.digitToInt(): Int {
    if (this in '0'..'9') {
        return this - '0'
    }
    throw IllegalArgumentException("Char $this is not a decimal digit")
}
```
ちなみに、上記のコードはKotlin1.4以降でExperimentalで実装されている。

## 参考
https://stackoverflow.com/questions/51961220/what-happens-with-toint

https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-char/to-int.html
AWSではじめてhttps通信＆CDNをしてみた。超ざっくりまとめてみた。

AWSでの証明書発行およびクライアントからの通信の暗号化(https)とCloudFrontを利用したCDNの実現をしました。
実現したものは、こんなイメージです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/8cf237b4-d454-ff49-6d63-bee457febf25.png)

細かい作業過程は割愛しますが環境構築で理解した基本構成の概要を自分の理解を深めるために、超ざっくりと基本要素をまとめます。

これを見れば、何の目的のために何を作るのか、一目で思い出せるはず！
また、この記事が、これからAWSの基礎学習を始める方の理解の助けとなり、AWSを触るハードルを下げる助けとなれば幸いです。私も初心者です。みなさん頑張りましょう！
<img width="200" alt="qiita-square" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/c632153a-ba03-b27e-f715-8fb61574e746.png">

---

- 作図には [AWS 公式アイコンセット](https://aws.amazon.com/jp/architecture/icons/)を利用してます
- 全般的に概念的な説明のみとしています。
- 詳細な設定/オペレーションを知りたい方は、他サイトをご覧ください。
    - [この記事(証明書の発行～https化)](https://zenn.dev/anaka/articles/a2c12873a5d617)や[この記事(CloudFront)](https://zenn.dev/kuma2/articles/f7eeb470e930e7)、[クラスメソッドさんの記事](https://dev.classmethod.jp/articles/mesoko-r53-cdn/)に画面キャプチャ付きで細かく説明されてました！
 

超ざっくりまとめ
---

超ざっくりと説明すと、以下を行うだけです。
 1. ELBでリスナー(https)登録(＆SSL証明書の設定)
 2. バージニアリージョンで、AWS Certificate Manager で証明書を作成
 3. CloudFrontでDistributionの作成(※)
 4. Route53でホストゾーンにAレコード登録(CloudFront, ELBのへのルーティング)
※Origin Domain Name(キャッシュ元情報)・証明書の登録、キャッシュに関する詳細設定を行う

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/229b8652-35e5-7938-37d7-25eadf94a880.png)


これだけで、さくっと作れてしまいます。

<img width="200" alt="qiita-square" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/5767d37d-a259-85da-39af-5f6a53175a16.png">

詳細な手順の説明は、必要に応じて以下を参照ください。
- 証明書の発行～https化：[この記事](https://zenn.dev/anaka/articles/a2c12873a5d617)
- CloudFrontの詳細設定方法：[この記事](https://zenn.dev/kuma2/articles/f7eeb470e930e7)


おまけ
---
Amazon CloudFrontのキャッシュ機構を利用することで、グローバルなアクセスが必要なケースで、クライアントからの距離を近くし、レスポンスの向上を見込めます。
今回の記事では触れませんでしたが、AWS Global Accelerator を利⽤することにより⾮キャッシュコンテンツの⾼速化も図れ、ユースケースがいろいろと考えられる機能だと思います。(日本とネットワーク回線が細い海外拠点とのファイル共有など)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/ae88a623-2f23-02d4-16c2-e38485212887.png)


※上記は、[『AWS のネットワークで知っておくべき10のこと』](https://pages.awscloud.com/JAPAN-event-OE-At-least-10-Network-2020-reg-event-LP.html?trk=aws_introduction_page)に分かりやすく説明されています

こちらは、別途勉強しておこうかと思います。



さいごに
---
この記事はAWS初学者を導く体系的な動画学習サービス[「AWS CloudTech」](https://aws-cloud-tech.com/)の課題カリキュラムで作成しました。

このサービスは、テンポの良い/わかりやすい動画説明をもとに、気軽に実践を積み、自分の血肉とできるオンラインスクールです。
コミュニティも存在し、Slackで会員通しの情報交換/質問も気楽にできます。
<img width="100" alt="qiita-square" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/8889d9eb-2c72-293d-fda8-73dbd95eb1ab.png">

書籍を購入するような値段で学習ができ、とてもお得です。(個人的な感想です)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1038334/1b330d17-6e3f-50ab-d6f1-2a96300cd626.png)

では、また次回お会いしましょう！
アンケート結果をSplunk DLTK を使って自然言語分析してみました


# はじめに

昨年、Splunk のGojasというユーザー会で話させて頂く機会がありまして、そこで DLTKにある spacyというライブラリーを使った自然言語処理をアンケート結果に対して利用し分析してみたという発表をさせていただきました。ここではそちらの内容をシェアさせていただきたいと思います。

当時利用したスライドはこちらからご覧いただけます。[slideshare](https://www.slideshare.net/MaruyamaJunichi/splunk-238457640)

# サマリー

Splunkのワークショップ後のアンケートコメントを使って以下のような分析をしてみました。
1. Token化 (形態素解析) /  品詞タグ付け　＋　ワードクラウドによる可視化
2. TFIDFによる重み付けによる、重要コメントの抽出
3. 類似度判定 + クラスタリングによるコメント傾向分析

## 1. Token化 (形態素解析) /  品詞タグ付け　＋　ワードクラウドによる可視化

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/6ade0e91-1fd5-0f27-7c77-e599700440e2.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/58cd571a-9aec-3dd4-ca6f-9332ea0b650e.png)

これは、ワークショップ毎にどのようなキーワードがコメントで発せられているかがわかります。日本語は形態素解析するだけでも一苦労なのですが、spacy(ginza)を使うと簡単にトークン化してくれて、品詞タグまで付けてくれるので、必要なワードを洗い出すことができます。ストップワードも入力できるのでワードクラウドと組み合わせると相性抜群です。


# 2. TFIDFによる重み付けによる、重要コメントの抽出

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/a118d26d-f2c6-f185-50cf-f46e3829f50b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/42542452-ecd3-a6f5-8622-ac8be29fa487.png)

単純な単語だけでなく、その頻出度などと組み合わせながらコメント全体で重要度の高いと思われるものを洗い出すことができます。大量のコメントがあるときはこのような方法で絞ることも必要になってきます。（ただ付け加えておきますと、きちんと全部のコメントに目を通してます！!）


# 3. 類似度判定 + クラスタリングによるコメント傾向分析

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/d0ba7e57-8b1e-ea8e-0d2d-1df32e0ef911.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/392303/11c01b6f-3347-b478-ed83-8dedc248fb9c.png)

類似度判定の機能とクラスターの機能を組み合わせた分析手法です。類似ワードがまとまるため、全体でどのようなコメントの傾向があるのか傾向分析できます。PCAと組み合わせることで図のように可視化もできて雰囲気出ますね。


# さいごに

Splunk の DLTKと組み合わせることで自然言語処理のできる幅が大きく広がりました。残念ながら spacyは感情分析には対応していないため、他の方法を利用する必要がありますが、それ以外のことはかなりできそうです。

今回利用したDLTKのコードは[こちら](https://github.com/maroon-spec/splunk_spacy_vector)からご利用できます。
QiitaのMarkdown。URLに対して、これは機能かバグか。(バグなわけはないと思いますが。。。)

#URLに対して、中味が表示されたりします。(2021/02/28)

|<font color=green>記事本文に入る前ですが、これは、「仕様です」。:tada:　コメント欄参照。|
|:--:|



以下

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481161/65add22c-f770-4c0d-3efe-842e63fbe771.png)|
|:--|

に対して、いきなり、自動で、以下のような表示になります。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481161/f89fb990-31c0-d5e0-977d-82d10b14b214.png)|
|:--|

世間で見かける機能ではありますが。。。。
記事に適用？？

#これは、機能かバグか1
https://www.itmedia.co.jp/news/articles/2102/28/news018.html

##これは、機能かバグか2
https://www.itmedia.co.jp/news/articles/2102/28/news018.html

#これは、機能かバグか3
　
https://www.itmedia.co.jp/news/articles/2102/28/news018.html

※手前に全角スペースの1行あり。その場合は、作用せず。


#逃げ方

##クォートで囲む
"https://www.itmedia.co.jp/news/articles/2102/28/news018.html"

#まとめ
驚いたので、記事にした。
世間でよくみかけるが、、、記事内のURLの使い方は、注意かも。
上記の「逃げ方」を整理したい。

#補足
上記は、Chrome(Windows10)での確認事項ですが、
Edge(Window10)だと、何も、起こりませんね。

|いやいや、URLが表示されないのは、ダメでしょう。Edge、やさぐれてますか？|
|:--|


最近ブラウザ、、、また、怪しい世界に入ろうとしているんですかね。。。

|![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/481161/ff334f38-a7b6-a9d9-2a2f-d8d5f3504f9c.png)|
|:--|
コンテナの検証環境をためしてみる～　ネコンテナ3回


# コンテナの検証環境
コンテナを勉強していくには検証環境が必要である。今回はローカルマシンでつかうコンテナ検証環境を比較してみる。

##  コンテナの検証環境
  1. docker
  2. minikube
  3. crc (code ready container)


難しいので今回は確実に覚えなくてもいいが、コンテナオーケストレーションはAIO環境という1台で構成される環境であり、外部から参照するのが難しい環境のため、商用リリース用で考えるものではない。


## 比較内容

| 種類 | 何の検証環境 | windows環境 | windows pro環境 |mac|linux|最低必要SPEC|
|--- |---|---|---|---|---|---|
|docker|docker|仮想環境を使えば導入可能|導入可能|導入可能|導入可能|考慮必要なし|
|minikube|kubernetes|導入可能|導入可能|導入可能|導入可能|cpu:2,memory:2GB,20GB disk|
|CRC|Openshift4|導入不可能|導入可能|導入可能|導入可能|cpu:4v,memory:8GB,35GB disk|

※windows home では昔はdockerインストールできなかったが、202102時点では対応されている情報アリ
※最低必要スペックのためのセルアプリケーションのリソースは追加で必要。

- 参考情報
 - https://minikube.sigs.k8s.io/docs/start/

## 1. docker
いろんな書籍で聞くdockerです。RHEL(centos)環境ではdocker.systemで動かすものです。クライアントもdocker、サービスもdockerなので初めての人だと言葉が混在してしまいます。
デファクトスタンダードではありますが最近下火になっているdockerです。2022年を生き延びるのは難しいかもしれません。
docker -> kubernetes には移行はありますが、逆はないに等しいです。

## 2.minikube
商用利用したり、コンテナ開発の優位性を生かすためのオーケストレーションのkubernetesの検証環境がminikubeです。kubernetesは管理ツールの役目が強いため、いきなり商用を使うと外部設定の箇所で躓いてしまします。
少し前までは最初からyamlファイルを書かないとアプリケーションのテストもできなかったため、最初の『Hello,world』までに時間がかかって嫌われてきました。

```
kubectl create 'kind'
```
kindはdeployment（runみたいなもの）やservice（ネットワーク紐づけ)等を使うと、簡単に最初のデプロイができます。

## crc (code ready container)　　1押し（コンテナのメリットを考えるなら）
kubernetesにコンテナの有用機能をたっぷり付けたOpenshiftのローカル検証用、優秀なGUIがついているもの。
商用運用はredhatのわかりにくく高い料金体系を考えないといけませんが、コンテナ初期学習において一番わかりやすいです。

ただ動作環境がかなり縛られているため、最初の初期構築で悩んでしまいます。
※低スペックPCで試してはいけない。
※現バージョンはvirtualBOXでは動きません。

- crcを使ったデプロイ例(S2Iデプロイ)
 1. 下記のようなカタログから自分の環境を選ぶ
 2. githubにソースをアップロード
 3. GUIの手順に従ってデプロイ

![crcカタログ画像.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590346/bc3ef8a8-5f2b-b28d-a28c-c319b1b93689.png)

![以上.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/590346/39e04d06-7154-0798-7204-273ce4d7806e.png)

CRCはデプロイのみ考えると、こんなに簡単なんです。
基盤の設計はアーキテクトに詳しい人に任せてコンテナ開発をCRCを使って遊んでください。
商用利用は商用利用の時に考えればいい、コンテナのメリットを考えるなら一押し

# 最後に
コンテナの開発環境も各種クラウドマネージドサービスでたくさん出ています。そちらを使って最初からやる方法もありです。どのサービスでもいいので使いやすいのを使っていただければと思います。今回はあくまで費用の掛からないローカル環境での構築3つを上げさせていただきました。

コンテナ開発は一度きりの開発ではないため、初期の学習コストが低いからdockerで勉強したが、最終的にk8s環境の勉強をしないといけないという無駄勉強が発生することがあります。そうならないように注意してください。
WolframAlphaで（無限和）「2021 京都大学 前期日程 数学（理系） 第3問」 をやってみたい(途中)

(問題)
https://www.yomiuri.co.jp/nyushi/sokuho/k_mondaitokaitou/kyoto/mondai/img/kyoto_zenki_sugaku_ri_mon.pdf#page=2
(解答)
https://www.yomiuri.co.jp/nyushi/sokuho/k_mondaitokaitou/kyoto/kaitou/img/kyoto_zenki_sugaku_ri_kai.pdf#page=3


qiitaの仕様が、変わりましたか？気のせいですか？
罫線枠が表示されるようになりました。

##WolframAlphaで

https://www.wolframalpha.com/input/?i=%E7%84%A1%E9%99%90%E5%92%8C&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumupperlimit2%22%7D+-%3E%22%E2%88%9E%22&assumption=%7B%22C%22%2C+%22%E7%84%A1%E9%99%90%E5%92%8C%22%7D+-%3E+%7B%22Calculator%22%7D&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumfunction%22%7D+-%3E%22%281%2F2%29%5Ex*cos%28x*pi%2F6%29%22&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumlowerlimit%22%7D+-%3E%220%22&lang=ja

　無限和:

sum_(x=0)^∞ (1/2)^x cos((x π)/6) = 1/13 (14 + 3 sqrt(3))≈1.4766


https://www.wolframalpha.com/input/?i=%E7%84%A1%E9%99%90%E7%B4%9A%E6%95%B0&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumupperlimit2%22%7D+-%3E%22%E2%88%9E%22&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumfunction%22%7D+-%3E%22%281%2F2%29%5Ex*cos%28x*pi%2F6%29%22&assumption=%7B%22MC%22%2C+%22%E7%84%A1%E9%99%90%E7%B4%9A%E6%95%B0%22%7D+-%3E+%7B%22Calculator%22%7D&assumption=%7B%22F%22%2C+%22Sum%22%2C+%22sumlowerlimit%22%7D+-%3E%220%22&lang=ja

　無限和:
sum_(x=0)^∞ (1/2)^x cos((x π)/6) = 1/13 (14 + 3 sqrt(3))≈1.4766

# sympyで
【Java】Listの重複を削除する方法

# 1. Setクラスを使う方法

以下では、HashSetクラスに数値が重複する List を渡し、重複なしのリストに詰め替えています。

```java
        //数値が重複するListを作成
		List<Integer> listWithDuplicates = Arrays.asList(0, 1, 2, 3, 4, 4, 5, 5);

		//HashSetに数値が重複するListを渡し、重複なしのリストに詰め替える
		List<Integer> listWithoutDuplicates = new ArrayList<>(new HashSet<>(listWithDuplicates));

	    System.out.println(listWithoutDuplicates); // 出力 -> [0, 1, 2, 3, 4, 5]
```

# 2. Streamのdistinct メソッドを使う方法

以下では、Streamのdistinctメソッドで重複を削除し、新たなListに詰め替えています。

```java
        //数値が重複するListを作成
        List<Integer> listWithDuplicates = Arrays.asList(0, 1, 2, 3, 4, 4, 5, 5);

        //distinct()で重複を削除し、重複なしのリストに詰め替える
	    List<Integer> listWithoutDuplicates = listWithDuplicates.stream()
	     .distinct()
	     .collect(Collectors.toList());

	    System.out.println(listWithoutDuplicates); // 出力 -> [0, 1, 2, 3, 4, 5]

```

#参考
[HowToDoInJava : Java Stream distinct()](https://howtodoinjava.com/java8/java-stream-distinct-examples/)
[HowToDoInJava : How to remove duplicate elements in ArrayList](https://howtodoinjava.com/java/collections/arraylist/remove-duplicate-elements/#:~:text=Remove%20duplicates%20in%20arraylist%20%E2%80%93%20Java,elements%20as%20List%20using%20Collectors.)
AWS EC2 AmazonLinux2 とのファイルダウンロード・アップロード

よく忘れるのでメモ

前提
SSHでEC2に接続出来ている。

EC2のホームディレクトリからファイルダウンロード

```
scp -i 秘密鍵の場所.pem ec2-user@xxx.xxx.xxx.xxx:/home/ec2-user/test.txt  ./
```

EC2のホームディレクトリへファイルアップロード

```
scp -i 秘密鍵の場所.pem test.txt ec2-user@xxx.xxx.xxx.xxx:/home/ec2-user/
```

ディレクトリ毎操作するには -r を付ける 

```
scp -r -i 秘密鍵の場所.pem ~以下省略~ 
```
【全13サイト】各金融機関サイトにPythonとSeleniumを使ってログインするサンプル一覧と注意点


「各金融機関の明細データを自動で取得できるようにしたい」と思い立ち、手始めにログイン部分のコードを書いてみました。

最終的に13サイト分できあがったので一覧化しました。参考になれば幸いです。

## 全体的な処理の流れ
各サイトとも、全体的な処理の流れは同じです。異なる部分はIDやパスワードを入力する要素を取得する部分です。

全体的な処理の流れを下記記事で解説しているので、こちらもあわせて確認してみてください。

[楽天銀行サイトにPythonとSeleniumを使ってログインする](https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104)

## サンプルコード紹介記事一覧
2021/2/28時点のサイト数：全13サイト

### 銀行

- [三菱UFJ銀行](https://qiita.com/yoshi2045/items/765c589ce0c02e9d888d)
- [三井住友銀行（SMBCダイレクト）](https://qiita.com/yoshi2045/items/4d642b6d89c88e894628)
- [NEOBANK（住信SBIネット銀行）](https://qiita.com/yoshi2045/items/299858da6f0e23de056b)
- [楽天銀行](https://qiita.com/yoshi2045/items/2fff5bf5f0fa763f7104)


### 証券会社
- [楽天証券](https://qiita.com/yoshi2045/items/24b3287e34bfb1c42f88)
- [SBI証券](https://qiita.com/yoshi2045/items/5ce522bfc1ba5dc055d4)
- [マネックス証券](https://qiita.com/yoshi2045/items/342a9380944fa7aec37a)

### ロボアド
- [WealthNavi](https://qiita.com/yoshi2045/items/4b7fb704f0632df99688)
- [THEO](https://qiita.com/yoshi2045/items/052a67940f5e40e7042d)

### iDeco
- [SBIベネフィットシステムズ](https://qiita.com/yoshi2045/items/eda286bac10ddbae71e0)


### クレジットカード会社
- [楽天カード（楽天e-NAVI）](https://qiita.com/yoshi2045/items/856def50927c12dd4701)
- [VIEWカード](https://qiita.com/yoshi2045/items/f699fee4ecb22feade22)
- [SAISONカード](https://qiita.com/yoshi2045/items/7f64ff193e0d29a40c2f)


## 注意点
コーディング時における注意点や、実際に試していて気づいた点などを紹介します。

### その１． 設定ファイルの管理は厳重に
今回のサンプルコードでは、ログイン情報を"login_info.json"というJSON形式のテキストファイルに保存しています。

万が一このファイルが外部に漏れたりすると一大事なのでくれぐれも管理方法には注意しましょう！

できればファイルを暗号化しておき、毎回パスワード入力させて復号化してから使う、くらいやってもいいかもしれません。

### その２. 要素を取得する時のメソッド名に注意

ログインボタンのように1つの要素を取得したい時、
find_element_by_***
ではなく、
find_elements_by_***
（"s"があるほうのメソッド）
を使用すると以下のようなエラーが発生します。

```python
AttributeError: 'list' object has no attribute 'click'
```

"s"は複数形の場合に使用しますよね。
そのため、
find_elements_by_***
はリスト型のオブジェクトを返却します。

#### ダメな例
```python
# "s"付きのメソッドを呼び出す
button = browser.find_elements_by_name("ボタン名")
button.click() # click()はリスト型オブジェクトには存在しないメソッドなのでエラー発生
```

#### 正しい例
```python
button = browser.find_elements_by_name("ボタン名")
button.click()
```


#### IDEの自動補完でメソッド名選択する時に間違いやすい
このコーディング誤りは、PyCharmやVSCodeのようなIDE環境で、コードの自動補完機能を使っている場合に間違いやすいです。
しかもビルド時にはエラーにならないため気が付きにくいです。


### その３. Ajax要素のロード完了に注意

画面遷移後、ページロードが完了するまでWebDriverWait()を使って待機させます。

```python
# ページロード完了まで待機
WebDriverWait(browser, 10).until(
    ec.presence_of_element_located((By.ID, "任意の要素のID"))
)
```
ここで指定する要素を気をつけないと、思うような待機ができず後続処理が失敗するケースがあります。

画面によっては、下記例のように非同期通信で画面要素を取得・描画している場合があります。

![home_rakuten.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/a967ecfa-7767-7cdb-2a5c-21343e6230b6.png)

WebDriverWait()で指定する要素は、極力後続処理で参照する要素を指定するようにしましょう。

#### 普段と違う画面が挟まることがある

ログインしたあと、普段と違う画面が挟まることがあります。

#### 例. キャンペーンのポップアップ

![home_wn.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/459893/96d1d9ae-fa1f-7deb-ccdf-6a584cf20d4a.png)

この他にもパスワード変更や重要なお知らせなどがある場合、通常と違う画面が挟まることがあります。
 
ログインしたあと、色々操作する予定の場合はこういった画面遷移時の挙動も考慮に入れておく必要があります。

## さいごに
以上、各金融機関サイトにPythonとSeleniumを使ってログインするサンプル一覧と注意点でした！

ログイン部分については一通りできあがったので、次は明細データを取得する部分を作っていく予定です。できあがったらまた記事アップしていきますね。