OmniAICreator/Qiita-1.07M huggingface dataset:
ドロップメニュー

#HTML
```html:filename.html
      <div class="menu-bar">
        <ul>
          <li><a href="home.html"><i class="fa fa-home" aria-hidden="true"></i>TOP</a></li>
          <li><a href="works.html"><i class="fa fa-briefcase" aria-hidden="true"></i>Works</a>
            <div class="sub-menu-1">
              <ul>
                <li>
                  <a href="" target="_blank">
                  大学資料請求フォーム
                  <i class="fa fa-external-link-alt" aria-hidden="true"></i>
                  </a>
                </li>
                <li>
                  <a href="" target="_blank">
                  スタッフ管理WEBアプリ
                  <i class="fa fa-external-link-alt" aria-hidden="true"></i>
                  </a>
                </li>
                <li>
                  <a href="" target="_blank">
                  歯科サイト
                  <i class="fa fa-external-link-alt" aria-hidden="true"></i>
                  </a>
                </li>
              </ul>
            </div>
          </li>
          <li><a href="about.html"><i class="fa fa-user" aria-hidden="true"></i>
          AboutMe</a>
          </li>
          <li><a href="form.html"><i class="fa fa-envelope-square" aria-hidden="true">
            Contact
          </i>
          </a></li>
          </ul>
      </div>
```

#CSS
```css:filename.css
.menu-bar {
  text-align: center;
  background:linear-gradient(#20b2aa, darkturquoise);
}
.menu-bar ul {
  display: inline-flex;
  list-style:none;
  color: white;
  margin-top: 1rem;
}
.menu-bar ul li {
  width: 140px;
  margin: 10px;
  padding: 20px;
  /*box-shadow: 1px 1px 5px; */
  border-bottom: 2px solid white;
  border-top: 2px solid white;
}
.menu-bar ul li a{
  text-decoration: none;
  color: black;
}
.active, .menu-bar ul li:hover {
  /*background: #D6F1F5;*/
  background-color: aliceblue;
  transition: all 0.5s;
  border-radius: 3px;
  border-bottom: 2px solid #20b2aa;
  border-top: 2px solid white;
}
.menu-bar .fa {
  margin-right: 8px;
}
.sub-menu-1 {
  display: none;
}
.menu-bar ul li:hover .sub-menu-1 {
	display: block;
  position: absolute;
  background: white;
  margin-top: 15px;
  margin-left: -15px;
  z-index: 501;
}

.menu-bar ul li:hover .sub-menu-1 ul {
  display: block;
  margin: 10px;
}
.menu-bar ul li:hover .sub-menu-1 ul li {
  width: 150px;
  padding: 10px;
  border-bottom: 1px dotted #fff;
  background: transparent;
  border-radius: 0;
  text-align: left;
  box-shadow: none;
}
.menu-bar ul li:hover .sub-menu-1 ul li:last-child {
  border-bottom: none;
}

.menu-bar ul li:hover .sub-menu-1 ul li a:hover {
  color: #999;
}
```
Infratasterを触ってみる

## 概要

構築したサーバの動作確認をする時に、URLが正しく閲覧できるか確認したいということがあるかと思います。一つずつ確認するのは簡単ですが、それが大量にあったりすると時間もかかりますし、確認漏れなどが出るかもしれません。

