OmniAICreator/Qiita-1.07M huggingface dataset:
Gitを使ってみよう（backlogも）

入社して1か月半経ったある日…

上司:bust_in_silhouette:＜この案件はGitを使うから覚えてね～
a-takano＜わかりました。（Gitってなんぞ？:rolling_eyes:）

a-takano＜本格的にbacklogを使うようになってきたな…

とりあえず[サルでもわかるGit入門](https://backlog.com/ja/git-tutorial/)から始めよう！:monkey:
こっちもわかりやすいなー→[【イラストで覚える】初心者のためのGitとGitHub用語集](https://zukulog098r.com/git/)
随時更新していこう。

使っているのはTortoiseGit→https://tortoisegit.org/

##Gitってなんぞや？
分散型バージョン管理システムの1つ。読みは「ぎっと」。
ファイルの状態を更新履歴として残せて、過去の状態に戻せたり編集した部分との差が見れる→**ファイル名に_aとか日付とか付けなくてもいい！**

同じファイルを2人以上で編集してアップロードをしようとしてもアラートが出るから、「間違って他の人の編集内容を上書きしちゃった！:scream:」なんてこともない。

##リポジトリってなんぞや？
ファイルやディレクトリの状態を記録するとこ。変更履歴は格納され記録されていく。
普段の作業はローカルリポジトリで、作業が完了したらリモートリポジトリに
プッシュ（＝アップロード）する。

###リモートリポジトリ
自分の手元外にあるリポジトリ。他の人と共有するために使う。
個人開発でも使える。
Cloudとはちょっと違う。

###ローカルリポジトリ
自分の手元にあるリポジトリ。自分のマシン内に作られる。


##リポジトリを共有しよう！
Gitをインストール後諸々設定して最初にやったのが【リモートリポジトリのクローン】だったので、これから記述する。

###リモートリポジトリのクローン
他の人が作ったり変更したリモートリポジトリを、丸ごと複製（＝クローン）して自分の手元に置くこと。

###リモートリポジトリにプッシュ
ローカルリポジトリで加えた変更を、リモートリポジトリで共有すること。
つまりアップロードすること。

###リモートリポジトリからプル
リモートリポジトリからローカルリポジトリへダウンロードすること。
リモートリポジトリの方が変更履歴が新しかったら、その内容を取り込む。
**ファイル編集前は必ず行う！！**

##ブランチを切ろう！（ブランチの作成）
同じリポジトリで修正が何か所もあって、それを複数人が同時に操作したら「いつの間にか変わってる！？」となってしまう。それを防ぐためにブランチを切る（作る）必要がある。「切る」って言っているのは【枝は切るもの】だからでしょうか。
【ブランチA】【ブランチB】【ブランチC】と修正内容ごとに分ければ、**他の人の作業の影響を受けなくて済む**。

###チェックアウト
ブランチを切り替えること。自分が作業するリモートブランチに切り替えて、作業する！

##ファイルをコミットしよう！
ファイルのコミットとは、**ファイルの変更や追加したことを記録すること**。

###コミットメッセージ
編集した内容は**コミットメッセージ**に記述する。**メッセージの記述は必須**。

```
案件名・タスク名など
空行
変更した点・変更理由など
```
こんな感じで書くと分かりやすい。


###コミットファイル
自分が編集したファイルだけが表示されていればOK。
**編集していないファイルが表示されたり、足りなかった場合は、masterからプルしてやり直し**。

##プッシュしよう！
プッシュ＝アップロードのこと。ローカルリポジトリの変更履歴をリモートリポジトリで共有する。
コミットするときに【コミットしてプッシュ】を選択しクリック。
プッシュ先ブランチは、対象の作業ブランチを選択。
成功すればリモートブランチが作成され、backlogにも通知。

##プルリクエストしよう！
「コードレビューをしてください！」とお願いする＆ローカルリポジトリでの変更を他の開発者に通知することが**プルリクエスト**。

backlogからプルリクエストができるので

1. ターゲットブランチ（マージ先のブランチ、masterとか）を選択
2. プルリクエストブランチ（マージするブランチ）を選択
3. タイトル・コメントを分かりやすく書く
4. 担当者を選択（自分ならマークを選択すればいい）
5. お知らせしたいユーザも入力
6. 適切に内容を入力し終わったら、**【プルリクエストを追加】**

これでプルリクエストが追加された。

##マージしよう！
差分確認もOKだったので、**加えた修正を元のブランチ（masterなど）に統合する**。
マージもbacklogからできる。

##ブランチを削除しよう！
backlogからは【マージ】の隣に

- [ ] **マージ後に作業ブランチを削除する**

というのがあるので、チェックを入れればブランチが削除される。
**トピックブランチが削除されるだけで、リモートブランチは削除されない！**
リモートブランチも必要ないなら削除。

##競合が発生した:fearful::sweat_drops:
初Git&初backlogでいよいよマージ！と思ったら
>**競合が発生してマージ出来ません**

:scream:　:scream:　:scream:

一度リモートリポジトリからプルして、更新したファイル反映させようと思ったけど
>gitは正常に終了しませんでした（終了コード 1）

とエラー発生。
ググって「バグかもしれないから更新すれば良い」とあったが、これは関係なさそうと判断。

###先輩方に助けを求める
マージできるようにしたい旨を説明し、無事に解決しました。
そもそもリモートリポジトリからプルできないのも問題だったので、そこから解決していった。

1. リモートリポジトリからプル→エラー発生
2. エラーメッセージで「コミット出来てないよ」という旨が出た
3. 自分が作業しているリモートブランチが原因かもと思い、削除しプルしたけど失敗
4. 変更の取り消しを試みる。右クリック→TortoiseGit→変更の取り消し
5. もう一度リモートリポジトリからプル→成功！
6. 改めてブランチを作成→ファイル修正→コミット&プッシュ→プルリクエスト→マージ&ブランチを削除
rsyncでグローバルの除外リストを設定する

`rsync`を使っているときに，大体どんなプロジェクトでも共通して無視したいファイルがあるのでそれを設定する．

自分はfishを使っているので設定に以下の `alias` を追加する．ホームディレクトリに `.rsyncignore` があればそれを読み込んでくれる．

- `fish`の場合

```shell
# rsync global excluding setting
if test -f ~/.rsyncignore
  alias rsync "rsync --exclude-from ~/.rsyncignore"
end
```

- `bash` / `zsh` の場合

```shell
if [ -e ~/.rsyncignore ]; then
  alias rsync="rsync --exclude-from ~/.rsyncignore"
fi
```


`rsync`では `--exclude-from` でファイルを渡すことで除外リストを設定できる．このとき，ファイルの記述形式は各行が`--exlude`に渡されるものと思えば良い．（`.gitignore`とかと同じように書けばだいたい大丈夫）

`--exlude`と同様，`--exclude-from` も複数指定できるので，ローカルの除外リストをさらに付け加えても支障はない．

```shell
rsync -auv --dry-run --exclude-from ./rsyncignore.local from/ to/
```
CentOS7でPostgreSQLをLANに公開する方法

#設定ファイル「pg_hba.conf」で認証方法を設定
*※「host」と各「all」の定義はこのファイルのコメントに記載されています。*
下記の設定で、
・TCP/IPで
・すべてのデータベースへ
・すべてのユーザから
・すべてのアドレスから
・「trust」という認証方法で
接続可能になります。

```shell:pg_hba.conf
・・・（略）・・・
# IPv4 local connections:
host    all             all             all            trust
・・・（略）・・・
```

#設定ファイル「postgresql.conf」でネットワークを設定
下記の設定で
・ポート5432
・すべてのアドレス
を監視するになります。

```shell:postgresql.conf
・・・（略）・・・
# - Connection Settings -
listen_addresses = '*'          # what IP address(es) to listen on;
port = 5432                     # (change requires restart)
・・・（略）・・・
```

#ファイアウォールの設定

```shell
[root@centos7 data]# firewall-cmd --add-service=postgresql --zone=public --permanent
success
[root@centos7 data]# firewall-cmd --reload
success
```
スパコンで急に計算が止まった

## スパコンで計算が止まった

今まで計算がイタレーション回数回っていたところ、こんなエラーが出てきた

<font color="Red">=>> PBS: job killed: walltime 3627 exceeded limit 3600</font>

なんかリミットが制限されたと書かれている
調べたところ異常終了に関するエラーだそうで

- 経過時間制限による終了

<p><code>=>> PBS: job killed: walltime 3602 exceeded limit 3600 aprun: Apid 379565: Caught signal Terminated, sending to application </code></p>

- どうやら経過時間を増やすオプションがあるらしいので実行してみる

<p><code>会話型でプログラムを実行する場合，経過時間が標準の制限を超えると，プログラムは強制終了されます． -Wオプション を指定することで，時間を上限まで増やすことができます．</code></p>


-W　オプションをつけてやってみた。しかしジョブが回らずに止まってしまったのでジョブを終了させた。

- オプションつけるのはうまくいかなかったのでいったん置いておく。次に計算時間を指定させる方法を使ってみる。

'''

    #PBS -l　cput=時:分:秒

        例)　#PBS -l walltime=03:00:00
        ジョブの実行時間を最大で3時間まで使用する指定です。

'''

無事回ってるっぽいです。

- デフォルトのwalltime
- 今までのwalltime

が分からないと今後同じ壁にぶつかりそうなので、リサーチしようと思います。
TwitterScraperを使ってスクレイピングできるのでは

自前でTwitter APIを用意するのが規約上面倒くさくなっているけど、Twitterをスクレイピングしたいってことあると思います。
OSSで[TwitterScraper](https://github.com/taspinar/twitterscraper)というPythonライブラリがある（みたいです）。

## はじめに
Twitter社的には、Twitterの事前の承諾なしにスクレイピングすることは禁止されています。
そのため、当記事はあくまでこんな風に使えるかもしれないという想像の記事です。（という予防線を張っておきます）

>(iii) Twitterから提供されている当社の現在利用可能な公開インターフェースを経由する (かつ、該当する使用条件に従う) ことなく、その他の何らかの手段 (自動その他を問わず) で本サービスへのアクセスもしくはその検索を行うか、またはアクセスもしくは検索を試みること。ただし、Twitterと別途締結した契約によりこれを行うことが特に認められている場合はこの限りではありません (注: 本サービスのクローリングは、robots.txtファイルの定めによる場合には許されます。ただし、Twitterの事前の承諾なしに本サービスのスクレイピングを行うことは明示的に禁じられています)。
https://twitter.com/ja/tos/previous/version_9

これを見て使ってみようという人はあくまで自己責任でお願いします。

## やりたいこと

「コンプティーク 2019年10月号」でアイカツオンパレード！の特集記事が掲載されました。
その中で、「アイカツオンパレード緊急読者アンケート」なる企画があり、Twitter上で2019年8月23日18:00～2019年8月25日17:59の短い期間でしたがアンケートが行われました。

そのアンケート回答の収集として使えたらいいなというのがやりたかったことになります。

## 実装

```python
from twitterscraper import query_tweets
import datetime as dt
import pandas as pd


# input
begin_date = dt.date(2019,8,23)
end_date = dt.date(2019,9,1)
pool_size = (end_date - begin_date).days

# tweetの収集
tweets = query_tweets("#コンプアイカツアンケート", begindate=begin_date, enddate=end_date, poolsize=pool_size, lang="ja")

tuple_tweet=[(tweet.user_id, tweet.text.replace("\n","\t"), tweet.timestamp) for tweet in tweets]
# ツイートが重複しているので重複削除する
df = pd.DataFrame(set(tuple_tweet), columns=['user_id', 'tweet', 'post'])

df.sort_values('post').reset_index(drop=True)
```

欲しい情報はあくまでツイート内容のみなので、不要なユーザ名やリツイート回数などは除去しています。

この後前処理として整形作業が必要なので、改行をタブ区切りに変更して作業しやすくしています。

注意点として、TwitterScraperは単純に処理しようとするとレコードが重複します。
（ぱっと見、`begindate`、`enddate`の期間が重複して取れるという感じではないっぽいけど、詳細は分からないです。）
そのため、setで重複削除しています。


`poolsize`もよくわからなかったのですが、内部の処理を見る限りsinceとuntilの期間の設定に必要でデフォルト値が20のため、そのままデフォルト値を使うと同日のデータが生まれてしまうので、終了-開始の日付をセットしています。


## 最後に
『アイカツオンパレード！』は
**テレビ東京系 毎週土曜日 午前10時30分～
BSテレ東毎週月曜日夕方5時～**
から好評放送中です！



また、分析結果についてははてなブログ上でやっているので、興味あれば併せてみてもらえればと思います。

[投票総数816票から見る「アイカツ！」シリーズの人気キャラクターとは](https://snofra.hatenablog.com/entry/2019/11/01/160000)

[投票総数1036票から「アイカツ！」シリーズの人気エピソードトップ30をチェックしよう](https://snofra.hatenablog.com/entry/2019/11/09/110000)
php 配列 キーを任意の値にしたい

```php

    $assignedUsersList = $this->repository->getList()->unique('assigned_user_id');
    $assignedUsersName = [];
    foreach ($assignedUsersList as $assignedUser) {
        $assignedUsersName[$assignedUser['assigned_user_id']]<-ここ = $assignedUser->assigned_user->name;
    }
//        dd($assignedUsersName);
    $comicTrialPager = $this->repository->getPager($requestParams);

```
Git操作まとめ 〜Gitのコミット履歴確認(git log)

この記事では、Ubuntu18.04LTSにインストールしたGit(version 2.17.1)を使用しています。

チームではもちろんですが、個人での使用であっても今までのコミット履歴を確認する必要が出てきます。
そうすることで、誰が、いつ、どんな意図でその作業をしたのを理解することができ、効果的に開発を進めていくことができるようになります。

## 履歴確認

履歴を確認するには、以下のコマンドを使用します。

```shell
git log
```

実際に使ってみます。

```shell
git log

commit 76d180faf45d1da99905f225830a07f7b9c31603 (HEAD -> master)
Author: xxxxxx <xxxxxxxx@gmail.com>
Date:   Tue Nov 12 08:30:47 2019 +0900

    initial commit
```

このように表示されます。
1行目・・・commit コミットナンバー
2行目・・・Author コミットした人の名前とメールアドレス
3行目・・・Date コミットした日付
4行目・・・コミットコメント

この形式で、新しいコミットが前のコミットの上に表示されます。

---

## 履歴の簡易表示

git logで履歴を見ると、初めのうちはコミット数も少なくコミットの詳細を見ることができるため便利ではありますが、場合によっては「もっと簡略化したものでいいから、履歴をザッと確認したい」というときも出てきます。
そういうときは、onelineオプションをつけることで、コミットごとに1行表示で履歴を見ることができます。

```shell
git log --oneline
76d180f (HEAD -> master) initial commit
```
---

### 本記事目次ページ
[Git操作まとめ](https://qiita.com/tsweblabo/items/6aec9d022c08954f5024)
AWS CloudSearch の Suggester を JSON で設定する

AWS CLI で CloudSearch の Suggester を設定しようとして、少し迷ったため、備忘録として置いておきます。

## ファイルの設置

設定したいパラメータを入れた json を適当な場所に設置しておきます。

- name.json

```json
{
  "SuggesterName": "name",
  "DocumentSuggesterOptions": {
    "SourceField": "name",
    "FuzzyMatching": "low"
  }
}
```

## 実行

置いた Json を指定して　command line で実行する。

```sh
$ aws cloudsearch define-suggester --domain-name $domain --cli-input-json file://$file
```

# 複数設定する場合

```sh
#!/bin/sh

domain=$1
json_files_path="../config"

if [ -z $domain ]; then
    echo "usage: mkfield <domain> <mode>"
    echo ""
    echo "domain: `aws cloudsearch list-domain-names`"
    echo ""
    exit -1
fi

for file in `\find $json_files_path -name '*.json' | sort`; do
    echo ""
    echo "############################"
    echo "run... aws cloudsearch define-suggester --domain-name $domain --cli-input-json file://$file"
    aws cloudsearch define-suggester --domain-name $domain --cli-input-json file://$file
done

exit 0
done
```
tomcatのインストール

# javaのインストール

openjdkで動いたのでこれで。

```
yum install java-1.8.0-openjdk-devel
java -version
#openjdk version "1.8.0_212"
#OpenJDK Runtime Environment (build 1.8.0_212-b04)
#OpenJDK 64-Bit Server VM (build 25.212-b04, mixed mode)
```

# tomcatのインストール

```
pwd
#/root
wget http://ftp.riken.jp/net/apache/tomcat/tomcat-8/v8.5.41/bin/apache-tomcat-8.5.41.tar.gz
tar zxvf apache-tomcat-8.5.41.tar.gz
mv apache-tomcat-8.5.41/ /usr/local/tomcat
rm apache-tomcat-8.5.41.tar.gz

#自動起動設定
vi /etc/systemd/system/tomcat.service
===
[Unit]
Description=Apache Tomcat 8
After=syslog.target network.target

[Service]
User=tomcat
Group=tomcat
Type=oneshot
PIDFile=/usr/local/tomcat/tomcat.pid
RemainAfterExit=yes

ExecStart=/usr/local/tomcat/bin/startup.sh
ExecStop=/usr/local/tomcat/bin/shutdown.sh
ExecReStart=/usr/local/tomcat/bin/shutdown.sh;/usr/local/tomcat/bin/startup.sh

[Install]
WantedBy=multi-user.target
===
chmod 755 /etc/systemd/system/tomcat.service
#user作成（ログインなし）
useradd -s /sbin/nologin tomcat
chown -R tomcat:tomcat /usr/local/tomcat
echo 'export CATALINA_HOME=/usr/local/tomcat'  >  /etc/profile.d/tomcat.sh
source /etc/profile.d/tomcat.sh

systemctl start tomcat
systemctl enable tomcat
```

# apacheの設定

```
adduser example
passwd example
su - example
chmod 701 .
mkdir public_html
exit

vi /etc/httpd/conf.d/vhosts.conf
<VirtualHost *:80>
    ServerName example.com
    DocumentRoot /home/example/public_html
    ProxyPass /.well-known/ !
    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/
    ProxyPassReverseCookiePath / /
</VirtualHost>

vi /etc/httpd/conf.d/vhosts-ssl.conf
<VirtualHost *:443>
    ServerName example.com
    DocumentRoot /home/example/public_html
    ProxyPass /.well-known/ !
    ProxyPass / ajp://localhost:8009/
    ProxyPassReverse / ajp://localhost:8009/
    ProxyPassReverseCookiePath / /
    SSLEngine on
    SSLProtocol +TLSv1 +TLSv1.1 +TLSv1.2
    SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!EXP:!LOW:!MEDIUM
    SSLCertificateFile /etc/letsencrypt/live/example.com/cert.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
    SSLCertificateChainFile /etc/letsencrypt/live/example.com/chain.pem
</VirtualHost>

apachectl configtest
systemctl reload httpd
```

表示されるか確認する。

# プロジェクトインストール

```
pwd
#/usr/local/tomcat/webapps/

#デフォルトのファイルを移動
mkdir backup
mv ROOT/ backup/
mv docs/ backup/
mv examples/ backup/
mv host-manager/ backup/
mv manager/ backup/

#ROOT.warファイルの場合、ここに置くと自動で展開される

# springフレームワークの場合
vi /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/application-pro.properties
#DBの設定など

#再起動で反映
systemctl restart tomcat
```

# プロジェクトの修正

・application-pro.properties
・templates/にあるviewファイル
は、変更後再起動で反映される。

ロジック的な部分はビルドが必要。

# ログの場所

```
# rootが必要
/usr/local/tomcat/logs/
```
Rails データ内容の制限

# データの内容を制限する
<h5>NOT NULL制約</h5>
すでに作成してあるhogeテーブルのnameカラムにNOT NULL制約をつける場合。

```:ターミナル
$ rails g migration ChangeHogesNameNotNull
Running via Spring preloader in process 6959
      invoke  active_record
      create    db/migrate/xxxxxxxxxxx_change_hoges_name_not_null.rb
```
マイグレーションファイルが生成されたらそのファイルの中身を編集する。

```ruby:db/migrate/xxxxxxxxxxx_change_hoges_name_not_null.rb
class ChangeHogesNameNotNull < ActiveRecord::Migration[5.2]
  def change
    change_column_null :hoges, :name, false
  end
end
```
編集したら、マイグレーションファイルをデータベースに適用する。

```:ターミナル
$ rails db:migrate
```
これで、データベースにおいて、hogesテーブルのnameカラムにNULLを入れることができなくなった。
しかし、今の状態だと、""のような空文字を保存できてしまう。この対応の仕方は、hoge.rbの方でバリデーションを記述すれば良い。記述方法は割愛。
#### NOT NULL制約を加えることでどうなるかRailsコンソールで確認する
```:ターミナル
$ rails c
Running via Spring preloader in process 7167
Loading development environment (Rails 5.2.3)
>> Hoge.new(name: nil).save
   (0.3ms)  BEGIN
  Hoge Create (27.2ms)  INSERT INTO "hoges" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"  [["created_at", "2019-11-12 05:35:19.735447"], ["updated_at", "2019-11-12 05:35:19.735447"]]
   (0.2ms)  ROLLBACK
Traceback (most recent call last):
        1: from (irb):1
ActiveRecord::NotNullViolation (PG::NotNullViolation: ERROR:  null value in column "name" violates not-null constraint)
DETAIL:  Failing row contains (7, null, null, 2019-11-12 05:35:19.735447, 2019-11-12 05:35:19.735447).
: INSERT INTO "hoges" ("created_at", "updated_at") VALUES ($1, $2) RETURNING "id"
>> 
```
ActiveRecord::NotNullViolationという例外が発生し、登録に失敗していることがわかる。
Ubuntuのデスクトップ壁紙をシェルから変更

# Gsettingsを使ってデスクトップ壁紙を変更
何かのきっかけでスクリプトから壁紙を変更したくなることもあるかと。

##  背景色を黒く
```
gsettings set org.gnome.desktop.background primary-color 000000
```

##  背景ビットマップ指定パスをを消す（デフォルト背景に変わる）
```
gsettings set org.gnome.desktop.background picture-uri none         
```

##  背景色表示に切り替える（上記の結果、「黒く」なる）
```
gsettings set org.gnome.desktop.background picture-options 'none'   
```

##  背景ビットマップ指定パスを設定（まだ背景は表示されない）
```
gsettings set org.gnome.desktop.background picture-uri "file:///home/ubuntu/new_wall_paper.png"         
```

#  背景ビットマップ表示モードを設定（ここで初めて背景が表示される）
```
gsettings set org.gnome.desktop.background picture-options 'scaled' 
```
Railsのコントローラ名とモデル名の書き方について【初心者】

少し気になっていたので以下のコマンドについて整理してみました。

- rails g controller コントローラ名
- rails g model　モデル名

##コントローラ名は複数形
例) rails g controller **tests**

##モデル名は単数形
例) rails g model **test**

####**※それぞれの名前のイニシャルは大文字でも小文字でも結果は変わりません。**

例) rails g controller **tests**　と　rails g controller **Tests**　の結果は同じです。
例) rails g model **test**　と rails g model **Test**　の結果は同じです。
S&P500構成銘柄の株価のデータをyahoo financeから取得し、相関の高いペアを見つける。


#記事概要
「株Aが上がると、株Bも上がる」「株Aが下がると、株Bも下がる」というような現象を「連れ高」、「連れ安」と言います。天才トレーダーのBNFさんは株式の売買にこれを利用して大儲けしたそうです。
自分も真似をして大儲け！と思ったのですが、連動するペアを見つける方法って調べてもいいものがでてこない。
そこで、Pythonで実装してみたので、コードとその説明を公開します。

#コード
Githubに置いています。ご自由にどうぞ
https://github.com/toshiikuoo/puclic/blob/master/%E6%A0%AA%E4%BE%A1%E7%9B%B8%E9%96%A2.ipynb

#動作
動作の流れは次のようになります

[wikipediaのS＆P500のページ](https://en.wikipedia.org/wiki/List_of_S%26P_500_companies)から銘柄一覧の情報を取得
↓
取得した銘柄一覧の株価をyahoo financeから取得
↓
全ての銘柄の組み合わせのペアについて株価の相関を算出　※相関：二つのデータがどれだけ似ているかを数値化したもの
↓
相関が大きい順にペアを並び替え

#コードの説明
上のコードを抜粋しながら説明します。

* 必要なライブラリのインポート

```python

# 必要なライブラリimport
!pip install lxml html5lib beautifulsoup4

import pandas as pd
from pandas import Series,DataFrame
from pandas_datareader import DataReader

import numpy as np

from datetime import datetime

from scipy.stats.stats import pearsonr
import itertools

# Install yfinance package.

!pip install yfinance
 
# Import yfinance
import yfinance as yf  

```
* wikipediaのS＆P500のページから銘柄一覧の情報を取得。銘柄のlistを作成。

```python
# S&P全銘柄のリストを作成
url="https://en.wikipedia.org/wiki/List_of_S%26P_500_companies"
sp500_list=pd.read_html(url)[0].Symbol.values.tolist()
len(sp500_list)
```

* yahoo financeから銘柄のlistの株価を取得。

```python
# sp500銘柄の終値を１つのDataFrameに格納
close_sp500_list=yf.download(sp500_list_yahoo,'2019-10-04','2019-11-01')["Adj Close"]
```
* 取得した株価から相関を算出

```python
# 列ごとのペアで相関を算出

# 算出した相関を入れるための辞書型作成
correlations={}

# 相関を算出
for cola,colb in itertools.combinations(sp500_list_yahoo,2):
  nas=np.logical_or(np.isnan(close_sp500_list.loc[:,cola]),np.isnan(close_sp500_list.loc[:,colb]))
  try:
    correlations[cola + '__'+ colb]=pearsonr(close_sp500_list.loc[:,cola][~nas],close_sp500_list.loc[:,colb][~nas])
  except ValueError:
    pass    

# 出力された結果"correlations"はリスト形式なのでDataFrameに変換
result=DataFrame.from_dict(correlations,orient='index')
result.columns=['PCC','p-value']
print(result.sort_values('PCC'))
```
# 結果
最終的な出力は以下。各銘柄ペアの相関がソートされて出力されている。

```
           PCC       p-value
BKR__SPGI   -0.968878  1.437804e-03
BIIB__HAS   -0.962712  8.038530e-13
BKR__PGR    -0.959178  2.465597e-03
PGR__WCG    -0.941347  6.818268e-11
CI__PGR     -0.935051  1.840799e-10
...               ...           ...
CNC__WCG     0.996087  1.493074e-22
BKR__PRGO    0.997290  1.101006e-05
CBS__VIAB    0.998546  7.579099e-27
BBT__STI     0.998835  8.266321e-28
GOOGL__GOOG  0.999502  1.701271e-31

[127260 rows x 2 columns]
```

# 今後のアクション
出力結果を使って相関の高い銘柄群のグループ化をしたい。
（質問・改善点など気軽に連絡ください。初投稿なのでおかしなとこあると思います。Github難しい。。。）
AWS Text to Speech

#AWS喋らせよう!(~~備忘録~~ 貧乏録)
```
#!/usr/local/bin/python3.6
# AWS
from boto3 import Session
from botocore.exceptions import BotoCoreError, ClientError
from contextlib import closing
import os,sys,subprocess

session = Session(region_name="us-west-2")
polly = session.client("polly")
ttsdt=[
    ('Ivy'   ,"Thank you for calling. I'm sorry but I can't answer your call right now. Please leave a message at  the tone . I'll get back to you as soon as possible."),
    ('Joey'  ,"Thank you for calling. I'm sorry but I can't answer your call right now. Please leave a message at  the tone . I'll get back to you as soon as possible."),
    ('Mizuki',"お電話ありがとうございます。ただいま、電話に出ることができません。ピーッという音が鳴りましたら[発信音の後に]、メッセージをお願いします。こちらからすぐにお電話いたします。"),
    ('Takumi',"お電話ありがとうございます。ただいま、電話に出ることができません。ピーッという音が鳴りましたら[発信音の後に]、メッセージをお願いします。こちらからすぐにお電話いたします。")
]
for id,tx in ttsdt:
    print(tx)
    try:
        response = polly.synthesize_speech(Text=tx, OutputFormat="mp3", VoiceId=id)
    except (BotoCoreError, ClientError) as error:
        print(error)
        sys.exit(-1)
    if "AudioStream" in response:
        with closing(response["AudioStream"]) as stream:
            output = id+".mp3"
            try:
                with open(output, "wb") as file:
                    file.write(stream.read())
            except IOError as error:
                print(error)
                sys.exit(-1)
            print("synthesize_speech OK ->>" + output)
            subprocess.Popen(['mpg123', '-q',output ]).wait()
    else:
        print("Could not stream audio")
        sys.exit(-1)

```
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">AWSサンプル　TTS <a href="https://t.co/OTwYQ9mY5D">pic.twitter.com/OTwYQ9mY5D</a></p>&mdash; utaca.rich (@RichUtaka) <a href="https://twitter.com/RichUtaka/status/1127095422688776192?ref_src=twsrc%5Etfw">May 11, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
最新の記事n番目までを取得する

<?php query_posts('showposts=n'); ?>

```php
<?php 
query_posts('showposts=n');
if (have_posts()) : 
while (have_posts()) : 
the_post();
?>
<li><a href="<?php the_permalink() ?>"><?php the_title(); ?></a></li>
<?php
endwhile;
endif;
?>
```

```php
<?php
//showpostsを4にすれば最新4番目まで 
query_posts('showposts=4');
?>
```
検索サイトを作ったのでまとめてみた１

■目次
・始めに
・サイト構成
・DB構成
・テーブル内容
・及第点

■始めに
Jsp・サーブレットを学習し、何か作ろうと思ったのでスポーツジムの検索サイトを作ってみた。
現在のスポーツジム検索サイトは欲しい情報に行き着くまでのフローが長いため、できるだけ簡単に欲しい情報に行き着くことを意識して構築しました。さらに、登録関係をサイトだけで完結できる作りにしてみました。
サイトURL
http://fit-gym-search.net/pro_seller/

■サイト構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/dbd75f19-02b0-b8bd-70f6-8b072f39a523.png)

簡単な図ですがこのような感じになってます。

■DB構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/198113c3-399e-58a2-4e61-bca7371ba389.png)

■テーブル内容
・city
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/16108f96-8668-6d25-fda2-fbc91a79d158.png)
・general_administrator
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/fa53f767-c6d4-08dc-25c5-97667b92f526.png)
・gym
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/ae72e9e2-49c0-b87a-abc8-cfbb545b64f0.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/29e33843-5cbd-1aa0-8c94-bcdf32125890.png)
・gym_master_user
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/87df394d-f5db-3b66-5431-9fad33cff56d.png)
・info
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/7f141700-072f-89de-fa4f-8bf4752bb8e0.png)
・line
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/aef74657-aeeb-6afd-97de-e1258f9fd16d.png)
・master_info
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/32a17c2f-d48f-2ab5-8778-fecf3b64743a.png)
・prefecture
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/a8633083-0600-97c0-e63b-67fe27384727.png)
・query
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/2d003c3c-4bed-95f4-ea77-d2720ee6c655.png)
・station
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/521889/417df7d8-6e3c-7a44-70ef-755683e9e88c.png)
■及第点
DBのテーブル設計の正規化が甘く、gymテーブルのカラムが多くなってしまった。
この他にもまだまだあると思うので良ければ教えてください！

