OmniAICreator/Qiita-1.07M huggingface dataset:
PandasTools.LoadSDFで読み込んだときROMolに画像が表示されないのを一旦解決

- jupyter-notebookを使っている
- RDKitで複数化合物が含まれるSDFデータをPandasTools.LoadSDFで読み込んだときROMolに画像が表示されないのをなんとかした
- 自分の環境は下記
    - MacOSX 10.15.2 Catalina
    - 下記を参考にしてAnacondaでRDKit環境を構築した
        - [インストールの仕方 — RDKit_unofficial_translation_JP 1.00 ドキュメント](https://magattaca.github.io/RDKit_unofficial_translation_JP/Installation_jp.html#linux-and-os-x)
    - anaconda3-5.3.1のPython 3.7.5を利用
    - rdkit version:  2019.09.2 
    - pandas version:  0.25.3




下記サイトを参考にRDKitを練習してた

[RDKitでケモインフォマティクスに入門 | 化学の新しいカタチ](https://future-chem.com/rdkit-intro/)



[複数分子の読み込み](https://future-chem.com/rdkit-intro/#i)のところでSDFファイルをpandasのDataFrame形式で読み込んだあと表示させてみたところ、ROMolのところに画像が表示されず `<img data-content="rdkit/molecule" src="data:i...` みたいなカラムになっていた (下記画像)


<img width="1132" alt="Screen Shot 2020-02-05 at 18.35.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44492/51bfb7ad-ccae-19d6-3e3f-b4a7e7546bb9.png">

下記issueによると、どうやら、pandas 0.25.0 より上のバージョンだと起こってるっぽい

[Mol rendering within DataFrames in a Jupyter Notebook is broken with Pandas 0.25.1 · Issue #2673 · rdkit/rdkit](https://github.com/rdkit/rdkit/issues/2673)



たしかに、自分の場合pandasのバージョンは0.25.3だった

```python
import pandas as pd
print('pandas version: ', pd.__version__)
#=> pandas version:  0.25.3
```

解決策としては pandasのバージョンを0.25.0まで戻すかも考えられたが
めんどかったので他に方法が無いか探した

画像で表示されたほうが便利な部分もあるのでissueたどったり検索してみたりすると
HTMLのライブラリ使うようにってのがあったので

https://github.com/rdkit/rdkit/issues/2673#issuecomment-570898398

[Molecules not rendered in Pandas DF in Jupyter Lab · Issue #2825 · rdkit/rdkit](https://github.com/rdkit/rdkit/issues/2825)

下記のようにやってみたらできた(sdfファイルはダウンロード済み、ライブラリはimport済みとする)


```python
df = PandasTools.LoadSDF('./sdf/somesdffile.sdf')

from IPython.display import HTML
HTML(df.to_html())
```

<img width="1143" alt="Screen Shot 2020-02-06 at 8.56.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44492/aecfd033-a5d2-8499-8ee0-92edb370064c.png">

画像がちゃんと出てきたら成功

ひとまず、画像があったほうがわかりやすいときはこうやればちゃんと出てくる
Leetcode: Swap Nodes In Pairs

```ruby

require 'minitest/autorun'
require 'pry'
class SwapNodesInPairs < Minitest::Test

  def test_run
    list = ListNode.new(1)
    list.next = ListNode.new(2)
    list.next.next = ListNode.new(3)
    list.next.next.next = ListNode.new(4)
    new_list = swap_pairs(list)
    assert_equal(2, new_list.val)
    assert_equal(1, new_list.next.val)
    assert_equal(4, new_list.next.next.val)
    assert_equal(3, new_list.next.next.next.val)


    list = ListNode.new(1)
    new_list = swap_pairs(list)
    assert_equal(1, new_list.val)
  end

  def swap_pairs(head)
    return if head.nil?
    return head if head.next.nil?
    head_val = head.val
    next_head_val = head.next.val
    head.val = next_head_val
    head.next.val = head_val
    swap_pairs(head.next.next)
    head

  end

end

class ListNode
  attr_accessor :val, :next

  def initialize(val)
    @val = val
    @next = nil
  end

end
Leetcode: Reverse String

```ruby

require 'minitest/autorun'
require 'pry'
class ReverseString < Minitest::Test

  def test_run
    input = ["h", "e", "l", "l", "o"]
    output = ["o", "l", "l", "e", "h"]

    assert_equal(output,
                 reverse_string(input))
  end

  def reverse_string(s, index = 0)
    return s if index == s.size / 2

    first_char = s[index]
    last_char = s[s.size - 1 - index]
    s[index] = last_char
    s[s.size - 1 - index] = first_char
    index += 1
    reverse_string(s, index)
    s
  end

end
AWS Solution Architect Professional合格レポート


昨日AWS Solution Architect Professionalを受験し、無事合格できましたのでまとめておきます。

合格とは言っても、点数は合格ギリギリなので参考程度に見て下さい。

先日AWS Certified DevOps Engineer - Professionalも一応合格していて、同じくレポート書いてます。

[⇛AWS DevOps Professional合格レポート](https://qiita.com/jusotech10/items/f315d90ceac282b93f53)

## 資格取得状況


| 資格 | 取得日 
| -------- | -------- |
| AWS Certified Solutions Architect - Associate (SAA)     | 2019-03-01     |
| AWS Certified Developer - Associate (DVA) | 2019-08-29 |
| AWS Certified SysOps Administrator - Associate (SOA) | 2019-09-28 |
| AWS Certified DevOps Engineer - Professional (DOP)| 2020-01-18 |
| AWS Certified Solution Architect Professional (SAP)| 2020-02-05 |

ようやく５冠…！前回のDevOpsから20日程度での受験となってます。
AWS勉強して約1年で取得することができました。


## 学習方法

* Advanced Architecting on AWS
* 公式E-ラーニング
* 模擬試験
* Blackbelt
* ユーザーガイド
* Udemy問題集


### Advanced Architecting on AWS
会社で枠が残っていたので受験の１週間前に受講。
業務で触ったことがあるサービス以外については浅く広く学習する良い機会でした。

ただこれだけで合格するのは難しいと思いますし、BlackBelt読む方がサービスに対しての理解が深まります。

とはいえディスカッションの時間と講師への質問できる環境だったため、とても有意義に過ごすことができました。


### [公式E-ラーニング](https://www.aws.training/Details/eLearning?id=42403)

こちらも学習の足がかりとしてはとても便利です。
ただDevOps Proとは違い、一番大事かと言われると優先度は少し下がるかもしれません。

### 模擬試験
結果は70%でこれまで受けた模擬試験で一番高かったです。ここで少し安心してしまったのが良くなかった…

もうPro受ける方々は承知だと思いますが、必ず試験中のスクリーンショットを撮って復習できるようにしておきましょう。

### Blackbelt

私は以下のサービスを中心に読みました。
正直これでも足りなかったかなと思っています。DevOps Proを受けた後だったので、Code系やCloudWatch、Systems Manager等のサービスは特に勉強していません。

API GatewayやLambdaは読むの忘れてましたが、Dynamoと合わせて出題されることが多いのでカバー必須です。

太字は強いて言えば重要だと思うサービスです。

* **AWS Organizations**
* AWS Shield
* AWS WAF 
* AWS CloudHSM
* Amazon Cognito
* **AWS Certificate Manager**
* **Amazon Kinesis**
* Amazon Redshift
* **Amazon Route 53**
* **Amazon CloudFront**
* AWS Database Migration Service
* **Amazon DynamoDB**
* AWS Storage Gateway
* Amazon S3

### ユーザーガイド

模擬試験や問題集でわからない部分を確認するために使用していました。

### Udemy問題集
前回のDevOpsと同じ人の問題集が良かったのですが、まだ出ていないようだったので、評価が高めのこちらをセールで購入しました。

[AWS Certified Solutions Architect Professional Practice Exam](https://www.udemy.com/course/aws-solutions-architect-professional-practice-exams-amazon/)

75×4回分が入っているのですが、時間がなく２回分しか解けませんでした。
多分ですが、しっかり４回分解いて復習していれば、合格ラインは超えられるように作られていると思います。

ただとにかく文章量が多く２回でも辛かったです。

## 感想
* とにかく範囲が広く、AWS最高難度と言われているだけあります。受験中は自信を持って回答できない問題が多く正直落ちたと思いました。

* 私自身がDNSや暗号化、認証の知識に疎く、ACMやRoute53、CognitoやAD絡みの問題に非常に苦労しました。この辺はAWSというより一般的なIT知識として勉強しなければならない部分なので、これから受験される方は基礎から勉強してもいいかもしれません。

* DDoS関連のサービスは全く出題されなくて少し凹みました。

* 噂には聞いていましたが、問題の誤訳が多くてびっくりしました。笑っちゃうような誤訳なら許せますが、言っている意味がわからない問題がいくつかあり、足りない英語力で解き直す必要があったのが辛かったです。


## まとめ

とにかく難しいので十分に勉強時間をとってから挑みましょう。受験料も高いので。

以下の流れで、特に6を頑張れば合格に近づくはずです。

1. E-ラーニングを見る
2. 模擬試験を受ける
3. 模擬試験の復習
4. Udemy問題集を解く
5. 解けなかった問題の復習
6. 4と5を全問できるまで繰り返す

参考になれば幸いです。
画像ファイルの拡張子を付け直す

## これなに

大量の絵文字ファイルをDLしてカテゴリーの整理をしようと思ったら・・・
なんと、拡張子がついてなかった😱😱😱

`file`コマンドでファイルのMIME typeを判別できるので、
それを利用してとりあえず拡張子を付けようと思って作ってみた

## コード

```bash:ext.sh
#!/bin/bash

DIRECTORY=$(dirname $1)
FILENAME=$(basename $1)

pushd $DIRECTORY > /dev/null
if [ -f $FILENAME ]; then
  INPUT="$FILENAME"
  OUTPUT=$(basename ${INPUT} | awk -F. '{ print $1 }').$(file --mime-type -b ${INPUT} | awk -F/ '{ print $2 }')
  if [ $INPUT != $OUTPUT ]; then
    echo RENAME $DIRECTORY/$INPUT TO $DIRECTORY/$OUTPUT
    mv $INPUT $OUTPUT
  else
    echo $DIRECTORY/$FILENAME
  fi
elif [ -d $FILENAME ]; then
  echo ENTER DIRECTORY $FILENAME
  for f in $FILENAME/*; do
    $0 $f
  done
  echo LEAVE DIRECTORY $FILENAME
fi
popd > /dev/null
```

### 結果
```terminal
（前略）
blob/meowgiggle.png
blob/meowhuggies.png
blob/meowovo.png
blob/meowpats.png
blob/pikablob.png
blob/thinking_blob.png
blob/thinkingwithblobs.png
blob/yayblob.png
LEAVE DIRECTORY blob
ENTER DIRECTORY Blobs
RENAME Blobs/blobboo TO Blobs/blobboo.png
RENAME Blobs/sblob TO Blobs/sblob.png
RENAME Blobs/sblob_0w0 TO Blobs/sblob_0w0.png
RENAME Blobs/sblob_3c TO Blobs/sblob_3c.png
RENAME Blobs/sblob_amused TO Blobs/sblob_amused.png
RENAME Blobs/sblob_angel TO Blobs/sblob_angel.png
RENAME Blobs/sblob_angry TO Blobs/sblob_angry.png
RENAME Blobs/sblob_artist TO Blobs/sblob_artist.png
（後略）
```

ちゃんと動いた
めでたしめでたし
docker compose run とdocker compose execの違い ( #docker )

# exec

- docker-compose up などで起動しているコンテナを利用する
- 起動中の docker コンテナがないと実行できない
- 同じコンテナに接続するのでコマンド履歴が残っている
- おおむね高速

```
docker-compose exec <service_name> bash
```


# run

- コンテナを新しく作って実行する
- docker-compose up などで コンテナが起動していなくても利用できる
- 新しいコンテナに接続するのでコマンド履歴は残っていない
- おおむね低速
- docker コンテナ同士がうまく連携するように、依存関係を考慮して compose ファイルが書かれていないと、思わず動かない処理があったりするかもしれない


```
docker-compose run <service_name> bash
```



# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/2976








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
AWS学習　初期学習~ソリューションアーキテクト-アソシエイト試験までの学習メモ~

###まえがき　このページはAWSの学習用のメモです。

####学習の目的
・AWSの基礎学習
・AWS認定ソリューションアーキテクト-アソシエイト試験の合格
・ハンズオンでAWSの操作方法を学習


##AWSのサービス名

###・IAM(Identity and Access Management)
　AWSを利用するユーザーに対しAWSへのアクセスを安全に制御するための仕組み。
###[・EC2(Elastic Compute Cloud)](https://qiita.com/takuma-yoshida/items/2b2a1123d9ba551612a2)
　AWSが仮想サーバーを提供するサービスで必要な数の仮想サーバーを起動しネットワーク構成、ストレージ管理などが可能。
###・[VPC(Virtual Private Cloud)](https://qiita.com/takuma-yoshida/items/eb8a12e883d37397e2b8)
　仮想的なネットワークを構築しその範囲内に自由なネットワークを作ることができる
###[・S3(Simple Storage Service)](https://qiita.com/takuma-yoshida/items/2bb4e51900cb124efda5)
　高耐久でファイルや画像などをバックアップなど保存容量決める必要がなく、入れた分だけ課金される。
###・Route53
　DNS（ドメインネームサービス）と呼ばれるサービスで、ドメインからIPアドレスを参照するためサービス。
###・RDS(Relational Database Service)
　AWSのRDSはAWS側で提供されているデータベースを使うかEC2などに直接構築するなどいろいろな選択できる。パッチ適用やバックアップをAWS側で行ってくれるサービスなどもある。
##ハンズオン



##学習教材

著書
[・徹底攻略 AWS認定 ソリューションアーキテクト – アソシエイト教科書](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-AWS%E8%AA%8D%E5%AE%9A-%E3%82%BD%E3%83%AA%E3%83%A5%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%88-%E2%80%93-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88%E6%95%99%E7%A7%91%E6%9B%B8/dp/4295005495/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&keywords=AWS+%E9%BB%92%E6%9C%AC&qid=1581342988&sr=8-1)

動画学習「Udemy」
[・これだけでOK！ AWS 認定ソリューションアーキテクト – アソシエイト試験突破講座
（初心者向け22時間完全コース）](https://www.udemy.com/course/aws-associate/)

[・AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（5回分325問）]
(https://www.udemy.com/course/aws-knan/)

[・youtuber くろかわこうへい【渋谷で働くクラウドエンジニアTV】](https://www.youtube.com/channel/UCX30pfp4p82rIiSJmBygADw/videos)
最小限の手間でMac上にOACISを導入する方法

この記事ではMac上で最小限の手順で[OACIS](https://github.com/crest-cassia/oacis)の環境をセットアップする手順について説明します。

OACISは様々な環境で動作する様に汎用的に作られている一方で、Linuxの知識がないとセットアップが難しい部分もあります。ここではMac使い向けに「とにかくこの手順に従えばセットアップできる」という方法をお伝えします。
詳細が知りたくなったら[公式ドキュメント](http://crest-cassia.github.io/oacis/ja/)を参照してください。
ここでは2020年１月時点で最新のv3.7.0をインストールします。

手順は以下の通り。

1. Rubyをインストールする
1. MongoDBとRedisをインストールする
1. localhostに対してSSHログインできるように設定する
1. OACISのソースコードをダウンロードする
1. OACISを起動する
1. OACISにlocalhostを登録する

## Rubyをインストールする

rbenvを使ってインストールします。rbenv自体のインストール手順は[rbenvのreadme](https://github.com/rbenv/rbenv)参照してください。
rbenvをインストール後は、rubyをインストールします。

```
rbenv install 2.6.5 && rbenv global 2.6.5
gem update bundler
rbenv rehash
```

## MongoDBとRedisをインストールする

homebrewを使ってMongoDBをインストールします。
詳細は[MongoDBの公式ドキュメント](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-os-x/)を参照してください。

```
brew tap mongodb/brew
brew install mongodb-community@4.2
brew services start mongodb-community@4.2
```

同様にhomebrewを使ってRedisをインストールします。

```
brew install redis
brew services start redis
```

## localhostに対してSSHログインできるように設定する

「システム環境設定」-「共有」を開き、「リモートログイン」にチェックを入れます。
場合によっては「ファイアウォールによりブロック」と表示されているかもしれませんが問題ありません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28792/8f1323d4-dcd6-4236-0ff4-1304d9c46343.png)

続いてパスワード無しでログインできるように鍵認証の設定をします。

```
ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
```

これで自分自身の端末(localhost)にパスワード無しでログインできるようになります。
ここまでの設定がうまくいっていれば、以下のコマンドを実行してホームディレクトリのパスが表示されることを確認します。

```
ssh localhost pwd
```

## OACISのソースコードをダウンロードする

OACISのソースコードをダウンロードします。

```
git clone --recursive -b master https://github.com/crest-cassia/oacis.git
cd oacis
bundle install
```

また、[xsub](https://github.com/crest-cassia/xsub)というツールも同様にインストールします。

```
cd ~    # home directoryに移動
git clone https://github.com/crest-cassia/xsub.git
echo 'export PATH="$HOME/xsub/bin:$PATH"' >> ~/.bash_profile
echo 'export XSUB_TYPE="none"' >> ~/.bash_profile
```

## OACISを起動する

先ほどダウンロードしたOACISのディレクトリに移動して、OACISを起動します

```
cd ~/oacis
bundle exec rake daemon:restart
```

これで http://localhost:3000 にブラウザからアクセスすると、OACISのトップ画面が表示されます。

## OACISにlocalhostを登録する

OACISの画面からlocalhostをジョブの投入先として登録します。
画面上部の"Host"、"New Host"を選択し、以下の項目を入力します。

- Name : localhost

これで`localhost`というホストが登録され、ジョブの投入先として選べるようになります。

![image.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/28792/34763e96-9eaa-3540-3262-2e02230276e1.gif)
Rails Tutorialの知識から【ポートフォリオ】を作って勉強する話 #18.5 環境変数, Gmail送信設定編

# こんな人におすすめ
* プログラミング初心者でポートフォリオの作り方が分からない
* Rails Tutorialをやってみたが理解することが難しい

前回：[#18 EC2環境構築, Nginx+Puma+Capistrano編](https://qiita.com/aokyo17/items/281b5a1658ea58bc7b24)
次回：[#19 Docker編](https://qiita.com/aokyo17/items/370739ca8595db35b248)

# 今回の流れ

1. Railsの環境変数を設定する
2. 本番環境でのGmailの送信を設定する

# Railsの環境変数を設定する
Rails5.2以降の環境変数の設定には、credentials.yml.encを使います。
デフォルトで.gitignoreになり暗号化されているのでおすすめです。
以下のように設定します。

```shell:shell
EDITOR=vim rails credentials:edit
```

```yml:credentials.yml.enc
# aws:
#   access_key_id: XXXX
#   secret_access_key: XXXX

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: XXXX
```

おそらくこんな感じかと思うので、以下のように環境変数を追加します。

```yml:credentials.yml.enc
# 省略
a:
  b: bbb
  c: ccc
# 省略
```

以上で設定が終わりました。
試しにコンソールで値を引き出してみます。
値を引き出すには、以下のように行います。

```shell:shell
$ rails c
```

```rb:
> Rails.application.credentials.a[:b]
=> "bbb"
```

この後のGmailの送信の設定には、このcredentials.yml.encを使います。

# 本番環境でのGmailの送信を設定する
前提として本番環境には、EC2を使っています。
またActionMailerの生成はすでに行なっているものとします。
（お済みでない方は[#12](https://qiita.com/aokyo17/items/f916ba608319b3323b7a)などをご確認ください。）

それではGmailを送信の設定をします。
ここでの手順は以下の通りです。

* Googleアカウントのアプリパスワードを有効にする
* production.rbの設定を変更する
* 環境変数を設定する

## Googleアカウントのアプリパスワードを有効にする
お手持ちのGoogleアカウントのアプリパスワードを有効にします。
有効にするまでに、いくつかの手順を踏みます。

1. [googleアカウント](https://myaccount.google.com/intro?utm_source=OGB&tab=mk&utm_medium=act) → 画面左ダッシュボード『セキュリティ』 → Googleへのログイン『2段階認証プロセス』 → 有効にする
2. [googleアカウント](https://myaccount.google.com/intro?utm_source=OGB&tab=mk&utm_medium=act) → 画面左ダッシュボード『セキュリティ』 → Googleへのログイン『アプリパスワード』 → 16桁のパスワードをコピーする

これで次の手順に使うパスワードを手に入れました。

## production.rbの設定を変更する
Gmail用に設定を変更します。

```rb:config/environments/production.rb
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.default_url_options = { host: Rails.application.credentials.host_server[:ip] }
  ActionMailer::Base.smtp_settings = {
    :address        => 'smtp.gmail.com',
    :port           => '587',
    :authentication => :plain,
    :user_name      => Rails.application.credentials.gmail[:user_name],
    :password       => Rails.application.credentials.gmail[:password],
    :domain         => 'gmail.com',
    :enable_starttls_auto => true
  }
```

先ほど見かけた、環境変数を引き出す記述があります。
最後はこれが動作するよう、環境変数を設定します。

## 環境変数を設定する
環境変数の設定です。
送信に使うアドレスやアプリパスワードはここに記述します。

```yml:credentials.yml.enc
host_server:
  ip: XX.XX.XX.XX # EC2のIPアドレス

gmail:
  user_name: hogehoge@gmail.com # Gmailアドレス
  password: hogehoge # コピーしたアプリパスワード
```

これで送信の設定が完了しました。

参考になりました↓
[【Rails】メール送信設定 〜gmail利用〜](https://qiita.com/ozackiee/items/f260f34db4e5c887460d)

---
前回：[#18 EC2環境構築, Nginx+Puma+Capistrano編](https://qiita.com/aokyo17/items/281b5a1658ea58bc7b24)
次回：[#19 Docker編](https://qiita.com/aokyo17/items/370739ca8595db35b248)
Thoughtbotのコードレビューガイド[和訳]

# はじめに

こちらの記事は[ThoughtbotのCode Review](https://github.com/thoughtbot/guides/tree/master/code-review)を和訳したものです。
すでにRyo Yonemataさんが和訳された素敵な記事([コードレビューの心構え](https://yulii.github.io/how-to-code-review-20150422.html))もありますのでそちらと合わせて読んでいただけるとより補完されるかと思います。

# コードレビューガイド

こちらはコードをレビューし、 レビューしてもらう際のガイドです。

# コードレビューをし、されるみなさんに

- 多くのプログラミングに関する解決案は意見として受け入れよう。トレードオフやどちらの書き方が好みかなどを議論し、より素早く解決に導こう。
- 良い提案をしよう。要求はしないこと。（`:user_id`とかの命名だとどう？）
- 良い提案であれば作者は様々な判断や想定をしなくてよくなります。
- 明確にするための質問をしよう。（ちょっとよくわからなかったから説明してもらえる？）
- だれのコードか言及するのはやめよう。（俺の、俺のじゃない、お前の）
- 個人を攻撃するような言葉を使うのはやめよう。（クソが、アホ）みんな知性的で友好的であろう。
- 明確に書こう。オンラインでは意図が他人に明確に伝わるわけではないということを肝に命じておこう。
- 誇張表現はやめよう。（常に、絶対ない、永遠に、全くない）
- 皮肉はやめよう。
- 自己を保とう。絵文字やgifはそういう気分じゃなかったら無理やり使う必要はないです。逆にそういう気分なら自信を持って使おう。
- 「よくわかりません」や「代替案：」などのコメントが大量についている場合はリアルタイムで話し合いましょう（チャットや画面共有、対面で）。議論をまとめたコメントを後から確認できるように投稿しておこう。

# コードレビューしてもらう時に

- レビュアーが提案してくれたら感謝しよう。（名案だね。その修正を取り込むよ。）
- 「レビューはコードに対するものであなたに対するものではありません。個人として捉えるのはやめましょう。」を共通認識として持っておこう、というのを以前は入れていました。ですが今は「[オンラインで感情を伝えるのはとても難しく](https://www.fastcompany.com/3036748/why-its-so-hard-to-detect-emotion-in-emails-and-texts)、フィードバックはいとも簡単に誤解されるということを心に留めておきましょう」と言うようにしています。もしレビューが攻撃的であったり、怒気を孕んでいたり、個人に言及するように見えたなら一度その意図があるかを考えたのち、できれば対面で、その人に明確な意図を尋ねよう。
- 上のことを心に留めたうえで、レビュアーは善意からコメントしてくれたのだと捉えよう。
- コードの意図を伝えよう。（これこれの理由でこういう修正をしました。クラス/ファイル/メソッド/変数名を変えた方がわかりやすいですか？）
- いくつかの修正やリファクタリングは別途抽出して先のチケットやストーリーに追加しよう。
- チケットやストーリーとコードレビューは紐付けよう。（訳注：リンク切れだったのでURLは貼りません）
- 前のフィードバックのコミットは別のブランチを切ってプッシュしよう。マージ可能な状態になるまでまとめてはいけません。レビュアーが以前のフィードバックに対する個別の更新として読めるようにするべきです。
- レビュアーの意図をなるべく汲み取ろう。
- 全部のコメントに返信するようにしよう。
- CI（TDDium、Travis CI、CircleCIなど）が通るまではマージするのを待とう。
- コードとプロジェクトに与える影響に自信が持てたならマージしよう。
- 最終的に修正するかどうかはプルリクの作者次第だ。

# コードをレビューする時に

まずなぜその修正が必要なのか理解しよう。（バグフィックス、ユーザー体験の向上、既存コードのリファクタリング）その上で：

- 良いと思うアイディアもそうでもないと思ったアイディアも伝えよう。
- 課題を解決しつつ、コードをシンプルにできる方法を見つけよう。
- もし議論があまりに哲学的であったり学術的になってしまったら、金曜午後の技術部定例ミーティングに場所を移そう。その間に作者に代替案に関して最終的な決定をしてもらおう。
- 別の実装を提案する際は、作者もその案をすでに考慮したあとかもしれないと考えておこう。（ここでカスタムバリデータを使うのどう？）
- 作者の意図をなるべく汲み取ろう。
- プルリクには:thumbsup:や「マージしてOK」などと署名しよう。
- 自分はゲートキーパーではなくフィードバックをするためにいるということを忘れないで。

# コーディングスタイルに対するコメント

- レビュアーは[スタイル](https://github.com/thoughtbot/guides/tree/master/style)ガイドラインに沿っていない箇所を指摘することがあるでしょう。例えば：

`> Resourcefulルーティングはアルファベット順に並べてください`

返答としては例えば：

`おっと、間違えてた。ありがとう。a4994ec で直したよ`

もしガイドラインに異議がある場合はコードレビューで話し合うよりガイドラインのレポジトリでissueを立てましょう。それまでの間はガイドラインに従いましょう。

# 最後に

最初に書きました通りこちらは[ThoughtbotのCode Review](https://github.com/thoughtbot/guides/tree/master/code-review)を和訳したものです。
素晴らしいガイドラインを公表してくださっていることに感謝いたします。

訳の間違いや不適切な表現がありましたらおしらせください。
また、フィードバック等はいつでもお待ちしております。

# 参考

Code Review: https://github.com/thoughtbot/guides/tree/master/code-review
コードレビューの心構え: https://yulii.github.io/how-to-code-review-20150422.html
ラズパイ4のsshが超遅いときはIPv6を無効化するとよい

# 環境
セットアップ環境の詳細は[ラズパイ4にraspbian busterをセットアップ](https://qiita.com/rootpia/items/4ec94793a7d77686fbef)を参照。

* Raspberry Pi 4 Model B (RAM 4GB)
* raspbian buster (2019-09-26-raspbian-buster.zip)

# 現象
ラズパイにssh接続すると、繋がるまでに時間がかかる。

# 原因
デフォルトがIPv6接続→IPv4接続の順となっており、IPv6接続のタイムアウトまでの時間がかかっていた。(セットアップ時にどっかミスったのかもしれないけど）

Windows Powershellから接続しても、他のLinuxから接続しても遅いためラズパイ側の問題だろうとあたりをつけた。

sshするときに-vオプションを付けて実行すると、デバッグ情報が表示できる。ここではWindowsからラズパイに接続しており、IPv6アドレスっぽい接続にタイムアウトで失敗したあと、IPv4で接続していることが分かる。

```shell
$ ssh -v ユーザ名@マシン名
OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
debug1: Connecting to マシン名 [xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx] port 22.
debug1: connect to address xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx port 22: Connection timed out
debug1: Connecting to マシン名 [yyy.yyy.yyy.yyy] port 22.
debug1: Connection established.
```

# 改善方法
ラズパイの設定を変更する。

```shell
$ sudo vi /etc/sysctl.conf
```

sysctl.confに下記を追記する。

```
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
```

sysctl.confの変更を反映する。

```shell
$ sudo sysctl -p
```

下記コマンドでinet6という項目がないことを確認する。

```
$ ip a
```

一度、ssh接続を終了.

```shell
$ exit
```

再度sshで接続して確かめる。

```shell
$ ssh -v ユーザ名@マシン名
OpenSSH_for_Windows_7.7p1, LibreSSL 2.6.5
debug1: Connecting to マシン名 [yyy.yyy.yyy.yyy] port 22.
debug1: Connection established.
```


## ( ..)φメモ
上記は、全インターフェースでIPv6を無効化している。特定のインターフェースのみ無効化したい場合は、/etc/sysctl.confへの追記項目を下記にすればよい。以下、eth0のみ無効にする例。

```
net.ipv6.conf.eth0.disable_ipv6 = 1
```
SSL暗号化通信について

# SSL暗号化通信とは
>SSL（Secure Sockets Layer）は、インターネット上での通信を暗号化する技術です。 SSLを利用することで、ユーザーが利用するブラウザとサーバ間の通信を暗号化し、第三者によるデータの盗聴やなりすまし、改ざんなどを防ぐことができます。

例えば、暗号化されていない通信でクレジットカードを使ったショッピングをすると、クレジット情報などが筒抜けで不正利用に繋がるといったことが考えられます。
アドレスバーで**https://**形式(httpにセキュア（Secure）のsがついた形式)が確認できるとSSLによって保護されているページと判断できます。

次はSSL暗号化通信を支える2つの技術について記述します。

# 暗号化技術
・暗号化されていないファイルを**平文**という
・ファイルを暗号化することを**暗号化**という
・暗号化されたファイルを復元することを**復号**という
・下記の**鍵**というのは実際にはロジックのようなものとイメージ

## 公開鍵暗号化方式
[![Image from Gyazo](https://i.gyazo.com/e0dae3814988f0a4c05b135c1c244592.png)](https://gyazo.com/e0dae3814988f0a4c05b135c1c244592)

## 共通鍵暗号化方式

[![Image from Gyazo](https://i.gyazo.com/e6f75e226ec16eeac00cd607f49d55b5.png)](https://gyazo.com/e6f75e226ec16eeac00cd607f49d55b5)

# SSL暗号化通信の流れ

・SSLサーバ証明書とは、**通信先(サーバー)が信頼できることを、認証局が証明した、身分確認証**
・④〜⑥**公開鍵暗号化方式**の技術を使用
・⑦**共通鍵暗号化方式**の技術を使用

[![Image from Gyazo](https://i.gyazo.com/28e9eacc91f2c2faced8150fd51ec870.png)](https://gyazo.com/28e9eacc91f2c2faced8150fd51ec870)

# プロトコルスタック

今回の通信規格のプロトコルスタックを作ってみました。
プロトコルスタックとは、前後の層とインターフェースを持って重なり、地層のように積み重なっている概念のことです。

[![Image from Gyazo](https://i.gyazo.com/ad3f4f14f02fe7f9a59dfac4cfcb897b.png)](https://gyazo.com/ad3f4f14f02fe7f9a59dfac4cfcb897b)

クライアントからのリクエスト、サーバーからのレスポンスはHTTPに従います。他の層も同様です。

# まとめ
図にするのは頭への残り方が抜群に良いことがわかりました。
毎回は手間がかかりすぎるのでやりませんが、たまには図にして記事に残したいですね。
間違った認識していればコメントいただけると嬉しいです。
円グラフを描画したらラベルが被ってムカついた話。

HTML上に円グラフを描画する必要があって、描画してみたらしてみたで偏ったデータでラベルが重なってストレスがたまったのでその記録。

【やりたかったこと】
円グラフを描画する。
とりあえず、chart.jsで円グラフを描画してみる。
(前任者がこれを採用してたのがすべての元凶なのだろうか)
cahrt.js ：https://github.com/chartjs/Chart.js/releases/tag/v2.9.3
Labelのプラグイン：https://github.com/emn178/chartjs-plugin-labels


【実装①】

```javascript:drowChart.js
var data = {
    datasets:[{
        data:[90,1,1,1],
            backgroundColor: ["#009900","#009990","#909990","#300030"]
        }],
        labels: ["一人ぼっちは…","寂しいもんな","いいよ","一緒にいてやるよ"],
    }
    var ctx = document.getElementById('myChart').getContext('2d');
    var myPieChart = new Chart(ctx,{
        type: 'pie',
        data: data,
        options: {
            legend: {
                display: false
            },
            plugins: {
                labels: {
                    render: 'label',
                    position:'outside'
                }
            }
        }    
    });
```
```HTML:index.html
<canvas id="myChart"></canvas>
```

【実装①の結果】
![①.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323752/1641bf6c-388e-d2cc-cc8b-abbb098007c2.png)


ラベルがめっちゃ被った・・・

ということで、色々と検索。
やっぱり同じようなことで悩んでる方はいるようだった。
http://danlec.com/st4k#questions/45352194
質問者が「パーフェクトだ！」みたいな返事をしている回答があったので、
さては天才だな？って思ってこの通りに実装してみた。

【実装②】

```javascript:drowChart.js
angular.module("app", ["chart.js"]).controller("ChartCtrl", function($scope) {
    $scope.labels = ["一人ぼっちは…","寂しいもんな","いいよ","一緒にいてやるよ"];
    $scope.data = [90,1,1,1];
    $scope.options = {
        pieceLabel: {
            render: 'label',
            fontColor: '#000',
            position: 'outside',
            segment: true
        }
    };
});
```
```HTML:index.html
<div ng-app="app" ng-controller="ChartCtrl">
        <canvas id="pie" class="chart chart-pie" chart-data="data" chart-labels="labels" chart-options="options"></canvas> 
</div>
```

【実装②の結果】
![②.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323752/6a7ef0af-749c-7075-eecb-9806d695309b.png)



ラベル消えたが（#＾ω＾）ﾋﾟｷﾋﾟｷ




【解決法】
chart.jsを切り捨てて、d3.js + d3pie.js　を使用する。

D3.js ：https://d3js.org/
d3pie：https://github.com/benkeen/d3pie

```javascript:drowChart.js
var pie = new d3pie("myChart", {
    data: {
        content:[
            {label:"一人ぼっちは…",value:90},
            {label:"寂しいもんな",value:1},
            {label:"いいよ",value:1},
            {label:"一緒にいてやるよ",value:1}
        ]
    },
    labels:{
        percentage: {
            fontSize: 0
        }
    },
    tooltips:{
        enabled: true,
        type: "placeholder",
        string: "{label}: {value}"
    }
});
```
```HTML:index.html
<div id="myChart"></div>
```


【結果】

![③.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323752/6e5c45bf-4593-3a2f-f737-becfed5e020b.png)


できたー(^^♪
デスクトップPCとノートPCを用いたマルチディスプレイ

新しい職場ではあまりマルチディスプレイが主流ではないものの、作業をしているとどうしてもマルチで作業をしたいシーンが出てきます。
申請をすればマルチも出来なくはないようですが、手元にあるノートPCをうまく活用ができないかと調べてみたら、どうやらmiracastという方式があるようなので試してみた。

## Miracast
[Miracast - Wikipedia](https://ja.wikipedia.org/wiki/Miracast)
```Miracast（ミラキャスト）とはWi-Fi Allianceによって策定された、1対1の無線通信によるディスプレイ伝送技術である。ストリーミング技術を用いてホストの画像、音声、動画を、無線でペアリングされた別のデバイスに送ることができる。現在の技術仕様ではマルチキャストはできない。```

というわけで、画面共有の仕組みそのもののよう。

Windowsでは、この仕組みがデフォルトでWindows10から搭載されている。
技術的な縛りでいうと、BluetoothかWifiが可能なモデルである必要があるようで、手元のPCは対応していそう。
そもそも今時Bluetoothが非搭載も珍しいか。（デスクトップだとありそうだけど）

## Windowsの設定
ネット上にはあまり詳しくは書かれていないが、とりあえずやったことは以下のこと。

### 映される側の設定
1."設定" → "このPCへのプロジェクション"を選択
![Miracast-2-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25184/bc5bde4d-5294-a827-cde8-a37a4aae0f7b.png)
2.接続設定をする

### 映す側の設定
3."設定" → "ワイヤレスディスプレイに接続する"
![Miracast-2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25184/fa763b08-9853-9760-fd8f-a7af668fb9b5.png)
4.検索して検出されたPCを選択

これで可能になる。

## 結果と感触
無事にディスプレイを映すことはできた。

ただ、直接ケーブルでつないでいるわけではなく無線でつないでいるので、どうしても微妙なラグを感じる。
入力作業はやはり大元のPC側で作業を行い、参照資料等を表示させておくような使い方になりそうだ。
動画や、ゲームをやろうとするのには向かないように思える。

また、時々表示がおかしくなってしまうことがあった。
それほど頻発しているわけではないけれど、画面の一部が表示されないような状態になる。
あくまで補足用途になりそうだ。

とはいえ、両方のディスプレイで入力作業を行うことがそれほどあるわけではないのでこれで十分といえそう。

## 問題発生
問題なく使えていたのだが、急に「ここのデバイスでは、保護されたコンテンツを表示できません。」と出て接続が出来なくなった。

AndroidからのMiracast時にYoutubeなどの著作権関連コンテンツを表示させようとすると、このメッセージが出るようという話があるようだが、アプリケーションとして新たに立ち上げた際に失敗するというわけでもなさそう。
翌朝になると再び接続可能な状態になっているので、何が判定基準となっているのかが気になるところだ。

一部、ネット上ではウィルス対策ソフトを切ると大丈夫という話もあるが、そういう定義ベースで動くものであれば上記のような挙動はおかしいと思われる。
せめてもう少し何がエラーの原因になっているか見つける方法があればと思うのだが。。。

ちなみに、問題なく1日使える時もあるので、もう少し発生状況を整理して特定したいところだ

## 追記(2020/03/03)
ノートPCのWifi接続時に不安定になることが多いので切ってみたところ、比較的安定するようになった。
もちろん時々画像が乱れたりすることはあるけれど、ひとまずこの環境で進めてみることにしています。

調べてみると、Wifiと混線するようだ。
参考：[Miracastを試す -パソコン工房](https://www.pc-koubou.jp/blog/miracast.php)

Miracast自体がどの帯で接続しているのかを調べられればいいのだが、よくわからず。
会社のWifiは5GHz帯しかなかったので、ちょっと選択の余地がなかったのと、そもそもMiracast使用時は使い道がないので
Wifi切っていても問題ないというのが実情なのだ
リファクタリングでモブプロみたいなことをしたお話

弊社内でエンジニア3人が集まって楽しくリファクタリングをした話です。

# 背景
社内のプロダクトで「手が空いてるならリファクタリングやってくれると嬉しい。手が足らない」というようなSOSを受け取り、
そのプロダクトをある程度知っている人 1人 + 知らない人 2人 の3人でリファクタリング部隊を作ってリファクタリングしていこうという話になりました。

今回は、モブプロ「みたいなこと」です。厳密なモブプロではないです。
なので、

- ドライバーも考える (みんなで考える)
- ドライバーは変わらない


という感じでゆるく進行しました。

## プロダクトについて
Railsで動いています。Rails3から始まり、今Rails5です。

- 7年ぐらい前から動いているプロダクト
- 新しく書いたところは新しく、古いものは古いという歴史が積み重なっている
- Rails3からのコードが残っている
- Rails何それ？Ruby何それ？から始まったコードが存在している
- ただファイルが分割されただけのコードがConcernsとして存在している
- でもテストはちゃんと書かれている

という感じで、とても歴史のあるプロダクトです。

## 今回やった人について
A: このプロダクトわかる。設計強い。DDD好き。Ruby, Railsともに得意。
B: このプロダクトわからない。インフラ強い。Rubyそんなに得意じゃない。 (本人談)
C: このプロダクトわからない。設計好き。DDD好き。Ruby得意。型を欲しがる。

という感じで思想やスキルの差が若干ありつつ、

- 仲が良いので思想のぶつけ合いになっても険悪にはなりづらい
- 誰か一人が発言しづらいということはない
- お互いの技術に信頼/リスペクトしている

というメンバーです。今回はBさんがドライバーをしました。

# 今回の流れ
実際にどんな感じでやったのか？ですが、基本は

1. つっつき会
2. メシ
3. 修正会

という3つのフェーズで行いました。
会議室で大画面を使用してみんなで唸ります。

## つっつき会
今回のメインはモブプロをやることではないので、まずはリファクタリング対象(ディレクトリ/ファイル単位)を決め、
コードを読んでみてよくなさそうなところをつっついて、方針決めをします。大体4時間ぐらい。

このつっつきは`TODO: つっつき serviceとして切り出す` というようなTODOコメントとして残し、コミットします。

今回は、以下のような観点でつっついていきました。

- そのファイルの構造、ネームスペースが正しいか(分割されただけのファイルがconcernsとして存在しているため)
- そのクラスの責務を逸脱したメソッドがあるか(↑と大体一緒)
- 冗長(わかりづらい)な書き方をしていないか
- これらを大幅な変更せず綺麗にできるか

この時点でも、3人分の目と知識があるので、誰かが「この書き方はなんだ？」「これどうなってるんだ」となっても、知ってる/わかってる人が説明するということもあり、一人でやるときよりもスムーズです。

また、
>これらを大幅な変更せず綺麗にできるか

という判断も1人だと消極的な理由でやらないことを選択してしまいそうな部分も、誰かの「実は簡単に修正できるのでは」という知識の後押しにより、積極的な判断をすることもできます。もちろん、やらないという判断もあります。

特に、やるか/やらないか という部分以外にも判断材料を出せる人が増えるというのは多人数の有利な部分です。

## メシ
![ramen.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/475927/b9873b35-d4c7-6e4b-0f50-63c27666f47a.jpeg)

## 修正会
実際につっつき会でつっついた部分をリファクタリングしていきます。大体2時間ぐらい
基本的につっつき会で方針が出ているのでその方針に沿ってリファクタリングするだけです。
とはいえ、この段階でも「あ、もっといい方法あるじゃん」というのはあるので、随時取り入れていきます。

# KPT
## Keep
- 誰かの「これどうなるんだろう？」に対して「じゃあ、試してみるか」というラフな形でやってみることができる
- コードではわからないお互いの思考フローが知れる
- ドメインエキスパートが居ないことによる「名前から直感的に判断できるか」という部分に焦点をあてれる

## Problem
- 仲が良いからこそ、脱線すると脱線し続けそうになる
- ドメインエキスパートが居ないので仕様がわからないのでパスというのがあった
- 複数人いるのでガッツリ集中して書くというのは難しい

## Try
- ドメインエキスパートも呼んでみる
  - 仕様についてをサクッと聞けるので時間短縮になりそう
  - keepの部分とコンフリクトしそう
- 人数を増やしてみる
  - 人が増えれば集合知というのは単純な加算になるのか

# 終わりに
ペアプロ、モブプロは**人と人の知識をリアルタイムでつなぎ合わせる** というのがコアだと思うので、
「ドライバーは10分」「ナビゲーターの指示に従う」といった感じで厳密にやる必要は別になく、人が集まってみんなでコードに向かうというのは大事だと感じました。
特にkeepでも書いた、

>コードではわからないお互いの思考フローが知れる

というのはお互いに勉強になります。
また、エンジニア間のコミュニケーションも取れるのでお互いに刺激になり、メインの業務にもハリが出ると思います。

更に、人間誰しも見落としや勘違いもあるので、単純に人数が増えることにより、見落としや勘違いなどをし続けることがなくなりやすいです。 (ダブルチェックと一緒で単純に増えればいいわけではないですが)

と、いう感じで、定期/不定期に限らずこういうことをやるのはいい感じだと思います。

おわり。
highlight.js で一部の言語のみに対応して webpack のビルドサイズを減らす方法

こんにちは、フロントエンジニアの ku6ryo です。
コード文字列をハイライトしてくれる [highlight.js](https://highlightjs.org/) を使う機会があったのですが、highlight.js のライブラリ全体のファイルサイズが大きくて webpack ビルドのサイズを大きくしていたので必要な言語のみ対応して、ビルドサイズを**大幅に**削減する方法を紹介します。

まず、highlight.js の大きさは webpack で build した場合、Gzip しないとサイズが 746.69 KB、Gzip すると 246.18 KB のサイズがあります。

<img width="465" alt="Screen Shot 2020-02-06 at 1.46.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450664/d0b4bc1a-dcde-c8fc-61ca-ff23124e9b01.png">

いずれにしても、とても大きなサイズなことは代わりありませんね（汗）
すべての対応言語を読み込んでしまうと、このようなサイズになります。
必要な言語をのみを読み込むには、以下のように必要な言語のファイルのみを読み込む設定ファイルを作ります。例えば、Javascript, CSS, JSON のみに対応するには、以下のようなファイルを作ります。


```javascript
// my-highlight.js
import hljs from 'highlight.js/lib/highlight'

hljs.registerLanguage('css', require('highlight.js/lib/languages/css'))
hljs.registerLanguage('javascript', require('highlight.js/lib/languages/javascript'))
hljs.registerLanguage('json', require('highlight.js/lib/languages/json'))

export default hljs

```

そして、このファイルを highlight.js を呼ぶときと同じように使えば OK です。

```javascript
// 通常
import hljs from 'highlihgt.js'

// 必要なものだけ読み込む
import hljs from './my-highlight.js'
```

上記の言語セットの場合、Gzip 前 19KB、Gzip 後 7.14 KB になります。Gzip 前 700 KB 以上、Gzip 後 200 KB 以上のサイズ削減になります。これはだいぶ大きですよね！ highlight.js 使っている方はぜひやってみてくださいね〜

<img width="586" alt="Screen Shot 2020-02-06 at 2.01.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/450664/e46c4c39-bc45-d249-8ab7-5de441da18b7.png">
Spring Java

* Spring Tools 4 for Eclipseを入手し以下で解凍

```bash
java -jar spring-tool-suite-4-4.5.1.RELEASE-e4.14.0-win32.win32.x86_64.self-extracting.jar
```
* 必要によってSpringToolSuite4.iniに-vm追加

```bash
-vm
C:\Program Files\Java\jdk1.8.0_211\bin\javaw.exe
```

* springプロジェクト作成

File → New → Spring Starter Project → Next →
web機能とホットデプロイを使うため以下をチェック
1. Developer Tools→Spring Boot DevTools
2. Web→Spring Web
→ Finish

![new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500676/7436d9d2-77f6-21cb-a47c-8be5f989e743.png)

```pom.xml
<dependencies>
･･･
　<!-- web -->
　<dependency>
　　<groupId>org.springframework.boot</groupId>
　　<artifactId>spring-boot-starter-web</artifactId>
　</dependency>
　<!-- ホットデプロイ -->
　<dependency>
　　<groupId>org.springframework.boot</groupId>
　　<artifactId>spring-boot-devtools</artifactId>
　　<scope>runtime</scope>
　　<optional>true</optional>
　</dependency>
･･･
</dependencies>
```

```java:IndexController.java


package com.example.demo;
import java.util.HashMap;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class IndexController {
	private static final Logger log = LoggerFactory.getLogger( IndexController.class );

    @RequestMapping("/")
    private String index() {
        return "index";
    }

    @RequestMapping(value="/", method=RequestMethod.GET)
    private Map<String, Object> index( @RequestParam("id") Integer id) {
        Map<String, Object> map = new HashMap<>();
        map.put("id", id);
        return map;
    }

    @RequestMapping(value="/items/{id}", method=RequestMethod.GET)
    private Item get(@PathVariable int id) {
    	return new Item(id);
    }

    @RequestMapping(value="/items", method=RequestMethod.POST)
    private void post(@RequestBody String body) {
    	log.info("post, " + body);
    }

    @RequestMapping(value="/items/{id}", method=RequestMethod.PUT)
    private void put(@PathVariable int id, @RequestBody String body) {
    	log.info("put, " + id + ", " + body);
    }

    @RequestMapping(value="/items/{id}", method=RequestMethod.DELETE)
    private void delete(@PathVariable("id") int id) {
    	log.info("delete, " + id);
    }

    public static class Item {
        private int id;

    	Item (int id) {
    		this.setId(id);
    	}

    	public int getId() {
    		return id;
    	}

    	public void setId(int id) {
    		this.id = id;
    	}
    }
}
```
syslog受信 → S3保存 してくれるDockerコンテナ お手軽セット

https://github.com/yagrush/docker-td-agent-syslog-to-s3
↑成果物は、こちらへどうぞ！

# 実現したかったこと

syslogをS3に勝手に保存してくれる環境を、簡単に量産できるようにしたい！

# 作ったもの概要

ポート514にsyslogを送ると S3にgzipで1時間毎に保存してくれるDockerコンテナが、すぐ作れます。
（実際は、Dockerコンテナの中で td-agent が常駐しています）

# 必要なもの

## syslogを保存するS3バケット

## S3バケットにアクセス権限を持つIAMユーザー

## `docker`, `docker-compose` が入ったEC2インスタンス

Amazon Linux release 2 (Karoo) で動作確認済。
ポート514の受信許可（セキュリティグループの設定）もお忘れなく。

→ 必要でしたら [こちら（AWS EC2 AmazonLinux2 のdockerホスト用初期設定）](https://qiita.com/yagrush/items/e85d2da1b0ef9997fa07 "AWS EC2 AmazonLinux2 のdockerホスト用初期設定")もご参照下さい。


# 使い方

詳細部分は [README.md](https://github.com/yagrush/docker-td-agent-syslog-to-s3/blob/master/README.md) をご参照頂ければと思いますが、
全体的な流れも含めてざっくり説明しますと…

* S3に、syslogを保存するためのバケットを作成。
* そのバケットに書き込む権限を持つIAMユーザーを作成。
* そのIAMユーザーのアクセスキーとシークレットをダウンロードしておく。
* DockerホストとなるEC2インスタンスを作成。
* そのインスタンスがポート514でsyslogを受信できるようセキュリティグループを設定しておく。
* そのインスタンスにSSHで接続。
* `docker`, `docker-compose` をインストールしてセットアップする。
* [本成果物](https://github.com/yagrush/docker-td-agent-syslog-to-s3)をダウンロードする。（gitとかcurlなどで。）
* 中のディレクトリに `cd` する。
* `.env.template` を `.env` にリネーム。
* `.env` を編集する。（S3に接続するための設定を書く。）
* （保存間隔やファイル名のカスタムなどは、td-agent.conf をお好みで編集。）
* Dockerイメージをビルドする。 `docker-compose build`
* イメージからコンテナを起動する。 `docker-compose up -d`
* 余裕があれば、動作テストなどしておく。
* syslog送信側端末にて、送信先を上記のインスタンスのポート514に設定！

# ミソ

## 1: .env から S3接続設定を拾って Dockerfile 内で（ビルド中に）使う

今回、S3接続設定を td-agent.conf から外出し（.env）したのですが、これができるまで結構ハマりました・・・

外部ファイルから docker-compose.yml 内で値を拾うことは割とすんなりできたのですが、
環境変数として

* docker-compose.yml 内の environment で渡し、
* Dockerfile 内の ENV で拾う

でビルド中に渡そうとしても、どうにもできず・・・
どうやらその方法では、コンテナが起動した後でないと有効にならないそうでした。
（起動後、コンテナ内のシェルに繋いで `env` すると、間違いなく設定されてはいるのですが・・・）

で、アンサーはというと

* docker-compose.yml 内の args で渡し、
* Dockerfile 内の ARG で拾う

これで、Dockerfile内で `$HOGE_HOGE` で利用可能には、なりました。が・・・

## 2: td-agent.conf 内で使う

しかーし！
今度は、td-agent.conf 内で環境変数として引用 `${ENV{'HOGE_HOGE'}}` できない・・・

Dockerfile 内でわざわざ ARG → ENV で拾い直してもダメ・・・

どうやら、今回 td-agent を Docker内のサービス（デーモン）として起動する仕組みにした影響っぽく。
工数的限界もあり、ここはゴリ押しで `sed` で置換する方法にしました:laughing:
Hello world!から始めるPython


## はじめに
Pythonを始める初心者向けの記事です。
今回は"Hello world!"を出力するプログラムを書いてみましょう。

## 何故"Hello world!"から始めるのか
言語を学ぶにあたり、まずは文字列の出力という一番簡単な操作を実践してみることはとても大切です。

例えグーグルの超優秀なAIエンジニアであっても、最初の一歩は必ず"Hello world!"からだったはずです。

AIエンジニアを目指した駆け出しエンジニアのあなたも、さっそく"Hello world!"をpythonで記述してみましょう。

## 環境構築
Macではpython2.7がデフォルトでインストールされているので環境構築は不要です。
Windowsを使っている方はMacを買いましょう。

## Pythonの起動
terminalを開いて、次のワンコマンドでpythonが起動できます。

```
python
```
## Hello world!の出力
`import __hello__`コマンドを利用します。

```
>>>  import __hello__
Hello world!
```

以上が"Hello world!"の出力方法でした。

ちなみのこのコマンドは一度しか使えません。
挨拶は一度でよく、何回も挨拶すると失礼になるだろうという開発者の配慮のためです。

## 終わりに
いかがでしたでしょうか。

pythonでは他にも`import this`などを利用し文字列を出力できます。
文字列出力のためのコマンド`import`からマスターし、AIエンジニアへの第一歩を踏み出しましょう。

ちなみにpythonでは、`import antigravity`コマンドで漫画を読む機能がついているので、勉強で疲れたら是非利用してみてください。
初心者！current_userの使い方　〜ログイン中のユーザ名を表示〜

current_userでログイン中のユーザ名とメールアドレスの表示の仕方を紹介します。

**書き始めるときは`current_user`の前に`=`を忘れないでくださいね！**

###ユーザー名を表示　〜current_user〜

```haml
.header__left-box__list
  = current_user.user
```

<img width="600" alt="スクリーンショット 2020-02-06 0.57.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538880/e2b29c56-98fe-1e99-c1b8-a91201b20fd0.png">


メールアドレスを表示させたい↓

```haml
.header__left-box__list
  = current_user.email   #nameからemailに変更
          
```

<img width="600" alt="スクリーンショット 2020-02-06 0.58.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538880/cb1009ae-8f5a-182a-6c30-20fa73685d26.png">


なぜ、このように
= current_user`.name`や= current_user`.email`
のようになるかというと、、、テーブルに注目。

　　　↓

###○usersテーブル
|id |  `name `  |`email `           |
|---|:---------:|:-----------------:|
|1  |  mirai    |mirai@mirai.com    |
|2  |    :      |  :                |
|3  |    :      |  :                |

`name`カラムや`email`カラムから引っ張ってきているのです！
**`=current_user`の後ろには`.`を忘れず書く事！！**

また、each doも同じです。

ではまた(^_^ )

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

おまけ

###ユーザー名を表示 〜each do〜

```haml
.header__left-box__list
  - @group.users.each do |hhgg|
    = hhgg.name
```

<img width="600" alt="スクリーンショット 2020-02-06 0.57.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538880/e3b4fa58-826d-1039-5f86-d1731a1c9e5d.png">


メールアドレスを表示させたい↓

```haml
.header__left-box__list
  - @group.users.each do |hhgg|
    = hhgg.email   #nameからemailに変更
```

<img width="600" alt="スクリーンショット 2020-02-06 0.58.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/538880/9ebd27ef-c7ed-2eb9-727f-200871f6869e.png">
🤔でコーディングする言語作った

🤔が好きです🤔
そこで、🤔だけでコーディングする言語を作ってみました🤔

[🤔 language](https://github.com/asny23/thinking-language)

# 🤔言語
愛に溢れた言語を作るといえばbrainfuck派生語ですね🤔
というわけで [r-fxxk](https://github.com/masarakki/r-fxxk) を使ってサクッと作ります🤔

Hello, world!はこうなります🤔

```text:helloworld.thinking
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔🤔🤔🤔🤔
🤔🤔🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔🤔
🤔🤔🤔🤔
🤔🤔🤔🤔
🤔🤔
🤔🤔🤔🤔🤔🤔🤔🤔
🤔🤔🤔
🤔🤔🤔🤔🤔
🤔🤔🤔
🤔
🤔
🤔🤔🤔🤔🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔🤔🤔
🤔🤔🤔🤔🤔
🤔
🤔
🤔
🤔🤔🤔🤔🤔
🤔🤔🤔
🤔🤔
🤔🤔🤔🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔🤔🤔🤔
🤔🤔🤔🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔
🤔🤔🤔🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔🤔🤔🤔
🤔
🤔
🤔
🤔🤔🤔🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔🤔🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔
🤔🤔🤔🤔🤔
🤔🤔🤔
🤔
🤔🤔🤔🤔🤔
```

r-fxxk はRuby gemなのでRubyの環境は用意していただき、

`$ bundle install`
`$ ./thinking helloworld.thinking`

で実行できます🤔

🤔を愛して止まない人は🤔でプログラムが書けるのですが、そうも行かない場合はbrainfuckのソースを🤔に変換する簡易コンバータもリポジトリにあるのでお使いください🤔
パパっと作ったのでうまく変換できないときもあるかもしれませんが🤔🤔🤔

[thinking-language/bf2thinking.sh](https://github.com/asny23/thinking-language/blob/master/bf2thinking.sh)

---
Have a good 🤔!
Angular cliの隠しコマンド`ng make-this-awesome`

Angularのソースコードを見てたらこんな隠しコマンドを発見しました。

```
ng make-this-awesome
```

このコマンドを打つと、ランダムで以下のどれかのフレーズで褒めてもらえます。

```
      `You're on it, there's nothing for me to do!`,
      `Let's take a look... nope, it's all good!`,
      `You're doing fine.`,
      `You're already doing great.`,
      `Nothing to do; already awesome. Exiting.`,
      `Error 418: As Awesome As Can Get.`,
      `I spy with my little eye a great developer!`,
      `Noop... already awesome.`,
```

すごいね、とか。もう完璧だからすることないね、みたいなメッセージが送られてきます。
暇な時に使ってみてください。
aws cli S3でよく使うコマンド


aws cli S3でよく使うコマンドについて記載。

```
#バケットの内容を表示
$aws s3 ls s3://bucket-name/path

#バケットの内容を表示（更新日順でソート）
$aws s3 ls s3://bucket-name/path  | sort -n

#バケットの内容を表示（更新日の降順でソート）
$aws s3 ls s3://bucket-name/path  | sort -nr

#バケットの内容を表示して絞り込む（ファイル名、ファイル更新日時など）
$aws s3 ls s3://bucket-name/path  | grep file-name

#バケットを作成
$aws s3 mb s3://bucket-name

#バケットを削除(空の場合は削除されない)
$aws s3 rb s3://bucket-name

#バケットを削除(強制削除) 
$aws s3 rb s3://bucket-name --force 

#バケット内のファイルを削除
$aws s3 rm s3://bucket-name/file-name

#バケット内のフォルダを削除
$aws s3 rm s3://bucket-name/file-name --recursive

#ローカルのファイルをバケットにコピー
$aws s3 cp {ファイルパス} s3://bucket-name/path

#ローカルのファイルをバケットに移動
$aws s3 mv {ファイルパス} s3://bucket-name/path

#バケットをローカルのフォルダと同期(追加・更新のみ) 
$aws s3 sync {フォルダパス} s3://bucket-name/path

#ローカルのフォルダをバケットと同期(ローカルにダウンロード、追加・更新のみ) 
$aws s3 syncs3://bucket-name/path {フォルダパス} 

#バケットをローカルのフォルダと同期(追加・更新のみ、　ファイルサイズは同じだがタイムスタンプが更新されたものも更新する場合) 
$aws s3 sync {フォルダパス} s3://bucket-name/path --exact-timestamps

#バケットをローカルのフォルダと同期(ローカルに存在しないものは削除される) 
$aws s3 sync {フォルダパス} s3://bucket-name/path --delete

#バケットの中身をすべてs
$aws s3 cp s3://bucket-name . --recursive


```

以上


参考

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-services-s3-commands.html

https://docs.aws.amazon.com/cli/latest/reference/index.html#cli-aws
[Rust] HashMap は collect で生成できる

Rust の HashMap は `FromIterator` なので, キー (`K`) と値 (`V`) のタプル `(K, V)` を返すイテレータを直接 `.collect` して生成することができます. これは HashMap の `.into_iter` の逆操作になっていると言ってもよいです.

具体例として [言語処理100本ノック](http://www.cl.ecei.tohoku.ac.jp/nlp100/) から「[04. 元素記号](http://www.cl.ecei.tohoku.ac.jp/nlp100/#sec04)」を解いてみます.

```rust
use std::collections::HashMap;

const ONE_CHAR: &[usize] = &[ 0, 4, 5, 6, 7, 8, 14, 15, 18 ];
const TEXT: &str = "Hi He Lied Because Boron Could Not Oxidize Fluorine. \
New Nations Might Also Sign Peace Security Clause. Arthur King Can";

fn main() {
    let elements: HashMap<&str, usize> = TEXT.split_whitespace()
        .enumerate()
        .map(|(i, text)| {
            if ONE_CHAR.contains(&i) {
                (&text[0..1], i+1)
            } else {
                (&text[0..2], i+1)
            }
        }).collect();
 
    println!("{:?}", elements);
}
```

`{"C": 6, "Be": 4, "P": 15, "F": 9, "Al": 13, "Si": 14, "Ne": 10, "Na": 11, "N": 7, "Mi": 12, "Li": 3, "B": 5, "He": 2, "S": 16, "Ar": 18, "H": 1, "K": 19, "Cl": 17, "O": 8, "Ca": 20}` のような出力 (順不同) が得られるはずです. それにしてもこの問題, `"Mg"` じゃないのとても落ち着かないのですが...


# 参考文献

* [std::collections::HashMap - Rust](https://doc.rust-lang.org/std/collections/struct.HashMap.html)
Codeforces Round #617 B.Food Buying

# 題意
- あなたはお金をs持っておりxを支払うと食べ物xが単位買える。もし、x支払ったとき、$ \left\lfloor \frac{x}{10} \right\rfloor $がキャッシュバックされる
- あなたは最大で何単位の食べ物を得られるか？

# 例
s=19とする。まず、10を買い1のキャッシュバックを得る。
今、s=19 - 10 + 1 = 10あるから、10買って1のキャッシュバックを得る。
その1で1を買い、合計21単位の食べ物を得る。

# 例2
s=9876であるから、9870円でf1 = 9870 を得てキャッシュバック987を得る。
次に、残額6 + 987で993円から990円でf2 =990を得て、キャッシュバック99を得る。
次に、残額3 + 99 で102円から100円でf3= 100を得て、キャッシュバック10を得る。
次に、残額2 + 10 で12円から、10円払い、f4=10を得て、キャッシュバック1円と残額2でf5=3を得る。

# コード: という動作をひたすら実装する
```Python
q = int(input())
for _ in range(q):
    s = int(input())
    res = 0 # 買った合計
    while s > 9:
        sm = s % 10 # 残額
        res += (s - s % 10) # 綺麗な金額分
        s = s // 10 # キャッシュバック
        s += sm # 残額と足す
        if s < 9:
            break
    res += s
    print(res)
```

https://codeforces.com/contest/1296/submission/70373733
while構文

while構文

```
繰り返す条件を作るための初期化処理
while (繰り返す条件){
　　繰り返したい処理
　　更新処理
}
```
↓↓↓↓↓

```
$i = 1;
while ($i <= 365){
     print $i . PHP_EOL;
     $i = $i + 1;
}
```
- 一番重要なところは「繰り返す条件」`($i <= 365)`
  - ◯◯が△△になったら繰り返してください、◯◯が△△ではなくなったら繰り返しをやめてください、といった条件を記述する
  - 上記の場合は『$iという変数の内容が365以下の間繰り返す』と言った条件になっている
- `$i`は最初どういう状態なのか？
  - 「初期化処理」`$i = 1;`の部分で行われる
  - `$i = 1`として数字の1を代入しているので、最初の`$i`の状態は 1 であることがわかる
    - while構文の条件である『$iが365以下』に該当するので、while構文の中括弧に入って「繰り返したい処理」が行われる
  - while構文は「繰り返したい処理」が終わると、元の部分に戻るという性格がある
  - `$i`が365以下の場合は、画面に数字が表示された後、またwhile構文に戻ってくる
  - ここで更新処理を書かないと、`$i`には1が代入されたままとなり**無限ループ**となってしまう。
- 更新処理
  - 繰り返す条件に使っている変数などは、最終的に条件から外れるような計算などを行う必要がある
  - 「更新処理」`$i = $i + 1;`
     - `$i` に `$i+1` を代入する。
  - 1 を画面に表示した後、`$i`には1+1である 2 が代入される
  - またwhile構文の最初に戻るので`$i`が365以下であることは変わらないが、`$i`の内容自体は変わっている。（1が2になっている）
  - 2 が画面に表示された後、`$i`は2+1である 3 が代入される
     - 3が画面に表示されて4・・・5・・・６と1ずつ増えていく
  - 364が画面に表示された後、365になった`$i`のままwhile構文に戻る。
     - 条件は「365以下」なので365も含まれる
  - 画面には365と表示され、`$i`が366になった後while構文に戻るが、この時点で条件から外れる。
  - 画面には365が表示されて処理が終わる。（条件から外れたので）

※参考：Udemy/Webサーバーサイドプログラミング入門
unityでCSVからステージを作成するエディター拡張

##Unityエディター拡張でステージを作ってみる
今回はこのように3Dでステージを展開できるエディター拡張の紹介です
2019.2のバージョンでは動作確認してあります。
![キャプチャ.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577107/04da8f9d-0497-6b5e-6ad9-ee757b0c1aa2.jpeg)

今回のコードはこちらになります
https://gist.github.com/rx1242/c574f5b9289293a5fce5984c59fe979a

#CSV読み込みについて
読み込みはReadCsvメソッドで行っていて
このメソッドは、読み込みボタンを押すと呼ばれます。
1. EditorUtility.OpenFilePanelを使いエクスプローラーで直接CSVファイルを指定して、パスを取得してきます。
2. 取得したパスを使い、StreamReaderでCSVをstringに変換します。
3. stringをカンマごとに分割して、分割データの配列から行列の数値を取得。
4. 二十配列に番地ごとのデータを入力していきます
#マップチップデータ
これは簡単
各マップチップのデータをスクリプタブルオブジェクトで作成したクラスに設定するだけ！
#ステージ展開
展開はApplyメソッドで行っています。

二重for文で行列ごとのデータと一致する番号のマップチップをInstantiateしていきます。

この時xyのポジションを行列と合うように移動します。
#キャンセル処理
キャンセルはRollbackメソッドで行っています。
生成したステージを削除しているだけです。
#工夫したポイント
そもそもの制作目的が15人チームでストラテジーゲームを作るときに、ステージの作成の高速化というのがあります。
複数人で使用されるだろうという前提があります。
ここで問題なのがファイル構造の問題で、人によってCSVを保存する場所が違うと予想。

EditorUtility.OpenFilePanelを使い直接保存場所からパスを取得できるようにしています。
これで使用するときにAssetsフォルダー内にCSVが無くてもOK!
Codeforces Round #617 A.Array with Odd Sum 

コーナーケースへの不安が大敵。

# 題意
```
- n 個の1以上の正の整数が配列aとして与えられる
- その中のある数字を選んで他の好きな数をその数で上書きしていい
- 配列aの総和が奇数にできるか述べよ
```

# 例を見る
```
2 3 - Yes 偶数と奇数が１つでもあれば交互に変え次第
2 2 8 8 -> NO 偶数しかないと何をしても偶数
3 3 3 -> Yes 奇数が奇数個だからOK
5 5 5 5 -> NO 奇数が偶数個だからNG
1 1 1 1 -> NO　同様
```

# 考える
上記のパターンですべて必要なものは網羅されている。

- パターン1: すべてが偶数の場合(=奇数が一つもない場合) は奇数が作れないのでNG
- パターン2: すべて奇数だが、偶数個しかないとき、奇数にならないのでNG (奇数を奇数で置き換えても変わらない)
- パターン3: そのすべての場合、YES。
    - 3-1: すべて奇数で奇数個あるとき。なにもしなくても奇数である
    - 3-2: 偶数が1つでもあり、奇数が1つでもあるとき。その偶数を置き換えれば偶数奇数は買えられる
    
```Python
q = int(input())
for _ in range(q):
    n = int(input())
    dat=list(map(int, input().split()))
    ocount = 0
    ecount = 0
    for i in range(len(dat)):
        if dat[i] % 2 ==0:
            ecount += 1
        else:
            ocount += 1
    if ocount == 0:
        print("NO")
    elif ocount % 2 == 0  and ecount == 0:
        print("NO")
    else:
        print("YES")
```

https://codeforces.com/contest/1296/submission/70371654
jinja2のget_template()のパスをカレントディレクトリに依存させない

パステンプレートファイルのパスが間違っているとこんなエラーが出る(検索用)

```python3
jinja2.exceptions.TemplateNotFound: xxxx.html
```

* デフォルトではFileSystemLoaderに渡すパスをルートとして相対パスでファイルを検索するようになっている
    * 仮に`'.'`と指定するとカレントディレクトリからの相対パスになる
* そこでこのコードを書くファイル自体の絶対パスをルートにすることによって実行場所、ファイルの配置場所を選ばなくなる 

```python3
from jinja2 import Environment, FileSystemLoader
from os import  path
env = Environment(loader=FileSystemLoader(path.dirname(__file__)))
template = env.get_template('template.html')
```
aws cliを複数のプロファイルで使う

aws cliで複数のプロファイルを使う方法について記載

すでにaws cliインストール、デフォルトのプロファイルが設定されている前提。



1.新しいプロファイルを作成する

```
$aws configure --profile new-user

AWS Access Key ID [None]: xxxxxxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]: json
```
Default output formatについては以下のような感じ、

json – JSON 文字列形式で出力されます。
yaml – YAML 文字列形式で出力されます。（AWS CLI バージョン 2 でのみ利用できます。）
text – 複数行のタブ区切り文字列値の形式で出力されます。これは、grep、sed、または awk などのテキストプロセッサに出力を渡すのに役立ちます。
table – セルの罫線を形成する文字列 +|- を使用して表形式で出力されます。通常、情報は他の形式よりも読みやすい「わかりやすい」形式で表示されますが、プログラムとしては役立ちません。


2.プロファイルを指定してコマンドを実行する

```
$aws s3 ls --profile new-user
```


3.面倒な場合は、環境変数で指定する

```
$export AWS_PROFILE=new-user
```

補足、デフォルトユーザーの変更

```
$export AWS_DEFAULT_PROFILE=new-user
```

以上





参考

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-chap-configure.html
Windows10 HomeにDocker for Windowsをインストールする (WSL2を利用)

https://download-stage.docker.com/win/edge/41944/Docker%20Desktop%20Installer.exe

上記の`Docker Desktop Installer.exe`がWindows Home(WSL2が有効)にインストールできることを確認した。

`docker run hello-world`が動作することも確認した。

URL的にStage版のedgeかと思うので、正式版はもうすぐリリースされるのではないかと思う。

## 参考

- https://github.com/docker/for-win/issues/4378#issuecomment-573062762 (2月上旬にはedgeをリリースすると説明されている)
- https://github.com/docker/for-win/issues/4586#issuecomment-577294824 (Windows Homeで動くDocker for Windowsのリンク元)

## 追記

2.2.2.0 (43066)でWindos10 HomeのWSL2に正式に対応された。
golang dbr

どうしてもdbrを使わないといけない場面に出くわしたので、忘れそうなものを記録する
SELECTの情報が少なすぎる。
どうやって、SQLビルダーから、文字列を追い出すか、それが問題だ・・・


①godocから探る
https://godoc.org/github.com/gocraft/dbr

①テストから、探る
https://github.com/gocraft/dbr/blob/master/select_test.go


※例なのでテーブル名、カラム名に変数は使わず記述している

#Joinしたテーブルに別名をつける
``` go
LeftJoin(dbr.I("users").As("staffs"), "staff.id=companies.user_id").

```
#サブクエリにエイリアスをつける。サブクエリをJoinする
``` go
	subQuery := Select("company_id").
		From("users").
		Where("id = ?", userId).
		As("staffs")

	_, err := Select("*")
		From("companies").
		LeftJoin(subQuery, "staffs.company_id=companies.id").
		Load(&results)
```
# 構造体にではなく、単一のカラムをプリミティブな型のスライスに取得

一時変数を、いちいち構造体定義するのは面倒。また構造体をスライスに変換する手間もコードが汚れる
取得したらIN句などで利用する

``` go
	var myCompanyUserIds []int64
	_, err := Select("users.id").
		From("users").
		Where("users.company_id = ?", myCompanyID).
		Load(&myCompanyUserIds)
```

#プレースホルダを使わず Whereを記述する
``` go
Where(dbr.Eq("company.id", myCompanyID))
```

# 複合条件的なWhereを記述する
``` go
Where(
	dbr.Or(
		dbr.Eq("company.id", myCompanyID1),
		dbr.Eq("company.id", myCompanyID2),
	),
)
// OrはAnd, EqはNeq、Like、、NotLike,Lt,Lte,Gt,Gte,Exprなどに差し替え可能
```

#生のSQL式を途中に挟む
``` go
// プレースホルダも使える
dbr.Expr("REPLACE(CONCAT(`user`.`last_name`, `user`.`first_name`),' ','') like ?", term),
```