そんな作業を自動化できそうな [Infrataster](https://github.com/ryotarai/infrataster) というツールを見つけましたので、試しに使ってみたいと思います。(Infrataster＝インフラテイスター、インフラの味見・毒味という意味らしい)

## 初期設定

Rubyで作られたツールなので、Rubyのコンパイラが必要です。また、RSpecの仕組みを使って確認していくようです。

まずは Gemfile を用意します。最低限 Infrataster と、JSONで値の確認をするためにお好みで追加のライブラリも一緒に指定します。

```
source 'https://rubygems.org'

gem 'infrataster'
gem 'rspec-json_matcher'
```

依存関係のインストールを行います。

```
$ bundle install
...
Bundle complete! 1 Gemfile dependency, 28 gems now installed.
Use `bundle info [gemname]` to see where a bundled gem is installed.
```

Infratasterはrspecの上で動作するので設定ファイルの生成を行います。

```
$ bundle exec rspec --init
  create   .rspec
  create   spec/spec_helper.rb
```

ここまでで基本的な準備が完了したので、テストの構築に入っていきます。

まず、テスト対象を定義します。spec/spec_helper.rbの先頭に下記を定義していきます。

```
require 'rspec/json_matcher'
require 'infrataster/rspec'

RSpec.configuration.include RSpec::JsonMatcher
Infrataster::Server.define(
  :production,
  'www.holmescloud.com'
)
```

テストしたい内容を spec/production_spec.rb に記載していきます。テスト対象のページに対してテストケースを複数書くことももちろん可能です。

```
require 'spec_helper'

describe server(:production) do
  describe http('https://www.holmescloud.com/index.html') do
    it 'returns 200' do
      expect(response.status).to eq(200)
    end
  end
  describe http('https://www.holmescloud.com/login.html') do
    it 'returns 200' do
      expect(response.status).to eq(200)
    end
    it 'has header' do
      expect(response.headers['X-Application-Context']).to eq('application')
    end
  end
  describe http('https://www.holmescloud.com/news/') do
    it 'returns 200' do
      expect(response.status).to eq(200)
    end
  end
end
```

一通りテストが書けたら実行してみましょう。

```
$ bundle exec rspec spec/production_spec.rb 
....

Finished in 0.76616 seconds (files took 1.31 seconds to load)
4 examples, 0 failures
```

作成したものは下記の場所にアップロードしてあります。
https://github.com/nabe256/infratest

今回はテストが通る前提の書き方で進めていますが、インフラの構築中であればテスト駆動開発にも有効に使えると思います。
率直に便利だと感じたので今後どんどん使っていきたいですね。

## 参考ページ

* 偉大なる開発元サイト  
  https://github.com/ryotarai/infrataster
* コードの書き方をかなり参考にさせていただきました  
  https://techlife.cookpad.com/entry/2014/11/19/151557
* DNSの確認も可能なようです  
  https://inokara.hateblo.jp/entry/2016/07/02/101157
TJBotがメキシコで大活躍

TJBotがメキシコでのIT教育で活躍しているお話です。

http://www.ibm.com/blogs/corporate-social-responsibility/2019/12/ibm-cloud-and-tjbots-in-guadalajara/

# メキシコのシリコンバレー

メキシコは人口の3分の１以上が25歳未満で年間12万人以上のエンジニアが学校を卒業しているそうです。中でもGuadalajara市はテクノロジー、クラウドのソリューション、AI、およびIoTの急速な増加と使用により、メキシコのシリコンバレーとして知られているそうです（知らなかった）。
# TJBotが教育の現場で活躍
このIT分野のスキルに投資が必要なこの都市に、IBMが地元の公立高校と提携してIBM Cloud および TJBotによる新しい技術カリキュラムを提供しているそうです。高校生たちはTJBotを組み立て、APIやクラウドコンピューティング、そしてプログラミング技術も学んでいます。
メキシコがソフトウェア開発の拠点となる日もそう遠くないですね。
ESP32でBLE使いながら電圧(アナログ入力)を取得する

IoTLT Advent calendar 2019 11日目を担当しますnorippyです。
大した記事ではないですが、開発の助けになればと思います。

#はじめに
ESP32でラフなプロトタイプを作るときにArduino-ESPライブラリを使って開発を行なっているのですが、その開発をする中でこんな問題を発見しました。

**BLEを使いながらアナログ入力を取得すると、値が貼りついて正しい値が取得できない**

最初センサーが壊れたのかな？と思ってセンサーを交換したのですが、状況は変わらず。
1つずつ確認したところ、BLEを使いながら、電圧値が取れないというこの問題を見つけました。

対策は無いのか・・・と思い調べたところ、解決策があったので備忘録として残しておきます。

#esp-idfのライブラリを使え！
Arduinoの`analogRead()`を使うと動かないです。
ずっと同じ値を出し続けます・・・

この問題の解決方法がesp-idfライブラリを使うというものでした。
この対策ですが、ESP32をArduino-IDEを使おうとした時にインストールするライブラリの中に含まれているライブラリ(多分Arduino用にラップする前のライブラリ)を使います。
そのため、**すでにArduino IDEを使ってESP32の開発をされている方は別途何かをインストールする必要はありません！**

実際に必要な要素のみを抽出してサンプルコードにしました。
コード上に説明も追加したので、読んでみてください。

```sample.c

#include <driver/adc.h>//このヘッダファイルを忘れないように！！

void setup() {
  //ESP32は2つのADコンバーターをサポートしていて、最大で18チャンネル使うことができます。
  //ただ、ADC1とADC2でコードの書き方が違います・・・
  //AD1 GPIO 32~39
  //AD2 GPIO 0,2,4,12~15,25~27

  //セットアップ方法
  //AD1の場合

  adc1_config_width(ADC_WIDTH_BIT_12);
  //何ビットのADCを使うか設定する。今回は12bitにします。
  //adc1の場合はこのように使うチャンネル全体の設定をするコマンドが用意されている。

  adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_DB_0);
  //AD1のチャンネルの設定をする。
  //ここでどのチャンネルを使うか、0 V　~xx Vの値で変換するかを設定する。
  //引数は(設定したいGPIO,AD変換する電圧範囲)を示している。
  //ADC_ATTEN_DB_0 -> 0~1.1VでAD変換する


  //AD2の場合

  adc2_config_channel_atten(ADC2_CHANNEL_5, ADC_ATTEN_DB_11);
  //AD2と違い、この設定コマンドしかない。
  // ADC_ATTEN_DB_11 -> 0~3.9VでAD変換する


  //set upは以上
}

void loop() {

  int value; //analog値を代入する変数を定義
  //loop内で実際に値を取得します。

  //AD1の場合
  value = adc1_get_raw(ADC1_CHANNEL_0);
  //取得したいチャンネルを指定したらOK！

  Serial.println(value);


  //AD2の場合

  
  //注意　AD2はwi-fiを使っていると使えません！！！！

  esp_err_t r = adc2_get_raw(ADC2_CHANNEL_5, ADC_WIDTH_BIT_12, &value);
  //引数は(どのチャンネルの値を取得するか、その時何ビットでAD変換した結果にするのか、値を代入する変数)を示しています。
  if ( r == ESP_OK ) {//AD1と違い、errorハンドリングがしやすいようになっています。
    printf("%d\n", value );
  } else if ( r == ESP_ERR_TIMEOUT ) {
    printf("ADC2 used by Wi-Fi.\n");
  }

  Serial.println(value);
}
```

`analogRead()`より面倒ですが、こうすることでBLEを使いながらanalog値を取得できるようになります。
またコード上に若干書きましたが、この方法で万事解決では無く、仕様上

**Wi-Fiを使うと、AD2が使えない！**

という問題もあるのでご注意ください。
またコード中に出てきた変数は以下のページに詳細があるので、確認してください。

https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/peripherals/adc.html


## さいごに
IoTと言いながら、IoT感が無く、すごいシンプルな内容ですみません。
でもセンシングをするという時に意外と使うのがADC。とても重要な機能です。

結局Arduino-IDEを卒業して全てをesp-idfでコードを書けということかもしれませんが、ライブラリが充実しているArduinoをやめるのも中々難しいものです。
ViewPager2でスワイプを無効にする方法

# `setUserInputEnabled` を使えばOK :ok_woman: 

```java:Javaの場合
viewPager2.setUserInputEnabled(false)
```

```kotlin:Kotlinの場合
viewPager2.isUserInputEnabled = false
```

https://developer.android.com/reference/androidx/viewpager2/widget/ViewPager2.html#setUserInputEnabled(boolean)

---
`ViewPager` の場合だとサブクラスを作って独自に対応などしないといけなかったので、こういうメソッドがあると非常に良いですね。

 `ViewPager2` いいぞ :muscle:
Ansible AWX のインストール

## 環境
* OS: CentOS Linux release 7.6.1810 (Core)
* Ansible AWX 9.0.1.0

## 参考情報
Installing AWX
https://github.com/ansible/awx/blob/devel/INSTALL.md

こことかも。
https://qiita.com/matchpon23/items/7442632bd23b3cf0554e
https://qiita.com/nakacya/items/b80575210d2168284d89

## 事前準備
上記「Installing AWX」の「Prerequisites」を実施。
あと、python3 の導入も併せて実施

### python3 & Ansible

python3 & Ansible インストール

```bash
# yum install -y https://centos7.iuscommunity.org/ius-release.rpm
# yum install -y python36 python36-pip python36-devel
# pip3 install --upgrade pip #ここで OS 再起動
# pip3 install ansible
```

### Docker & docker (Python module) 

Docker & docker (Python module) インストール

```bash
# yum install -y yum-utils device-mapper-persistent-data lvm2
# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# yum install -y docker-ce docker-ce-cli containerd.io
# systemctl enable docker
# pip install docker
```

### git

git インストール

```bash
# yum -y install https://centos7.iuscommunity.org/ius-release.rpm
# yum -y install perl-TermReadKey perl-Error libsecret
# yum --disablerepo=* --enablerepo=ius -y install git2u
```

### Node.js,npm

Node.js,npm インストール

```bash
# curl -sL https://rpm.nodesource.com/setup_10.x | bash -
# yum install -y nodejs
# yum install -y gcc-c++ make
```

### docker-compose

docker-compose インストール

```bash
# pip install docker-compose
```

## Ansible AWX のインストール

Ansible AWX インストール

```bash
# git clone https://github.com/ansible/awx
# cd awx/installer/
# ansible-playbook -i inventory install.yml
```
以下が出力される可能性がある。

```bash
TASK [local_docker : Start the containers] ************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK
for Python: docker (Python >= 2.7) or docker-py (Python 2.6)) on localhost.localdomain's Python /usr/bin/python. Pl
ease read module documentation and install in the appropriate location. If the required library is installed, but A
nsible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for e
xample via `pip install docker` or `pip install docker-py` (Python 2.6). The error was: No module named requests.ex
ceptions"}
```
その場合は以下を実施。

```vimscript:/awx/installer/inventory
#localhost ansible_connection=local ansible_python_interpreter="/usr/bin/env python"
localhost ansible_connection=local ansible_python_interpreter="/usr/bin/python3"
```
Haskellの直和型とBool型のおはなし

# はじめに
[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の十一日目の記事です。

とてもネタ切れと時間のなさを痛感しています。

今回はHaskellの直和型とBool型に関するお話です。

# 直和型とは

集合論的に考えて、これかこれかこれみたいな「or」の関係の型となります。
フィールドを与えて直積の列挙みたいな感じの表現もでき多彩なことができます。

## HaskellにおけるBool型

```hs
data Bool = True | False
```

Haskelはdataキーワードを用いることで、新しい型を定義することができます。
Boolという型はTrueもしくはFalseという値(コンストラクタ)を持つということがわかります。

## 性別を型で管理したい

ある日、性別を型で管理したくなりました。

私は男性なので、プログラム上では、Bool型で男性ならTrue、女性ならFalseとなるでしょうか？

違います。そう、Haskellならね(ｷﾘｯ)


## 性別を型で管理する

計画当初は性別は男性もしくは女性だったかもしれませんが、時代の流れにのっとりその他の項目を追加したとしましょう。
Bool型では処理仕切れなくなってしまいます。

```hs
data Gender = Male | Female | Other
```
これで、三つの直和型になり、拡張もしやすくなりますね。
そして、このように型を定義することで、関数内での扱いも見通しがよくなります。
ここでは、性別はBool型にあわせるために男性もしくは女性でTrue,Falseとします。

```hs
genderInitial :: Bool -> Char
genderInitial True   = 'M'
genderInitial False  = 'F'

genderInitial' :: Gender -> Char
genderInitial' Male   = 'M'
genderInitial' Female = 'F'
```
こうやって、直和型として定義をすることで、関数内での扱いの見通しもよくなります。

さあ、直和型をすころう
フォールトトレランスとフェールソフトの違い

##前提知識
### 1.フォールトトレランス（fault tolerance)
  障害が発生した場合にどうするかを備えること。
  例）サーバを二台用意して冗長構成にする
 　  
### 2.フォールトアボイダンス（fault avoidance)
 障害が発生しないようにする
　例）リリース前にテストをする

#### 3.フェールソフト・・・障害が発生してもシステムが完全にはダウンしないようにする
 例)飛行機のエンジンが一つ故障しても、もう一個のエンジンで飛び続けられる

####4.フェールセーフ・・・障害が発生しても安全性を保つようにする
例）エレベータが落ちても、衝撃吸収機能があるから死なない。

##解説
2.フォールトアボイダンスは障害が発生するまえに防ぐ
1,3,4は障害が発生した場合にどうするかなので、

フォールトトレランスのなかにフェールソフトがふくまれるようです

参考
https://wa3.i-3-i.info/word14813.html
Friendly ArmのZeroPiでsambaを使ってファイルサーバを立てる【購入品編】


## 初めに
Qiita初投稿です。

業務の中で説明能力の不足を感じ、とりあえずアウトプットの機会を増やそうというのが理由で始めました。

定期的に書きたいとこですが、三日坊主の可能性が高いです。気楽にいこうと思います。

あんまり長々せずに、細かく刻むスタイルにしようかと思いますので、
今回は部材の購入品編です。


- [購入品編](https://qiita.com/kineneticnamaco/items/a7875cfa0956d9688407) この記事
- [個人輸入編](https://qiita.com/kineneticnamaco/items/df28c43e4eb83053312b)
- [OSインストール編](https://qiita.com/kineneticnamaco/items/261c6aac31ccd4c31b14)
- [samba設定編](https://qiita.com/kineneticnamaco/items/542d2bdf2a27fbd3de2e)


## 今回の目的
10年前に初自作で組んだ初代メイン機のセカンドHDDにあるデータに、未だにアクセスする機会があります。

ただ、

- いまだにブートドライブがHDDで起動が遅い
- サーバとしてつけっぱにするには消費電力が気になる(intel i7 860)
- ミドルタワーが地味に邪魔

という課題があります。

よって、セカンドHDDを取り出してNAS化する、というのが今回の目的になります。

…というのは嘘で、「安くて面白そう」と、とりあえず買ったZeroPiの用途がたまたまここに落ち着いただけです。

## 購入品

### ZeroPi

中国・シンセンのSBCメーカ、FriendlyElec社のボードになります。
https://www.friendlyarm.com/index.php?route=product/product&product_id=266

- 1GbpsのLANポート
- 小さい（40mm角）
- 安い　（ボードのみで$12.99≒￥1,500）
- ケースも一緒に出てる、かつ安い ($3)

というのに惹かれて購入しました。
ただグラフィック出力がないので、linux、コマンドライン、sshなどのキーワードがわかる人でないと少しつらいかもしれません。続編で説明しようと思います。

詳細は下記の記事をご覧ください。
https://gadgetrip.jp/2019/09/friendlyelec_zeropi/
私はこの記事を見て購入を決めました。


### 周辺機器

ほかにamazonでちょこちょこ必要なものを買いました。
最近は良くわからないメーカありすぎ問題が起きていますので、
amazon発送・販売のものを選んでおけばいいのではと思います。

- MicroSD 32GB
- Ethernetケーブル Cat6 1m
- Microカードリーダ

あとは流用品として下記のものも使っています。

- 3.5inch HDD 3TB
- 3.5inch HDDケース　USB2.0 外部電源つき

~~ZeroPi君のLANが100Mbpsですので、480MbpsのUSB2.0で十分です。~~
よく見たら1Gbpsやったあっれえ…というかそもそも1Gbpsでるから買ったんじゃなかったっけ…まあそのうち変えよう…
 

## 所感
- NASとかファイルサーバとか表記の揺らぎが気になる
- 買うだけ買ってあまり使ってなかったrealforceのキーボードがやっぱ打ちやすい
- 書くの時間かかる
RPA導入前にまず考えておくべきこと

# はじめに
RPA（Robotic Process Automation,業務の自動化）って
魔法のツールのように思われちゃうか「使えねぇな！！」って言われるかの二極化しがちなんですが
あれもこれもできる、そうRPAならね（実際はRPAツールだけでやっているわけではなく、他のツールと組み合わせたりしている）という広告を真に受けすぎていたり
プログラミング分からなくても大丈夫！！かんたん！！と勘違い
⇒話が違ってがっかり、ルートをたどってしまってたりというのが多いので、
今回はその辺の誤解を解いていきたいと思います。
（なお、アドベントカレンダーの日付を1日間違えました…すみません！）

# 前提：RPA業務の4分類
（表現の仕方の差異はあれど、皆大体似たようなこと言うかと思われます。
いきなりデカいヤマに手を付けず、大きなタスクを洗い出し・分解して
小さなタスクとしてスモールステップで作っていくのが王道ですね。）
![4分類.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427313/de14191c-4cc0-0793-19fb-982da2c28e8b.png)



# 1.決めていますか？音頭を取る人
何ならこれが全てと言っても過言ではないです。
この場合の「音頭を取る人」というのは「RPA導入だ！」と言っている偉い人…の事ではなく
実際的に以降の要件定義や設計を行い、実際のプログラミングを指揮する人の事です。
ちゃんと「ある程度の決定権」とセットにしてあげてくださいね。
ここがはっきりしていないと後の工程で大変つらい目にあいます（主にエンジニアが）。
また、会社としても「思ったよりRPAの効果が出ない」という事になり、誰も幸せになりませんので
ここはきっちり決めて、かつ定期的に見直しをしてください。
### よくある例
* EU（エンドユーザー）部門でEUCだ！！と、業務担当者（非エンジニア）に丸投げしてしまう。
    * 業務量の見積もりを正確に算出することが出来ず、一人に負担が集中します。RPAを憎悪する人間がまた一人生まれてしまうのでやめてください。
* 派遣エンジニアに丸投げする。
    * 社内の業務・部門などが分からない派遣エンジニアに、きちんとした業務の洗い出しをしないまま要件定義からやらせると（洗い出ししたと思っていても出来ていない例もよくある）工数が膨らむ可能性があります。派遣エンジニアのいう事に「はい」か「Yes」で答える、予算をどぶに捨てるくらいの覚悟がないならやめましょう（しかしそのお金で最初から業務改善コンサル入れたほうがいいです）。
* IcT部門の社内SE（非管理職）に社内全部面倒見てもらう
    * 上記2つよりはマシですが、RPA化をどこまで行うかによっては一番の地獄になる場合もあり。RPAには些末な事の洗い出し・検証などが多く、一つ一つは大したことがなくても、膨大な量となって襲い掛かってきます。RPAは「簡単でしょ？」と思われがちで（1件1件は実際大したことがない）助けが入りにくい・本人も助けを求めづらく、気付いた時には末期症状ケースもあるので周囲のフォローが必要です。

# 2.見直してますか？業務フロー
上記１の音頭を取る人次第なところがありますけれども。
通常のシステム開発だと要件定義する時に洗い出されますが（んなことない、と思う気持ちは一旦棚上げしてください）
RPAだと、なぜか何の洗い出しもしないまま着手させちゃったり
洗い出ししても不十分（後から要件が変わる）が頻発しますね。
「使うシステム」とか「ファイル形式」は後からでもいいので、
「どのような事をしたいのか、例外は何か、制約条件は何か」だけははっきりさせておきましょう。
（いわゆる、要件定義ではなく「要求定義」ですね）
### 明確にすべきこと
* RPA化する範囲（いきなり大きな切り口でやるのはやめ、タスクを小さく分割する）
* ユーザーが何を求めているか？（慣例でやっていて必要のないことまでRPA化しない）
* 誰にどの程度の権限を割り振って、誰が決裁するか（ここがあやふやだと仕様変更ばかりでRPAエンジニアが地獄を見る事となる。１．でも書いたけれども大事なので2回言うやつです。）

# 3.使ってますか？RPA以外の自動化ツール
RPAはなんかいい感じの魔法で全てをシャランラ～♪…<b>できるわけではない</b>ので
別のツールを使用したほうがいい場合も多々あります。
あるあるなのがExcelの操作ですが、VBAやVB.netで書いたコードを
RPAにキックさせて動かし、その結果データをまたRPAで操作していく…とか。
もう少しプログラミングに抵抗なければ、JavaScriptで書いたコードを動かすとか
Pythonでコード書いちゃうとか。
Python書けるならRPAツールいらなくね？と思われるかもしれませんが、
メンテできる人員が制限されてしまう事も考えられるので
変更可能性の低い基幹部分だけコードで書いて、
変更になる可能性のある部分をRPAツールを使用して作るのが最適解の場合もあります。
（例えば、外部サイトへのログイン部分はログインページなどの変更がありえるので
RPAで作成、データ取得した後のデータ解析部分はPythonでなど。）



# おまけ：独断と偏見コミコミのRPAツール選定表
なお異論は認める。（個人的にはUIPathとAAEが好き）
![選定表.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427313/9074897f-f095-8ed0-8890-eb2d9d8de369.png)
コスモを感じた初めてのRSpec

#自己紹介

**さっそくだが、君は、小宇宙（コスモ）を感じたことがあるか！？**

はじめまして。営業からRuby on RailsのWebエンジニアになったたっきー(半年)と言います。
僕は文系出身で開発は全くの未経験ですが、一念発起してJOBチェンジした者です。
とても優しく指導して下さっている先輩たちのもと、コツコツと勉強を進めているのですが、やはり分からない事も多く、先輩たちの時間を頂くことが多い恐縮な日々を過ごしています。。

とりあえずRubyを触って半年経ちました。
formの動きとか基礎的なものはようやく動かせるようになりましたが、まだまだ半人前。
そんなちょっとやそっと触っただけで、できる甘い世界ではないですね。

家はシェアハウスに住んでいて住人達から黒魔術ってタイトルのQiita記事をネタにされてブラックマジシャンって呼ばれてます。
今回は、会社で自分の書いたコードのテストを書いてねって言われた10月を振り返ります。

#スキル

HTMLとCSSは最低限作りたいイメージのものは作れるようになった。
JSはまだまだテンプレートとか調べながらじゃないと、全然できません。
rubyは分岐やら正規表現やら初歩中の初歩は理解したけど、綺麗には書いていない(らしい)
railsはチュートリアル二周半回って、イメージはつくけどまだお手本ないと辛い感じ。

#テスト元のコントローラー

細かくは書けないですが、ユーザーに設定してもらうユーザーに設定してもらうparamsを削除・作成・編集（RENAME）するものを作りました。
アクティブレコードで対象のモデルからデータを引っ張ってきて、idで合わせている書き方をしています。

#文法

作法は難しい。
これまで書いていたRails的なdef...endみたいな単純な書き方ではないからだ。
それでも任されたからに書き始めないといけない・・・

STEP１　RSpecのファイルを作る。該当のcontrollerの名前に合致するようにspecファイルを作成してください。
$ touchでコマンドで書いてもよし、該当フォルダで右クリックしてファイルを作ってもよし、まあ良しなにやってくれ。

STEP２　ファイルの中身をまずはdescribeを書いてく

例えば、GET関連のテストを書きたい時には一番最初にこのように書くんだ。

```categories_controller_spec.rb
describe'⚪︎◯#show'do
  コメント
  it "●●" do
    expect(××).to eq □□
  end
end
```
※実際にどのように書いていくかは伊藤さんの記事がとても丁寧に紹介されているよ。
https://qiita.com/jnchito/items/42193d066bd61c740612

#RSpecという小宇宙

テストを書く意義はテストにアサインされる身になるとよくわかる。
何十何百ってパターンを回さないといけないようなテストを人力なんかでやっちゃいけない。
勿論、必要なケースもあるだろうが、あまり生産性を感じない。

その点自動テストは、勝手にやってくれる。ロジックに誤りがないならヒューマンエラーも起きない。
ヒューマンエラーってのは最悪だ。時間を使って、無駄なことをしている。
だから、効率化効率化なんていろんなところで言われているんだ。

自分は自動テストというものに途轍もない「小宇宙(コスモ)」を感じてしまった。


#勉強法

書籍
https://leanpub.com/everydayrailsrspec-jp
おすすめ記事
https://qiita.com/jnchito/items/42193d066bd61c740612
実践
http://tech-drill.in/questions/12

#最後に

割愛しすぎた部分もあるので、今後はもう少しhogeとか使って、イメージしやすい記事にします！
Pythonでアルゴリズム（ABC 146 C 二分探索

今日からatcoderをpythonで解いていきます。

https://atcoder.jp/contests/abc146/tasks/abc146_c
　
この問題は二分探索の最も典型的な問題です。
二分探索、理論はシンプルですが実装すると境界でWAしたりしなかったりしてしまいますよね。
かといって最後の２つに絞れたら２つとも試してみて答える、なんて泥臭いこともしたくないですｗｗ

今回は、<font color="red">左側から詰めていく二分探索（ある数を超えないぎりぎりの数を探すタイプの二分探索です）

```python
l = 0
r = 1000000001

a, b, x = tuple(map(int, input().split(" ")))
while l < r - 1:
  m = l + (r - l) // 2
  p = m * a + b * len(str(m))
  if p > x:
    r = m
  else:
    l = m
    
print(l)
#l = left, m = middle, r = right
```

境界でバグらせないための今回のポイントは

```python

  if p > x:
    r = m
  else:
    l = m
```
の部分です。 
なんでここがポイントなの！？

それは、l + (r - l) // 2
ここを見てください。
書き換えると、(l + r) // 2
の部分ですね。（桁数がオーバーしないように。PYTHONなら不要という説をよく聞きます）

この値って、//で割られているのl+rが奇数のときは10.5とか1000.5とか、floatだと端数が出てきててこれを切り捨てています。
つまり、mは<font color="red">キモチ左によっている</font>

これを読んで「いい加減すぎる！ふざけるな！！」と怒る人がいるかもしれません。

そういう人たちには声を大にして言いたい。


~~すみませんでした~~


超えちゃいけないから恐る恐る左から寄ってくる感じにしたらいいんじゃないかな
くらいの発想です。


ではでは
2Dデータ(DXF)に適当な高さ情報を与えて3Dデータ(STL)を出力

open3dとdxfgrabberを使えばよい．

```python:dxf2stl.py
import open3d as o3d
import dxfgrabber

# DXFを読み込み
dxf = dxfgrabber.readfile("test.dxf")
# 実線の円だけ選択
c_cirs = [e for e in dxf.entities if e.dxftype == 'CIRCLE' and e.linetype == 'CONTINUOUS']

# 立体化
mesh = None
H = 50.0 # 円筒の高さ
Z = 0.0  # 円筒を並べるZ値
for c in c_cirs:
    m = o3d.geometry.TriangleMesh.create_cylinder(radius=c.radius, height=H)
    m.translate([c.center[0], c.center[1], Z])
    if mesh is None:
        mesh = m
    else:
        mesh += m
mesh.compute_vertex_normals()

# STLで出力
o3d.io.write_triangle_mesh("sample.stl", mesh)
```
色とかレイヤー毎に高さ決めたDXF描いて，自動で立体化したい．
[GAS] Driveのファイル一覧からダウンロードしたcsvファイルをShopifyにインポートしたら文字化け

## Driveからファイルをダウンロードするやり方の一つして、以下のようなものがある。

<img width="974" alt="Screen Shot 2019-12-11 at 22.40.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174991/069defbb-9905-78e6-e3d2-d1a1a3d16217.png">

この特定のフォルダにあるファイルを右クリックしてメニューからダウンロードができる。

しかし、全てGASで `content-type = 'text/csv', charset = 'Shift-JIS'` で生成したファイルなんだが、この方法でダウンロードしてファイルを開くと、MacでもWindowsでも文字化けはしなかった。

Macの自分はそのままローカルのCSVファイルをShopifyのCSVインポート機能にアップロードしたが、日本語部分が文字化けしてプレビューされた。

`charset = 'UTF-8'` で生成したCSVファイルを同様の方法でダウンロードしたところ、windowsでは文字化けがあった。

しかし、このファイルがShopifyでは文字化けを引き起さずにプレビューされた。

## CSVファイルの文字化けの原因
CSVファイルの文字コードはUTF-8で設定されているようで、Excelは"Shift-JIS"だと認識して開くので文字化けが生じるようです。

## 結論
Shopifyのインポート機能のなかで、アップされたCSVファイルをオープンした時にUTF-8を前提として処理を行なっているためにこのようなことが起きたと言えそう（自信ない）

あーハマった。

## 追記
ShopifyのCSV出力ドキュメントに書いてあった。

「CSVファイルにはUTF-8エンコーディングを使用してください。」

mmmm
Node-RED Dashboardのコンポーネントにイベントを追加する

# 動機：ボタンを押したらスマホを振動させたい

この前[Node-RED Dashboardでスマートリモコンを作ってみた](https://qiita.com/dozensofdars/items/43ec9e51cc3e33239e5c)のですが、スマホ上でボタンをクリックした時に「ボタン押した感」が欲しいなぁと何となく感じました[^haptics]。

JavaScriptには[Vibration API](https://developer.mozilla.org/ja/docs/Web/Guide/API/Vibration)というハードウェアのバイブレーションにアクセスできるAPIがあるので、これを使ってボタンをクリックした時にちょっと振動させてやればよさそうです。

ただ、Node-RED Dashboardのボタンはクリックイベントを設定するプロパティ等はないので、少し工夫が必要でした。
少し試した結果、ボタン以外のコンポーネントにも汎用的にイベントを設定できそうな方法があったのでメモしておきます。

[^haptics]: こういうフィードバックを与える技術を[ハプティクス](https://ja.wikipedia.org/wiki/%E3%83%8F%E3%83%97%E3%83%86%E3%82%A3%E3%82%AF%E3%82%B9)というらしいです。

# 環境
- Node-RED 1.0.2
- Node-RED Dashboard 2.19.0
- スマホ： Google Pixel 3 (Chrome)
    - 上記のVibration APIが現状Android ChromeとFirefox Mobileくらいしか対応していないようなので、iPhoneの場合は使えないかもしれません

# 結論
1. `ui_template`ノードを使う
2. コード種別は`<head>セクションへ追加`にする
3. jQueryで`document`に対してセレクタ付きのイベントを設定する(下記画像参照)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/7303ceb5-dec7-ebc6-d9a5-c2753a9903be.png)

# `ui_template`ノード
この子です。Dashboardのカスタムコンポーネントを作ることができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428874/250a35e8-5dc1-d213-627f-93278db5fdb8.png)
コード種別で

- `グループ内のWidget`
- `<head>セクションへ追加`

の2つが選択できますが、今回は`<head>セクションへ追加`を使います。
これを使うことで`<head>`タグ内にHTMLコードを追加できるので、`<script>`タグを使って任意のJavaScriptコードを埋め込むことができます。


# jQueryでセレクタ付きのイベントを設定
Node-RED DashboardはAngularJSとjQueryを利用して作られています。
なので、クリックイベントを追加する際はjQueryの`.on('click')`で簡単に追加できます。
例えばボタンは`<button class="md-raised md-button md-ink-ripple" type="button" ...`のように出力されているので[^button]、`button.md-raised.md-button`等と指定すればボタンを選択できます（※この辺は結構雑です）。

ただし、Dashboardのコンポーネントは動的に生成されるので、以下のように指定しても動きません。

[^button]: Dashboardのコンポーネントはおそらく[AngularJS Material](https://material.angularjs.org/latest/)を使用しているので、これのクラスを使用できます。

```html:正しく動かない
<script>
$('button.md-raised.md-button').on('click', function() {
  window.navigator.vibrate(10)
})
</script>
```

動的に生成された項目に対してもクリックイベントを追加するには、以下のように`document`に対してセレクタ付きでイベントを設定します。

```html:正しく動く
<script>
$(document).on('click', 'button.md-raised.md-button', function() {
  window.navigator.vibrate(10)
})
</script>
```

これを応用すれば、Dashboardのコンポーネントに対して汎用的にイベントを追加して機能拡張できます。

# まとめ
- Node-RED Dashboardのコンポーネントじゃ少し物足りない
- コンポーネントに少しだけ機能追加したい

といった時には`ui_template`ノードを活用できます。
`<head>セクションへ追加`を使うことで任意のJavaScriptコードを`<head>`内に埋め込めるため、コンポーネントに対してjQueryで各種イベントを設定できます。
Dashboardはデフォルトでコンポーネントが揃っているので簡単に使える + 拡張性も高い、という構成になっているので良いですね。
HDKでアニメーションをSOPに取り込む

SOP でなんでも処理したいマンの最大の悩み「SOPでアニメーションを扱いたい！」を解決すかもしれない、FBX アニメーションを取り込む SOPノードを開発しました、という話をしたいと思います。

#モチベーション

Houdini 18ベータテスト中のある日、BoneDeform のマニュアルに以下の記載をみつけました。
https://www.sidefx.com/docs/houdini/nodes/sop/bonedeform.html
>
Since Houdini 18.0, Bone Deform can also be used with point attributes in its second and third inputs. 
The capture paths in the boneCapture attribute in its first input are matched with the point name attribute in the second and third inputs. Instead of using the rest transform within boneCapture, it is taken from the second input’s P and transform (matrix3) point attribute values. Instead of using the transforms from bone objects, they are instead taken from the third input’s P and transform (matrix3) point attribute values.

解説すると、Houdini 18 の Bone Deformer はインプット2 及び 3 にポイントアトリビュートを使用できるようになりました。bone object の代わりに、ポイントアトリビュートの name は boneCapture にマッチした名称、P、transform(matrix3) へ姿勢を与えることでボーン変形を解けるようになりました。インプット2 はバインドポーズ、インプット3 はカレントポーズになります。

と、これを発見した時に、あとはアニメーションさえ取り込めればいいのでは？ という思いに至りました。

#FbxAnimationSOP
前置きはこれくらいにして、FBXアニメーションを読み込み SOP を開発しました。Houdini をゲーム開発で活用している、活用していきたいと奮闘されている同志の助けになればと思いソースコードを公開しました。
https://bitbucket.org/hideki/houdinifbxanimation

ビルド方法を解説します。

#準備
事前に用意するものは以下です

- Houdini 18
- Visual Studio 2017
- cmake
    - 恐らくv3.6以上


#ビルド
ビルドはcmakeでプロジェクトファイルを生成する必要があります。プロジェクトファイルは以下の手順で作成できます。 ※フォルダは例ですので、環境に合わせて変更してください。

```
>mkdir d:\work
>cd d:\work
>git clone https://bitbucket.org/hideki/houdinifbxanimation.git 
>cd houdinifbxanimation
>mkdir build
>cd build
>cmake -G "Visual Studio 15 2017 Win64" ..
```
Houdiniのプラグイン開発に慣れていない方は以下の手順でコマンドプロンプトを開いてください。
1. Houdini 18を起動
2. WindowsメニューからShellを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144656/cf83e3e4-5872-7a38-eb23-e48930943312.png)


無事プロジェクトファイル (SOP_FbxAnimation.sln) が生成されたら、Visual Studioでプロジェクトを開いてビルドします。
ビルドが成功したら
```%USERPROFILE%/Documents/houdini18.0/otls```
に SOP_FbxAnimation.dll が追加されます。

![fbxanim.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144656/aec5351d-f1d1-da3e-6e44-7c81586bab99.gif)

BoneDeformと併用すると
![fbxanim2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144656/16f991c8-f333-24f5-522f-c4244fdf2ac5.gif)


#最後に
コードの解説をと考えていましたが締め切りを死守するために割愛しました… 公開したコードはこれから Houdiniでプラグインを実装したいと考えられている方に向けて、出来るだけコンパクトに実装しています。Houdini で FBXSDK を扱う方法や SOPノードでジオメトリを生成する方法を理解するためのサンプルコードとしても活用してもらえれば幸いです。
Javascriptまとめ 【if文】【for文】2019.12.11

#### 【if文】

```
if(条件式１) {
　　条件式１がtureのとき実行される処理
} else if(条件式２){
　　条件式１がfalseで、条件式２がtureのとき実行される処理
} else {
　　条件式１、２がfalseのとき実行される処理
}
```
※条件式の()と、処理文の{}は省略不可

#### 【for文】

```
for(let i = 0; i < 10; i = i + 1){
  繰り返される処理
}
```
※「i < 10」の部分で回数を決めている
※「i = i + 1」の部分は処理が１回繰り返されるごとに呼ばれる
RowからTextがあふれないようにする

RowからTextが溢れる。
すごく簡単な話だったわけで、しょーもないことではまった。

### 問題
Rowの中に親のサイズ以上になるTextを含めると、横に溢れる。

### 解決

- TextをFlexibleで囲む
- ちゃんとDoc読もう
- 参考
    - https://flutter.dev/docs/development/ui/layout/box-constraints
    - https://youtu.be/CI7x0mAZiY0

解決っていうか自分への戒め。。

### 試したこと

```dart
String get longString => '<長いテキスト>';
...
Column(
  children: <Widget>[
    Text(
      longString,
      maxLines: 1,
    ),
    SizedBox(height: 8,),
    Row(
      children: <Widget>[
        Text(
          longString,
          maxLines: 1,
        ),
      ],
    ),
  ],
)
```

結果・・・
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375661/29b59ed3-d05f-20c5-6bbd-8ee4f6f66d9e.png">

Flexibleで囲めば問題なし。

```dart
Row(
  children: <Widget>[
    Flexible(
      child: Text(
        longString,
        maxLines: 1,
      ),
    ),
  ],
),
```

RowとかColumnで `mainAxisAlignment` を指定したとしても

- `MainAxisAlignment.min` は子要素のサイズに合わせた場合はRow/Columnのサイズが変化
- `MainAxisAlignment.max` は子要素のサイズによらず、Row/Columnが広がることができるサイズ（＝親のサイズ）に合わせる

という挙動（仕組みは知らない）。なので `mainAxisAlignment` は解決にならないことは把握していた。

flutter.devのページを見て、あーなるほどねえ、みたいな理解はした。（深くは調べていないので、余計な意訳を書いても・・・と思ったので省略）

YouTubeの*Flutter Widget of the Week*は毎日でも見た方がいいね。
Reactで簡単アプリ開発した話

# この記事は？

Reactを使って簡単なアプリを開発しました。

- 開発の中で感じたことを残すことで、他の人がReactで開発する際のヒントになれば。
- 自身の備忘録のため。


# 何を作ったのか

商品の金額をxx%offしてくれる計算機
https://nouka.github.io/price-calculator/

**ソースコード**

https://github.com/nouka/price-calculator


# なぜ作ったのか

- 身近に困っている人がいた。
- React x TypeScriptの学習のため。


# 何に配慮したのか

- サーバコストをかけないこと。
- オフラインでも動作すること。
- 設定値を端末に保持しておけること。


# 利用したライブラリなど

| ライブラリ名 | 説明 | 使用した理由 |
|----|----|----|
| create-react-app | コマンド1つでReactアプリの雛形を作ってくれるツール | Reactのプロジェクト作成時には必須。<br>オフライン動作するためのServiceWorkerも梱包されている。(利用するか否かは選べる) |
| redux, redux-localstorage | アプリのデータを管理するフレームワーク | redux-localstorageを使うと、Storeをローカルストレージに保存できる。 |
| material-ui | マテリアルデザインに沿ったUIコンポーネントを提供してくれるライブラリ | アプリっぽいデザインにしたかったため。<br>なるべくデザインに時間をかけたくなかったため。 |
| gh-pages | コマンド1つで特定のファイル/ディレクトリをgh-pagesブランチにpushしてくれるツール | npm run deployでGitHub Pagesに公開するため。 |


# Tips

## 今後、考慮した方が良いと感じたこと

- CSS-in-JSを使ったが、スタイルの量が多くなる場合はCSS-Modulesを使った方が、IDEのサポートが得られるので良いと思った。
- Reducerを1つにしたが、複雑なアプリであれば確実に分けることになるので、この辺りは将来性も考えてどうするか最初に考えた方が良い。

## 躓いたこと

- 計算の際に小数点の精度の問題が起こるので注意必要。
- inputのvalueをintでキャストすると、入力値を全て削除できなくなる(0が勝手に入る)ため、注意。
- GitHub Pagesでreact-routerを使う場合は、`<Router basename={process.env.PUBLIC_URL}>`とする。

## よかったと感じたこと

- TypeScript使うとPropTypesから解放される。typeの継承やインポートが使えるので、再利用性が増す。

## 難しいと感じたこと

- react-reduxのconnectが分かりづらい。dispatchを毎回呼んだ方がわかりやすかった。
- atomic design本当に難しくて、一旦共通のコンポーネントはsharedに入れることに。

# 開発してみた感想

- 主に嫁しか使っていないが、喜んでいるので良かった。
ALBのIPを固定したい？ GlobalAccelaratorを紹介するよ！

この記事は [CBcloud Advent Calendar 2019 10日目](https://qiita.com/advent-calendar/2019/cbcloud)の記事です。
CBcloud 徳盛です。最近オフィスで飲みながら仕事をすることが増えました。
今回は、AWSのGlobalAccelaratorについて書いていきたいと思います。このサービスにいきついた背景としては、ALBで運用している最中、「IP固定して」という依頼を早急に対応する必要があったことが始まりです。

## 忙しい人向け要約
- リージョンを跨いだロードバランシングが可能なので、耐障害性を向上させることができる！
- GlobalAccelaratorにALBをぶら下げることができるので、これまでの環境を変えずにIPを固定できる
- ALBを複数ぶら下げることができるため、Blue-Green Deployができる
- weightの変更での１分以内にはほぼ全てのリクエストが切り替わるため、Blue-Green DeployするならEBのswap機能より使いやすい
- 2019年9月より、接続元IPアドレスを保持できるようになり、さらに便利になった

# GlobalAccelarator(GA)とは
かなり端折って説明するとリージョン間のロードバランサーです。
が、実はそれ以外での使い道もあります。それと名前がかっこいい。

## ALB運用そのままにIPが固定できる
GAの特徴として、作成時に固定IPが二つ割り振られます。
また、ALB・NLB・EC2インスタンス・EIPをぶら下げることが可能なので、これまでALB運用していたサービスでも簡単にIPを固定することが可能になります。
![Kobito.jQ7DPu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124149/88724bee-efb8-6a86-88e0-fc36c8ee4110.png "Kobito.jQ7DPu.png")

## Blue-Green Deployに利用できる
複数のALBをぶら下げた際に、Weightの設定でリクエストを振り分けることが可能です。
この機能を利用し、デプロイの際に新しく立ち上げる環境を始めはWeight0で紐づけておき、環境が整ったらWeight設定を元の環境と逆転させることで実現させます。

### EBとGAのBlue Green デプロイした際の比較
Blue-Green Deployを簡単に行う手段として、他にElasticBeanstalk(EB)のswap機能を利用した方法があります。ただ、DNSレコードの有効期限が切れるまで旧環境へのリクエストが発生する可能性があるため、切り替えてすぐ旧環境を止めることはできません。
公式でもEBのスワップは以下のように注意事項があります。
> Elastic Beanstalk がスワップ操作を完了した後、古い環境の URL に接続するときに新しい環境が応答することを確認します。DNS の変更が一括適用され、古い DNS レコードの有効期限が切れるまで、古い環境を終了しないでください。DNS サーバーは、ユーザーが DNS レコードで設定したライブ期間 (TTL) に基づいてキャッシュから古いレコードを消去するわけではありません。

![Kobito.SAibpI.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124149/3bd999f8-d21f-e05a-ac92-9ed37ef5a101.png "ElasticBeanstalkのswap時のrequest振り分け")

その点、GAは１分以内にほとんどのリクエストが切り替わるため、扱いやすいです。

![Kobito.EjZpEs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124149/fbcd48e0-424a-bf77-f1e6-46ad2f13b587.png "GlobalAccelaratorのweightを利用したリクエスト振り分け")

# 利用コスト
固定料金+データ転送量で課金されます。
固定料金は0.025USD/hです。
また転送量はGB単位の課金になっており、クロスリージョンだとさらに価格が上がります。

```
アジア→アジア 0.01USD/GB
米国→アジア 0.035USD/GB
```

弊社ではGAを本番で運用した際の転送量が90GB程度だったため、だいたい$20/月ぐらいの利用料に収まりました。


# まとめ
今回はGlobalAcceralatorについて書かせていただきました。
もともとALBのIPを固定するために利用を始めたGAですが、その他にも恩恵があり、意外と便利です。

また、今回は速度面をそこまでシビアに考えていないため書きませんでしたが、エニーキャストを介してトラフィックを最も近いエッジロケーションにルーティングし、さらに最も近いリージョナルエンドポイントにルーティングすることによってアプリケーションのパフォーマンスを向上させてくれるようです。
Firebase Extensions 「Translate Text」を使ってコードを1行も書かずに翻訳する

## Firebase Extensionsとは？
Firebase Extensionsは、あらかじめパッケージ化されたソリューションを簡単に使用できるやつです。ベータの現在9つのソリューションがオフィシャルで用意されています。
本日はそのうちの一つTranslate Textの使い方を説明。

Translate Textとは？
Firebaseのイベント（CREATE,DELETE,UPDATE）をトリガーに、テキストを特定の言語に翻訳して、指定したフィールドに書き込んでくれるFunction。

## 使い方

FirebaseコンソールのExtensionsのセクションからTranslate Textをインストール。
<img width="265" alt="スクリーンショット 2019-12-12 4.10.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54825/5d481f25-037e-e7e5-26d1-ef9043e6d899.png">

FreeプランではTranslate Textは使えないので、プランのアップグレードしてください（無料枠での使用なら課金されないので、安心して。）


以下の構成を聞かれるのでそれぞれ入力してインストールします。
- リージョン
- 翻訳言語（対応言語）https://cloud.google.com/translate/docs/languages
- コレクションパス
- 翻訳元テキストのある`field名`
- 翻訳されたテキストを保存する`field名`

ここでは、コレクションを`translations`
翻訳されるテキストfield名を`input`
翻訳されたテキストfield名を`translated`
に指定してます。

<img width="657" alt="スクリーンショット 2019-12-12 4.13.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54825/b86a898d-ea41-25e6-bf10-b94b67177de4.png">


設定はこれだけでインストールが完了し、Function一覧に`ext-firestore-translate-text-fstranslate`（下図）の関数が追加されてたらokです。

<img width="1032" alt="スクリーンショット 2019-12-12 4.18.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54825/bcf8355b-35d0-424e-79c6-33b2de908f4b.png">


指定したコレクションのfieldにテキストを追加するとトリガーが走り翻訳されたテキストが追加されていきます。
`translations`の`input`にテキストを入れることで、`translated`が作られ翻訳されたテキストが追加されました。

<img width="424" alt="スクリーンショット 2019-12-12 5.10.51.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54825/c22523f4-6f62-79df-63d1-dc0d7d0e76df.png">


## Translate Text Extensionsのコード

https://github.com/firebase/extensions/blob/master/firestore-translate-text/functions/src/index.ts

fucntion内でやっていることはfirestoreの`onWrite`イベントをトリガーに`Cloud Translation API`でテキストを翻訳し、ドキュメントに書き込んでいるだけです。簡単ですね。


## おわりに

今はまだ簡単なExtensionsが公開されているだけですが、今後の発展に期待です。
開発者がfunctionをextension化して公開したり、公開されたものを利用したりしてエコシステムが充実したらコード書かずになんでもできちゃうんじゃないかって夢が広がりますね！
あんなextensionが欲しい、このfunctionをextension化したいとか、とか。
規模が大きいfirebaseの運用とか世にはあまり出ない、知見やtipsをextensionという形で共有できるんじゃないか、そしたらより良いfirebase生活を送れそうです。

## クローズドFirebase勉強会@アル

実はアルでは、Firebaseを本番投入運用している人たちだけで知見を持ち寄りクローズドなFirebase勉強会を開催してたりします。

知見を溜め込んでいるそこのあなた、次回は1/30ですよ。
どうぞ私のTwitterまでご連絡ください〜

#### ↓↓↓extensionが公開された直後ぐらいの勉強会のトピック↓↓↓
<img width="618" alt="スクリーンショット 2019-12-12 5.02.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54825/e8b43987-9a9e-4dd5-0dd2-d28d9b3b2cd6.png">

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">アルでやってるクローズドなFirebase勉強会、次回は2020/1/31です</p>&mdash; ken5@アルEngineer (@keng0o_) <a href="https://twitter.com/keng0o_/status/1204868683308228608?ref_src=twsrc%5Etfw">December 11, 2019</a></blockquote>
行列の対角化を考えるときに固有値や固有ベクトルを求めれば良い理由

$A$ を**対角化可能な** $n$ 次正方行列とすると，ある $n$ 次正方行列 $P$ が存在して

```math
P^{-1}AP=
\begin{pmatrix}
\lambda_1 &  & O \\
 & \ddots &  \\
O &  & \lambda_n
\end{pmatrix}
```

が成り立つ．このとき

```math
AP=P
\begin{pmatrix}
\lambda_1 &  & O \\
 & \ddots &  \\
O &  & \lambda_n
\end{pmatrix}
```

である．$p_1,\cdots,p_n$ を $n$ 次列ベクトルとして $P=(p_1,\cdots,p_n)$ と書き表すと

```math
A(p_1,\cdots,p_n)=(p_1,\cdots,p_n)
\begin{pmatrix}
\lambda_1 &  & O \\
 & \ddots &  \\
O &  & \lambda_n
\end{pmatrix}
```

となり，これより各 $k=1,\cdots,n$ に対して

```math
Ap_k=\lambda_kp_k
```

が得られる．すなわち，$\lambda_k$ は $A$ の固有値であり，$p_k$ は $\lambda_k$ に対応する $A$ の固有ベクトルである．従って，$A$ の対角化を実現するには $A$ の固有値と固有ベクトルを求めればよい．
MacOS環境構築あるある

#Xcodeが古くてそれがネックで全て中断される！Merde!

```
Error: Your Xcode (10.2.1) is too outdated.
Please update to Xcode 11.2.1 (or delete it).
Xcode can be updated from the App Store.
```

コマンドでダウンロードできないからさらにMerde!
https://developer.apple.com/download/

あとドチャクソダウンロードが遅い！8G近くあるから「あと12時間です」とか表示されてMerde!

せめてワンタッチとかMacアプデとかで楽に最新化されていかないかな:frowning2:


#気を取り直して今日のひとネタ
###python女子が自分に彼氏がいる事を匂わせる時にありそうなこと

```
>>> はぁ…好き。
  File "<stdin>", line 1
    はぁ…好き。
    ^
SyntaxError: invalid syntax
>>> 'はぁ…好き。'
'\xe3\x81\xaf\xe3\x81\x81\xe2\x80\xa6\xe5\xa5\xbd\xe3\x81\x8d\xe3\x80\x82'
```

以上、寝よ

#合わせて読みたい
[MacでPythonインストールなら知っておきたい・いろは](https://qiita.com/masajiro/items/6d79205b79483d1ee00a)
勉強記録　15日目 〜クラスのメンバ変数の初期化〜 - Effective C++ 第3版 -

#　はじめに

Effective C++ 第3版の4項19ページから勉強していきます。
今回は、「クラスのメンバ変数の初期化」についです。

# Effective C++ 第3版 - 4項　オブジェクトは、使う前に初期化しよう -

## クラスのメンバ変数の初期化

### 初期化と代入

以下のコードのようなPersonクラスを考えます。

```cpp
class Person {
 public:
  explicit Person(const std::string &name, const int &age);
  explicit Person();

 private:
  std::string name_;
  int         age_;
};
```

このクラスのコンストラクタを定義します。

```cpp
Person::Person(const std::string &name, const int &age) {
  name_ = name;                 // 代入であって初期化でない
  age_ = age;                   // 代入であって初期化でない
}
```

上のコードのように書けば、コンストラクタで初期化することができます。
しかし、これはベストな方法ではありません。
C++では、コンストラクタが実行される前に、データメンバが初期化されることになっています。
そのため、上のコードでは、デフォルトコンストラクタが呼ばれた後に、代入を行っています。
ただし、組み込み型(int 等)は、代入の前に初期化されている保証はありません。

一般に、コンストラクタでは、メンバ初期化リストを使って、メンバ変数を初期化したほうが良い。
メンバ初期化リストを使った初期化の仕方は、以下のコードです。

```cpp
Person::Person(const std::string &name, const int &age)
 : name_(name), 
   age_(age)
   {}
```

上のコードは、先ほど、定義したコンストラクタと同様の結果となるが、
デフォルトコンストラクタが呼ばれた後に、代入するといった無駄な処理を省くことができる。
つまり、メンバ変数 name_ は、name を引数にしてコピーコンストラクタで初期化されることになる。

デフォルトコンストラクタで初期化するメンバ変数に対しても、初期化子を用いて、初期化ができます。
そのコードは、以下のようになります。

```cpp
Person::Person()
  : name_(),                // デフォルトコンストラクタを呼び出す
    age_(0)                 // ここでは明示的に0で初期化
  {}
```

ユーザー定義型のデータメンバは、初期化子で初期化しなければ、自動的にコンパイラがデフォルトコンストラクタが呼び出します。
そのため、上のようなコードをやりすぎ（無駄）と考えるプログラマもいるそうです。。

私は、メンバ変数の数が少なければ、すべて初期化子リストで初期化していました。
また、メンバ変数の数が多すぎると、初期化子リストを使わず、代入で済ましていました。


以下に、勉強で使用したコードを示します。

### サンプルコード

```cpp:4_initialize_class.cpp
#include <iostream>

/*
Person::Person(const std::string &name, const int &age) {
  name_ = name;  // これらは代入であって初期化ではない
  age_  = age;
}
*/
// は、コンストラクタの本体が実行される前に、データメンバが初期化され、その後に代入している。
// 一般に、classの初期化には、代入ではなく、メンバ初期化子リストを使う
// Person::Person(const std::string &name, const int &age) : name_(name), age_(age) {}
// のように書くと、一度初期化された後に、代入する無駄を省くことができる。

class Person {
 public:
  explicit Person(const std::string &name, const int &age);
  explicit Person();

 private:
  std::string name_;
  int         age_;
};

/*Person::Person(const std::string &name, const int &age) {
  name_ = name;  // これらは代入であって初期化ではない
  age_  = age;
}*/

Person::Person(const std::string &name, const int &age) : name_(name), age_(age) {}

Person::Person() : name_(), age_(0) {}

int main(int argc, char *argv[]) {
  std::cout << "4_initialize_class.cpp" << std::endl;
  Person per("Mike", 25);

}
```

### 実行結果


## 参考文献

・https://www.amazon.co.jp/gp/product/4621066099/ref=dbs_a_def_rwt_hsch_vapi_taft_p1_i0
弱い紐帯の強さとコミュニティ

この記事は[静岡アドベントカレンダー13日目の記事](https://qiita.com/advent-calendar/2019/shizuoka)です。

はじめに
----

朝ツイッター見てたら[私の知っている静岡中部のIT勉強会](https://qiita.com/secondarykey/items/2566edc61e577c006374)というエントリーがドンブラコと流れてきて、うっかり拾ってしまい、つい埋めねばならない気がしたので、今回書くことにしました。ちなみに言語戦争の歴史は私の駄スライドなので、その当時の事はそっちを見てください。

私自身はShizuoka.pyの主催をやっていますが、最近は頻度高くは開催していません。ガチのPythonistaが東京に流れちゃったりとか、忙しくなって参加しにくくなったりとか色々あって参加者が減ってしまった、、、かといって初心者対応は静岡読書会で疲れちゃったしなーっていうのが主な理由です。

最近の静岡のPython事情については20日目に載るようなので今回は特にここでは触れません。

弱い紐帯の強さとプログラミングコミュニティ
----

[弱い紐帯の強さ](https://www.nttcom.co.jp/comzine/no133/asuni/index.html)という言葉をご存知でしょうか？要するに社会的なつながりが強いほど、保持している情報は類似してしまい、ある程度弱いつながりからのほうが新しい情報やアイデアがもたらされるという一見逆説的な理論です。

プログラミングコミュニティはまさに弱い紐帯を構成しているわけで、プログラミングという弱い共通項で多様な背景の人間が情報交換することで得られるものは大きいと思うし、皆さん恩恵を感じていると思います。そういう意味で、静岡に色々なコミュニティが形成されて多様なエコシステムが出来上がっている現状は望ましいことだと思います。

Mishima.sykという謎コミュニティ
----

静岡で開催されているコミュニティのなかでも特に秘密のヴェールに包まれている感があるのが[Mishima.syk](http://mishima-syk.github.io/)でしょう。Mishima.sykは主にライフサイエンス業界の人が集まってPythonやRやJavascriptとか機械学習や深層学習の話をしています。静岡には製薬企業の研究所があったり、遺伝研があるので、そっち系の研究者がかなり集まっている関係でそういうコミュニティが形成されました。

資料や内容などもできるだけオープンにしているので、もし機械学習とかプログラミングをベースにしていて、バイオインフォマティクスとかケモインフォマティクスにも興味があるんだよねーという方がいましたら、気軽に参加してください。色々勉強になったり新しい発見があったりすると思うし、弱い紐帯の強さというものも実感できると思います。

静岡でバイオ・ケミストリ関連の学部に通っていて、Dryにも興味のある学生さんとか、バイオ系のDryの仕事をしてみたいなーというIT系の方も参加するとコネクションができていいことあるかもしれません。


Shizuoka.pyどうなってんの？
----

海外のPyConに遊びに行くのが忙しくてさぼってます。来年には開催しようと思っています。
【合格】AWS認定ソリューションアーキテクトプロフェッショナル(AWS-SAP)受験体験記（2019/12）

<center>
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/207381/6ef632fd-2baa-541f-2508-08fbcd1c623f.png">
</center>
###概要
タイトルのまんまですが、既に同様のエントリーが大量にあり
お腹一杯の方もいると思うので、受験対策でやった内容を簡潔にお届けます。
12月9日に受けて760点でかろうじて合格しました。
受験料は３万円かかるので１万円/時間も払って脳を酷使する贅沢なひと時を味わえます😅
AWS-SAPの試験情報は下記が参考になると思います。

■AWS-SAP試験情報
[AWS 認定ソリューションアーキテクト – プロフェッショナル](https://aws.amazon.com/jp/certification/certified-solutions-architect-professional)

###自分のレベル
・エンジニア歴は6年ですがクラウドに携わって３年目です。
・AWS環境上に構築された商用Web環境の構築・保守経験が２年ほどあります。
・３年前にAWS認定ソリューションアーキテクトアソシエイトを取りました。

###やったこと
・[koiwaclub](https://aws.koiwaclub.com/)の問題集を解き、正解と間違いの理由を理解できるレベルにしました。
問題数が多いので試験改定後に更新された問題（＃２８以降）に絞り解きました。
回し者ではないですが受験対策としてkoiwaclubはかなりオススです:bangbang:

・解説が難しいところ（自分の知識不足により）については、[AWSドキュメント](https://aws.amazon.com/jp/documentation/gettingstarted/)や[Tutorialsdojoのチートシート](https://tutorialsdojo.com/aws-cheat-sheets/)を参考にしました。
・勉強期間は１ヶ月間で、平均して平日１時間、休日は２〜３時間程取り組みました。

・AWS Trainingで「AWS Certified Solutions Architect – Professional」を受けました。
日本語で説明してくれるので有難いです。無料ですが内容は４時間とボリューミーで、くどくど説明することもなくテンポもよかったです。チャーミングなおじさんが問題の解説や解き方のポイントを説明してくれるのでオススメです。

・あとは、Twitterで積み上げ報告をして怠けないようにしました。

###試験内容
・koiwaclubの類似問題が全体の3/4程度で出題されました😍
・残りの1/4もkoiwaclubの内容をきちんと把握できてれば応用できる内容でした。
　※自分はここが上手く解けなかったです；
・日本語訳のおかしいところがあるので英語原文に切り替えてみると良いです。（日本語に戻せます）
・問題を全部解いたところで３０分程度残り、見直している内に時間切れとなりました。
　３時間では足りないくらいの感覚です。



みなさんの参考になれば幸いです😀
ラインみたいなwebアップリケーションを作ろう！！　２日目

#はじめに
この記事は、2019/11/1からプログラミング学習を始めた学生がプロのプログラマーになるまでのアウトプットする為の書き込みの場である。

#学んだ事
- **haml変数**


```hello.haml
- name='yoppy'
%p= "私の名前は#{name}です。"

```
```hello.html
<p>私の名前はピカわかです。</p>

```

- **inputタグ**
 - フォームを構成する様々な入力部品を作成する
 - type属性というものを使用します
  - type属性には、色々な使い方がありますが、今回は、一行テキストボックスが必要だった為type="hidden"を使いました
  - こちらの記事を参考にした為こちらのサイトをみていただけるとわかりやすいと思います
  - http://www.htmq.com/html5/input.shtml

#感想
学習の集中力を上げる為には、朝昼のご飯を抜きコーヒーとガムで学習をすれば学習に集中できる時間が圧倒的に上がることがわかりました！！

メンタリストのDaigoさんが書いた『知識を操る読書術』を読んで得た知識

- 情報を仕入れる為に、本を読んでいるならば、目次をみて、自分が読みたいと思ったところを読めば良い
- 本を読む前の準備が大切なこと
- 仕入れた情報をアウトプットする大切さ

#終わりに
もっとこうした方が良いよなどご指摘頂けると幸いです
ボタンクリックでランダムでペンギンの画像が出るページを作る その2


概要・目次は[こちら](https://qiita.com/xcx_04/items/332ab141de4aad6fc5c5)

# ベースづくり
整理のために、ひとまず必要なページなどを書き出してみます。
いわゆるサイトマップ。

index.html
⇃（ボタンクリックで遷移）
result.php（ランダムでペンギンの画像表示）

サイトマップ作るほどでもないのでこれで

Javascriptとか組み合わせればページ遷移せずに（index.html内で）画像表示までできるんだろうけど、とりあえずシンプルにこの形で…

### コーディング
サイトマップが出来たらページデザイン、
デザインが出来たらコーディングしていきます。
（複雑なものだとワイヤー作ったほうがいいと思います…）

ひとまずphp無しに作りますが、作りながらどこを動的に処理したいか考えつつコーディングします。
![コメント 2019-12-01 175345.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531501/bc566da7-eebc-91f8-ffc1-9dd5bc3e4da9.png)
![コメント 2019-12-01 17534dsdsd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531501/24a1514c-c098-4c80-5d69-7f43ec6ba32d.png)
画像、画像のalt、画像のタイトル、説明文が変わっていくな～～とか思いながらコーディングします



# phpを実装する
ベースが出来たら、phpで動きを実装していきます。

```html
<body>
	<div class="wrap">
		<header class="header">Qiita</header>
		<article class="main">
			<h1 class="main-ttl">Random Penguin</h1>
			<p class="main-img"><img src="img/01.jpg" alt="タイトル01"></p>
			<p class="main-img-ttl">タイトル01</p>
			<p class="main-img-caption">説明文01</p>
		</article>
		<footer class="footer">&copy; 2019 Random Penguin</footer>
	</div>
</body>
```
`main-img`、`main-img-ttl`、`main-img-caption`の部分をまとめて変えたいので、配列でセットを作ります。

###画像・タイトル・説明文を設定する

```php
<?php
	$set = array(
		array( //[0]
			'title' => 'タイトル01', 
			'img' => '01', 
			'caption' => '説明文01'
		),
		array( //[1]
			'title' => 'タイトル02', 
			'img' => '02', 
			'caption' => '説明文02'
		),
		array( //[2]
			'title' => 'タイトル03', 
			'img' => '03', 
			'caption' => '説明文03'
		),
	);

	echo 'タイトル：'.$set[0]['title'].'<br>';
	echo '画像：'.$set[0]['img'].'<br>';
	echo '説明文：'.$set[0]['caption'];
?>

//実行結果
タイトル：タイトル01
画像：01
説明：キャプション01
```
`$set[0]`の数字を変えればその中にセットしたtitleなどが表示されます。

###ランダムな数字を発生させる
rand関数を使います。

```php
//0～2の数字からランダムな数字を$randomに入れる
$random = rand(0, count($set)-1);
//$set[0～2]を$resultに入れる
$result = $set[$random];
```
`rand(0, 2)`でもいいけど、`$set`の中身が増えても対応させていきたいので、`$set`の中身をcountで数えて-1します。
あとは`$result['title']`などで表示させるだけ。


###htmlに組み込む
```php
<?php
	$set = array(
		array( //[0]
			'title' => 'タイトル01', 
			'img' => '01', 
			'caption' => '説明文01'
		),
		array( //[1]
			'title' => 'タイトル02', 
			'img' => '02', 
			'caption' => '説明文02'
		),
		array( //[2]
			'title' => 'タイトル03', 
			'img' => '03', 
			'caption' => '説明文03'
		),
	);

	$random = rand(0, count($set)-1);
	$result = $set[$random];
?>
<body>
	<div class="wrap">
		<header class="header">Qiita</header>
		<article class="main">
			<h1 class="main-ttl">Random Penguin</h1>
			<p class="main-img"><?php echo '<img src="img/'.$result['img'].'.jpg" alt="'.$result['title'].'">' ;?></p>
			<p class="main-img-ttl"><?php echo $result['title']; ?></p>
			<p class="main-img-caption"><?php echo $result['caption']; ?></p>
		</article>
		<footer class="footer">&copy; 2019 Random Penguin</footer>
	</div>
</body>
```
結果ページで更新かけるとまたランダムに変わってしまったり、いろいろ改善すべき点はあるけども、
やりたいことはなんとなくできたのでオッケーとします。

[テストページ](http://xcx04.php.xdomain.jp/randompenguin)
Global Day of Coderetreat 2019 in Aoyamaに参加してきました。【モブプロ・ペアプロ】

Global Day of Coderetreatは世界で同じ日に開催されるモブプロの勉強会です。
同日に日本各地で勉強会が開催されました。

私は青山で開催された勉強会に参加してきました。
https://connpass.com/event/150030/

## タイムスケジュール
08:45 開場
09:15 説明
09:30 セッション1
10:30 セッション2
11:30 ランチ
12:30 セッション3
13:30 セッション4
14:30 おやつ
15:00 セッション5
16:00 セッション6
17:00 全体ふりかえり

各セッションはモブプロ (45分) ふりかえり (10分) 休憩 (5分) です。
※connpassより引用

## モブプロの時の流れ
・モブプロ(45min)➡︎ふりかえり(10min or 5min)➡︎休憩(10min or 5min)
・Mobster➡︎ドライバーとナビゲーターを設定できる。
・ふりかえりはKPT(続けるべきこと, 抱えている問題, 次にトライしたいこと) or YWT(やったこと、わかったこと、次にすること)で行う。
・モブプロ時はMobsterというアプリを使う。
・Mobster➡︎ドライバーとナビゲーターを設定できる。
・DriverとNavigatorは5min交代。
・モブプロ45minは別タイマーで代用。
・ナビゲーターはパソコンを使って調べたりしてもよい。
・総括、全体の振り返りはfun/done/learn + wantで行う。
・1人1枚ずつ付箋で貼っていき、感想をいう。
・モブプロのメリット: 複数人で実装するためコードレビューによる手直しが少ない。コード修正の工数が削減できる。

![unnamed (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/0ef47974-a7b9-176c-e624-8ede5b1586c9.jpeg)


## こうするとより良いかも
ミドル1人以上 + ジュニア 2人以上で組む
ドライバーは自分のコーディング時の思考をできるだけ詳細にそのまま喋る
例えば
ここでは◯◯の処理をしたいから、このメソッドを読んで☓☓する
書こうとしている処理は前に書いた処理と似てるから同じところで処理したい
◯◯する処理を書きたいけど、どこから手を付けていいかわからないで困った
ナビゲーターはその思考にツッコミいれたり、フォローをいれる
ナビゲーターはその思考をトレースして、詰まりそうな箇所があれば先回りして調べておく
ドライバーの視野は狭くなりがちなので、ナビゲーターが広げてあげる
ミドルの人はできるだけ詳細に喋りながらコードを書く
ジュニアはそのレベル感を真似して喋りながら書く
ジュニアは、ナビゲーターのときにミドルの人の思考を見て学び（インプット）、自分がドライバーのときに学んだことを実施（アウトプット）しつつ、変な箇所があればリアルタイムでミドルに修正してもらうイメージ

## 会場について
会場はDataSignさま提供。
![IMG-1423.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/07f28181-cbcf-790f-27a4-1d6f80b5b489.jpeg)

![IMG-1422.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/24466616-6fbb-272a-ccfd-f36f6ef465fa.jpeg)

昼食とおやつが提供されました。
コーヒーはスタバ！🤩

![IMG-1416.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/5cf2b0ed-16c1-741d-287c-b5aa2aa817b3.jpeg)

![IMG-1425.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/890488ac-0464-9d5e-51ed-1aec26a607a1.jpeg)

![IMG-1424.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276894/e3a76ec1-4063-7060-8e52-e246ee44e91f.jpeg)

パウンドケーキ、サンドイッチともに、とても美味しかったです。

おやつの提供はやっとむさま
https://twitter.com/yattom

美味しいパウンドケーキはこちらです⬇︎⬇︎
ゴンドラ
http://patisserie-gondola.com/


## 参考
・モブプログラミングに特化したタイマーアプリ「Mobster」 - kakakakakku blog
https://kakakakakku.hatenablog.com/entry/2018/07/01/170255
・Amazon | Wincle カウントタイマー 19cm カチカチ音の静かなクオーツ駆動 時間感覚を養い 時間管理 に適した アナログ タイマー (0〜60分計測可能) 時間管理の為のお役立ちツール | 知育時計・時計のおもちゃ | おもちゃ
https://www.amazon.co.jp/dp/B07L3TTSLD/
・YWTという振り返り手法について | ナカシマガジン
https://hisa-magazine.net/blog/manabutikara/ywt/
・【徹底解説】正しい「KPT」が仕事の成果を生み出す！進め方のコツ、現場の事例を紹介 | SELECK [セレック]
https://seleck.cc/kpt
・ふりかえりでFun! Done! Learn! | オブジェクトの広場
https://www.ogis-ri.co.jp/otc/hiroba/others/ActivityPocket/FunDoneLearn.html
TerraformでAWS ECRのリポジトリを作成してpushする

## はじめに
SREエンジニアやってます。@hayaosatoです。
今回はAWS ECR(以下、ECR)でのリポジトリ作成をTerraformで作成した際に、その勢いでコンテナイメージのpushまでやっちゃおうという小ネタです。

terraform及びプロバイダのバージョンは以下の通りです。

```shell
Terraform v0.12.12
+ provider.aws v2.40.0
+ provider.null v2.1.2
```

## ECR
ECRのリポジトリ作成のTerraformは簡単で、Terraformのリソースの中でもArgumentは非常に少ないです。
リポジトリは以下のように作成できます。

```tf
resource "aws_ecr_repository" "default" {
  name                 = var.image_name
  image_tag_mutability = "MUTABLE"

  image_scanning_configuration {
    scan_on_push = true
  }
}
```
`image_scanning_configuration`でコンテナイメージのセキュリティ診断も行ってくれるようなので有効にしておくと良いと思います。

## コンテナイメージのpush
ここからが本題です。
上記のように作成したECRリポジトリに`terraform apply`の際に同時にコンテナイメージをpushしてしまいましょう。
ECRへのpushコマンドは以下のようになっています。

```shell
$(aws ecr get-login --no-include-email --region ${リージョン})
docker build -t ${コンテナイメージ名} ${Dockerfileのディレクトリ}
docker tag ${コンテナイメージ名}:latest ${リポジトリURL}
docker push ${リポジトリURL}
```
terraformでは、このようなコマンド実行はprovisioningで実行すると良いのですが、ECRリソースにはprovisionerが提供されていません。
そこで、そのような場合には`null_resource`というリソースを使うことで任意のコマンドを`terraform apply`時に実行することができます。
コンテナイメージのpushコマンドをterraformで実現すると以下のようになります。

```tf
resource "null_resource" "default" {
  provisioner "local-exec" {
    command = "$(aws ecr get-login --no-include-email --region ${var.region})"
  }

  provisioner "local-exec" {
    command = "docker build -t ${var.image_name} ${var.docker_dir}"
  }

  provisioner "local-exec" {
    command = "docker tag ${var.image_name}:latest ${aws_ecr_repository.default.repository_url}"
  }

  provisioner "local-exec" {
    command = "docker push ${aws_ecr_repository.default.repository_url}"
  }
}
```

## 最後に
このように、ECRのリポジトリを作成してその流れでコンテナイメージのビルド&プッシュも実現しました。
現実的に使うかは別として、Fargateとか作成するときにちょっとだけ使えるんじゃないかな。。。と思っています。

## 参考
- [Terraform Documentation](https://www.terraform.io/docs/index.html)