次回以降はプログラム作成中に詰まったところを書いていきたいと思います。
WEBフロントエンドで使う「いつもの」メモ

## はじめに

よく使うツールやページ、アプリやらが増えてきたので、整理も兼ねての備忘録。

## Chrome Extension
メインブラウザはChromeを使っているので、拡張機能をいくつか。

- [PerfectPixel by WellDoneCode (pixel perfect) ](https://chrome.google.com/webstore/detail/perfectpixel-by-welldonec/dkaagdgjmgdmbnecmcefdhjekcoceebi)  
  ページの上に画像を乗せて表示できる。デザインチェックに。
- [The QR Code Extension](https://chrome.google.com/webstore/detail/the-qr-code-extension/oijdcdmnjjgnnhgljmhkjlablaejfeeb)  
  表示しているページのQRを生成。実機チェックに。
- [Alt & Meta viewer](https://chrome.google.com/webstore/detail/alt-meta-viewer/jjcjblcbnjhgjlnclhficglfjedhpjhl)  
  Alt/Metaのチェックに。
- [ウェブページ全体をスクリーンショット - FireShot](https://chrome.google.com/webstore/detail/take-webpage-screenshots/mcbpblocgmgfnpjjppndjkmgjaogfceg)  
  ページのスクリーンショットに。
- [Pasty](https://chrome.google.com/webstore/detail/pasty/hdjihnnclpjhfdbbinmgoiehhoehhlgf)  
  スプレッドシート等からコピーした複数のURLを全て別のタブで表示できる。
- [Page Ruler](https://chrome.google.com/webstore/detail/page-ruler/emliamioobfffbgcfdchabfibonehkme)  
  ページ内をドラッグして大きさを測れる。定規がわりに。

## WEBページ

- [TinyPNG](https://tinypng.com/)  
  画像の圧縮に。パンダ。
- [W3C Markup Validation Service](https://validator.w3.org/)  
  HTMLのvaridation。
- [Placehold.jp](http://placehold.jp/)  
  ダミー画像の生成に
- [CSS LINT](http://csslint.net/)  
  CSSのlint。

## アプリケーション

- [station](https://getstation.com/)  
  WEBアプリの一括管理に。
- [Sourcetree](https://www.sourcetreeapp.com/)  
  Git GUIクライアント。見やすくてわかりやすい。
- [coteditor](https://coteditor.com/)  
  メインエディタとは別で開く用。Windows31Jも確認できる。
- [Pngyu](https://nukesaq88.github.io/Pngyu/ja.html)  
  png縮小用。
- FileMerge  
  差分確認に。

## まとめ

なるべくツールをうまく使って手間をかけないように進めたいですね。  
おすすめとかあればコメント歓迎です。
rake routesの見方で誤解したこと【初心者】

Railsでルーティングの情報を詳しく見るときに、ターミナルでよく使用するコマンドが「rake routes」。

Railを学習し始めの頃にこのrake routesの見方で誤解してしまった点があったので、他に誤解する人が出ない為にも記録しておきます。

#Prefixが空欄なワケ
<img width="441" alt="スクリーンショット_2019-10-26_13_52_40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305648/9109e62e-3e3a-0c87-750d-227169953452.png">


上記はroutes.rbで resources :books と記載してrake routesコマンドを実行したときに表示される情報です。このときのPrefixに注目してください。

Verb(HTTPメソッドのこと)がGET以外のものについてはPrefixの欄が<b>空欄</b>になっています。自分は最初にこれを見たときにGET以外のPrefixは存在しないのだと思いましたが、実はこれは<b>`空欄の上のPrefixと同じなので省略されているだけ`</b>なのです。

つまり仮に上記のrake routesのPrefixを省略せずに記述したとすると、以下の通りになります。

<img width="441" alt="スクリーンショット_2019-10-26_13_52_40 2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/305648/0598d9a7-d6fc-46e7-1070-313cc4f96c7e.png">

全てを表示するよりも省略している方が見やすいということですね。
強化学習５　CartPoleをプログラミングしてみる？

強化学習４までが終了していることが前提になります。

簡単なプログラミングをしてみます。


```CartPole2.py
import gym
env = gym.make('CartPole-v0')
for i in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        action = 0
        if observation[2]>0:
            action = 1
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode{} finished after {} timesteps".format(i, t+1))
            break
env.close()
```

CartPole.pyはランダムに動いていました。
CartPole.pyとの違いは、observationの違いで、actionを変えているいことです。feedback制御になります。
padding によるレイアウトの崩れ

# 問題点

要素の幅を100%に設定している時に、その要素に`padding`を設定してしまうと、要素の幅の合計が100%を超えてしまいレイアウトが崩れてしまう。

# 改善策

```css
* {
  box-sizing: border-box;
}
```
全ての要素に対して`box-sizing: border-box;`を適用し、要素の幅の合計(width)に`padding`,`border`を含めるようにすることでレイアウトの崩れを防ぎ、この問題を解決することができる。
【Ruby】7桁の整数で保存した郵便番号にハイフン（-）を入れる方法

`1234567`のように、DBに7桁の整数で郵便番号を保存。
一方、ビューでは`123-4567`のようにハイフンを入れて表示したい場合。

以下のように記述すればOKです。

```rb
1234567.to_s.insert(3, "-")
```
`to_s`で整数を文字列に変換。
`insert(3, "-")`で3文字目の後にハイフンを挿入しています。


参考になった記事
https://qiita.com/_kkoichi/items/f8758a438b2363943922
クリックしたときに別タブで開くように設定する方法

htmlで、aタグの中にhrefと合わせて「target="_blank"」を追記。

```html:例
<a href="リンク先のURL" target="_blank">ここをクリックすると別タブで開きます</a>
```
これでクリックすることで別タブにを開いてジャンプするようになります。

また、aタグの中にimgタグを入れることで、画像をクリックして別タブで開くように設定することもできます。

```html:例
<a href="リンク先のURL" target="_blank"><img scr="画像ファイル">
</a>
```
※画像ファイルは絶対参照(http://testdirectory/test.png)
でも相対参照(test/ping)でもどちらでもOK。
M5Stick-CでGROVEユニット番外編

# M5Stick-CのGROVEポートに汎用の[BME280](https://www.bosch-sensortec.com/bst/products/all_products/bme280)(I2C接続)を繋いでみる
M5Stick-CにはENV HATもあるしGROVE用のENV UNITも使えるのでわざわざ生でBME280を繋ぐ意味は無いのですが、会社での社員研修でHATやUNITの中身を理解させる意味もあってBME280が載ったモジュールをGROVEポートへと接続してみました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148717/9e992129-8301-7e96-119f-84107f7cddfc.jpeg" width="40%">

BME280は3.3V駆動でM5tick-CのGROVEポートは5V駆動なので今回は5V<->3.3Vのレベルコンバーターが載ったボードをAliExpressから購入してこれを使用しました。
さすが大陸の通販サイトだけあってデータシートとかは明示されていなかったのですが、製品的には[ここに詳細が書かれている物](https://lastminuteengineers.com/bme280-arduino-tutorial/)と同等品のようです。
[GROVE用のコネクタが付いたヘッダーピン用ケーブル](https://www.switch-science.com/catalog/1048/)はスイッチサイエンスから購入しましたが、このケーブルM5Stick-CのケーブルとSCL、SDAの配線の色が入れ替わっているので要注意でした。 （調べていないけど、この辺りってGROVEで規定されていないのかな？)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148717/5e5b9fe8-b3d1-a87d-b909-ffca77672fa2.jpeg" width="40%"> <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148717/8d1bb1d4-360b-2009-93d2-82cbdb883bcd.jpeg" width="40%">
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148717/5cca67ed-b008-53ed-5154-ae090ea30ad4.jpeg" width="40%">

ケーブルの結線自体は基板上のVINにM5Stick-CのVOUTを、GNDにはGを、SDAをG32に、SCLをG33へと繋ぐだけなので簡単です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148717/80bd16a7-c802-93be-cf8a-33802d7300bb.jpeg" width="40%">

スケッチもM5Stick-Cのサンプルスケッチの「ENV」でインクルードするセンサー用のライブラリを `Adafruit_BMP280.h` から `Adafruit_BME280.h` へと変更し、センサーライブラリのインスタンスを生成する部分も同様にクラスを `Adafruit_BMP280` から `Adafruit_BME280` へと変更するだけです。
あとは不要なDHT12に関する処理をコメントアウトし、元々のENV UNITではDHT12から取得していた温度と湿度の情報をBME280から取得するように修正します。

```diff:スケッチの変更点
@@ -3,13 +3,13 @@
 */

 #include <M5StickC.h>
-#include "DHT12.h"
+//#include "DHT12.h"
 #include <Wire.h> //The DHT12 uses I2C comunication.
 #include "Adafruit_Sensor.h"
-#include <Adafruit_BMP280.h>
+#include <Adafruit_BME280.h>

-DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.
-Adafruit_BMP280 bme;
+//DHT12 dht12; //Preset scale CELSIUS and ID 0x5c.
+Adafruit_BME280 bme;

 void setup() {
     M5.begin();
@@ -27,8 +27,8 @@

 void loop() {

-    float tmp = dht12.readTemperature();
-    float hum = dht12.readHumidity();
+    float tmp = bme.readTemperature();
+    float hum = bme.readHumidity();
     float pressure = bme.readPressure();
     Serial.printf("Temperatura: %2.2f*C  Humedad: %0.2f%%  Pressure: %0.2fPa\r\n", tmp, hum, pressure);
```
Sphinxのドキュメントビルド時に、特定の拡張をスキップしたかった

## 前提

自分は自作の`sphinx-revealjs`をもとに、SphinxでReveal.jsのスライドを書いている人です。

## Sphinxで拡張を使うまで

Sphinx + Revealjsの組み合わせでスライドのソースを書いてると、こういうシーンがあります。

```reStructuredText:presentation.rst
Ansibleの動き(中身)
-------------------

.. 60sec

.. todo:: 上記デモのPlaybook

インベントリファイル

* 処理実行先のサーバー一覧や簡単な情報を定義
```

ここで使われる`todo`ディレクティブは、Sphinx内でtodoをとして表示できるようにするもので、
「この後書くこと」や「書いておきたかったこと」などをメモるするのに便利です。

で、ビルトインの拡張でないため、sphinxでのビルド時に用いる`conf.py`には拡張として指定してあげる必要があるのですが、、、

```py3:conf.py
extensions = [
    'sphinx.ext.todo',
    'sphinx_revealjs',
]
```

## カスタムのビルダーでビルドすると、失敗してしまう

実行すると、このようなエラーが出てビルドに失敗してしまいます。

```bash
$ pipenv run make revealjs
例外が発生しました
  File "/home/attakei/.local/share/virtualenvs/slides-P9x2JL-m/lib/python3.7/site-packages/sphinx/writers/html5.py", line 885, in unknown_visit
    raise NotImplementedError('Unknown node: ' + node.__class__.__name__)
NotImplementedError: Unknown node: todo_node
```

はて、きちんとSphinx拡張が登録されているはずなのにこんなエラーが出てしまう。
ビルダーを`html`に設定したみると正常にビルドが完了するらしい。ということは、自作の方のrevealjsビルダーに原因がありそう

### エラーを追跡...はまた今度

※そのうち、自分のライブラリを直します

## `conf.py`の側から拡張の呼出を分割する

ライブラリ修正は色々大変な匂いがするので、ひとまず`conf.py`を弄って

**「ビルダーに`revealjs`を指定した場合は、`sphinx.ext.todo`を拡張に登録しない」**

をゴールにします。

```python:conf.py
extensions = [
    'sphinx_revealjs',
]

if is_not_builder_revealjs:
    extensions += [
       'sphinx.ext.todo',
    ]
```

こんな感じ

### `conf.py`の時点でビルダーを雑に確定する（限定条件下

Sphinxはmakeベースでのビルドを推奨しているのですが、

```
%: Makefile
	@$(SPHINXBUILD) -b $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
```

こんなふうに、`sphinx-build`コマンドを通すようになっています。
そして、ありがたいことにコマンドのもとである`sphinx.cmd.build`モジュールは、引数パーサーを関数で別途生成した上でコマンドライン上で使うようです。

https://github.com/sphinx-doc/sphinx/blob/master/sphinx/cmd/build.py#L97

ざっくり見る感じ、そのまま活かせそうなので、`conf.py`に突っ込んでみます。

```python:conf.py
import sys
from sphinx.cmd.build import get_parser


sphinx_args = get_parser().parse_args(sys.argv[1:])

extensions = [
    'sphinx_revealjs',
]

if sphinx_args.builder != 'revealjs':
    extensions += [
        'sphinx.ext.todo',
    ]
```

こうなりました。ビルドすると、、、

```bash
$ pipenv run make revealjs



静的ファイルをコピー中... ... 完了
copying extra files... 完了
dumping search index in Japanese (code: ja)... 完了
dumping object inventory... 完了
build 成功, 3 warnings.
```

無事成功しました:+1:
Reactで画像の遅延ロードするためのコンポーネント

ReactでHooksとIntersection Observer API使って、プレースホルダー付きで画像の遅延読み込みするコンポーネントをだいぶ前に作った時のメモ。

```js
使い方
<LazyImage src="https://your-image-url" />
```

```js
import React, { useState, useRef, useEffect } from 'react'
import PropTypes from 'prop-types'
import styled from 'styled-components'
require('intersection-observer') // intersection-observer api polyfill

const Img = styled.img`
  transition: all 1s ease-in-out;

  @keyframes placeHolder {
    0% {
      background-position: -468px 0;
    }
    100% {
      background-position: 468px 0;
    }
  }

  ${props => props.imageLoaded
    || props.noPlaceholder
    || `
    animation-name: placeHolder;
    animation-duration: 1.5s;
    animation-fill-mode: forwards;
    animation-iteration-count: infinite;
    animation-timing-function: linear;
    background: #f6f7f8;
    background: linear-gradient(to right, #eeeeee 8%, #dfdfdf 20%, #eeeeee 33%);
    background-size: 800px 104px;
    filter: blur(5px);
    position: relative;
  `}
`

function LazyImage({ src, ...props }) {
  const imageRef = useRef()
  const [imageLoaded, setImageLoaded] = useState(false)

  let observer

  useEffect(() => {
    observer = new IntersectionObserver(startLoading, { rootMargin: '50px' })
    if (!imageLoaded) {
      observer.observe(imageRef.current)
    }
    return () => observer.unobserve(imageRef.current)
  }, [])

  function startLoading(entries, object) {
    entries.forEach((entry) => {
      if (!entry.isIntersecting) return

      if (entry.intersectionRatio > 0) {
        observer.unobserve(entry.target)
      }

      if (!imageLoaded) {
        const downloadingImage = new Image()
        downloadingImage.onload = () => {
          if (imageRef.current) {
            imageRef.current.setAttribute('src', downloadingImage.src)
            setImageLoaded(true)
          }
        }

        downloadingImage.src = src
        object.unobserve(entry.target)
      }

      object.unobserve(entry.target)
    })
  }

  return (
    <Img
      {...props}
      alt="GOOD BOYE"
      ref={imageRef}
      imageLoaded={imageLoaded}
    />
  )
}

LazyImage.propTypes = {
  src: PropTypes.string,
  noPlaceholder: PropTypes.bool,
}

LazyImage.defaultProps = {
  src: '',
  noPlaceholder: false,
}

export default LazyImage
```
強化学習４　CartPole　はじめの一歩

早速、CartPoleを動かしてみましょう。

```CartPole.py
import gym
env = gym.make('CartPole-v0')
for i_episode in range(20):
    observation = env.reset()
    for t in range(100):
        env.render()
        action = env.action_space.sample()
        observation, reward, done, info = env.step(action)
        if done:
            print("Episode finished after {} timesteps".format(t+1))
            break
env.close()
```

```bash
python ./CartPole.py
```

動いたらOK。
CartPoleは基本のようで、多くの解説があるので、解説は無視。
Flutterでキーボードを出すとレイアウトが変わってしまう現象修正

#結論
ScaffoldのresizeToAvoidBottomInsetプロパティをfalseにすると直る

#現象
まず、こういう構造の画面を作った
・ScaffoldのbodyにStackを配置
・GoogleMapの上にTextFieldとRaisedButton等を置いている。
![default.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154354/6116262d-f001-0ced-308b-d4c42ef51653.png)

さて、問題の現象だがTextFieldをタップした際、
キーボードの上昇に合わせて表示領域が変わってしまった。
画面下部のRaisedButtonが分かりやすいと思う。
GoogleMapもリビルドが走って微妙に表示が変わっている。
![wtf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154354/6724b5f6-018a-2e08-01e1-51b619034f2a.png)

こういう仕様もありだとは思うが、自分はそうしたくない。
レイアウトを崩さずに何とかする方法はないか、という点で結論に行き当たった。
デフォルトだと true らしいので false にするとこうなる。
![ok.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154354/47a3f590-0a2c-baee-f9eb-7da0a768d385.png)

##補記
別解としては、SingleChildScrollViewを使う手法もあるらしい。
今回のパターンで言えば
Scaffold>SingleChildScrollView>Stack　という入れ子にする感じか。
キーボード入力中に画面をスクロール操作したい時は、こっちでも良さそう
SQL 置き換え カウント


①既存の「やまだクリエイティブ・エージェンシー」・「やまだクリエイティブエージェンシー」の件数を確認

```
SELECT COUNT(*) FROM artist_profile WHERE genre="owarai" AND profile LIKE "%やまだクリエイティブ%";
```
②アップデートをかける(アップデート件数の合計値が①のカウント数と一致することを確認)

```
UPDATE artist_profile SET profile=REPLACE(profile,"やまだクリエイティブ・エージェンシー","田中エージェンシー") WHERE genre="owarai" AND profile LIKE "%やまだクリエイティブ・エージェンシー%";

UPDATE artist_profile SET profile=REPLACE(profile,"やまだクリエイティブエージェンシー","田中エージェンシー") WHERE genre="owarai" AND profile LIKE "%やまだクリエイティブエージェンシー%";
```
③再度①を流し、0件になっていることを確認

```
SELECT COUNT(*) FROM artist_profile WHERE genre="owarai" AND profile LIKE "%やまだクリエイティブ%";
```
ただ、この場合、profileの所属での記載以外に「やまだクリエイティブエージェンシー」が記載されていても変更してしまうので、条件を、"%所属：やまだクリエイティブエージェンシー%"に？
オブジェクト指向という幻惑

# オブジェクトしこうは　マヌーサを　となえた！

## はじめに
この記事は、オブジェクト指向と言う幻惑に包まれた人に届けたい記事となります。
オブジェクト指向やってるぜ！と言う勇者に読んでほしい記事です。

## オブジェクト指向の幻惑１
**Javaやってるからオブジェクト使ってます！**

・・・

そんな訳はありません。

Javaもマルチパラグイムを採用しており、以下のスタイルでコーディング可能です。
- オブジェクト指向
- 手続き型
- 関数型

Java=オブジェクト指向となってしまってる原因は
Javaを広げるためのマーケティング用語として**オブジェクト指向**というワードを使ってしまったから。
オブジェクト指向を正しく理解しない人を増やした犯人はJava自体だったわけです。

## オブジェクト指向の幻惑２
**データクラス作って、ロジッククラスを作って、役割毎にちゃんとクラスわけしてます**
**俺、オブジェクト指向やってるぜ！**

・・・

それは手続き型です。

これは従来の開発スタイルが
機能毎に担当を別けて、機能毎に開発を行う、**機能分割式**のスタイルが多いために
手続き型と親和性が高く利用されるようになったと考えられます。

# コロスケは　マヌーハを　となえた！

## オブジェクト指向とは簡単に言うと、次の通りです

**データクラスとロジッククラスを同じクラスに実装する**

これが本来、オブジェクト指向が目指す「変更容易性」です。

## 具体的に「変更容易性」とは何なのか

**オブジェクト指向**
Aクラス（ロジック＋データ）
Bクラス（ロジック＋データ）

**手続き型**
データクラスα
データクラスαを使うAクラス（ロジック）
データクラスαを使うBクラス（ロジック）

この場合、データクラスに修正が入った場合、
同じデータクラスを使い回す手続き型では
Aクラス、Bクラスともに改修・テストの必要が出てきます。

オブジェクト指向の場合、Aクラスの方に修正が入っても
Bクラスは揺らぎません。

これがオブジェクト指向の真髄です。

## ここまで読んでオブジェクト指向を利用してると言える人がいるでしょうか？ ##

ここまで読んでオブジェクト指向に興味を持ったか方は以下
[オブジェクト指向をきちんと使いたいあなたへ (Software Design別冊)](https://www.amazon.co.jp/dp/4774179817)
【初心者】JavaScript　配列を操作するメソッド(push,forEach,find,filter,map)【備忘録１４】

##11/10～11/11に勉強したこと
###push
既にある配列の最後に新しい要素を追加するメソッド。
【例】

```js

const numbers = [1,2,3];
console.log(numbers);

numbers.push(4);
console.log(numbers);

```

【出力】
[1,2,3]
[1,2,3,4]

【！】
numbers.push(4)を書く際に「=」を付けないように気を付ける！

###forEach
配列の要素１つずつ取り出し、全要素に繰り返し同じ処理を行うメソッド。
【例】

```js

const numbers=[1,2,3];
numbers.forEach((number)=>{
  console.log(number);
)};

```

【出力】
1
2
3

【！】
-　{console.log...}の箇所で改行をすることで見やすくなるので癖づける。
-　forEachの後の()の中のことをコールバック関数と呼ぶ。
-　一番最後の「;」を忘れやすいので、()や{}を書いたときに先に「;」を書く。

###find
コールバック関数に記した条件に合う＜１つ目の要素＞を取り出す。
【例１】

```js

const numbers=[1,3,5,7];
const foundNumber=numbers.find((number)=>{
    return number > 4 ;
});

```

【出力】
5 （１つ目のみなので7は出力されない）

【例２】

```js

const animals=[
 {id:1,name:"犬"},
 {id:2,name:"猫"}
];

const foundAnimal=animals.find((animal)=>{
   return animal.id ===1;
});

console.log(foundAnimal);

```

【出力】
{id:1,name:"犬"}　（オブジェクトそのものが出力される）

【！】
-　animals.findの「.」を忘れやすいので気を付ける！
-　return　の後を「animal」だけにしてしまわない！「animal.id」or「animal.name」
-　条件式の語尾に「;」の付け忘れがあったので気を付ける！

###filter
findの全要素ver.　（記した条件に合う要素すべてを取り出す）
【例】

```js

const numbers=[1,2,3,4,5];
const filteredNumbers=numbers.filter((number)=>{
  return number % 2 === 0;
});

console.log(filteredNumbers);

```
【出力】
[2,4]

###map
配列内のすべての要素に処理⇒その戻り値から新しい配列を作る。
【例１】

```js

const numbers=[1,2,3];
const doubledNumbers = numbers.map((number)=>{
  return number * 2;
});

console.log(doubledNumbers);

```

【出力】
[2,4,6]

【例２】

```js

const names=[
 {firstName="Misa",lastName="Yamada"},
 {firstName="Hana",lastName="Tanaka"}
];

const fullNames=names.map((name)=>{
  return name.firstName + name.lastName ;
});

console.log(fullNames);

```

【出力】
[Misa Yamada,Hana Tanaka]

【！】
returnの後の「name.firstName」を「names.firstName」と何度か
してしまったのでコールバック関数の引数でしっかり書くよう気を付ける。

##振り返り・今後について
まだJavaScriptの章が一つ残っていますが、今までしてきたことが
すべて覚えきれているかとても不安です。
できるだけリセットして復習をしたり、ここで出力したり
別ノートでまとめを見直したりはしていますが
もし他に何か良い復習法があれば教えてほしいです。

一人で勉強しているので、めげないように此処に書き記して
行くのが当面の目標です。毎日時間を作って今後も頑張ります！
jsbookで本文が片側に寄る問題の解決方法

ドキュメントクラス「jsbook」で文書を作成すると、片側の余白が大きくなって文章が片側に寄ってしまうことがあります。TeXは米国規格のレターボックスサイズ（A4サイズより小さい）向けにチューニングされており、1行の長さが全角40文字を超えないようにしているそうです。紙の幅が全角40文字以上ある場合、本文の幅は強制的に1行40文字となり、本文は左右どちらかに寄せられてしまいます

↓こんな感じ
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531808/51ed6a5c-756d-5e4c-998e-5b7d2371c489.png)

これを避けるためには、 \begindocument の前に

```latex
\setlength{\textwidth}{\fullwidth}	%本文の幅(textwidth)を全体の幅(=ヘッダ部の幅)にそろえる
\setlength{\evensidemargin}{\oddsidemargin}	%偶数ページの余白と奇数ページの余白をそろえる
```

と入れれば、1行40文字の制限が取っ払われて左右に極端に寄ることがなくなります

↓こんな感じ
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531808/c95ff6df-ba7a-accb-3106-7ac2d302adfc.png)

ただ、このようにすると1行の文字数が増えてレイアウトが大きく変わってしまうことが想定されます。1行の文字数を維持しながら左右に寄るのを防ぐためには \begindocument の前に

```latex
\addtolength{\fullwidth}{-26truemm}	%全体の幅(ヘッダ部の幅)を既定値から26mm小さくする
\setlength{\textwidth}{\fullwidth}	%本文の幅(textwidth)を全体の幅(=ヘッダ部の幅)にそろえる
\setlength{\evensidemargin}{10truemm}	%偶数ページの左余白を10mm(+1インチ)にする
\setlength{\oddsidemargin}{10truemm}	%奇数ページの左余白を10mm(+1インチ)にする
```

と入れると、1行の文字数を40文字程度に保ちながら左右に偏るのを防ぐことができます。（細かい数値調整は要検討）

↓こんな感じ
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531808/956c8d0b-43a4-9090-5931-0c57bdb6958c.png)

ホチキス止めする側の余白を広めにとりたい場合は、偶数ページの左余白を小さく、奇数ページの左余白を大きくすれば良いので

```latex
\addtolength{\fullwidth}{-26truemm}	%全体の幅(ヘッダ部の幅)を既定値から26mm小さくする
\setlength{\textwidth}{\fullwidth}	%本文の幅(textwidth)を全体の幅(=ヘッダ部の幅)にそろえる
\setlength{\evensidemargin}{1truemm}	%偶数ページの左余白を1mm(+1インチ)にする
\setlength{\oddsidemargin}{19truemm}	%奇数ページの左余白を19mm(+1インチ)にする
```

みたいにすれば良いと思います

↓こんな感じ
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531808/f2eee764-0d97-df74-bc8c-576578e98181.png)
Azure App Service の Tomcat で Javaのヒープサイズを変更する

#前提
Azure WebApp のサーバータイプはWindows

#操作

1. Azure Webコンソール上で App Service を開く
2. Development Toolsのうち「Advanced Tools」を開く（Kudu）
3. Debug Consoleから「CMD」を開く（単なるコマンドラインではなくGUI的にも使える）
4. デフォルトで「D:\home」が開いている状態なので「D:\home\site\wwwroot」を開く（マウス操作でも可能）
5. [wwwroot]の右側にある「＋」をクリックして「New File」を選択する
6. 「web.config」というファイルを作成して以下のようにする。「%AZURE_TOMCAT90%」はTOMCATのバージョンによって異なるので確認する。（SETコマンドで環境変数一覧が表示されるのでそこで確認できる）
7. アプリを再起動する

```xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
        <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
    </handlers>
    <httpPlatform processPath="%AZURE_TOMCAT90_HOME%\bin\startup.bat" arguments="">
      <environmentVariables>
        <environmentVariable name="JAVA_OPTS" value="-Xmx1500m -Xms1024m -Djava.net.preferIPv4Stack=true" />
      </environmentVariables>
    </httpPlatform>
  </system.webServer>
</configuration>
```

以上。
三項演算子の説明と三項演算子の例題

今回は**JavaScript**で使われてる**三項演算子の説明**と、**HTML上で入力した数字が奇数か偶数かを判断するページ**を作ってみます。

#三項演算子とは？
**「？」と「:」を組見合わせ**て、**if~else文のような処理を簡略化**したものです。

#書き方
```JavaScript
条件式？式1：式2
```

# ページの制作
JavaScriptをHTMLに繋げる方法を知ってる前提で説明します。

### JavaScriptのソース
```JavaScript
function checkEven() {
  var v = document.getElementById("number").value;
  var r = document.getElementById("result");
  if(v.length == 0) {
    r.textContent = "何かの入力値が必要です";
  } else if(isNaN(v)){
    r.textContent = v + "は数字ではありません";
  } else {
    r.textContent = (v%2==0) ? "偶数です":"奇数です";
  }   
}
```

### HTMLのソース

```html
<h1>奇数か偶数かを判断します。</h1>
<input id="number" />
<button onclick="checkEven()">入力判定</button>
<p id="result"></p>
```

> 引用 : [Dripcoke](https://dripcoke.com/)

>> [初めてのJavascript-(8)-制御式](https://dripcoke.com/%e5%88%9d%e3%82%81%e3%81%a6%e3%81%aejavascript-8-%e5%88%b6%e5%be%a1%e5%bc%8f%e5%ae%8c/)
情報技術者試験の勉強計画　第4週（11/11週）

## 目標と結果
### 目標
・FE73まで終了する
・過去問道場の分野別でシステム開発技術まで終了する
### 結果
・FE66まで終えた。
・過去問道場セキュリティまで終えた。
・目標達成には至らなかったが、テキストではシステム開発に手を付けているので第5週で計画に追いつけると思う。
## 振り返り
### keep
・過去問道場を電車の中や大学の講義の休憩時間で解く。
・試験勉強のためにバイトを控えめにする。
・少独習ゼミのボタンを押す習慣がついてきた。
### problem
・目標達成に至らなかったこと。
・家で勉強しないこと。
### try
・いつも図書館に行ってしまうので、家でも集中力が続くようにやってみる。
SSHのCA認証

# 参考URL

OpenSSHの認証に証明書を使う方法
https://support.conoha.jp/v/openssh/

SSH CA認証まとめ
https://kontany.net/blog/?p=211

OpenSSH の 証明書認証
https://qiita.com/Hexa/items/79897f7df5ad59bb5ca1

SSH-KEYGEN (1)
https://euske.github.io/openssh-jman/ssh-keygen.html

# できること

- 鍵の有効期間の設定
- 接続元IPの制限
- 発行した証明書の失効

# 手順

## CA用のキーペア作成

```
$ ssh-keygen -f ca.key
```

## 証明書を発行

- CAの秘密鍵
- クライアントの公開鍵

が必要

```
$ ssh-keygen -s ./ca.key -I "ca test" -n "test" -z 1 -V +1d -O source-address=123.123.123.123 ./client/client.key.pub
```

- -V
    - 有効期限
- -z
    - 指定したシリアルNoは証明書を失効させるときに使用する。デフォルトの0だと失効できない。
- -O
    - オプション。source-address=123.123.123.123でIPを制限できる。他にも色々あるようだ。

## 証明書の内容確認

```
$ ssh-keygen -L -f ./client/client.key-cert.pub

client/client.key-cert.pub:
        Type: ssh-rsa-cert-v01@openssh.com user certificate
        Public key: RSA-CERT SHA256:Sr7h0w3I+FP7QghNRETs8W5TdygzZ57bH4sgSQkqsDQ
        Signing CA: RSA SHA256:JCpHzCX91c53T+iddH5tQFa8ihgVSTl+5IUJfx43P1Y
        Key ID: "ca test"
        Serial: 1
        Valid: from 2019-09-28T14:53:00 to 2019-09-29T14:54:31
        Principals:
                test
        Critical Options:
                source-address 123.123.123.123
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc
```

## サーバの設定

- CAの公開鍵を置く。
- 許可するPrincipalsをファイルに書く。複数ある場合は改行する。

```
$ vi /etc/ssh/sshd_config
# 下記を追加
TrustedUserCAKeys /etc/ssh/ca.key.pub
AuthorizedPrincipalsFile /etc/ssh/authorizedprincipals

# チェック
$ sshd -t

# 再起動
$ systemctl restart sshd
```

## 使用方法

- 証明書はクライアントの鍵と同じところに置く

```
$ ssh -i ./client/client.key test@192.168.0.1
```

## 証明書の失効

```
$ vi list.txt
serial:1
serial:2
↑
0は指定できない

# KRL を更新する場合は -u を付ける
$ ssh-keygen -k -f krl -s ca.key.pub list.txt

$ vi /etc/ssh/sshd_config
# 下記を追加
RevokedKeys /etc/ssh/krl

$ systemctl restart sshd
```
UE4、それっぽく明滅してくれるライト

なぜ昨日の[記事](https://qiita.com/lo2_/items/62a59cf0630b0de6b265)みたいなFloatで困っていたかというと
これを作るためである。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">それっぽく明滅するライトできた <a href="https://t.co/M9s1sfW1m4">pic.twitter.com/M9s1sfW1m4</a></p>&mdash; 赤井ろにー🦇🌻 (@lo2_) <a href="https://twitter.com/lo2_/status/1194116115141554176?ref_src=twsrc%5Etfw">November 12, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ちなみに困ってたのはこの部分
![明滅ライト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531299/5f9cd919-893a-6dd0-d199-24f0ccd19ead.png)
PointLightとLamp（Mesh）の明滅が同期してくれなくて、なんでー？　となっていたがお察しのとおりである。
Ruby 配列、範囲オブジェクトについて

配列での範囲オブジェクトの使い方についてさらっと解説します。
配列zに対して1.2.3.4.5の要素を入れたい場合

```ruby
z = [1,2,3,4,5]

puts z
1
2
3 
4
5
```
とすると思います。
しかし、範囲オブジェクトを使えば

```ruby
z = (1..5)to_a

puts z
1
2
3 
4
5
```
わざわざ全ての数字を記入しなくても範囲を指定してあげるだけで済みます。
【学習ノート】AWS SAA取得に向けて(ストレージ、EBS)

# ストレージサービス

## 概要

- 大きく4つのストレージサービスが提供されている
    1. EBS(Elastic Block Store)
    1. EFS(Elastic File System)
    1. S3
    1. Glacier
- オンプレからクラウドへデータ移行するためのゲートウェイ(StrageGateway)も提供される
- 他にも移行を支援するサービスとしてSnowballがある
    - Snowballはペタバイト以上のサイズがあるデータを移動するためのサービス
    - ハードウェアアプライアンスとデータ転送用のクライアントツールが提供される
        - 詳細は[こちら](https://aws.amazon.com/jp/snowball/)。　まとめは割愛
- ストレージサービスは3種類に分割される
    - ブロックストレージ
        - データをブロック単位で管理する
        - 頻繁に更新がかかり、高速なアクセスが求められる場合に利用する
            - データベース、仮想サーバのイメージなど
        - AWSの該当するサービスはEBS
    - ファイルストレージ
        - データをファイル単位で管理する
        - 複数のクライアントからネットワーク経由でのファイル共有などで利用する
        - AWSの該当するサービスはEFS
    - オブジェクトストレージ
        - データに任意のメタデータを追加したオブジェクトとして管理する
        - 更新頻度が低いデータ、大容量のマルチメディアコンテンツの保存などに利用する
            - 作成済みデータに対するHTTP(s)経由の登録・削除・参照といった操作が可能
        - AWSの該当するサービスはS3、Glacier

|-|ブロックストレージ|ファイルストレージ|オブジェクトストレージ|
|:-:|:--|:--|:--|
|管理単位|ブロック|ファイル|オブジェクト|
|データライフサイクル|追加/更新/削除|追加/更新/削除|追加/削除|
|プロトコル|SATA,SCSI、FC|cifs、nfs|http(s)|
|メタデータ|固定情報のみ|固定情報のみ|変更可能|
|ユースケース|データベース、トランザクションログ|ファイル共有、データアーカーブ|マルチメディアコンテンツ、データアーカイブ|

## EBS(Elastic Block Store)

### 特徴

- AWSの提供するブロックストレージ
- 主な利用用途
    - EC2のOS領域
    - EC2の追加ボリュームとして割り当て
    - RDSのデータ保存
- EC2にアタッチして利用する
    - 注意点
        - AZ毎に作成するため、対象のEC2と同AZ内に作成する必要がある
        - 複数のEC2へ同時にアタッチすることはできない
        - 作成したAZと異なるAZで利用したい場合、スナップショットを作成して復元するなどの対応が必要

### ボリュームタイプ

EBSではSSD2種類、HDD2種類の計4種類からボリュームタイプを選択することができる
それぞれに特徴がありコストにもはねるので、適切なボリュームタイプの選択が必要
プロビジョンドIOSP SSD以外には、ストレージ容量に応じてバースト機能が用意されているが、
***バースト機能は1時的な性能増加のため、バースト機能を前提とした設計を行ってはいけない***

- 汎用SSD(gp2)
    - EC2インスタンス作成時のデフォルトボリュームタイプ
    - 性能指標はIOPS(秒あたりに処理できるI/Oアクセス数)
    - 1TB未満のボリュームには1時的にIOPSを増加させるバースト機能が用意されている
        - 最大で1時的には3,000IOPSまで性能を向上させることが可能
- プロビジョンドIOSP SSD(io1)
    - EBSの中で最も高性能なSSDをベースにしたボリュームタイプ
    - 汎用SSDのIOPSでは処理が間に合わない場合に利用を検討する
    - 最大で64,000IOPSまで容量に応じたベースライン性能がある
- スループット最適化HDD(st1)
    - スループット重視のHDD
        - ユースケース
            - ログデータの処理や、バッチ処理のインプットファイルを読み取るなど
    - 性能指標はスループット
        - 最大スループットは500MB/秒のベースライン性能がある
- ColdHDD(sc1)
    - 4種類の中ではもっとも性能が低いHDD
    - その代わりにもっとも低コスト
        - ユースケース
            - アクセス頻度が低く、高速アクセスを求められないアーカイブ領域など
    - 最大スループットは250MB/秒のベースライン性能がある
- マグネティックHDD
    - 古いタイプのHDD
    - 必然性がなければ選択肢には入らない

### EBSの拡張・変更

#### 共通

- EBSの設定は6時間に1回しかできない
- EC2にアタッチされているEBSを変更する場合、一度デタッチが必要となる可能性がある

#### 容量の増加

- 何度でも可能
- 但し、縮小はできない
    - 一時的に増加して後で戻すといった運用はできない

    
#### ボリュームタイプの変更

- 現行4世代のボリューム間で変更が可能
- プロビジョンドIOPS値は増減のどちらも変更可能
    - 反映までに最大で24時間かかる
    - 変更中はステータスが「modifying」となる

### 可用性・耐久性

- SLAは月当たりの利用可能時間の99.99%
- EBSはスナップショットが利用可能
    - 定期的にバックアップを行えばスナップショットから復元可能
- 復元時の手順
    - スナップショットから新規EBSを作成
    - EC2インスタンスにあたっちする

### セキュリティ
- EBSにはストレージの暗号化機能がある
- 但し、作成後に暗号化することはできない
    - その場合は以下のようにEBSを再作成する必要がある
        - 既存のEBSのスナップショットを作成
        - スナップショットから復元
        - 復元したEBSを暗号化
        - 暗号化したEBSをEC2インスタンスへアタッチ
    - ブートボリュームの場合は以下の手順で暗号化が可能
        - AMIを取得する
        - AMIコピー時に暗号化
        - コピーしたAMIからEC2インスタンスを作成

参考図書:AWS認定資格試験テキスト　AWS認定ソリューションアーキテクト[アソシエイト]